merge mozilla-inbound to mozilla-central
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 27 Feb 2014 14:45:02 +0100
changeset 171303 0b930fe64a1ed3441b5e1ffe9344c0053c7e95c4
parent 171302 a98a1d78817fff4653e39b10d09b47feaefd8abb (current diff)
parent 171263 83fc9dab3ddb4c329b18be8f96302318f147b7e6 (diff)
child 171318 f8e801b991bcc20c5eea6b9558b743ab15c73bf9
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
merge mozilla-inbound to mozilla-central
dom/events/nsDOMDataTransfer.cpp
dom/events/nsDOMDataTransfer.h
toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in
xpcom/base/nsTraceRefcntImpl.cpp
xpcom/base/nsTraceRefcntImpl.h
xpcom/glue/nsTraceRefcnt.h
--- a/accessible/src/base/Logging.cpp
+++ b/accessible/src/base/Logging.cpp
@@ -12,17 +12,17 @@
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 #include "OuterDocAccessible.h"
 
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionPrivate.h"
-#include "nsTraceRefcntImpl.h"
+#include "nsTraceRefcnt.h"
 #include "nsIWebProgress.h"
 #include "prenv.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIURI.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
@@ -795,17 +795,17 @@ logging::DOMEvent(const char* aDescr, ns
   logging::MsgEnd();
 }
 
 void
 logging::Stack()
 {
   if (IsEnabled(eStack)) {
     printf("  stack: \n");
-    nsTraceRefcntImpl::WalkTheStack(stdout);
+    nsTraceRefcnt::WalkTheStack(stdout);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // namespace logging:: initialization
 
 bool
 logging::IsEnabled(uint32_t aModules)
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -428,16 +428,25 @@ this.Logger = {
     if (aEvent.eventType == Events.STATE_CHANGE) {
       let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
       let stateStrings = event.isExtraState ?
         Utils.AccRetrieval.getStringStates(0, event.state) :
         Utils.AccRetrieval.getStringStates(event.state, 0);
       str += ' (' + stateStrings.item(0) + ')';
     }
 
+    if (aEvent.eventType == Events.VIRTUALCURSOR_CHANGED) {
+      let event = aEvent.QueryInterface(
+        Ci.nsIAccessibleVirtualCursorChangeEvent);
+      let pivot = aEvent.accessible.QueryInterface(
+        Ci.nsIAccessibleDocument).virtualCursor;
+      str += ' (' + this.accessibleToString(event.oldAccessible) + ' -> ' +
+	this.accessibleToString(pivot.position) + ')';
+    }
+
     return str;
   },
 
   statesToString: function statesToString(aAccessible) {
     return Utils.getState(aAccessible).toString();
   },
 
   dumpTree: function dumpTree(aLogLevel, aRootAccessible) {
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -395,16 +395,18 @@ addMessageListener(
     addMessageListener('AccessFu:MoveCaret', moveCaret);
     addMessageListener('AccessFu:MoveByGranularity', moveByGranularity);
     addMessageListener('AccessFu:ClearCursor', clearCursor);
 
     if (!eventManager) {
       eventManager = new EventManager(this);
     }
     eventManager.start();
+
+    sendAsyncMessage('AccessFu:ContentStarted');
   });
 
 addMessageListener(
   'AccessFu:Stop',
   function(m) {
     Logger.debug('AccessFu:Stop');
 
     removeMessageListener('AccessFu:MoveToPoint', moveToPoint);
--- a/accessible/tests/mochitest/jsat/a11y.ini
+++ b/accessible/tests/mochitest/jsat/a11y.ini
@@ -1,13 +1,15 @@
 [DEFAULT]
 support-files =
   jsatcommon.js
   output.js
   doc_traversal.html
+  doc_content_integration.html
 
 [test_alive.html]
+[test_content_integration.html]
 [test_explicit_names.html]
 [test_landmarks.html]
 [test_live_regions.html]
 [test_output.html]
 [test_tables.html]
 [test_traversal.html]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/doc_content_integration.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Traversal Rule test document</title>
+  <meta charset="utf-8" />
+  <script>
+    var frameContents = '<html>' +
+      '<head><title>such app</title></head>' +
+      '<body>' +
+      '<h1>wow</h1>' +
+      '<label><input type="checkbox">many option</label>' +
+      '</body>' +
+      '</html>';
+
+  </script>
+  <style>
+    #windows > iframe {
+      width: 320px;
+      height: 480px;
+    }
+  </style>
+
+</head>
+<body>
+  <div>Phone status bar</div>
+  <div id="windows"></div>
+  <button>Home</button>
+</body>
+</html>
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -150,8 +150,122 @@ var AccessFuTest = {
       }
     };
 
     // Invoke the whole thing.
     SpecialPowers.setIntPref("accessibility.accessfu.activate", 1);
     SpecialPowers.setIntPref("accessibility.accessfu.notify_output", 1);
   }
 };
+
+function AccessFuContentTest(aFuncResultPairs) {
+  this.queue = aFuncResultPairs;
+}
+
+AccessFuContentTest.prototype = {
+  currentPair: null,
+
+  start: function(aFinishedCallback) {
+    this.finishedCallback = aFinishedCallback;
+    var self = this;
+
+    // Get top content message manager, and set it up.
+    this.mms = [Utils.getMessageManager(currentBrowser())];
+    this.setupMessageManager(this.mms[0], function () {
+      // Get child message managers and set them up
+      var frames = currentTabDocument().querySelectorAll('iframe');
+      var toSetup = 0;
+      for (var i = 0; i < frames.length; i++ ) {
+        var mm = Utils.getMessageManager(frames[i]);
+        if (mm) {
+          toSetup++;
+          self.mms.push(mm);
+          self.setupMessageManager(mm, function () {
+            if (--toSetup === 0) {
+              // All message managers are loaded and ready to go.
+              self.pump();
+            }
+          });
+        }
+      }
+    });
+  },
+
+  setupMessageManager:  function (aMessageManager, aCallback) {
+    function contentScript() {
+      addMessageListener('AccessFuTest:Focus', function (aMessage) {
+        var elem = content.document.querySelector(aMessage.json.selector);
+        if (elem) {
+          if (aMessage.json.blur) {
+            elem.blur();
+          } else {
+            elem.focus();
+          }
+        }
+      });
+    }
+
+    aMessageManager.addMessageListener('AccessFu:Present', this);
+    aMessageManager.addMessageListener('AccessFu:Ready', function (aMessage) {
+      aMessageManager.addMessageListener('AccessFu:ContentStarted', aCallback);
+      aMessageManager.sendAsyncMessage('AccessFu:Start', { buildApp: 'browser' });
+    });
+
+    aMessageManager.loadFrameScript(
+      'chrome://global/content/accessibility/content-script.js', false);
+    aMessageManager.loadFrameScript(
+      'data:,(' + contentScript.toString() + ')();', false);
+  },
+
+  pump: function() {
+    this.currentPair = this.queue.shift();
+
+    if (this.currentPair) {
+      if (this.currentPair[0] instanceof Function) {
+        this.currentPair[0](this.mms[0]);
+      } else {
+        this.mms[0].sendAsyncMessage(this.currentPair[0].name,
+                                     this.currentPair[0].json);
+      }
+    } else if (this.finishedCallback) {
+      for (var mm of this.mms) {
+	mm.sendAsyncMessage('AccessFu:Stop');
+      }
+      this.finishedCallback();
+    }
+  },
+
+  receiveMessage: function(aMessage) {
+    if (!this.currentPair) {
+      return;
+    }
+
+    var expected = this.currentPair[1];
+
+    if (expected) {
+      if (expected.speak !== undefined) {
+        var speech = this.extractUtterance(aMessage.json);
+        if (!speech) {
+          // Probably a visual highlight adjustment after a scroll.
+          return;
+        }
+        var checkFunc = SimpleTest[expected.speak_checkFunc] || is;
+        checkFunc(speech, expected.speak);
+      }
+    }
+
+    this.pump();
+  },
+
+  extractUtterance: function(aData) {
+    for (var output of aData) {
+      if (output && output.type === 'Speech') {
+        for (var action of output.details.actions) {
+          if (action && action.method == 'speak') {
+            return action.data;
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+};
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/test_content_integration.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Tests AccessFu content integration</title>
+  <meta charset="utf-8" />
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
+  </script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/chrome-harness.js">
+  </script>
+
+  <script type="application/javascript" src="../common.js"></script>
+  <script type="application/javascript" src="../browser.js"></script>
+  <script type="application/javascript" src="../events.js"></script>
+  <script type="application/javascript" src="../role.js"></script>
+  <script type="application/javascript" src="../states.js"></script>
+  <script type="application/javascript" src="../layout.js"></script>
+  <script type="application/javascript" src="jsatcommon.js"></script>
+
+  <script type="application/javascript">
+    function doTest() {
+      var doc = currentTabDocument();
+      var iframe = doc.createElement("iframe");
+      iframe.mozbrowser = true;
+      iframe.addEventListener("mozbrowserloadend", function () {
+        var simpleMoveNext = { name: 'AccessFu:MoveCursor',
+                               json: { action: 'moveNext',
+                                       rule: 'Simple',
+                                       inputType: 'gesture',
+                                       origin: 'top' }
+                             };
+
+        var simpleMovePrevious = { name: 'AccessFu:MoveCursor',
+                                   json: { action: 'movePrevious',
+                                           rule: 'Simple',
+                                           inputType: 'gesture',
+                                           origin: 'top' }
+                                 };
+
+        var activateCurrent = { name: 'AccessFu:Activate',
+                                json: { origin: 'top' } };
+
+        var simpleMoveLast = { name: 'AccessFu:MoveCursor',
+                               json: { action: 'moveLast',
+                                       rule: 'Simple',
+                                       inputType: 'gesture',
+                                       origin: 'top' }
+                             };
+
+        var simpleMoveFirst = { name: 'AccessFu:MoveCursor',
+                                json: { action: 'moveFirst',
+                                        rule: 'Simple',
+                                        inputType: 'gesture',
+                                        origin: 'top' }
+                              };
+
+        var clearCursor = { name: 'AccessFu:ClearCursor',
+                            json: { origin: 'top' }
+                          };
+
+        function focusFunc(aSelector, aBlur) {
+         return function (mm) {
+          mm.sendAsyncMessage(
+            'AccessFuTest:Focus', { selector: aSelector, blur: aBlur });
+          };
+        }
+
+        var contentTest = new AccessFuContentTest(
+          [
+            // Simple traversal forward
+            [simpleMoveNext,
+            { speak: 'Phone status bar Traversal Rule test document' }],
+           [simpleMoveNext,
+            { speak: 'wow heading level 1 such app' }],
+           [simpleMoveNext,
+            { speak: 'many option not checked check button' }],
+            // check checkbox
+           [activateCurrent,
+            { speak: 'checked' }],
+            [null,
+             { speak: 'checked', speak_checkFunc: 'todo_isnot' }],
+            // uncheck checkbox
+           [simpleMoveNext,
+            { speak: 'Home button' }],
+
+            // Simple traversal backward
+           [simpleMovePrevious,
+            { speak: 'many option checked check button such app' }],
+           [activateCurrent,
+            { speak: 'unchecked' }],
+           [null,
+            { speak: 'unchecked', speak_checkFunc: 'todo_isnot' }],
+           [simpleMovePrevious,
+            { speak: 'wow heading level 1' }],
+           [simpleMovePrevious,
+            { speak: 'Phone status bar' }],
+
+            // Moving to the absolute last item from an embedded document fails.
+            // Bug 972035.
+            [simpleMoveNext,
+            { speak: 'wow heading level 1 such app' }],
+            // Move from an inner frame to the last element in the parent doc
+            [simpleMoveLast,
+             { speak: 'Home button', speak_checkFunc: 'todo_is' }],
+
+            [clearCursor, null], // Reset cursors
+
+            // Moving to the absolute first item from an embedded document fails.
+            // Bug 972035.
+            [simpleMoveNext,
+            { speak: 'Phone status bar Traversal Rule test document' }],
+            [simpleMoveNext,
+             { speak: 'wow heading level 1 such app' }],
+            [simpleMoveNext,
+             { speak: 'many option not checked check button' }],
+            [simpleMoveFirst,
+             { speak: 'Phone status bar', speak_checkFunc: 'todo_is' }],
+
+            // Reset cursors
+            [clearCursor, null],
+
+            // Move cursor with focus in outside document
+            [simpleMoveNext,
+            { speak: 'Phone status bar Traversal Rule test document' }],
+            [ focusFunc('button', false), { speak: 'Home button' }],
+
+            // Blur button and reset cursor
+            [focusFunc('button', true), null],
+            [clearCursor, null],
+
+            // Set focus on element outside of embedded frame while cursor is in frame
+            [simpleMoveNext,
+            { speak: 'Phone status bar Traversal Rule test document' }],
+            [simpleMoveNext,
+             { speak: 'wow heading level 1 such app' }],
+            [focusFunc('button', false), { speak: 'Home button' }]
+
+            // XXX: Set focus on iframe itself.
+            // XXX: Set focus on element in iframe when cursor is outside of it.
+            // XXX: Set focus on element in iframe when cursor is in iframe.
+        ]);
+
+        contentTest.start(function () {
+          closeBrowserWindow();
+          SimpleTest.finish();
+        });
+
+      });
+      iframe.src = 'data:text/html;charset=utf-8,' + doc.defaultView.frameContents;
+      doc.querySelector('#windows').appendChild(iframe);
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(
+      function () {
+        openBrowserWindow(
+          function () {
+            SpecialPowers.pushPrefEnv({
+              "set": [
+                // TODO: remove this as part of bug 820712
+                ["network.disable.ipc.security", true],
+
+
+                ["dom.ipc.browser_frames.oop_by_default", true],
+                ["dom.mozBrowserFramesEnabled", true],
+                ["browser.pagethumbnails.capturing_disabled", true]
+              ]
+            }, doTest) },
+          getRootDirectory(window.location.href) + "doc_content_integration.html");
+        });
+  </script>
+</head>
+<body id="body">
+
+  <a target="_blank"
+     title="Add tests for OOP message handling and general integration"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=972047">Mozilla Bug 933808</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+</body>
+</html>
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -21,17 +21,16 @@ LIBS += \
   $(MOZ_ZLIB_LIBS) \
   $(NULL)
 ifeq ($(ANDROID_VERSION),$(findstring $(ANDROID_VERSION),17 18 19))
 LIBS += \
   -lgui \
   -lsuspend \
   $(NULL)
 endif
-OS_LDFLAGS += -Wl,--export-dynamic
 endif
 
 STL_FLAGS=
 
 LIBS += $(JEMALLOC_LIBS)
 
 LIBS += \
   $(XPCOM_STANDALONE_GLUE_LDOPTS) \
--- a/b2g/app/moz.build
+++ b/b2g/app/moz.build
@@ -34,8 +34,10 @@ LOCAL_INCLUDES += [
     '/xpcom/base',
     '/xpcom/build',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     LOCAL_INCLUDES += [
         '/widget/gonk/libdisplay',
     ]
+
+    LDFLAGS += ['-Wl,--export-dynamic']
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -21,16 +21,17 @@ MOZ_SAFE_BROWSING=
 MOZ_SERVICES_COMMON=1
 MOZ_SERVICES_METRICS=1
 MOZ_CAPTIVEDETECT=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_DISABLE_CRYPTOLEGACY=1
 MOZ_APP_STATIC_INI=1
 NSS_NO_LIBPKIX=1
+MOZ_NO_EV_CERTS=1
 MOZ_DISABLE_EXPORT_JS=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
 MOZ_RAW=1
 MOZ_AUDIO_CHANNEL_MANAGER=1
 fi
 
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -62,32 +62,16 @@ RCINCLUDE = splash.rc
 # here.
 EXTRA_DEPS += firefox.exe.manifest
 endif
 
 PROGRAMS_DEST = $(DIST)/bin
 
 include $(topsrcdir)/config/rules.mk
 
-ifeq ($(OS_ARCH),WINNT) #{
-#
-# Control the default heap size.
-# This is the heap returned by GetProcessHeap().
-# As we use the CRT heap, the default size is too large and wastes VM.
-#
-# The default heap size is 1MB on Win32.
-# The heap will grow if need be.
-#
-# Set it to 256k.  See bug 127069.
-#
-ifndef GNU_CC #{
-LDFLAGS += /HEAP:0x40000
-endif #}
-endif #}
-
 ifneq (,$(filter-out WINNT,$(OS_ARCH)))
 
 ifdef COMPILE_ENVIRONMENT
 libs:: 
 	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 endif
 
 GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js)
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -35,8 +35,19 @@ LOCAL_INCLUDES += [
 
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DEFINES['MOZ_PHOENIX'] = True
+
+# Control the default heap size.
+# This is the heap returned by GetProcessHeap().
+# As we use the CRT heap, the default size is too large and wastes VM.
+#
+# The default heap size is 1MB on Win32.
+# The heap will grow if need be.
+#
+# Set it to 256k.  See bug 127069.
+if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
+    LDFLAGS += ['/HEAP:0x40000']
--- a/browser/base/content/test/newtab/head.js
+++ b/browser/base/content/test/newtab/head.js
@@ -487,34 +487,18 @@ function sendDragEvent(aEventType, aTarg
 
 /**
  * Creates a custom drag event.
  * @param aEventType The drag event's type.
  * @param aData The event's drag data (optional).
  * @return The drag event.
  */
 function createDragEvent(aEventType, aData) {
-  let dataTransfer = {
-    mozUserCancelled: false,
-    setData: function () null,
-    setDragImage: function () null,
-    getData: function () aData,
-
-    types: {
-      contains: function (aType) aType == "text/x-moz-url"
-    },
-
-    mozGetDataAt: function (aType, aIndex) {
-      if (aIndex || aType != "text/x-moz-url")
-        return null;
-
-      return aData;
-    }
-  };
-
+  let dataTransfer = new getContentWindow().DataTransfer("dragstart", false);
+  dataTransfer.mozSetDataAt("text/x-moz-url", aData, 0);
   let event = getContentDocument().createEvent("DragEvents");
   event.initDragEvent(aEventType, true, true, getContentWindow(), 0, 0, 0, 0, 0,
                       false, false, false, false, 0, null, dataTransfer);
 
   return event;
 }
 
 /**
--- a/browser/components/customizableui/src/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/src/CustomizableWidgets.jsm
@@ -673,45 +673,40 @@ const CustomizableWidgets = [{
       containerElem.addEventListener("command", this.onCommand, false);
 
       let list = this.charsetInfo[aSection];
 
       for (let item of list) {
         let elem = aDocument.createElementNS(kNSXUL, "toolbarbutton");
         elem.setAttribute("label", item.label);
         elem.setAttribute("type", "checkbox");
-        elem.section = aSection == "detectors" ? "detectors" : "charsets";
-        elem.value = item.id;
+        elem.section = aSection;
+        elem.value = item.value;
         elem.setAttribute("class", "subviewbutton");
         containerElem.appendChild(elem);
       }
     },
     updateCurrentCharset: function(aDocument) {
       let content = aDocument.defaultView.content;
       let currentCharset = content && content.document && content.document.characterSet;
-      if (currentCharset) {
-        currentCharset = aDocument.defaultView.FoldCharset(currentCharset);
-      }
-      currentCharset = currentCharset ? ("charset." + currentCharset) : "";
+      currentCharset = CharsetMenu.foldCharset(currentCharset);
 
       let pinnedContainer = aDocument.getElementById("PanelUI-characterEncodingView-pinned");
       let charsetContainer = aDocument.getElementById("PanelUI-characterEncodingView-charsets");
       let elements = [...(pinnedContainer.childNodes), ...(charsetContainer.childNodes)];
 
       this._updateElements(elements, currentCharset);
     },
     updateCurrentDetector: function(aDocument) {
       let detectorContainer = aDocument.getElementById("PanelUI-characterEncodingView-autodetect");
-      let detectorEnum = CharsetManager.GetCharsetDetectorList();
       let currentDetector;
       try {
         currentDetector = Services.prefs.getComplexValue(
           "intl.charset.detector", Ci.nsIPrefLocalizedString).data;
       } catch (e) {}
-      currentDetector = "chardet." + (currentDetector || "off");
 
       this._updateElements(detectorContainer.childNodes, currentDetector);
     },
     _updateElements: function(aElements, aCurrentItem) {
       if (!aElements.length) {
         return;
       }
       let disabled = this.maybeDisableMenu(aElements[0].ownerDocument);
@@ -757,23 +752,18 @@ const CustomizableWidgets = [{
 
       let window = node.ownerDocument.defaultView;
       let section = node.section;
       let value = node.value;
 
       // The behavior as implemented here is directly based off of the
       // `MultiplexHandler()` method in browser.js.
       if (section != "detectors") {
-        let charset = value.substring(value.indexOf('charset.') + 'charset.'.length);
-        window.BrowserSetForcedCharacterSet(charset);
+        window.BrowserSetForcedCharacterSet(value);
       } else {
-        value = value.replace(/^chardet\./, "");
-        if (value == "off") {
-          value = "";
-        }
         // Set the detector pref.
         try {
           let str = Cc["@mozilla.org/supports-string;1"]
                       .createInstance(Ci.nsISupportsString);
           str.data = value;
           Services.prefs.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
         } catch (e) {
           Cu.reportError("Failed to set the intl.charset.detector preference.");
--- a/config/config.mk
+++ b/config/config.mk
@@ -476,17 +476,17 @@ INCLUDES = \
   $(NSPR_CFLAGS) $(NSS_CFLAGS) \
   $(OS_INCLUDES) \
   $(NULL)
 
 include $(topsrcdir)/config/static-checking-config.mk
 
 CFLAGS		= $(OS_CPPFLAGS) $(OS_CFLAGS)
 CXXFLAGS	= $(OS_CPPFLAGS) $(OS_CXXFLAGS)
-LDFLAGS		= $(OS_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
+LDFLAGS		= $(OS_LDFLAGS) $(MOZBUILD_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
 
 # Allow each module to override the *default* optimization settings
 # by setting MODULE_OPTIMIZE_FLAGS if the developer has not given
 # arguments to --enable-optimize
 ifdef MOZ_OPTIMIZE
 ifeq (1,$(MOZ_OPTIMIZE))
 ifdef MODULE_OPTIMIZE_FLAGS
 CFLAGS		+= $(MODULE_OPTIMIZE_FLAGS)
@@ -582,20 +582,20 @@ HOST_CMMFLAGS += -fobjc-exceptions
 OS_COMPILE_CMFLAGS += -fobjc-exceptions
 OS_COMPILE_CMMFLAGS += -fobjc-exceptions
 ifeq ($(MOZ_WIDGET_TOOLKIT),uikit)
 OS_COMPILE_CMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
 OS_COMPILE_CMMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
 endif
 endif
 
-COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(EXTRA_COMPILE_FLAGS)
-COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
-COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
-COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
 ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS)
 
 ifndef CROSS_COMPILE
 HOST_CFLAGS += $(RTL_FLAGS)
 endif
 
 #
 # Name of the binary code directories
--- a/configure.in
+++ b/configure.in
@@ -1294,26 +1294,16 @@ if test "$GNU_CC"; then
     CFLAGS="$CFLAGS -std=gnu99"
     if test "${OS_ARCH}" != Darwin; then
         CFLAGS="$CFLAGS -fgnu89-inline"
     fi
     # FIXME: Let us build with strict aliasing. bug 414641.
     CFLAGS="$CFLAGS -fno-strict-aliasing"
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
-    DSO_LDOPTS='-shared'
-    if test "$GCC_USE_GNU_LD"; then
-        # Some tools like ASan use a runtime library that is only
-        # linked against executables, so we must allow undefined
-        # symbols for shared objects in some cases.
-        if test -z "$MOZ_NO_WLZDEFS"; then
-            # Don't allow undefined symbols in libraries
-            DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
-        fi
-    fi
     WARNINGS_AS_ERRORS='-Werror'
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-fPIC'
     ASFLAGS="$ASFLAGS -fPIC"
     AC_MSG_CHECKING([for --noexecstack option to as])
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS -Wa,--noexecstack"
     AC_TRY_COMPILE(,,AC_MSG_RESULT([yes])
@@ -1338,16 +1328,24 @@ if test "$GNU_CC"; then
     AC_MSG_CHECKING([for --build-id option to ld])
     _SAVE_LDFLAGS=$LDFLAGS
     LDFLAGS="$LDFLAGS -Wl,--build-id"
     AC_TRY_LINK(,,AC_MSG_RESULT([yes])
                   [NSPR_LDFLAGS="$NSPR_LDFLAGS -Wl,--build-id"],
                   AC_MSG_RESULT([no])
                   LDFLAGS=$_SAVE_LDFLAGS)
 
+    AC_MSG_CHECKING([for --ignore-unresolved-symbol option to ld])
+    HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED=
+    _SAVE_LDFLAGS=$LDFLAGS
+    LDFLAGS="$LDFLAGS -Wl,--ignore-unresolved-symbol,environ"
+    AC_TRY_LINK(,,AC_MSG_RESULT([yes])
+                  [HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED=1],
+                  AC_MSG_RESULT([no]))
+    LDFLAGS=$_SAVE_LDFLAGS
 
     # Check for -mssse3 on $CC
     AC_MSG_CHECKING([if toolchain supports -mssse3 option])
     HAVE_TOOLCHAIN_SUPPORT_MSSSE3=
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS -mssse3"
     AC_TRY_COMPILE([asm ("pmaddubsw %xmm2,%xmm3");],,AC_MSG_RESULT([yes])
                      [HAVE_TOOLCHAIN_SUPPORT_MSSSE3=1],
@@ -1373,16 +1371,38 @@ if test "$GNU_CC"; then
       AC_MSG_RESULT("$result")
       if test "$result" = "yes"; then
           HAVE_X86_AVX2=1
           AC_DEFINE(HAVE_X86_AVX2)
           AC_SUBST(HAVE_X86_AVX2)
       fi
     esac
 
+    DSO_LDOPTS='-shared'
+    if test "$GCC_USE_GNU_LD"; then
+        # Some tools like ASan use a runtime library that is only
+        # linked against executables, so we must allow undefined
+        # symbols for shared objects in some cases.
+        if test -z "$MOZ_NO_WLZDEFS"; then
+            # Don't allow undefined symbols in libraries
+            DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
+
+            # BSDs need `environ' exposed for posix_spawn (bug 753046)
+            case "$OS_TARGET" in
+            DragonFly|FreeBSD|NetBSD|OpenBSD)
+                if test -n "$HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED"; then
+                    DSO_LDOPTS="$DSO_LDOPTS -Wl,--ignore-unresolved-symbol,environ"
+                else
+                    DSO_LDOPTS="$DSO_LDOPTS -Wl,--warn-unresolved-symbols"
+                fi
+                ;;
+            esac
+        fi
+    fi
+
     # Turn on GNU-specific warnings:
     # -Wall - turn on a lot of warnings
     # -Wpointer-arith - good to have
     # -Wdeclaration-after-statement - MSVC doesn't like these
     # -Werror=return-type - catches missing returns, zero false positives
     # -Werror=int-to-pointer-cast - catches cast to pointer from integer of different size
     # -Wtype-limits - catches overflow bugs, few false positives
     # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
@@ -6266,16 +6286,24 @@ dnl ====================================
 dnl = Disable DOMCrypto
 dnl ========================================================
 if test -n "$MOZ_DISABLE_CRYPTOLEGACY"; then
     AC_DEFINE(MOZ_DISABLE_CRYPTOLEGACY)
 fi
 AC_SUBST(MOZ_DISABLE_CRYPTOLEGACY)
 
 dnl ========================================================
+dnl = Disable EV certificate verification
+dnl ========================================================
+if test -n "$MOZ_NO_EV_CERTS"; then
+    AC_DEFINE(MOZ_NO_EV_CERTS)
+fi
+AC_SUBST(MOZ_NO_EV_CERTS)
+
+dnl ========================================================
 dnl = Disable libpkix
 dnl ========================================================
 if test -n "$NSS_NO_LIBPKIX"; then
     AC_DEFINE(NSS_NO_LIBPKIX)
 fi
 AC_SUBST(NSS_NO_LIBPKIX)
 
 dnl ========================================================
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1638,30 +1638,41 @@ public:
   // mAnimationController isn't yet initialized.
   virtual nsSMILAnimationController* GetAnimationController() = 0;
 
   // Makes the images on this document capable of having their animation
   // active or suspended. An Image will animate as long as at least one of its
   // owning Documents needs it to animate; otherwise it can suspend.
   virtual void SetImagesNeedAnimating(bool aAnimating) = 0;
 
+  enum SuppressionType {
+    eAnimationsOnly = 0x1,
+
+    // Note that suppressing events also suppresses animation frames, so
+    // there's no need to split out events in its own bitmask.
+    eEvents = 0x3,
+  };
+
   /**
    * Prevents user initiated events from being dispatched to the document and
    * subdocuments.
    */
-  virtual void SuppressEventHandling(uint32_t aIncrease = 1) = 0;
+  virtual void SuppressEventHandling(SuppressionType aWhat,
+                                     uint32_t aIncrease = 1) = 0;
 
   /**
    * Unsuppress event handling.
    * @param aFireEvents If true, delayed events (focus/blur) will be fired
    *                    asynchronously.
    */
-  virtual void UnsuppressEventHandlingAndFireEvents(bool aFireEvents) = 0;
+  virtual void UnsuppressEventHandlingAndFireEvents(SuppressionType aWhat,
+                                                    bool aFireEvents) = 0;
 
   uint32_t EventHandlingSuppressed() const { return mEventsSuppressed; }
+  uint32_t AnimationsPaused() const { return mAnimationsPaused; }
 
   bool IsEventHandlingEnabled() {
     return !EventHandlingSuppressed() && mScriptGlobalObject;
   }
 
   /**
    * Increment the number of external scripts being evaluated.
    */
@@ -2482,16 +2493,18 @@ protected:
 
   // If we're an external resource document, this will be non-null and will
   // point to our "display document": the one that all resource lookups should
   // go to.
   nsCOMPtr<nsIDocument> mDisplayDocument;
 
   uint32_t mEventsSuppressed;
 
+  uint32_t mAnimationsPaused;
+
   /**
    * The number number of external scripts (ones with the src attribute) that
    * have this document as their owner and that are being evaluated right now.
    */
   uint32_t mExternalScriptsBeingEvaluated;
 
   /**
    * The current frame request callback handle
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -44,43 +44,43 @@
 #include "nsIPrincipal.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIWebBrowserPersist.h"
 #include "nsEscape.h"
 #include "nsContentUtils.h"
 #include "nsIMIMEService.h"
 #include "imgIContainer.h"
 #include "imgIRequest.h"
-#include "nsDOMDataTransfer.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "nsIMIMEInfo.h"
 #include "nsRange.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLAreaElement.h"
 
-using mozilla::dom::HTMLAreaElement;
+using namespace mozilla::dom;
 
 class MOZ_STACK_CLASS DragDataProducer
 {
 public:
   DragDataProducer(nsPIDOMWindow* aWindow,
                    nsIContent* aTarget,
                    nsIContent* aSelectionTargetNode,
                    bool aIsAltKeyPressed);
-  nsresult Produce(nsDOMDataTransfer* aDataTransfer,
+  nsresult Produce(DataTransfer* aDataTransfer,
                    bool* aCanDrag,
                    nsISelection** aSelection,
                    nsIContent** aDragNode);
 
 private:
-  void AddString(nsDOMDataTransfer* aDataTransfer,
+  void AddString(DataTransfer* aDataTransfer,
                  const nsAString& aFlavor,
                  const nsAString& aData,
                  nsIPrincipal* aPrincipal);
   nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
-                                    nsDOMDataTransfer* aDataTransfer);
+                                    DataTransfer* aDataTransfer);
   static nsresult GetDraggableSelectionData(nsISelection* inSelection,
                                             nsIContent* inRealTargetNode,
                                             nsIContent **outImageOrLinkNode,
                                             bool* outDragSelectedText);
   static already_AddRefed<nsIContent> FindParentLinkNode(nsIContent* inNode);
   static void GetAnchorURL(nsIContent* inNode, nsAString& outURL);
   static void GetNodeString(nsIContent* inNode, nsAString & outNodeString);
   static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
@@ -107,17 +107,17 @@ private:
 };
 
 
 nsresult
 nsContentAreaDragDrop::GetDragData(nsPIDOMWindow* aWindow,
                                    nsIContent* aTarget,
                                    nsIContent* aSelectionTargetNode,
                                    bool aIsAltKeyPressed,
-                                   nsDOMDataTransfer* aDataTransfer,
+                                   DataTransfer* aDataTransfer,
                                    bool* aCanDrag,
                                    nsISelection** aSelection,
                                    nsIContent** aDragNode)
 {
   NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
 
   *aCanDrag = true;
 
@@ -349,17 +349,17 @@ DragDataProducer::GetNodeString(nsIConte
   nsRefPtr<nsRange> range = doc->CreateRange(rv);
   if (range) {
     range->SelectNode(*node, rv);
     range->ToString(outNodeString);
   }
 }
 
 nsresult
-DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
+DragDataProducer::Produce(DataTransfer* aDataTransfer,
                           bool* aCanDrag,
                           nsISelection** aSelection,
                           nsIContent** aDragNode)
 {
   NS_PRECONDITION(aCanDrag && aSelection && aDataTransfer && aDragNode,
                   "null pointer passed to Produce");
   NS_ASSERTION(mWindow, "window not set");
   NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
@@ -698,31 +698,31 @@ DragDataProducer::Produce(nsDOMDataTrans
          dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_IF_ADDREF(*aDragNode = dragNode);
   return NS_OK;
 }
 
 void
-DragDataProducer::AddString(nsDOMDataTransfer* aDataTransfer,
+DragDataProducer::AddString(DataTransfer* aDataTransfer,
                             const nsAString& aFlavor,
                             const nsAString& aData,
                             nsIPrincipal* aPrincipal)
 {
   nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
   if (variant) {
     variant->SetAsAString(aData);
     aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
   }
 }
 
 nsresult
 DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
-                                           nsDOMDataTransfer* aDataTransfer)
+                                           DataTransfer* aDataTransfer)
 {
   NS_ASSERTION(aDragNode, "adding strings for null node");
 
   // set all of the data to have the principal of the node where the data came from
   nsIPrincipal* principal = aDragNode->NodePrincipal();
 
   // add a special flavor if we're an anchor to indicate that we have
   // a URL in the drag data
--- a/content/base/src/nsContentAreaDragDrop.h
+++ b/content/base/src/nsContentAreaDragDrop.h
@@ -16,17 +16,22 @@ class nsIDOMNode;
 class nsPIDOMWindow;
 class nsIDOMDragEvent;
 class nsISelection;
 class nsITransferable;
 class nsIContent;
 class nsIURI;
 class nsIFile;
 class nsISimpleEnumerator;
-class nsDOMDataTransfer;
+
+namespace mozilla {
+namespace dom {
+class DataTransfer;
+}
+}
 
 //
 // class nsContentAreaDragDrop, used to generate the dragdata
 //
 class nsContentAreaDragDrop
 {
 public:
 
@@ -47,17 +52,17 @@ public:
    *                    selection is being dragged.
    * aDragNode - [out] the link, image or area being dragged, or null if the
    *             drag occurred on another element.
    */
   static nsresult GetDragData(nsPIDOMWindow* aWindow,
                               nsIContent* aTarget,
                               nsIContent* aSelectionTargetNode,
                               bool aIsAltKeyPressed,
-                              nsDOMDataTransfer* aDataTransfer,
+                              mozilla::dom::DataTransfer* aDataTransfer,
                               bool* aCanDrag,
                               nsISelection** aSelection,
                               nsIContent** aDragNode);
 };
 
 // this is used to save images to disk lazily when the image data is asked for
 // during the drop instead of when it is added to the drag data transfer. This
 // ensures that the image data is only created when an image drop is allowed.
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -62,17 +62,17 @@
 #include "nsCPrefetchService.h"
 #include "nsCRT.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"
 #include "nsDataHashtable.h"
 #include "nsDocShellCID.h"
 #include "nsDocument.h"
 #include "nsDOMCID.h"
-#include "nsDOMDataTransfer.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMMutationObserver.h"
 #include "nsDOMTouchEvent.h"
 #include "nsError.h"
 #include "nsEventDispatcher.h"
 #include "nsEventListenerManager.h"
 #include "nsEventStateManager.h"
 #include "nsFocusManager.h"
@@ -4969,39 +4969,43 @@ nsContentUtils::SetDataTransferInEvent(W
   // drag events, get the object from the drag session.
   NS_ASSERTION(aDragEvent->message != NS_DRAGDROP_GESTURE &&
                aDragEvent->message != NS_DRAGDROP_START,
                "draggesture event created without a dataTransfer");
 
   nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
   NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
 
-  nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
-  dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
-  if (!initialDataTransfer) {
+  nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
+  nsCOMPtr<DataTransfer> initialDataTransfer;
+  dragSession->GetDataTransfer(getter_AddRefs(dataTransfer));
+  if (dataTransfer) {
+    initialDataTransfer = do_QueryInterface(dataTransfer);
+    if (!initialDataTransfer) {
+      return NS_ERROR_FAILURE;
+    }
+  } else {
     // A dataTransfer won't exist when a drag was started by some other
     // means, for instance calling the drag service directly, or a drag
     // from another application. In either case, a new dataTransfer should
     // be created that reflects the data.
-    initialDataTransfer = new nsDOMDataTransfer(aDragEvent->message, true, -1);
-
-    NS_ENSURE_TRUE(initialDataTransfer, NS_ERROR_OUT_OF_MEMORY);
+    initialDataTransfer = new DataTransfer(aDragEvent->target, aDragEvent->message, true, -1);
 
     // now set it in the drag session so we don't need to create it again
     dragSession->SetDataTransfer(initialDataTransfer);
   }
 
   bool isCrossDomainSubFrameDrop = false;
   if (aDragEvent->message == NS_DRAGDROP_DROP ||
       aDragEvent->message == NS_DRAGDROP_DRAGDROP) {
     isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
   }
 
   // each event should use a clone of the original dataTransfer.
-  initialDataTransfer->Clone(aDragEvent->message, aDragEvent->userCancelled,
+  initialDataTransfer->Clone(aDragEvent->target, aDragEvent->message, aDragEvent->userCancelled,
                              isCrossDomainSubFrameDrop,
                              getter_AddRefs(aDragEvent->dataTransfer));
   NS_ENSURE_TRUE(aDragEvent->dataTransfer, NS_ERROR_OUT_OF_MEMORY);
 
   // for the dragenter and dragover events, initialize the drop effect
   // from the drop action, which platform specific widget code sets before
   // the event is fired based on the keyboard state.
   if (aDragEvent->message == NS_DRAGDROP_ENTER ||
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -15,17 +15,17 @@
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIDOMRange.h"
 #include "nsRange.h"
 #include "imgIContainer.h"
 #include "nsIPresShell.h"
 #include "nsFocusManager.h"
 #include "nsEventDispatcher.h"
-#include "nsDOMDataTransfer.h"
+#include "mozilla/dom/DataTransfer.h"
 
 #include "nsIDocShell.h"
 #include "nsIContentViewerEdit.h"
 #include "nsIClipboardDragDropHooks.h"
 #include "nsIClipboardDragDropHookList.h"
 #include "nsIClipboardHelper.h"
 #include "nsISelectionController.h"
 
@@ -48,16 +48,17 @@
 
 #include "mozilla/ContentEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Selection.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 nsresult NS_NewDomSelection(nsISelection **aDomSelection);
 
 static NS_DEFINE_CID(kCClipboardCID,           NS_CLIPBOARD_CID);
 static NS_DEFINE_CID(kCTransferableCID,        NS_TRANSFERABLE_CID);
 static NS_DEFINE_CID(kHTMLConverterCID,        NS_HTMLFORMATCONVERTER_CID);
 
 // copy string data onto the transferable
@@ -638,19 +639,20 @@ nsCopySupport::FireClipboardEvent(int32_
     return false;
 
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(piWindow);
   const bool chromeShell =
     docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
 
   // next, fire the cut, copy or paste event
   bool doDefault = true;
-  nsRefPtr<nsDOMDataTransfer> clipboardData;
+  nsRefPtr<DataTransfer> clipboardData;
   if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
-    clipboardData = new nsDOMDataTransfer(aType, aType == NS_PASTE, aClipboardType);
+    clipboardData =
+      new DataTransfer(piWindow, aType, aType == NS_PASTE, aClipboardType);
 
     nsEventStatus status = nsEventStatus_eIgnore;
     InternalClipboardEvent evt(true, aType);
     evt.clipboardData = clipboardData;
     nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nullptr,
                                 &status);
     // If the event was cancelled, don't do the clipboard operation
     doDefault = (status != nsEventStatus_eConsumeNoDefault);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -9140,32 +9140,51 @@ nsIDocument::GetReadyState(nsAString& aR
   case READYSTATE_COMPLETE :
     aReadyState.Assign(NS_LITERAL_STRING("complete"));
     break;
   default:
     aReadyState.Assign(NS_LITERAL_STRING("uninitialized"));
   }
 }
 
+namespace {
+
+struct SuppressArgs
+{
+  nsIDocument::SuppressionType mWhat;
+  uint32_t mIncrease;
+};
+
+}
+
 static bool
 SuppressEventHandlingInDocument(nsIDocument* aDocument, void* aData)
 {
-  aDocument->SuppressEventHandling(*static_cast<uint32_t*>(aData));
+  SuppressArgs* args = static_cast<SuppressArgs*>(aData);
+  aDocument->SuppressEventHandling(args->mWhat, args->mIncrease);
   return true;
 }
 
 void
-nsDocument::SuppressEventHandling(uint32_t aIncrease)
-{
-  if (mEventsSuppressed == 0 && aIncrease != 0 && mPresShell &&
-      mScriptGlobalObject) {
+nsDocument::SuppressEventHandling(nsIDocument::SuppressionType aWhat,
+                                  uint32_t aIncrease)
+{
+  if (mEventsSuppressed == 0 && mAnimationsPaused == 0 &&
+      aIncrease != 0 && mPresShell && mScriptGlobalObject) {
     RevokeAnimationFrameNotifications();
   }
-  mEventsSuppressed += aIncrease;
-  EnumerateSubDocuments(SuppressEventHandlingInDocument, &aIncrease);
+
+  if (aWhat == eAnimationsOnly) {
+    mAnimationsPaused += aIncrease;
+  } else {
+    mEventsSuppressed += aIncrease;
+  }
+
+  SuppressArgs args = { aWhat, aIncrease };
+  EnumerateSubDocuments(SuppressEventHandlingInDocument, &args);
 }
 
 static void
 FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
                          bool aFireEvents)
 {
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (!fm)
@@ -9309,40 +9328,69 @@ public:
     FireOrClearDelayedEvents(mDocuments, true);
     return NS_OK;
   }
 
 private:
   nsTArray<nsCOMPtr<nsIDocument> > mDocuments;
 };
 
+namespace {
+
+struct UnsuppressArgs
+{
+  UnsuppressArgs(nsIDocument::SuppressionType aWhat)
+    : mWhat(aWhat)
+  {
+  }
+
+  nsIDocument::SuppressionType mWhat;
+  nsTArray<nsCOMPtr<nsIDocument>> mDocs;
+};
+
+}
+
 static bool
-GetAndUnsuppressSubDocuments(nsIDocument* aDocument, void* aData)
-{
-  uint32_t suppression = aDocument->EventHandlingSuppressed();
-  if (suppression > 0) {
+GetAndUnsuppressSubDocuments(nsIDocument* aDocument,
+                             void* aData)
+{
+  UnsuppressArgs* args = static_cast<UnsuppressArgs*>(aData);
+  if (args->mWhat != nsIDocument::eAnimationsOnly &&
+      aDocument->EventHandlingSuppressed() > 0) {
     static_cast<nsDocument*>(aDocument)->DecreaseEventSuppression();
-  }
-  nsTArray<nsCOMPtr<nsIDocument> >* docs =
-    static_cast<nsTArray<nsCOMPtr<nsIDocument> >* >(aData);
-  docs->AppendElement(aDocument);
-  aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, docs);
+  } else if (args->mWhat == nsIDocument::eAnimationsOnly &&
+             aDocument->AnimationsPaused()) {
+    static_cast<nsDocument*>(aDocument)->ResumeAnimations();
+  }
+
+  if (args->mWhat != nsIDocument::eAnimationsOnly) {
+    // No need to remember documents if we only care about animation frames.
+    args->mDocs.AppendElement(aDocument);
+  }
+
+  aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, aData);
   return true;
 }
 
 void
-nsDocument::UnsuppressEventHandlingAndFireEvents(bool aFireEvents)
-{
-  nsTArray<nsCOMPtr<nsIDocument> > documents;
-  GetAndUnsuppressSubDocuments(this, &documents);
+nsDocument::UnsuppressEventHandlingAndFireEvents(nsIDocument::SuppressionType aWhat,
+                                                 bool aFireEvents)
+{
+  UnsuppressArgs args(aWhat);
+  GetAndUnsuppressSubDocuments(this, &args);
+
+  if (aWhat == nsIDocument::eAnimationsOnly) {
+    // No need to fire events if we only care about animations here.
+    return;
+  }
 
   if (aFireEvents) {
-    NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(documents));
+    NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(args.mDocs));
   } else {
-    FireOrClearDelayedEvents(documents, false);
+    FireOrClearDelayedEvents(args.mDocs, false);
   }
 }
 
 nsISupports*
 nsDocument::GetCurrentContentSink()
 {
   return mParser ? mParser->GetContentSink() : nullptr;
 }
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -975,25 +975,34 @@ public:
   nsTArray<nsCString> mHostObjectURIs;
 
   // Returns our (lazily-initialized) animation controller.
   // If HasAnimationController is true, this is guaranteed to return non-null.
   nsSMILAnimationController* GetAnimationController() MOZ_OVERRIDE;
 
   void SetImagesNeedAnimating(bool aAnimating) MOZ_OVERRIDE;
 
-  virtual void SuppressEventHandling(uint32_t aIncrease) MOZ_OVERRIDE;
+  virtual void SuppressEventHandling(SuppressionType aWhat,
+                                     uint32_t aIncrease) MOZ_OVERRIDE;
+
+  virtual void UnsuppressEventHandlingAndFireEvents(SuppressionType aWhat,
+                                                    bool aFireEvents) MOZ_OVERRIDE;
 
-  virtual void UnsuppressEventHandlingAndFireEvents(bool aFireEvents) MOZ_OVERRIDE;
-  
   void DecreaseEventSuppression() {
+    MOZ_ASSERT(mEventsSuppressed);
     --mEventsSuppressed;
     MaybeRescheduleAnimationFrameNotifications();
   }
 
+  void ResumeAnimations() {
+    MOZ_ASSERT(mAnimationsPaused);
+    --mAnimationsPaused;
+    MaybeRescheduleAnimationFrameNotifications();
+  }
+
   virtual nsIDocument* GetTemplateContentsOwner() MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
                                                                    nsIDocument)
 
   void DoNotifyPossibleTitleChange();
 
   nsExternalResourceMap& ExternalResourceMap()
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1816,16 +1816,17 @@ GK_ATOM(columnSetFrame, "ColumnSetFrame"
 GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
 GK_ATOM(comboboxDisplayFrame, "ComboboxDisplayFrame")
 GK_ATOM(deckFrame, "DeckFrame")
 GK_ATOM(fieldSetFrame, "FieldSetFrame")
 GK_ATOM(flexContainerFrame, "FlexContainerFrame")
 GK_ATOM(formControlFrame, "FormControlFrame") // radio or checkbox
 GK_ATOM(frameSetFrame, "FrameSetFrame")
 GK_ATOM(gfxButtonControlFrame, "gfxButtonControlFrame")
+GK_ATOM(gridContainerFrame, "GridContainerFrame")
 GK_ATOM(HTMLButtonControlFrame, "HTMLButtonControlFrame")
 GK_ATOM(HTMLCanvasFrame, "HTMLCanvasFrame")
 GK_ATOM(subDocumentFrame, "subDocumentFrame")
 GK_ATOM(imageBoxFrame, "ImageBoxFrame")
 GK_ATOM(imageFrame, "ImageFrame")
 GK_ATOM(imageControlFrame, "ImageControlFrame")
 GK_ATOM(inlineFrame, "InlineFrame")
 GK_ATOM(leafBoxFrame, "LeafBoxFrame")
--- a/content/base/src/nsTextFragment.h
+++ b/content/base/src/nsTextFragment.h
@@ -11,17 +11,17 @@
 #ifndef nsTextFragment_h___
 #define nsTextFragment_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 
 #include "nsString.h"
 #include "nsReadableUtils.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 class nsString;
 class nsCString;
 
 // XXX should this normalize the code to keep a \u0000 at the end?
 
 // XXX nsTextFragmentPool?
 
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2867,17 +2867,17 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
     if (GetOwner()) {
       nsCOMPtr<nsIDOMWindow> topWindow;
       if (NS_SUCCEEDED(GetOwner()->GetTop(getter_AddRefs(topWindow)))) {
         nsCOMPtr<nsPIDOMWindow> suspendedWindow(do_QueryInterface(topWindow));
         if (suspendedWindow &&
             (suspendedWindow = suspendedWindow->GetCurrentInnerWindow())) {
           suspendedDoc = suspendedWindow->GetExtantDoc();
           if (suspendedDoc) {
-            suspendedDoc->SuppressEventHandling();
+            suspendedDoc->SuppressEventHandling(nsIDocument::eEvents);
           }
           suspendedWindow->SuspendTimeouts(1, false);
           resumeTimeoutRunnable = new nsResumeTimeoutsEvent(suspendedWindow);
         }
       }
     }
 
     ChangeState(XML_HTTP_REQUEST_SENT);
@@ -2891,17 +2891,18 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
         if (!NS_ProcessNextEvent(thread)) {
           rv = NS_ERROR_UNEXPECTED;
           break;
         }
       }
     }
 
     if (suspendedDoc) {
-      suspendedDoc->UnsuppressEventHandlingAndFireEvents(true);
+      suspendedDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents,
+                                                         true);
     }
 
     if (resumeTimeoutRunnable) {
       NS_DispatchToCurrentThread(resumeTimeoutRunnable);
     }
   } else {
     // Now that we've successfully opened the channel, we can change state.  Note
     // that this needs to come after the AsyncOpen() and rv check, because this
--- a/content/canvas/src/ImageData.h
+++ b/content/canvas/src/ImageData.h
@@ -10,17 +10,17 @@
 #include "nsIDOMCanvasRenderingContext2D.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/TypedArray.h"
 #include <stdint.h>
 
 #include "nsCycleCollectionParticipant.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "js/GCAPI.h"
 
 namespace mozilla {
 namespace dom {
 
 class ImageData MOZ_FINAL : public nsISupports
 {
 public:
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -3337,16 +3337,22 @@ WebGLContext::CompressedTexImage2D(GLenu
         return;
     }
 
     uint32_t byteLength = view.Length();
     if (!ValidateCompTexImageDataSize(target, internalformat, width, height, byteLength, func)) {
         return;
     }
 
+    if (!ValidateCompTexImageSize(target, level, internalformat, 0, 0,
+                                  width, height, width, height, func))
+    {
+        return;
+    }
+
     MakeContextCurrent();
     gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
     WebGLTexture* tex = activeBoundTextureForTarget(target);
     MOZ_ASSERT(tex);
     tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE,
                       WebGLImageDataStatus::InitializedImageData);
 
     ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
@@ -3371,29 +3377,29 @@ WebGLContext::CompressedTexSubImage2D(GL
     {
         return;
     }
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     MOZ_ASSERT(tex);
     WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(target, level);
 
+    uint32_t byteLength = view.Length();
+    if (!ValidateCompTexImageDataSize(target, format, width, height, byteLength, func))
+        return;
+
     if (!ValidateCompTexImageSize(target, level, format,
                                   xoffset, yoffset,
                                   width, height,
                                   levelInfo.Width(), levelInfo.Height(),
                                   func))
     {
         return;
     }
 
-    uint32_t byteLength = view.Length();
-    if (!ValidateCompTexImageDataSize(target, format, width, height, byteLength, func))
-        return;
-
     if (levelInfo.HasUninitializedImageData())
         tex->DoDeferredImageInitialization(target, level);
 
     MakeContextCurrent();
     gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
 }
 
 JS::Value
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -771,36 +771,64 @@ WebGLContext::ValidateCompTexImageSize(G
         if (yoffset % blockHeight != 0) {
             ErrorInvalidOperation("%s: yoffset must be multiple of %d",
                                   InfoFrom(func), blockHeight);
             return false;
         }
 
         /* The size must be a multiple of blockWidth and blockHeight,
          * or must be using offset+size that exactly hits the edge.
-         * Important for small mipmap levels. (s3tc extension appears
-         * to have changed and old code that checks 1x1, 2x2 doesn't
-         * appear necessary anymore)
+         * Important for small mipmap levels.
+         */
+        /* https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
+         * "When level equals zero width and height must be a multiple of 4. When
+         *  level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4.
+         *  If they are not an INVALID_OPERATION error is generated."
          */
-        if ((width % blockWidth != 0) &&
-            (xoffset + width != (GLint) levelWidth))
-        {
-            ErrorInvalidOperation("%s: width must be multiple of %d or "
-                                  "xoffset + width must be %d",
-                                  InfoFrom(func), blockWidth, levelWidth);
-            return false;
+        if (level == 0) {
+            if (width % blockWidth != 0) {
+                ErrorInvalidOperation("%s: width of level 0 must be multple of %d",
+                                      InfoFrom(func), blockWidth);
+                return false;
+            }
+
+            if (height % blockHeight != 0) {
+                ErrorInvalidOperation("%s: height of level 0 must be multipel of %d",
+                                      InfoFrom(func), blockHeight);
+                return false;
+            }
+        }
+        else if (level > 0) {
+            if (width % blockWidth != 0 && width > 2) {
+                ErrorInvalidOperation("%s: width of level %d must be multiple"
+                                      " of %d or 0, 1, 2",
+                                      InfoFrom(func), level, blockWidth);
+                return false;
+            }
+
+            if (height % blockHeight != 0 && height > 2) {
+                ErrorInvalidOperation("%s: height of level %d must be multiple"
+                                      " of %d or 0, 1, 2",
+                                      InfoFrom(func), level, blockHeight);
+                return false;
+            }
         }
 
-        if ((height % blockHeight != 0) &&
-            (yoffset + height != (GLint) levelHeight))
-        {
-            ErrorInvalidOperation("%s: height must be multiple of %d or "
-                                  "yoffset + height must be %d",
-                                  InfoFrom(func), blockHeight, levelHeight);
-            return false;
+        if (IsSubFunc(func)) {
+            if ((xoffset % blockWidth) != 0) {
+                ErrorInvalidOperation("%s: xoffset must be multiple of %d",
+                                      InfoFrom(func), blockWidth);
+                return false;
+            }
+
+            if (yoffset % blockHeight != 0) {
+                ErrorInvalidOperation("%s: yoffset must be multiple of %d",
+                                      InfoFrom(func), blockHeight);
+                return false;
+            }
         }
     }
 
     switch (format) {
     case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
     case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
     case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
     case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
@@ -1148,20 +1176,36 @@ WebGLContext::ValidateTexImageFormatAndT
         validCombo = (type == LOCAL_GL_UNSIGNED_SHORT ||
                       type == LOCAL_GL_UNSIGNED_INT);
         break;
 
     case LOCAL_GL_DEPTH_STENCIL:
         validCombo = (type == LOCAL_GL_UNSIGNED_INT_24_8);
         break;
 
+    case LOCAL_GL_ATC_RGB:
+    case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+    case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
+    case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+    case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+    case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+        validCombo = (type == LOCAL_GL_UNSIGNED_BYTE);
+        break;
+
     default:
         // Only valid formats should be passed to the switch stmt.
-        MOZ_ASSERT("Invalid format");
-        return false;
+        MOZ_ASSERT(false, "Unexpected format and type combo. How'd this happen?");
+        validCombo = false;
+        // Fall through to return an InvalidOperations. This will alert us to the
+        // unexpected case that needs fixing in builds without asserts.
     }
 
     if (!validCombo)
         ErrorInvalidOperation("%s: invalid combination of format %s and type %s",
                               InfoFrom(func), NameFrom(format), NameFrom(type));
 
     return validCombo;
 }
--- a/content/media/AudioNodeStream.cpp
+++ b/content/media/AudioNodeStream.cpp
@@ -510,32 +510,42 @@ AudioNodeStream::FinishOutput()
     AudioSegment emptySegment;
     l->NotifyQueuedTrackChanges(Graph(), AUDIO_TRACK,
                                 mSampleRate,
                                 track->GetSegment()->GetDuration(),
                                 MediaStreamListener::TRACK_EVENT_ENDED, emptySegment);
   }
 }
 
-TrackTicks
-AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination,
-                                          double aSeconds)
+double
+AudioNodeStream::TimeFromDestinationTime(AudioNodeStream* aDestination,
+                                         double aSeconds)
 {
-  MOZ_ASSERT(aDestination->AsAudioNodeStream() &&
-             aDestination->AsAudioNodeStream()->SampleRate() == SampleRate());
+  MOZ_ASSERT(aDestination->SampleRate() == SampleRate());
 
   double destinationSeconds = std::max(0.0, aSeconds);
   StreamTime streamTime = SecondsToMediaTime(destinationSeconds);
   // MediaTime does not have the resolution of double
   double offset = destinationSeconds - MediaTimeToSeconds(streamTime);
 
   GraphTime graphTime = aDestination->StreamTimeToGraphTime(streamTime);
   StreamTime thisStreamTime = GraphTimeToStreamTimeOptimistic(graphTime);
   double thisSeconds = MediaTimeToSeconds(thisStreamTime) + offset;
   MOZ_ASSERT(thisSeconds >= 0.0);
+  return thisSeconds;
+}
+
+TrackTicks
+AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination,
+                                          double aSeconds)
+{
+  AudioNodeStream* destination = aDestination->AsAudioNodeStream();
+  MOZ_ASSERT(destination);
+
+  double thisSeconds = TimeFromDestinationTime(destination, aSeconds);
   // Round to nearest
   TrackTicks ticks = thisSeconds * SampleRate() + 0.5;
   return ticks;
 }
 
 double
 AudioNodeStream::DestinationTimeFromTicks(AudioNodeStream* aDestination,
                                           TrackTicks aPosition)
--- a/content/media/AudioNodeStream.h
+++ b/content/media/AudioNodeStream.h
@@ -124,16 +124,22 @@ public:
     return true;
   }
 
   // Any thread
   AudioNodeEngine* Engine() { return mEngine; }
   TrackRate SampleRate() const { return mSampleRate; }
 
   /**
+   * Convert a time in seconds on the destination stream to seconds
+   * on this stream.
+   */
+  double TimeFromDestinationTime(AudioNodeStream* aDestination,
+                                 double aSeconds);
+  /**
    * Convert a time in seconds on the destination stream to TrackTicks
    * on this stream.
    */
   TrackTicks TicksFromDestinationTime(MediaStream* aDestination,
                                       double aSeconds);
   /**
    * Get the destination stream time in seconds corresponding to a position on
    * this stream.
--- a/content/media/mediasource/SourceBufferResource.cpp
+++ b/content/media/mediasource/SourceBufferResource.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SourceBufferResource.h"
 
 #include <string.h>
 #include <algorithm>
 
 #include "nsISeekableStream.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "prenv.h"
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gMediaSourceLog;
 #define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
 #else
 #define LOG(type, msg)
--- a/content/media/mediasource/test/mochitest.ini
+++ b/content/media/mediasource/test/mochitest.ini
@@ -1,4 +1,4 @@
 [DEFAULT]
-support-files = seek.webm
+support-files = seek.webm seek.webm^headers^
 
 [test_MediaSource.html]
new file mode 100644
--- /dev/null
+++ b/content/media/mediasource/test/seek.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/media/ogg/OggCodecState.cpp
+++ b/content/media/ogg/OggCodecState.cpp
@@ -9,17 +9,17 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Endian.h"
 #include <stdint.h>
 
 #include "nsDebug.h"
 #include "MediaDecoderReader.h"
 #include "OggCodecState.h"
 #include "OggDecoder.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "VideoUtils.h"
 #include <algorithm>
 
 // On Android JellyBean, the hardware.h header redefines version_major and
 // version_minor, which breaks our build.  See:
 // https://bugzilla.mozilla.org/show_bug.cgi?id=912702#c6
 #ifdef MOZ_WIDGET_GONK
 #ifdef version_major
new file mode 100644
--- /dev/null
+++ b/content/media/test/320x240.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/448636.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/VID_0001.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/audio-gaps.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/audio-overhang.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/audio.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/badtags.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/beta-phrasebook.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/big-buck-bunny-unseekable.mp4^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/big.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bogus.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bogus.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug461281.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug482461-theora.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug482461.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug495129.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug495794.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug498380.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug498855-1.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug498855-2.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug498855-3.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug499519.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/media/test/bug500311.ogv^headers^
+++ b/content/media/test/bug500311.ogv^headers^
@@ -1,2 +1,2 @@
 X-Content-Duration: 1.96
-
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug501279.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug504613.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug504644.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug504843.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug506094.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug516323.indexed.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug516323.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug520493.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug520500.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/media/test/bug520908.ogv^headers^
+++ b/content/media/test/bug520908.ogv^headers^
@@ -1,2 +1,2 @@
 X-Content-Duration: 9000
-
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug523816.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug533822.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug556821.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug557094.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug580982.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug603918.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug604067.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/chain.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/chain.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/chain.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/chained-audio-video.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/chained-video.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/detodos.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/detodos.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/dirac.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/file_a4_tone.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/gizmo.mp4^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/huge-id3.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/id3tags.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-cmap-s0c0.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-cmap-s0c2.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-cmap-s1c2.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-cmap-short.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-m0c0.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-m0c3.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-m1c0.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-m1c9.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-m2c0.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-m2c1.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/invalid-preskip.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/make-headers.sh
@@ -0,0 +1,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/.
+
+# Script to generate ^header^ files for all media files we use.
+# This is to ensure that our media files are not cached by necko,
+# so that our detection as to whether the server supports byte range
+# requests is not interferred with by Necko's cache. See bug 977398
+# for details. Necko will fix this in bug 977314. 
+
+FILES=(`ls *.ogg *.ogv *.webm *.mp3 *.opus *.mp4 *.wav`)
+
+rm *.ogg^headers^ *.ogv^headers^ *.webm^headers^ *.mp3^headers^ *.opus^headers^ *.mp4^headers^ *.wav^headers^
+
+# Restore special headers.
+echo "X-Content-Duration: 1.96" > bug500311.ogv^headers^
+echo "X-Content-Duration: 9000" > bug520908.ogv^headers^
+
+for i in "${FILES[@]}"
+do
+  echo "Cache-Control: no-store" >> $i^headers^
+done
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -19,174 +19,283 @@
 
 # To test for a specific bug in handling a specific resource type, make the
 # test first check canPlayType for the type, and if it's not supported, just
 # do ok(true, "Type not supported") and stop the test.
 
 [DEFAULT]
 support-files =
   320x240.ogv
+  320x240.ogv^headers^
   448636.ogv
+  448636.ogv^headers^
+  VID_0001.ogg
+  VID_0001.ogg^headers^
   allowed.sjs
   audio-gaps.ogg
+  audio-gaps.ogg^headers^
   audio-overhang.ogg
+  audio-overhang.ogg^headers^
   audio.wav
+  audio.wav^headers^
   badtags.ogg
+  badtags.ogg^headers^
   basic.vtt
   beta-phrasebook.ogg
+  beta-phrasebook.ogg^headers^
   big-buck-bunny-unseekable.mp4
+  big-buck-bunny-unseekable.mp4^headers^
   big.wav
+  big.wav^headers^
   bogus.duh
   bogus.ogv
+  bogus.ogv^headers^
   bogus.wav
+  bogus.wav^headers^
   bug461281.ogg
+  bug461281.ogg^headers^
   bug482461-theora.ogv
+  bug482461-theora.ogv^headers^
   bug482461.ogv
+  bug482461.ogv^headers^
   bug495129.ogv
+  bug495129.ogv^headers^
   bug495794.ogg
+  bug495794.ogg^headers^
   bug498380.ogv
+  bug498380.ogv^headers^
   bug498855-1.ogv
+  bug498855-1.ogv^headers^
   bug498855-2.ogv
+  bug498855-2.ogv^headers^
   bug498855-3.ogv
+  bug498855-3.ogv^headers^
   bug499519.ogv
+  bug499519.ogv^headers^
   bug500311.ogv
   bug500311.ogv^headers^
   bug501279.ogg
+  bug501279.ogg^headers^
   bug504613.ogv
+  bug504613.ogv^headers^
   bug504644.ogv
+  bug504644.ogv^headers^
   bug504843.ogv
+  bug504843.ogv^headers^
   bug506094.ogv
+  bug506094.ogv^headers^
   bug516323.indexed.ogv
+  bug516323.indexed.ogv^headers^
   bug516323.ogv
+  bug516323.ogv^headers^
   bug520493.ogg
+  bug520493.ogg^headers^
   bug520500.ogg
+  bug520500.ogg^headers^
   bug520908.ogv
   bug520908.ogv^headers^
   bug523816.ogv
+  bug523816.ogv^headers^
   bug533822.ogg
+  bug533822.ogg^headers^
   bug556821.ogv
+  bug556821.ogv^headers^
   bug557094.ogv
+  bug557094.ogv^headers^
   bug580982.webm
+  bug580982.webm^headers^
   bug603918.webm
+  bug603918.webm^headers^
   bug604067.webm
+  bug604067.webm^headers^
   bug883173.vtt
   can_play_type_dash.js
   can_play_type_mpeg.js
   can_play_type_ogg.js
   can_play_type_wave.js
   can_play_type_webm.js
   cancellable_request.sjs
   chain.ogg
+  chain.ogg^headers^
   chain.ogv
+  chain.ogv^headers^
   chain.opus
+  chain.opus^headers^
   chained-audio-video.ogg
+  chained-audio-video.ogg^headers^
   chained-video.ogv
+  chained-video.ogv^headers^
   contentDuration1.sjs
   contentDuration2.sjs
   contentDuration3.sjs
   contentDuration4.sjs
   contentDuration5.sjs
   contentDuration6.sjs
   contentDuration7.sjs
   contentType.sjs
   detodos.opus
+  detodos.opus^headers^
   detodos.webm
+  detodos.webm^headers^
   dirac.ogg
+  dirac.ogg^headers^
   dynamic_redirect.sjs
   dynamic_resource.sjs
   file_a4_tone.ogg
+  file_a4_tone.ogg^headers^
   file_access_controls.html
   file_audio_event_adopt_iframe.html
   fragment_noplay.js
   fragment_play.js
   gizmo.mp4
+  gizmo.mp4^headers^
   huge-id3.mp3
+  huge-id3.mp3^headers^
   id3tags.mp3
+  id3tags.mp3^headers^
   invalid-cmap-s0c0.opus
+  invalid-cmap-s0c0.opus^headers^
   invalid-cmap-s0c2.opus
+  invalid-cmap-s0c2.opus^headers^
   invalid-cmap-s1c2.opus
+  invalid-cmap-s1c2.opus^headers^
   invalid-cmap-short.opus
+  invalid-cmap-short.opus^headers^
   invalid-m0c0.opus
+  invalid-m0c0.opus^headers^
   invalid-m0c3.opus
+  invalid-m0c3.opus^headers^
   invalid-m1c0.opus
+  invalid-m1c0.opus^headers^
   invalid-m1c9.opus
+  invalid-m1c9.opus^headers^
   invalid-m2c0.opus
+  invalid-m2c0.opus^headers^
   invalid-m2c1.opus
+  invalid-m2c1.opus^headers^
   invalid-preskip.webm
+  invalid-preskip.webm^headers^
   long.vtt
   manifest.js
   multiple-bos.ogg
+  multiple-bos.ogg^headers^
   no-cues.webm
+  no-cues.webm^headers^
   noContentLength.sjs
   notags.mp3
+  notags.mp3^headers^
   owl-funnier-id3.mp3
+  owl-funnier-id3.mp3^headers^
   owl-funny-id3.mp3
+  owl-funny-id3.mp3^headers^
   owl.mp3
+  owl.mp3^headers^
   r11025_msadpcm_c1.wav
+  r11025_msadpcm_c1.wav^headers^
   r11025_s16_c1.wav
+  r11025_s16_c1.wav^headers^
   r11025_s16_c1_trailing.wav
+  r11025_s16_c1_trailing.wav^headers^
   r11025_u8_c1.wav
+  r11025_u8_c1.wav^headers^
   r11025_u8_c1_trunc.wav
+  r11025_u8_c1_trunc.wav^headers^
   r16000_u8_c1_list.wav
+  r16000_u8_c1_list.wav^headers^
   reactivate_helper.html
   redirect.sjs
   referer.sjs
   region.vtt
   seek.ogv
+  seek.ogv^headers^
   seek.webm
-  vp9.webm
-  vp9cake.webm
+  seek.webm^headers^
   seek.yuv
   seek1.js
   seek10.js
   seek11.js
   seek12.js
   seek13.js
   seek2.js
   seek3.js
   seek4.js
   seek5.js
   seek6.js
   seek7.js
   seek8.js
   seek9.js
   seekLies.sjs
+  seek_with_sound.ogg^headers^
   short-video.ogv
+  short-video.ogv^headers^
   small-shot.m4a
   small-shot.mp3
+  small-shot.mp3^headers^
   small-shot.ogg
+  small-shot.ogg^headers^
   sound.ogg
+  sound.ogg^headers^
   spacestorm-1000Hz-100ms.ogg
+  spacestorm-1000Hz-100ms.ogg^headers^
   split.webm
+  split.webm^headers^
   street.mp4
+  street.mp4^headers^
   test-1-mono.opus
+  test-1-mono.opus^headers^
   test-2-stereo.opus
+  test-2-stereo.opus^headers^
   test-3-LCR.opus
+  test-3-LCR.opus^headers^
   test-4-quad.opus
+  test-4-quad.opus^headers^
   test-5-5.0.opus
+  test-5-5.0.opus^headers^
   test-6-5.1.opus
+  test-6-5.1.opus^headers^
   test-7-6.1.opus
+  test-7-6.1.opus^headers^
   test-8-7.1.opus
+  test-8-7.1.opus^headers^
   variable-channel.ogg
+  variable-channel.ogg^headers^
   variable-channel.opus
+  variable-channel.opus^headers^
   variable-preskip.opus
+  variable-preskip.opus^headers^
   variable-samplerate.ogg
+  variable-samplerate.ogg^headers^
   variable-samplerate.opus
+  variable-samplerate.opus^headers^
   vbr-head.mp3
+  vbr-head.mp3^headers^
   vbr.mp3
-  VID_0001.ogg
+  vbr.mp3^headers^
   video-overhang.ogg
+  video-overhang.ogg^headers^
+  vp9.webm
+  vp9.webm^headers^
+  vp9cake.webm
+  vp9cake.webm^headers^
   wave_metadata.wav
+  wave_metadata.wav^headers^
   wave_metadata_bad_len.wav
+  wave_metadata_bad_len.wav^headers^
   wave_metadata_bad_no_null.wav
+  wave_metadata_bad_no_null.wav^headers^
   wave_metadata_bad_utf8.wav
+  wave_metadata_bad_utf8.wav^headers^
   wave_metadata_unknown_tag.wav
+  wave_metadata_unknown_tag.wav^headers^
   wave_metadata_utf8.wav
+  wave_metadata_utf8.wav^headers^
   wavedata_s16.wav
+  wavedata_s16.wav^headers^
   wavedata_u8.wav
+  wavedata_u8.wav^headers^
 
 [test_a4_tone.html]
 [test_access_control.html]
 [test_audio1.html]
 [test_audio2.html]
 [test_audio_event_adopt.html]
 [test_autoplay.html]
 [test_bug448534.html]
new file mode 100644
--- /dev/null
+++ b/content/media/test/multiple-bos.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/no-cues.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/notags.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/owl-funnier-id3.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/owl-funny-id3.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/owl.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/r11025_msadpcm_c1.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/r11025_s16_c1.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/r11025_s16_c1_trailing.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/r11025_u8_c1.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/r11025_u8_c1_trunc.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/r16000_u8_c1_list.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/seek.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/seek.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/seek_with_sound.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/short-video.ogv^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/small-shot.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/small-shot.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/sound.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/spacestorm-1000Hz-100ms.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/split.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/street.mp4^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-1-mono.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-2-stereo.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-3-LCR.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-4-quad.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-5-5.0.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-6-5.1.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-7-6.1.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/test-8-7.1.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/variable-channel.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/variable-channel.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/variable-preskip.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/variable-samplerate.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/variable-samplerate.opus^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/vbr-head.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/vbr.mp3^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/video-overhang.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/vp9.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/vp9cake.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wave_metadata.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wave_metadata_bad_len.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wave_metadata_bad_no_null.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wave_metadata_bad_utf8.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wave_metadata_unknown_tag.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wave_metadata_utf8.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wavedata_s16.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
new file mode 100644
--- /dev/null
+++ b/content/media/test/wavedata_u8.wav^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -51,21 +51,22 @@ NS_IMPL_RELEASE_INHERITED(AudioBufferSou
  * AudioNodeStream::SetInt32Parameter).
  */
 class AudioBufferSourceNodeEngine : public AudioNodeEngine
 {
 public:
   explicit AudioBufferSourceNodeEngine(AudioNode* aNode,
                                        AudioDestinationNode* aDestination) :
     AudioNodeEngine(aNode),
-    mStart(0), mStop(TRACK_TICKS_MAX),
+    mStart(0.0), mBeginProcessing(0),
+    mStop(TRACK_TICKS_MAX),
     mResampler(nullptr), mRemainingResamplerTail(0),
     mBufferEnd(0),
     mLoopStart(0), mLoopEnd(0),
-    mBufferSampleRate(0), mBufferPosition(0), mChannels(0), mPlaybackRate(1.0f),
+    mBufferSampleRate(0), mBufferPosition(0), mChannels(0),
     mDopplerShift(1.0f),
     mDestination(static_cast<AudioNodeStream*>(aDestination->Stream())),
     mPlaybackRateTimeline(1.0f), mLoop(false)
   {}
 
   ~AudioBufferSourceNodeEngine()
   {
     if (mResampler) {
@@ -89,30 +90,36 @@ public:
       break;
     default:
       NS_ERROR("Bad AudioBufferSourceNodeEngine TimelineParameter");
     }
   }
   virtual void SetStreamTimeParameter(uint32_t aIndex, TrackTicks aParam)
   {
     switch (aIndex) {
-    case AudioBufferSourceNode::START: mStart = aParam; break;
     case AudioBufferSourceNode::STOP: mStop = aParam; break;
     default:
       NS_ERROR("Bad AudioBufferSourceNodeEngine StreamTimeParameter");
     }
   }
   virtual void SetDoubleParameter(uint32_t aIndex, double aParam)
   {
     switch (aIndex) {
-      case AudioBufferSourceNode::DOPPLERSHIFT:
-        mDopplerShift = aParam;
-        break;
-      default:
-        NS_ERROR("Bad AudioBufferSourceNodeEngine double parameter.");
+    case AudioBufferSourceNode::START:
+      MOZ_ASSERT(!mStart, "Another START?");
+      mStart = mSource->TimeFromDestinationTime(mDestination, aParam) *
+        mSource->SampleRate();
+      // Round to nearest
+      mBeginProcessing = mStart + 0.5;
+      break;
+    case AudioBufferSourceNode::DOPPLERSHIFT:
+      mDopplerShift = aParam > 0 && aParam == aParam ? aParam : 1.0;
+      break;
+    default:
+      NS_ERROR("Bad AudioBufferSourceNodeEngine double parameter.");
     };
   }
   virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam)
   {
     switch (aIndex) {
     case AudioBufferSourceNode::SAMPLE_RATE: mBufferSampleRate = aParam; break;
     case AudioBufferSourceNode::BUFFERSTART:
       if (mBufferPosition == 0) {
@@ -127,32 +134,70 @@ public:
       NS_ERROR("Bad AudioBufferSourceNodeEngine Int32Parameter");
     }
   }
   virtual void SetBuffer(already_AddRefed<ThreadSharedFloatArrayBufferList> aBuffer)
   {
     mBuffer = aBuffer;
   }
 
-  SpeexResamplerState* Resampler(AudioNodeStream* aStream, uint32_t aChannels)
+  bool BegunResampling()
+  {
+    return mBeginProcessing == -TRACK_TICKS_MAX;
+  }
+
+  void UpdateResampler(int32_t aOutRate, uint32_t aChannels)
   {
-    if (aChannels != mChannels && mResampler) {
+    if (mResampler &&
+        (aChannels != mChannels ||
+         // If the resampler has begun, then it will have moved
+         // mBufferPosition to after the samples it has read, but it hasn't
+         // output its buffered samples.  Keep using the resampler, even if
+         // the rates now match, so that this latent segment is output.
+         (aOutRate == mBufferSampleRate && !BegunResampling()))) {
       speex_resampler_destroy(mResampler);
       mResampler = nullptr;
+      mBeginProcessing = mStart + 0.5;
+    }
+
+    if (aOutRate == mBufferSampleRate && !mResampler) {
+      return;
     }
 
     if (!mResampler) {
       mChannels = aChannels;
-      mResampler = speex_resampler_init(mChannels, mBufferSampleRate,
-                                        ComputeFinalOutSampleRate(aStream->SampleRate()),
+      mResampler = speex_resampler_init(mChannels, mBufferSampleRate, aOutRate,
                                         SPEEX_RESAMPLER_QUALITY_DEFAULT,
                                         nullptr);
-      speex_resampler_skip_zeros(mResampler);
+    } else {
+      uint32_t currentOutSampleRate, currentInSampleRate;
+      speex_resampler_get_rate(mResampler, &currentInSampleRate,
+                               &currentOutSampleRate);
+      if (currentOutSampleRate == static_cast<uint32_t>(aOutRate)) {
+        return;
+      }
+      speex_resampler_set_rate(mResampler, currentInSampleRate, aOutRate);
     }
-    return mResampler;
+
+    if (!BegunResampling()) {
+      // Low pass filter effects from the resampler mean that samples before
+      // the start time are influenced by resampling the buffer.  The input
+      // latency indicates half the filter width.
+      int64_t inputLatency = speex_resampler_get_input_latency(mResampler);
+      uint32_t ratioNum, ratioDen;
+      speex_resampler_get_ratio(mResampler, &ratioNum, &ratioDen);
+      // The output subsample resolution supported in aligning the resampler
+      // is ratioNum.  First round the start time to the nearest subsample.
+      int64_t subsample = mStart * ratioNum + 0.5;
+      // Now include the leading effects of the filter, and round *up* to the
+      // next whole tick, because there is no effect on samples outside the
+      // filter width.
+      mBeginProcessing =
+        (subsample - inputLatency * ratioDen + ratioNum - 1) / ratioNum;
+    }
   }
 
   // Borrow a full buffer of size WEBAUDIO_BLOCK_SIZE from the source buffer
   // at offset aSourceOffset.  This avoids copying memory.
   void BorrowFromInputBuffer(AudioChunk* aOutput,
                              uint32_t aChannels)
   {
     aOutput->mDuration = WEBAUDIO_BLOCK_SIZE;
@@ -182,84 +227,101 @@ public:
   // Resamples input data to an output buffer, according to |mBufferSampleRate| and
   // the playbackRate.
   // The number of frames consumed/produced depends on the amount of space
   // remaining in both the input and output buffer, and the playback rate (that
   // is, the ratio between the output samplerate and the input samplerate).
   void CopyFromInputBufferWithResampling(AudioNodeStream* aStream,
                                          AudioChunk* aOutput,
                                          uint32_t aChannels,
-                                         uint32_t aOffsetWithinBlock,
-                                         uint32_t& aFramesWritten,
+                                         uint32_t* aOffsetWithinBlock,
+                                         TrackTicks* aCurrentPosition,
                                          int32_t aBufferMax) {
     // TODO: adjust for mStop (see bug 913854 comment 9).
-    uint32_t availableInOutputBuffer = WEBAUDIO_BLOCK_SIZE - aOffsetWithinBlock;
-    SpeexResamplerState* resampler = Resampler(aStream, aChannels);
+    uint32_t availableInOutputBuffer =
+      WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock;
+    SpeexResamplerState* resampler = mResampler;
     MOZ_ASSERT(aChannels > 0);
 
     if (mBufferPosition < aBufferMax) {
       uint32_t availableInInputBuffer = aBufferMax - mBufferPosition;
+      uint32_t ratioNum, ratioDen;
+      speex_resampler_get_ratio(resampler, &ratioNum, &ratioDen);
       // Limit the number of input samples copied and possibly
       // format-converted for resampling by estimating how many will be used.
-      // This may be a little small when filling the resampler with initial
-      // data, but we'll get called again and it will work out.
-      uint32_t num, den;
-      speex_resampler_get_ratio(resampler, &num, &den);
-      uint32_t inputLimit = std::min(availableInInputBuffer,
-                                     availableInOutputBuffer * num / den + 10);
+      // This may be a little small if still filling the resampler with
+      // initial data, but we'll get called again and it will work out.
+      uint32_t inputLimit = availableInOutputBuffer * ratioNum / ratioDen + 10;
+      if (!BegunResampling()) {
+        // First time the resampler is used.
+        uint32_t inputLatency = speex_resampler_get_input_latency(resampler);
+        inputLimit += inputLatency;
+        // If starting after mStart, then play from the beginning of the
+        // buffer, but correct for input latency.  If starting before mStart,
+        // then align the resampler so that the time corresponding to the
+        // first input sample is mStart.
+        uint32_t skipFracNum = inputLatency * ratioDen;
+        double leadTicks = mStart - *aCurrentPosition;
+        if (leadTicks > 0.0) {
+          // Round to nearest output subsample supported by the resampler at
+          // these rates.
+          skipFracNum -= leadTicks * ratioNum + 0.5;
+          MOZ_ASSERT(skipFracNum < INT32_MAX, "mBeginProcessing is wrong?");
+        }
+        speex_resampler_set_skip_frac_num(resampler, skipFracNum);
+
+        mBeginProcessing = -TRACK_TICKS_MAX;
+      }
+      inputLimit = std::min(inputLimit, availableInInputBuffer);
+
       for (uint32_t i = 0; true; ) {
         uint32_t inSamples = inputLimit;
         const float* inputData = mBuffer->GetData(i) + mBufferPosition;
 
         uint32_t outSamples = availableInOutputBuffer;
         float* outputData =
           static_cast<float*>(const_cast<void*>(aOutput->mChannelData[i])) +
-          aOffsetWithinBlock;
+          *aOffsetWithinBlock;
 
         WebAudioUtils::SpeexResamplerProcess(resampler, i,
                                              inputData, &inSamples,
                                              outputData, &outSamples);
         if (++i == aChannels) {
           mBufferPosition += inSamples;
           MOZ_ASSERT(mBufferPosition <= mBufferEnd || mLoop);
-          aFramesWritten = outSamples;
+          *aOffsetWithinBlock += outSamples;
+          *aCurrentPosition += outSamples;
           if (inSamples == availableInInputBuffer && !mLoop) {
-            // If the available output space were unbounded then the input
-            // latency would always be the correct amount of extra input to
-            // provide in order to advance the output position to align with
-            // the final point in the buffer.  However, when the output space
-            // becomes full, the resampler may read all available input
-            // without writing out the corresponding output.  Add one more
-            // input sample, so that we know that enough output has been
-            // written when the last input sample has been read.  This may
-            // often write more than necessary but the extra samples will be
-            // based on (mostly) zero input.
+            // We'll feed in enough zeros to empty out the resampler's memory.
+            // This handles the output latency as well as capturing the low
+            // pass effects of the resample filter.
             mRemainingResamplerTail =
-              speex_resampler_get_input_latency(resampler) + 1;
+              2 * speex_resampler_get_input_latency(resampler) - 1;
           }
           return;
         }
       }
     } else {
       for (uint32_t i = 0; true; ) {
         uint32_t inSamples = mRemainingResamplerTail;
         uint32_t outSamples = availableInOutputBuffer;
         float* outputData =
           static_cast<float*>(const_cast<void*>(aOutput->mChannelData[i])) +
-          aOffsetWithinBlock;
+          *aOffsetWithinBlock;
 
         // AudioDataValue* for aIn selects the function that does not try to
         // copy and format-convert input data.
         WebAudioUtils::SpeexResamplerProcess(resampler, i,
                          static_cast<AudioDataValue*>(nullptr), &inSamples,
                          outputData, &outSamples);
         if (++i == aChannels) {
           mRemainingResamplerTail -= inSamples;
           MOZ_ASSERT(mRemainingResamplerTail >= 0);
-          aFramesWritten = outSamples;
+          *aOffsetWithinBlock += outSamples;
+          *aCurrentPosition += outSamples;
           break;
         }
       }
     }
   }
 
   /**
    * Fill aOutput with as many zero frames as we can, and advance
@@ -307,88 +369,63 @@ public:
                       TrackTicks* aCurrentPosition,
                       int32_t aBufferMax)
   {
     MOZ_ASSERT(*aCurrentPosition < mStop);
     uint32_t numFrames =
       std::min(std::min<TrackTicks>(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
                                     aBufferMax - mBufferPosition),
                mStop - *aCurrentPosition);
-    if (numFrames == WEBAUDIO_BLOCK_SIZE && !ShouldResample(aStream->SampleRate())) {
+    if (numFrames == WEBAUDIO_BLOCK_SIZE && !mResampler) {
       MOZ_ASSERT(mBufferPosition < aBufferMax);
       BorrowFromInputBuffer(aOutput, aChannels);
       *aOffsetWithinBlock += numFrames;
       *aCurrentPosition += numFrames;
       mBufferPosition += numFrames;
     } else {
       if (*aOffsetWithinBlock == 0) {
         AllocateAudioBlock(aChannels, aOutput);
       }
-      if (!ShouldResample(aStream->SampleRate())) {
+      if (!mResampler) {
         MOZ_ASSERT(mBufferPosition < aBufferMax);
         CopyFromInputBuffer(aOutput, aChannels, *aOffsetWithinBlock, numFrames);
         *aOffsetWithinBlock += numFrames;
         *aCurrentPosition += numFrames;
         mBufferPosition += numFrames;
       } else {
-        uint32_t framesWritten;
-        CopyFromInputBufferWithResampling(aStream, aOutput, aChannels, *aOffsetWithinBlock, framesWritten, aBufferMax);
-        *aOffsetWithinBlock += framesWritten;
-        *aCurrentPosition += framesWritten;
+        CopyFromInputBufferWithResampling(aStream, aOutput, aChannels, aOffsetWithinBlock, aCurrentPosition, aBufferMax);
       }
     }
   }
 
-  uint32_t ComputeFinalOutSampleRate(TrackRate aStreamSampleRate)
+  int32_t ComputeFinalOutSampleRate(float aPlaybackRate)
   {
-    if (mPlaybackRate <= 0 || mPlaybackRate != mPlaybackRate) {
-      mPlaybackRate = 1.0f;
-    }
-    if (mDopplerShift <= 0 || mDopplerShift != mDopplerShift) {
-      mDopplerShift = 1.0f;
-    }
-    return WebAudioUtils::TruncateFloatToInt<uint32_t>(aStreamSampleRate /
-                                                       (mPlaybackRate * mDopplerShift));
-  }
-
-  bool ShouldResample(TrackRate aStreamSampleRate) const
-  {
-    // There is latency in the resampler.  If there is already a resampler,
-    // then it will have moved mBufferPosition to after the samples it has
-    // read, but it hasn't output its buffered samples.  Keep using the
-    // resampler, even if the rates now match, so that this latent segment is
-    // output.
-    return mResampler ||
-      (mPlaybackRate * mDopplerShift * mBufferSampleRate != aStreamSampleRate);
+    // Make sure the playback rate and the doppler shift are something
+    // our resampler can work with.
+    int32_t rate = WebAudioUtils::
+      TruncateFloatToInt<int32_t>(mSource->SampleRate() /
+                                  (aPlaybackRate * mDopplerShift));
+    return rate ? rate : mBufferSampleRate;
   }
 
-  void UpdateSampleRateIfNeeded(AudioNodeStream* aStream, uint32_t aChannels)
+  void UpdateSampleRateIfNeeded(uint32_t aChannels)
   {
+    float playbackRate;
+
     if (mPlaybackRateTimeline.HasSimpleValue()) {
-      mPlaybackRate = mPlaybackRateTimeline.GetValue();
+      playbackRate = mPlaybackRateTimeline.GetValue();
     } else {
-      mPlaybackRate = mPlaybackRateTimeline.GetValueAtTime(aStream->GetCurrentPosition());
+      playbackRate = mPlaybackRateTimeline.GetValueAtTime(mSource->GetCurrentPosition());
+    }
+    if (playbackRate <= 0 || playbackRate != playbackRate) {
+      playbackRate = 1.0f;
     }
 
-    // Make sure the playback rate and the doppler shift are something
-    // our resampler can work with.
-    if (ComputeFinalOutSampleRate(aStream->SampleRate()) == 0) {
-      mPlaybackRate = 1.0;
-      mDopplerShift = 1.0;
-    }
-
-    if (mResampler) {
-      SpeexResamplerState* resampler = Resampler(aStream, aChannels);
-      uint32_t currentOutSampleRate, currentInSampleRate;
-      speex_resampler_get_rate(resampler, &currentInSampleRate, &currentOutSampleRate);
-      uint32_t finalSampleRate = ComputeFinalOutSampleRate(aStream->SampleRate());
-      if (currentOutSampleRate != finalSampleRate) {
-        speex_resampler_set_rate(resampler, currentInSampleRate, finalSampleRate);
-      }
-    }
+    int32_t outRate = ComputeFinalOutSampleRate(playbackRate);
+    UpdateResampler(outRate, aChannels);
   }
 
   virtual void ProduceAudioBlock(AudioNodeStream* aStream,
                                  const AudioChunk& aInput,
                                  AudioChunk* aOutput,
                                  bool* aFinished)
   {
     if (!mBuffer || !mBufferEnd) {
@@ -400,28 +437,29 @@ public:
     if (!channels) {
       aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
       return;
     }
 
     // WebKit treats the playbackRate as a k-rate parameter in their code,
     // despite the spec saying that it should be an a-rate parameter. We treat
     // it as k-rate. Spec bug: https://www.w3.org/Bugs/Public/show_bug.cgi?id=21592
-    UpdateSampleRateIfNeeded(aStream, channels);
+    UpdateSampleRateIfNeeded(channels);
 
     uint32_t written = 0;
     TrackTicks streamPosition = aStream->GetCurrentPosition();
     while (written < WEBAUDIO_BLOCK_SIZE) {
       if (mStop != TRACK_TICKS_MAX &&
           streamPosition >= mStop) {
         FillWithZeroes(aOutput, channels, &written, &streamPosition, TRACK_TICKS_MAX);
         continue;
       }
-      if (streamPosition < mStart) {
-        FillWithZeroes(aOutput, channels, &written, &streamPosition, mStart);
+      if (streamPosition < mBeginProcessing) {
+        FillWithZeroes(aOutput, channels, &written, &streamPosition,
+                       mBeginProcessing);
         continue;
       }
       if (mLoop) {
         // mLoopEnd can become less than mBufferPosition when a LOOPEND engine
         // parameter is received after "loopend" is changed on the node or a
         // new buffer with lower samplerate is set.
         if (mBufferPosition >= mLoopEnd) {
           mBufferPosition = mLoopStart;
@@ -439,30 +477,34 @@ public:
     // We've finished if we've gone past mStop, or if we're past mDuration when
     // looping is disabled.
     if (streamPosition >= mStop ||
         (!mLoop && mBufferPosition >= mBufferEnd && !mRemainingResamplerTail)) {
       *aFinished = true;
     }
   }
 
-  TrackTicks mStart;
+  double mStart; // including the fractional position between ticks
+  // Low pass filter effects from the resampler mean that samples before the
+  // start time are influenced by resampling the buffer.  mBeginProcessing
+  // includes the extent of this filter.  The special value of -TRACK_TICKS_MAX
+  // indicates that the resampler has begun processing.
+  TrackTicks mBeginProcessing;
   TrackTicks mStop;
   nsRefPtr<ThreadSharedFloatArrayBufferList> mBuffer;
   SpeexResamplerState* mResampler;
   // mRemainingResamplerTail, like mBufferPosition, and
   // mBufferEnd, is measured in input buffer samples.
   int mRemainingResamplerTail;
   int32_t mBufferEnd;
   int32_t mLoopStart;
   int32_t mLoopEnd;
   int32_t mBufferSampleRate;
   int32_t mBufferPosition;
   uint32_t mChannels;
-  float mPlaybackRate;
   float mDopplerShift;
   AudioNodeStream* mDestination;
   AudioNodeStream* mSource;
   AudioParamTimeline mPlaybackRateTimeline;
   bool mLoop;
 };
 
 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
@@ -527,17 +569,17 @@ AudioBufferSourceNode::Start(double aWhe
   // We can't send these parameters without a buffer because we don't know the
   // buffer's sample rate or length.
   if (mBuffer) {
     SendOffsetAndDurationParametersToStream(ns);
   }
 
   // Don't set parameter unnecessarily
   if (aWhen > 0.0) {
-    ns->SetStreamTimeParameter(START, Context(), aWhen);
+    ns->SetDoubleParameter(START, mContext->DOMTimeToStreamTime(aWhen));
   }
 }
 
 void
 AudioBufferSourceNode::SendBufferParameterToStream(JSContext* aCx)
 {
   AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
   MOZ_ASSERT(ns, "Why don't we have a stream here?");
--- a/content/media/webaudio/test/mochitest.ini
+++ b/content/media/webaudio/test/mochitest.ini
@@ -58,18 +58,20 @@ support-files =
 [test_bug866737.html]
 [test_bug867089.html]
 [test_bug867104.html]
 [test_bug867174.html]
 [test_bug867203.html]
 [test_bug875221.html]
 [test_bug875402.html]
 [test_bug894150.html]
+[test_bug938022.html]
 [test_bug956489.html]
 [test_bug964376.html]
+[test_bug972678.html]
 [test_channelMergerNode.html]
 [test_channelMergerNodeWithVolume.html]
 [test_channelSplitterNode.html]
 [test_channelSplitterNodeWithVolume.html]
 [test_convolverNode.html]
 [test_convolverNodeChannelCount.html]
 [test_convolverNodeWithGain.html]
 [test_convolverNode_mono_mono.html]
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_bug938022.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test audio element currentTime is correct when used as media source</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  var context = new AudioContext();
+  var audio = new Audio("small-shot.ogg");
+  audio.load();
+  audio.addEventListener("loadeddata", function (e) {
+    is(this.currentTime, 0, "currentTime must be 0");
+    SimpleTest.finish();
+  });
+  audio.play();
+
+  var source = context.createMediaElementSource(audio);
+  source.connect(context.destination);
+});
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_bug972678.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test buffers do not interfere when scheduled in sequence</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="webaudio.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var OFFSETS = [0.005, 0.01, 0.02, 0.03];
+var LENGTH = 128;
+
+var gTest = {
+  length: 128 * OFFSETS.length,
+  numberOfChannels: 1,
+
+  createGraph: function(context) {
+    var gain = context.createGain();
+
+    // create a repeating sample
+    var repeatingSample = context.createBuffer(1, 2, context.sampleRate);
+    var c = repeatingSample.getChannelData(0);
+    for (var i = 0; i < repeatingSample.length; ++i) {
+      c[i] = i % 2 == 0 ? 1 : -1;
+    }
+
+    OFFSETS.forEach(function (offset, offsetIdx) {
+      // Schedule a set of nodes to repeat the sample.
+      for (var i = 0; i < LENGTH; i += repeatingSample.length) {
+        var source = context.createBufferSource();
+        source.buffer = repeatingSample;
+        source.connect(gain);
+        source.start((offsetIdx * LENGTH + i + offset) / context.sampleRate);
+      }
+
+      buffer = context.createBuffer(1, LENGTH, context.sampleRate);
+      c = buffer.getChannelData(0);
+      for (var i = 0; i < buffer.length; ++i) {
+        c[i] = i % 2 == 0 ? -1 : 1;
+      }
+
+      var source = context.createBufferSource();
+      source.buffer = buffer;
+      source.connect(gain);
+      source.start((offsetIdx * LENGTH + offset) / context.sampleRate);
+    });
+
+    return gain;
+  },
+
+  createExpectedBuffers: function(context) {
+    return context.createBuffer(1, gTest.length, context.sampleRate);
+  },
+};
+
+runTest();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/media/webspeech/recognition/test/hello.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/media/webspeech/recognition/test/mochitest.ini
+++ b/content/media/webspeech/recognition/test/mochitest.ini
@@ -1,13 +1,15 @@
 [DEFAULT]
 support-files =
   head.js
   hello.ogg
+  hello.ogg^headers^
   silence.ogg
+  silence.ogg^headers^
 
 [test_abort.html]
 [test_audio_capture_error.html]
 [test_call_start_from_end_handler.html]
 [test_nested_eventloop.html]
 skip-if = toolkit == 'android'
 [test_preference_enable.html]
 [test_recognition_service_error.html]
new file mode 100644
--- /dev/null
+++ b/content/media/webspeech/recognition/test/silence.ogg^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/svg/content/test/mochitest.ini
+++ b/content/svg/content/test/mochitest.ini
@@ -52,16 +52,17 @@ skip-if = true
 [test_pathAnimInterpolation.xhtml]
 [test_pathSeg.xhtml]
 [test_pointAtLength.xhtml]
 [test_pointer-events-1a.xhtml]
 [test_pointer-events-1b.xhtml]
 [test_pointer-events-2.xhtml]
 [test_pointer-events-3.xhtml]
 [test_pointer-events-4.xhtml]
+[test_pointer-events-5.xhtml]
 [test_scientific.html]
 [test_selectSubString.xhtml]
 [test_stroke-linecap-hit-testing.xhtml]
 [test_SVGLengthList-2.xhtml]
 [test_SVGLengthList.xhtml]
 [test_SVGMatrix.xhtml]
 [test_SVG_namespace_ids.html]
 [test_SVGNumberList.xhtml]
copy from content/svg/content/test/test_pointer-events-2.xhtml
copy to content/svg/content/test/test_pointer-events-5.xhtml
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7974,18 +7974,26 @@ nsDocShell::RestoreFromHistory()
     nsCOMPtr<nsIDocument> document = do_QueryInterface(domDoc);
     uint32_t parentSuspendCount = 0;
     if (document) {
         nsCOMPtr<nsIDocShellTreeItem> parent;
         GetParent(getter_AddRefs(parent));
         nsCOMPtr<nsIDocument> d = do_GetInterface(parent);
         if (d) {
             if (d->EventHandlingSuppressed()) {
-                document->SuppressEventHandling(d->EventHandlingSuppressed());
-            }
+                document->SuppressEventHandling(nsIDocument::eEvents,
+                                                d->EventHandlingSuppressed());
+            }
+
+            // Ick, it'd be nicer to not rewalk all of the subdocs here.
+            if (d->AnimationsPaused()) {
+                document->SuppressEventHandling(nsIDocument::eAnimationsOnly,
+                                                d->AnimationsPaused());
+            }
+
             nsCOMPtr<nsPIDOMWindow> parentWindow = d->GetWindow();
             if (parentWindow) {
                 parentSuspendCount = parentWindow->TimeoutSuspendCount();
             }
         }
 
         // Use the uri from the mLSHE we had when we entered this function
         // (which need not match the document's URI if anchors are involved),
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -126,18 +126,16 @@
 #include "nsIDOMSVGLength.h"
 #include "nsIDOMSVGNumber.h"
 
 // Storage includes
 #include "nsIDOMStorage.h"
 #include "nsPIDOMStorage.h"
 
 // Drag and drop
-#include "nsIDOMDataTransfer.h"
-
 #include "nsIDOMFile.h"
 #include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
 
 #include "nsIEventListenerService.h"
 #include "nsIMessageManager.h"
 
 #include "nsDOMTouchEvent.h"
 
@@ -436,20 +434,16 @@ static nsDOMClassInfoData sClassInfoData
 #ifdef MOZ_B2G_RIL
   NS_DEFINE_CLASSINFO_DATA(MozMobileConnection, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
   NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  // data transfer for drag and drop
-  NS_DEFINE_CLASSINFO_DATA(DataTransfer, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(EventListenerInfo, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS |
                                        nsIXPCScriptable::IS_GLOBAL_OBJECT)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
@@ -1118,20 +1112,16 @@ nsDOMClassInfo::Init()
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 #endif // MOZ_B2G_RIL
 
   DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(DataTransfer, nsIDOMDataTransfer)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataTransfer)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(EventListenerInfo, nsIEventListenerInfo)
     DOM_CLASSINFO_MAP_ENTRY(nsIEventListenerInfo)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -81,18 +81,16 @@ DOMCI_CLASS(MozMobileMessageThread)
 
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(MozMobileConnection)
 #endif
 
 // @font-face in CSS
 DOMCI_CLASS(CSSFontFaceRule)
 
-DOMCI_CLASS(DataTransfer)
-
 DOMCI_CLASS(EventListenerInfo)
 
 DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1678,19 +1678,19 @@ nsDOMWindowUtils::SuppressEventHandling(
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   if (aSuppress) {
-    doc->SuppressEventHandling();
+    doc->SuppressEventHandling(nsIDocument::eEvents);
   } else {
-    doc->UnsuppressEventHandlingAndFireEvents(true);
+    doc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, true);
   }
 
   return NS_OK;
 }
 
 static nsresult
 getScrollXYAppUnits(nsWeakPtr mWindow, bool aFlushLayout, nsPoint& aScrollPos) {
   if (!nsContentUtils::IsCallerChrome()) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1563,18 +1563,21 @@ nsGlobalWindow::FreeInnerObjects()
 
   if (mDoc) {
     // Remember the document's principal and URI.
     mDocumentPrincipal = mDoc->NodePrincipal();
     mDocumentURI = mDoc->GetDocumentURI();
     mDocBaseURI = mDoc->GetDocBaseURI();
 
     while (mDoc->EventHandlingSuppressed()) {
-      mDoc->UnsuppressEventHandlingAndFireEvents(false);
-    }
+      mDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, false);
+    }
+
+    // Note: we don't have to worry about eAnimationsOnly suppressions because
+    // they won't leak.
   }
 
   // Remove our reference to the document and the document principal.
   mFocusedNode = nullptr;
 
   if (mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
     mApplicationCache = nullptr;
@@ -8277,17 +8280,17 @@ nsGlobalWindow::EnterModalState()
     nsIPresShell::SetCapturingContent(nullptr, 0);
   }
 
   if (topWin->mModalStateDepth == 0) {
     NS_ASSERTION(!mSuspendedDoc, "Shouldn't have mSuspendedDoc here!");
 
     mSuspendedDoc = topDoc;
     if (mSuspendedDoc) {
-      mSuspendedDoc->SuppressEventHandling();
+      mSuspendedDoc->SuppressEventHandling(nsIDocument::eAnimationsOnly);
     }
   }
   topWin->mModalStateDepth++;
 }
 
 // static
 void
 nsGlobalWindow::RunPendingTimeoutsRecursive(nsGlobalWindow *aTopWindow,
@@ -8374,17 +8377,18 @@ nsGlobalWindow::LeaveModalState()
 
   if (topWin->mModalStateDepth == 0) {
     nsCOMPtr<nsIRunnable> runner = new nsPendingTimeoutRunner(topWin);
     if (NS_FAILED(NS_DispatchToCurrentThread(runner)))
       NS_WARNING("failed to dispatch pending timeout runnable");
 
     if (mSuspendedDoc) {
       nsCOMPtr<nsIDocument> currentDoc = topWin->GetExtantDoc();
-      mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(currentDoc == mSuspendedDoc);
+      mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eAnimationsOnly,
+                                                          currentDoc == mSuspendedDoc);
       mSuspendedDoc = nullptr;
     }
   }
 
   // Remember the time of the last dialog quit.
   nsGlobalWindow *inner = topWin->GetCurrentInnerWindowInternal();
   if (inner)
     inner->mLastDialogQuitTime = TimeStamp::Now();
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -22,17 +22,17 @@
 #include "mozilla/dom/RootedDictionary.h"
 #include "mozilla/dom/workers/Workers.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsCycleCollector.h"
 #include "nsIXPConnect.h"
 #include "MainThreadUtils.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "qsObjectHelper.h"
 #include "xpcpublic.h"
 #include "nsIVariant.h"
 
 #include "nsWrapperCacheInlines.h"
 
 class nsPIDOMWindow;
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1964,9 +1964,8 @@ addExternalIface('SVGLength')
 addExternalIface('SVGNumber')
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
 addExternalIface('UserDataHandler')
 addExternalIface('XPathResult', nativeType='nsISupports')
 addExternalIface('XPathExpression')
 addExternalIface('XPathNSResolver')
 addExternalIface('XULCommandDispatcher')
-addExternalIface('DataTransfer', notflattened=True)
--- a/dom/bindings/NonRefcountedDOMObject.h
+++ b/dom/bindings/NonRefcountedDOMObject.h
@@ -2,17 +2,17 @@
 /* vim: set ts=2 sw=2 et tw=79: */
 /* 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_NonRefcountedDOMObject_h__
 #define mozilla_dom_NonRefcountedDOMObject_h__
 
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 // Natives for DOM classes with 'owned' as the value for nativeOwnership in
 // Bindings.conf need to inherit from this class.
 // If you're seeing objects of this class leak then natives for one of the DOM
 // classes with 'owned' as the value for nativeOwnership in Bindings.conf is
--- a/dom/bluetooth/ipc/BluetoothChild.cpp
+++ b/dom/bluetooth/ipc/BluetoothChild.cpp
@@ -5,18 +5,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "BluetoothChild.h"
 
 #include "mozilla/Assertions.h"
 #include "nsDebug.h"
+#include "nsISupportsImpl.h"
 #include "nsThreadUtils.h"
-#include "nsTraceRefcnt.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothServiceChildProcess.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 namespace {
--- a/dom/bluetooth/ipc/BluetoothParent.cpp
+++ b/dom/bluetooth/ipc/BluetoothParent.cpp
@@ -6,18 +6,18 @@
 
 #include "base/basictypes.h"
 
 #include "BluetoothParent.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/unused.h"
 #include "nsDebug.h"
+#include "nsISupportsImpl.h"
 #include "nsThreadUtils.h"
-#include "nsTraceRefcnt.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 
 using mozilla::unused;
 USING_BLUETOOTH_NAMESPACE
 
 /*******************************************************************************
--- a/dom/events/ClipboardEvent.cpp
+++ b/dom/events/ClipboardEvent.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ClipboardEvent.h"
 #include "mozilla/ContentEvents.h"
-#include "nsDOMDataTransfer.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "nsIClipboard.h"
 
 namespace mozilla {
 namespace dom {
 
 ClipboardEvent::ClipboardEvent(EventTarget* aOwner,
                                nsPresContext* aPresContext,
                                InternalClipboardEvent* aEvent)
@@ -33,70 +33,88 @@ NS_IMPL_ADDREF_INHERITED(ClipboardEvent,
 NS_IMPL_RELEASE_INHERITED(ClipboardEvent, nsDOMEvent)
 
 nsresult
 ClipboardEvent::InitClipboardEvent(const nsAString& aType,
                                    bool aCanBubble,
                                    bool aCancelable,
                                    nsIDOMDataTransfer* aClipboardData)
 {
-  nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<DataTransfer> clipboardData = do_QueryInterface(aClipboardData);
+  // Null clipboardData is OK
+
+  ErrorResult rv;
+  InitClipboardEvent(aType, aCanBubble, aCancelable, clipboardData, rv);
+
+  return rv.ErrorCode();
+}
+
+void
+ClipboardEvent::InitClipboardEvent(const nsAString& aType, bool aCanBubble,
+                                   bool aCancelable,
+                                   DataTransfer* aClipboardData,
+                                   ErrorResult& aError)
+{
+  aError = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
+  if (aError.Failed()) {
+    return;
+  }
 
   mEvent->AsClipboardEvent()->clipboardData = aClipboardData;
-
-  return NS_OK;
 }
 
 already_AddRefed<ClipboardEvent>
 ClipboardEvent::Constructor(const GlobalObject& aGlobal,
                             const nsAString& aType,
                             const ClipboardEventInit& aParam,
                             ErrorResult& aRv)
 {
   nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
   nsRefPtr<ClipboardEvent> e = new ClipboardEvent(t, nullptr, nullptr);
   bool trusted = e->Init(t);
 
-  nsRefPtr<nsDOMDataTransfer> clipboardData;
+  nsRefPtr<DataTransfer> clipboardData;
   if (e->mEventIsInternal) {
     InternalClipboardEvent* event = e->mEvent->AsClipboardEvent();
     if (event) {
       // Always create a clipboardData for the copy event. If this is changed to
       // support other types of events, make sure that read/write privileges are
-      // checked properly within nsDOMDataTransfer.
-      clipboardData = new nsDOMDataTransfer(NS_COPY, false, -1);
+      // checked properly within DataTransfer.
+      clipboardData = new DataTransfer(ToSupports(e), NS_COPY, false, -1);
       clipboardData->SetData(aParam.mDataType, aParam.mData);
     }
   }
 
-  aRv = e->InitClipboardEvent(aType, aParam.mBubbles, aParam.mCancelable,
-                              clipboardData);
+  e->InitClipboardEvent(aType, aParam.mBubbles, aParam.mCancelable,
+                        clipboardData, aRv);
   e->SetTrusted(trusted);
   return e.forget();
 }
 
 NS_IMETHODIMP
 ClipboardEvent::GetClipboardData(nsIDOMDataTransfer** aClipboardData)
 {
   NS_IF_ADDREF(*aClipboardData = GetClipboardData());
   return NS_OK;
 }
 
-nsIDOMDataTransfer*
+DataTransfer*
 ClipboardEvent::GetClipboardData()
 {
   InternalClipboardEvent* event = mEvent->AsClipboardEvent();
 
   if (!event->clipboardData) {
     if (mEventIsInternal) {
-      event->clipboardData = new nsDOMDataTransfer(NS_COPY, false, -1);
+      event->clipboardData =
+        new DataTransfer(ToSupports(this), NS_COPY, false, -1);
     } else {
       event->clipboardData =
-        new nsDOMDataTransfer(event->message, event->message == NS_PASTE, nsIClipboard::kGlobalClipboard);
+        new DataTransfer(ToSupports(this), event->message,
+                         event->message == NS_PASTE,
+                         nsIClipboard::kGlobalClipboard);
     }
   }
 
   return event->clipboardData;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/events/ClipboardEvent.h
+++ b/dom/events/ClipboardEvent.h
@@ -8,16 +8,17 @@
 
 #include "nsIDOMClipboardEvent.h"
 #include "nsDOMEvent.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/dom/ClipboardEventBinding.h"
 
 namespace mozilla {
 namespace dom {
+class DataTransfer;
 
 class ClipboardEvent : public nsDOMEvent,
                        public nsIDOMClipboardEvent
 {
 public:
   ClipboardEvent(EventTarget* aOwner,
                  nsPresContext* aPresContext,
                  InternalClipboardEvent* aEvent);
@@ -36,15 +37,20 @@ public:
   }
 
   static already_AddRefed<ClipboardEvent>
   Constructor(const GlobalObject& aGlobal,
               const nsAString& aType,
               const ClipboardEventInit& aParam,
               ErrorResult& aRv);
 
-  nsIDOMDataTransfer* GetClipboardData();
+  DataTransfer* GetClipboardData();
+
+  void InitClipboardEvent(const nsAString& aType, bool aCanBubble,
+                          bool aCancelable,
+                          DataTransfer* aClipboardData,
+                          ErrorResult& aError);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ClipboardEvent_h_
rename from dom/events/nsDOMDataTransfer.cpp
rename to dom/events/DataTransfer.cpp
--- a/dom/events/nsDOMDataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -2,171 +2,219 @@
 /* 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 "mozilla/ArrayUtils.h"
 #include "mozilla/BasicEvents.h"
 
-#include "nsDOMDataTransfer.h"
+#include "DataTransfer.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIVariant.h"
 #include "nsISupportsPrimitives.h"
-#include "nsDOMClassInfoID.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsDOMLists.h"
 #include "nsError.h"
 #include "nsIDragService.h"
 #include "nsIClipboard.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
 #include "nsCRT.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
+#include "mozilla/dom/DataTransferBinding.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/BindingUtils.h"
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataTransfer)
+namespace mozilla {
+namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DataTransfer)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DataTransfer)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
   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_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DataTransfer)
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMDataTransfer)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransfer)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransfer)
 
-DOMCI_DATA(DataTransfer, nsDOMDataTransfer)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataTransfer)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransfer)
+  NS_INTERFACE_MAP_ENTRY(mozilla::dom::DataTransfer)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDataTransfer)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DataTransfer)
 NS_INTERFACE_MAP_END
 
 // the size of the array
-const char nsDOMDataTransfer::sEffects[8][9] = {
+const char DataTransfer::sEffects[8][9] = {
   "none", "copy", "move", "copyMove", "link", "copyLink", "linkMove", "all"
 };
 
-nsDOMDataTransfer::nsDOMDataTransfer(uint32_t aEventType, bool aIsExternal, int32_t aClipboardType)
-  : mEventType(aEventType),
+DataTransfer::DataTransfer(nsISupports* aParent, uint32_t aEventType,
+                           bool aIsExternal, int32_t aClipboardType)
+  : mParent(aParent),
+    mEventType(aEventType),
     mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
     mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED),
     mCursorState(false),
     mReadOnly(true),
     mIsExternal(aIsExternal),
     mUserCancelled(false),
     mIsCrossDomainSubFrameDrop(false),
     mClipboardType(aClipboardType),
     mDragImageX(0),
     mDragImageY(0)
 {
+  MOZ_ASSERT(mParent);
+  SetIsDOMBinding();
   // For these events, we want to be able to add data to the data transfer, so
   // clear the readonly state. Otherwise, the data is already present. For
   // external usage, cache the data from the native clipboard or drag.
   if (aEventType == NS_CUT ||
       aEventType == NS_COPY ||
       aEventType == NS_DRAGDROP_START ||
       aEventType == NS_DRAGDROP_GESTURE) {
     mReadOnly = false;
-} else if (mIsExternal) {
+  } else if (mIsExternal) {
     if (aEventType == NS_PASTE) {
       CacheExternalClipboardFormats();
     } else if (aEventType >= NS_DRAGDROP_EVENT_START && aEventType <= NS_DRAGDROP_LEAVE_SYNTH) {
       CacheExternalDragFormats();
     }
   }
 }
 
-nsDOMDataTransfer::nsDOMDataTransfer(uint32_t aEventType,
-                                     const uint32_t aEffectAllowed,
-                                     bool aCursorState,
-                                     bool aIsExternal,
-                                     bool aUserCancelled,
-                                     bool aIsCrossDomainSubFrameDrop,
-                                     int32_t aClipboardType,
-                                     nsTArray<nsTArray<TransferItem> >& aItems,
-                                     nsIDOMElement* aDragImage,
-                                     uint32_t aDragImageX,
-                                     uint32_t aDragImageY)
-  : mEventType(aEventType),
+DataTransfer::DataTransfer(nsISupports* aParent,
+                           uint32_t aEventType,
+                           const uint32_t aEffectAllowed,
+                           bool aCursorState,
+                           bool aIsExternal,
+                           bool aUserCancelled,
+                           bool aIsCrossDomainSubFrameDrop,
+                           int32_t aClipboardType,
+                           nsTArray<nsTArray<TransferItem> >& aItems,
+                           Element* aDragImage,
+                           uint32_t aDragImageX,
+                           uint32_t aDragImageY)
+  : mParent(aParent),
+    mEventType(aEventType),
     mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
     mEffectAllowed(aEffectAllowed),
     mCursorState(aCursorState),
     mReadOnly(true),
     mIsExternal(aIsExternal),
     mUserCancelled(aUserCancelled),
     mIsCrossDomainSubFrameDrop(aIsCrossDomainSubFrameDrop),
     mClipboardType(aClipboardType),
     mItems(aItems),
     mDragImage(aDragImage),
     mDragImageX(aDragImageX),
     mDragImageY(aDragImageY)
 {
+  MOZ_ASSERT(mParent);
+  SetIsDOMBinding();
   // The items are copied from aItems into mItems. There is no need to copy
   // the actual data in the items as the data transfer will be read only. The
   // draggesture and dragstart events are the only times when items are
   // modifiable, but those events should have been using the first constructor
   // above.
   NS_ASSERTION(aEventType != NS_DRAGDROP_GESTURE &&
                aEventType != NS_DRAGDROP_START,
-               "invalid event type for nsDOMDataTransfer constructor");
+               "invalid event type for DataTransfer constructor");
+}
+
+DataTransfer::~DataTransfer()
+{
+  if (mFiles) {
+    mFiles->Disconnect();
+  }
+}
+
+// static
+already_AddRefed<DataTransfer>
+DataTransfer::Constructor(const GlobalObject& aGlobal,
+                          const nsAString& aEventType, bool aIsExternal,
+                          ErrorResult& aRv)
+{
+  nsAutoCString onEventType("on");
+  AppendUTF16toUTF8(aEventType, onEventType);
+  nsCOMPtr<nsIAtom> eventTypeAtom = do_GetAtom(onEventType);
+  if (!eventTypeAtom) {
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return nullptr;
+  }
+
+  uint32_t eventType = nsContentUtils::GetEventId(eventTypeAtom);
+  nsRefPtr<DataTransfer> transfer = new DataTransfer(aGlobal.GetAsSupports(),
+                                                     eventType, aIsExternal,
+                                                     -1);
+  return transfer.forget();
+}
+
+JSObject*
+DataTransfer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return DataTransferBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetDropEffect(nsAString& aDropEffect)
+DataTransfer::GetDropEffect(nsAString& aDropEffect)
 {
-  aDropEffect.AssignASCII(sEffects[mDropEffect]);
+  nsString dropEffect;
+  GetDropEffect(dropEffect);
+  aDropEffect = dropEffect;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::SetDropEffect(const nsAString& aDropEffect)
+DataTransfer::SetDropEffect(const nsAString& aDropEffect)
 {
   // the drop effect can only be 'none', 'copy', 'move' or 'link'.
   for (uint32_t e = 0; e <= nsIDragService::DRAGDROP_ACTION_LINK; e++) {
     if (aDropEffect.EqualsASCII(sEffects[e])) {
       // don't allow copyMove
       if (e != (nsIDragService::DRAGDROP_ACTION_COPY |
                 nsIDragService::DRAGDROP_ACTION_MOVE))
         mDropEffect = e;
       break;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetEffectAllowed(nsAString& aEffectAllowed)
+DataTransfer::GetEffectAllowed(nsAString& aEffectAllowed)
 {
-  if (mEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
-    aEffectAllowed.AssignLiteral("uninitialized");
-  else
-    aEffectAllowed.AssignASCII(sEffects[mEffectAllowed]);
+  nsString effectAllowed;
+  GetEffectAllowed(effectAllowed);
+  aEffectAllowed = effectAllowed;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::SetEffectAllowed(const nsAString& aEffectAllowed)
+DataTransfer::SetEffectAllowed(const nsAString& aEffectAllowed)
 {
   if (aEffectAllowed.EqualsLiteral("uninitialized")) {
     mEffectAllowed = nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
     return NS_OK;
   }
 
   static_assert(nsIDragService::DRAGDROP_ACTION_NONE == 0,
                 "DRAGDROP_ACTION_NONE constant is wrong");
@@ -183,145 +231,157 @@ nsDOMDataTransfer::SetEffectAllowed(cons
       break;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetDropEffectInt(uint32_t* aDropEffect)
+DataTransfer::GetDropEffectInt(uint32_t* aDropEffect)
 {
   *aDropEffect = mDropEffect;
   return  NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::SetDropEffectInt(uint32_t aDropEffect)
+DataTransfer::SetDropEffectInt(uint32_t aDropEffect)
 {
   mDropEffect = aDropEffect;
   return  NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetEffectAllowedInt(uint32_t* aEffectAllowed)
+DataTransfer::GetEffectAllowedInt(uint32_t* aEffectAllowed)
 {
   *aEffectAllowed = mEffectAllowed;
   return  NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::SetEffectAllowedInt(uint32_t aEffectAllowed)
+DataTransfer::SetEffectAllowedInt(uint32_t aEffectAllowed)
 {
   mEffectAllowed = aEffectAllowed;
   return  NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetMozUserCancelled(bool* aUserCancelled)
+DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
 {
-  *aUserCancelled = mUserCancelled;
+  *aUserCancelled = MozUserCancelled();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMDataTransfer::GetFiles(nsIDOMFileList** aFileList)
+nsDOMFileList*
+DataTransfer::GetFiles(ErrorResult& aRv)
 {
-  *aFileList = nullptr;
-
   if (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
       mEventType != NS_PASTE) {
-    return NS_OK;
+    return nullptr;
   }
 
   if (!mFiles) {
     mFiles = new nsDOMFileList(static_cast<nsIDOMDataTransfer*>(this));
 
     uint32_t count = mItems.Length();
 
     for (uint32_t i = 0; i < count; i++) {
       nsCOMPtr<nsIVariant> variant;
-      nsresult rv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
-      NS_ENSURE_SUCCESS(rv, rv);
+      aRv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
+      if (aRv.Failed()) {
+        return nullptr;
+      }
 
       if (!variant)
         continue;
 
       nsCOMPtr<nsISupports> supports;
-      rv = variant->GetAsISupports(getter_AddRefs(supports));
+      nsresult rv = variant->GetAsISupports(getter_AddRefs(supports));
 
       if (NS_FAILED(rv))
         continue;
 
       nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
 
       if (!file)
         continue;
 
       nsRefPtr<nsDOMFileFile> domFile = new nsDOMFileFile(file);
 
-      if (!mFiles->Append(domFile))
-        return NS_ERROR_FAILURE;
+      if (!mFiles->Append(domFile)) {
+        aRv.Throw(NS_ERROR_FAILURE);
+        return nullptr;
+      }
     }
   }
 
-  *aFileList = mFiles;
-  NS_ADDREF(*aFileList);
-  return NS_OK;
+  return mFiles;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetTypes(nsIDOMDOMStringList** aTypes)
+DataTransfer::GetFiles(nsIDOMFileList** aFileList)
 {
-  *aTypes = nullptr;
+  ErrorResult rv;
+  *aFileList = GetFiles(rv);
+  return rv.ErrorCode();
+}
 
+already_AddRefed<nsIDOMDOMStringList>
+DataTransfer::Types()
+{
   nsRefPtr<nsDOMStringList> types = new nsDOMStringList();
-
   if (mItems.Length()) {
     const nsTArray<TransferItem>& item = mItems[0];
     for (uint32_t i = 0; i < item.Length(); i++)
       types->Add(item[i].mFormat);
 
     bool filePresent, filePromisePresent;
     types->Contains(NS_LITERAL_STRING(kFileMime), &filePresent);
     types->Contains(NS_LITERAL_STRING("application/x-moz-file-promise"), &filePromisePresent);
     if (filePresent || filePromisePresent)
       types->Add(NS_LITERAL_STRING("Files"));
   }
 
-  *aTypes = types;
-  NS_ADDREF(*aTypes);
+  return types.forget();
+}
+
+NS_IMETHODIMP
+DataTransfer::GetTypes(nsIDOMDOMStringList** aTypes)
+{
+  *aTypes = Types().get();
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMDataTransfer::GetData(const nsAString& aFormat, nsAString& aData)
+void
+DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
+                      ErrorResult& aRv)
 {
   // return an empty string if data for the format was not found
   aData.Truncate();
 
   nsCOMPtr<nsIVariant> data;
   nsresult rv = MozGetDataAt(aFormat, 0, getter_AddRefs(data));
-  if (rv == NS_ERROR_DOM_INDEX_SIZE_ERR) {
-    return NS_OK;
+  if (NS_FAILED(rv)) {
+    if (rv != NS_ERROR_DOM_INDEX_SIZE_ERR) {
+      aRv.Throw(rv);
+    }
+    return;
   }
 
-  NS_ENSURE_SUCCESS(rv, rv);
-
   if (data) {
     nsAutoString stringdata;
     data->GetAsAString(stringdata);
 
     // for the URL type, parse out the first URI from the list. The URIs are
     // separated by newlines
     nsAutoString lowercaseFormat;
-    rv = nsContentUtils::ASCIIToLower(aFormat, lowercaseFormat);
-    if (NS_FAILED(rv)) {
-      return rv;
+    aRv = nsContentUtils::ASCIIToLower(aFormat, lowercaseFormat);
+    if (aRv.Failed()) {
+      return;
     }
 
     if (lowercaseFormat.EqualsLiteral("url")) {
       int32_t lastidx = 0, idx;
       int32_t length = stringdata.Length();
       while (lastidx < length) {
         idx = stringdata.FindChar('\n', lastidx);
         // lines beginning with # are comments
@@ -330,122 +390,174 @@ nsDOMDataTransfer::GetData(const nsAStri
             break;
         }
         else {
           if (idx == -1)
             aData.Assign(Substring(stringdata, lastidx));
           else
             aData.Assign(Substring(stringdata, lastidx, idx - lastidx));
           aData = nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(aData, true);
-          return NS_OK;
+          return;
         }
         lastidx = idx + 1;
       }
     }
     else {
       aData = stringdata;
     }
   }
+}
 
+NS_IMETHODIMP
+DataTransfer::GetData(const nsAString& aFormat, nsAString& aData)
+{
+  ErrorResult rv;
+  GetData(aFormat, aData, rv);
+  return rv.ErrorCode();
+}
+
+void
+DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
+                      ErrorResult& aRv)
+{
+  nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+  if (!variant) {
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  variant->SetAsAString(aData);
+
+  aRv = MozSetDataAt(aFormat, variant, 0);
+}
+
+NS_IMETHODIMP
+DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData)
+{
+  ErrorResult rv;
+  SetData(aFormat, aData, rv);
+  return rv.ErrorCode();
+}
+
+void
+DataTransfer::ClearData(const Optional<nsAString>& aFormat, ErrorResult& aRv)
+{
+  if (mReadOnly) {
+    aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
+    return;
+  }
+
+  if (mItems.Length() == 0) {
+    return;
+  }
+
+  if (aFormat.WasPassed()) {
+    MozClearDataAtHelper(aFormat.Value(), 0, aRv);
+  } else {
+    MozClearDataAtHelper(EmptyString(), 0, aRv);
+  }
+}
+
+NS_IMETHODIMP
+DataTransfer::ClearData(const nsAString& aFormat)
+{
+  Optional<nsAString> format;
+  format = &aFormat;
+  ErrorResult rv;
+  ClearData(format, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+DataTransfer::GetMozItemCount(uint32_t* aCount)
+{
+  *aCount = MozItemCount();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::SetData(const nsAString& aFormat, const nsAString& aData)
+DataTransfer::GetMozCursor(nsAString& aCursorState)
 {
-  nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
-  NS_ENSURE_TRUE(variant, NS_ERROR_OUT_OF_MEMORY);
-
-  variant->SetAsAString(aData);
-
-  return MozSetDataAt(aFormat, variant, 0);
-}
-
-NS_IMETHODIMP
-nsDOMDataTransfer::ClearData(const nsAString& aFormat)
-{
-  nsresult rv = MozClearDataAt(aFormat, 0);
-  return (rv == NS_ERROR_DOM_INDEX_SIZE_ERR) ? NS_OK : rv;
-}
-
-NS_IMETHODIMP
-nsDOMDataTransfer::GetMozItemCount(uint32_t* aCount)
-{
-  *aCount = mItems.Length();
+  nsString cursor;
+  GetMozCursor(cursor);
+  aCursorState = cursor;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::GetMozCursor(nsAString& aCursorState)
-{
-  if (mCursorState) {
-    aCursorState.AssignLiteral("default");
-  } else {
-    aCursorState.AssignLiteral("auto");
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMDataTransfer::SetMozCursor(const nsAString& aCursorState)
+DataTransfer::SetMozCursor(const nsAString& aCursorState)
 {
   // Lock the cursor to an arrow during the drag.
   mCursorState = aCursorState.EqualsLiteral("default");
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMDataTransfer::GetMozSourceNode(nsIDOMNode** aSourceNode)
+already_AddRefed<nsINode>
+DataTransfer::GetMozSourceNode()
 {
-  *aSourceNode = nullptr;
-
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
-  if (!dragSession)
-    return NS_OK;
+  if (!dragSession) {
+    return nullptr;
+  }
 
   nsCOMPtr<nsIDOMNode> sourceNode;
   dragSession->GetSourceNode(getter_AddRefs(sourceNode));
-  if (sourceNode && !nsContentUtils::CanCallerAccess(sourceNode))
-    return NS_OK;
+  nsCOMPtr<nsINode> node = do_QueryInterface(sourceNode);
+  if (node && !nsContentUtils::CanCallerAccess(node)) {
+    return nullptr;
+  }
 
-  sourceNode.swap(*aSourceNode);
-  return NS_OK;
+  return node.forget();
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::MozTypesAt(uint32_t aIndex, nsIDOMDOMStringList** aTypes)
+DataTransfer::GetMozSourceNode(nsIDOMNode** aSourceNode)
 {
-  *aTypes = nullptr;
+  nsCOMPtr<nsINode> sourceNode = GetMozSourceNode();
+  if (!sourceNode) {
+    *aSourceNode = nullptr;
+    return NS_OK;
+  }
 
+  return CallQueryInterface(sourceNode, aSourceNode);
+}
+
+already_AddRefed<nsIDOMDOMStringList>
+DataTransfer::MozTypesAt(uint32_t aIndex, ErrorResult& aRv)
+{
   // Only the first item is valid for clipboard events
   if (aIndex > 0 &&
       (mEventType == NS_CUT || mEventType == NS_COPY || mEventType == NS_PASTE)) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<nsDOMStringList> types = new nsDOMStringList();
-
   if (aIndex < mItems.Length()) {
     // note that you can retrieve the types regardless of their principal
     nsTArray<TransferItem>& item = mItems[aIndex];
     for (uint32_t i = 0; i < item.Length(); i++)
       types->Add(item[i].mFormat);
   }
 
-  *aTypes = types;
-  NS_ADDREF(*aTypes);
-
-  return NS_OK;
+  return types.forget();
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::MozGetDataAt(const nsAString& aFormat,
-                                uint32_t aIndex,
-                                nsIVariant** aData)
+DataTransfer::MozTypesAt(uint32_t aIndex, nsIDOMDOMStringList** aTypes)
+{
+  ErrorResult rv;
+  *aTypes = MozTypesAt(aIndex, rv).get();
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
+                           nsIVariant** aData)
 {
   *aData = nullptr;
 
   if (aFormat.IsEmpty())
     return NS_OK;
 
   if (aIndex >= mItems.Length()) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
@@ -517,28 +629,51 @@ nsDOMDataTransfer::MozGetDataAt(const ns
       NS_IF_ADDREF(*aData);
       return NS_OK;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMDataTransfer::MozSetDataAt(const nsAString& aFormat,
-                                nsIVariant* aData,
-                                uint32_t aIndex)
+JS::Value
+DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
+                           uint32_t aIndex, mozilla::ErrorResult& aRv)
 {
-  NS_ENSURE_TRUE(aData, NS_ERROR_NULL_POINTER);
+  nsCOMPtr<nsIVariant> data;
+  aRv = MozGetDataAt(aFormat, aIndex, getter_AddRefs(data));
+  if (aRv.Failed()) {
+    return JS::UndefinedValue();
+  }
+
+  if (!data) {
+    return JS::NullValue();
+  }
 
-  if (aFormat.IsEmpty())
+  JS::Rooted<JS::Value> result(aCx);
+  JS::Rooted<JSObject*> scope(aCx, GetWrapper());
+  if (!VariantToJsval(aCx, scope, data, &result)) {
+    aRv = NS_ERROR_FAILURE;
+    return JS::UndefinedValue();
+  }
+
+  return result;
+}
+
+NS_IMETHODIMP
+DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
+                           uint32_t aIndex)
+{
+  if (aFormat.IsEmpty()) {
     return NS_OK;
+  }
 
-  if (mReadOnly)
+  if (mReadOnly) {
     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
 
   // Specifying an index less than the current length will replace an existing
   // item. Specifying an index equal to the current length will add a new item.
   if (aIndex > mItems.Length()) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Only the first item is valid for clipboard events
@@ -553,124 +688,183 @@ nsDOMDataTransfer::MozSetDataAt(const ns
        aFormat.EqualsLiteral("application/x-moz-file")) &&
        !nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsresult rv = NS_OK;
   nsIPrincipal* principal = GetCurrentPrincipal(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
+
   return SetDataWithPrincipal(aFormat, aData, aIndex, principal);
 }
 
-NS_IMETHODIMP
-nsDOMDataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex)
+void
+DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
+                           JS::Handle<JS::Value> aData,
+                           uint32_t aIndex, ErrorResult& aRv)
 {
-  if (mReadOnly)
-    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  nsCOMPtr<nsIVariant> data;
+  aRv = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData,
+                                                    getter_AddRefs(data));
+  if (!aRv.Failed()) {
+    aRv = MozSetDataAt(aFormat, data, aIndex);
+  }
+}
+
+void
+DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
+                             ErrorResult& aRv)
+{
+  if (mReadOnly) {
+    aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
+    return;
+  }
 
   if (aIndex >= mItems.Length()) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return;
   }
 
   // Only the first item is valid for clipboard events
   if (aIndex > 0 &&
       (mEventType == NS_CUT || mEventType == NS_COPY || mEventType == NS_PASTE)) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return;
   }
 
+  MozClearDataAtHelper(aFormat, aIndex, aRv);
+}
+
+void
+DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
+                                   ErrorResult& aRv)
+{
+  MOZ_ASSERT(!mReadOnly);
+  MOZ_ASSERT(aIndex < mItems.Length());
+  MOZ_ASSERT(aIndex == 0 ||
+             (mEventType != NS_CUT && mEventType != NS_COPY &&
+              mEventType != NS_PASTE));
+
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
   nsresult rv = NS_OK;
   nsIPrincipal* principal = GetCurrentPrincipal(&rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv = rv;
+    return;
+  }
 
   // if the format is empty, clear all formats
   bool clearall = format.IsEmpty();
 
   nsTArray<TransferItem>& item = mItems[aIndex];
   // count backwards so that the count and index don't have to be adjusted
   // after removing an element
   for (int32_t i = item.Length() - 1; i >= 0; i--) {
     TransferItem& formatitem = item[i];
     if (clearall || formatitem.mFormat.Equals(format)) {
       // don't allow removing data that has a stronger principal
       bool subsumes;
       if (formatitem.mPrincipal && principal &&
-          (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
-        return NS_ERROR_DOM_SECURITY_ERR;
+          (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes)) {
+        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+        return;
+      }
 
       item.RemoveElementAt(i);
 
       // if a format was specified, break out. Otherwise, loop around until
       // all formats have been removed
       if (!clearall)
         break;
     }
   }
 
   // if the last format for an item is removed, remove the entire item
   if (!item.Length())
      mItems.RemoveElementAt(aIndex);
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::SetDragImage(nsIDOMElement* aImage, int32_t aX, int32_t aY)
+DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex)
 {
-  if (mReadOnly)
-    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  ErrorResult rv;
+  MozClearDataAt(aFormat, aIndex, rv);
+  return rv.ErrorCode();
+}
 
-  if (aImage) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aImage);
-    NS_ENSURE_TRUE(content, NS_ERROR_INVALID_ARG);
+void
+DataTransfer::SetDragImage(Element& aImage, int32_t aX, int32_t aY,
+                           ErrorResult& aRv)
+{
+  if (mReadOnly) {
+    aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
+    return;
   }
-  mDragImage = aImage;
+
+  mDragImage = &aImage;
   mDragImageX = aX;
   mDragImageY = aY;
-  return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDataTransfer::AddElement(nsIDOMElement* aElement)
+DataTransfer::SetDragImage(nsIDOMElement* aImage, int32_t aX, int32_t aY)
+{
+  ErrorResult rv;
+  nsCOMPtr<Element> image = do_QueryInterface(aImage);
+  if (image) {
+    SetDragImage(*image, aX, aY, rv);
+  }
+  return rv.ErrorCode();
+}
+
+void
+DataTransfer::AddElement(Element& aElement, ErrorResult& aRv)
+{
+  if (mReadOnly) {
+    aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
+    return;
+  }
+
+  mDragTarget = &aElement;
+}
+
+NS_IMETHODIMP
+DataTransfer::AddElement(nsIDOMElement* aElement)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
 
-  if (aElement) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-    NS_ENSURE_TRUE(content, NS_ERROR_INVALID_ARG);
-  }
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG);
 
-  if (mReadOnly)
-    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
-
-  mDragTarget = do_QueryInterface(aElement);
-
-  return NS_OK;
+  ErrorResult rv;
+  AddElement(*element, rv);
+  return rv.ErrorCode();
 }
 
 nsresult
-nsDOMDataTransfer::Clone(uint32_t aEventType, bool aUserCancelled,
-                         bool aIsCrossDomainSubFrameDrop,
-                         nsIDOMDataTransfer** aNewDataTransfer)
+DataTransfer::Clone(nsISupports* aParent, uint32_t aEventType,
+                    bool aUserCancelled, bool aIsCrossDomainSubFrameDrop,
+                    DataTransfer** aNewDataTransfer)
 {
-  nsDOMDataTransfer* newDataTransfer =
-    new nsDOMDataTransfer(aEventType, mEffectAllowed, mCursorState,
-                          mIsExternal, aUserCancelled, aIsCrossDomainSubFrameDrop,
-                          mClipboardType, mItems, mDragImage, mDragImageX, mDragImageY);
+  DataTransfer* newDataTransfer =
+    new DataTransfer(aParent, aEventType, mEffectAllowed, mCursorState,
+                     mIsExternal, aUserCancelled, aIsCrossDomainSubFrameDrop,
+                     mClipboardType, mItems, mDragImage, mDragImageX,
+                     mDragImageY);
 
   *aNewDataTransfer = newDataTransfer;
   NS_ADDREF(*aNewDataTransfer);
   return NS_OK;
 }
 
 already_AddRefed<nsISupportsArray>
-nsDOMDataTransfer::GetTransferables(nsIDOMNode* aDragTarget)
+DataTransfer::GetTransferables(nsIDOMNode* aDragTarget)
 {
   MOZ_ASSERT(aDragTarget);
 
   nsCOMPtr<nsISupportsArray> transArray =
     do_CreateInstance("@mozilla.org/supports-array;1");
   if (!transArray) {
     return nullptr;
   }
@@ -695,17 +889,17 @@ nsDOMDataTransfer::GetTransferables(nsID
       transArray->AppendElement(transferable);
     }
   }
 
   return transArray.forget();
 }
 
 already_AddRefed<nsITransferable>
-nsDOMDataTransfer::GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext)
+DataTransfer::GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext)
 {
   if (aIndex >= mItems.Length()) {
     return nullptr;
   }
 
   nsTArray<TransferItem>& item = mItems[aIndex];
   uint32_t count = item.Length();
   if (!count) {
@@ -762,19 +956,19 @@ nsDOMDataTransfer::GetTransferable(uint3
   if (added) {
     return transferable.forget();
   }
 
   return nullptr;
 }
 
 bool
-nsDOMDataTransfer::ConvertFromVariant(nsIVariant* aVariant,
-                                      nsISupports** aSupports,
-                                      uint32_t* aLength)
+DataTransfer::ConvertFromVariant(nsIVariant* aVariant,
+                                 nsISupports** aSupports,
+                                 uint32_t* aLength)
 {
   *aSupports = nullptr;
   *aLength = 0;
 
   uint16_t type;
   aVariant->GetDataType(&type);
   if (type == nsIDataType::VTYPE_INTERFACE ||
       type == nsIDataType::VTYPE_INTERFACE_IS) {
@@ -826,26 +1020,26 @@ nsDOMDataTransfer::ConvertFromVariant(ns
 
   // each character is two bytes
   *aLength = str.Length() << 1;
 
   return true;
 }
 
 void
-nsDOMDataTransfer::ClearAll()
+DataTransfer::ClearAll()
 {
   mItems.Clear();
 }
 
 nsresult
-nsDOMDataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
-                                        nsIVariant* aData,
-                                        uint32_t aIndex,
-                                        nsIPrincipal* aPrincipal)
+DataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
+                                   nsIVariant* aData,
+                                   uint32_t aIndex,
+                                   nsIPrincipal* aPrincipal)
 {
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
   // check if the item for the format already exists. In that case,
   // just replace it.
   TransferItem* formatitem;
   if (aIndex < mItems.Length()) {
@@ -884,59 +1078,59 @@ nsDOMDataTransfer::SetDataWithPrincipal(
   formatitem->mFormat = format;
   formatitem->mPrincipal = aPrincipal;
   formatitem->mData = aData;
 
   return NS_OK;
 }
 
 nsIPrincipal*
-nsDOMDataTransfer::GetCurrentPrincipal(nsresult* rv)
+DataTransfer::GetCurrentPrincipal(nsresult* rv)
 {
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
 
   nsCOMPtr<nsIPrincipal> currentPrincipal;
   *rv = ssm->GetSubjectPrincipal(getter_AddRefs(currentPrincipal));
   NS_ENSURE_SUCCESS(*rv, nullptr);
 
   if (!currentPrincipal)
     ssm->GetSystemPrincipal(getter_AddRefs(currentPrincipal));
 
   return currentPrincipal.get();
 }
 
 void
-nsDOMDataTransfer::GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat)
+DataTransfer::GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat)
 {
   // treat text/unicode as equivalent to text/plain
   nsAutoString lowercaseFormat;
   nsContentUtils::ASCIIToLower(aInFormat, lowercaseFormat);
   if (lowercaseFormat.EqualsLiteral("text") || lowercaseFormat.EqualsLiteral("text/unicode"))
     aOutFormat.AssignLiteral("text/plain");
   else if (lowercaseFormat.EqualsLiteral("url"))
     aOutFormat.AssignLiteral("text/uri-list");
   else
     aOutFormat.Assign(lowercaseFormat);
 }
 
 void
-nsDOMDataTransfer::CacheExternalData(const char* aFormat, uint32_t aIndex, nsIPrincipal* aPrincipal)
+DataTransfer::CacheExternalData(const char* aFormat, uint32_t aIndex, nsIPrincipal* aPrincipal)
 {
   if (strcmp(aFormat, kUnicodeMime) == 0) {
     SetDataWithPrincipal(NS_LITERAL_STRING("text/plain"), nullptr, aIndex, aPrincipal);
   } else {
     if (strcmp(aFormat, kURLDataMime) == 0) {
       SetDataWithPrincipal(NS_LITERAL_STRING("text/uri-list"), nullptr, aIndex, aPrincipal);
     }
     SetDataWithPrincipal(NS_ConvertUTF8toUTF16(aFormat), nullptr, aIndex, aPrincipal);
   }
 }
 
 void
-nsDOMDataTransfer::CacheExternalDragFormats()
+DataTransfer::CacheExternalDragFormats()
 {
   // Called during the constructor to cache the formats available from an
   // external drag. The data associated with each format will be set to null.
   // This data will instead only be retrieved in FillInExternalDragData when
   // asked for, as it may be time consuming for the source application to
   // generate it.
 
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
@@ -968,17 +1162,17 @@ nsDOMDataTransfer::CacheExternalDragForm
       if (supported) {
         CacheExternalData(formats[f], c, sysPrincipal);
       }
     }
   }
 }
 
 void
-nsDOMDataTransfer::CacheExternalClipboardFormats()
+DataTransfer::CacheExternalClipboardFormats()
 {
   NS_ASSERTION(mEventType == NS_PASTE, "caching clipboard data for invalid event");
 
   // Called during the constructor for paste events to cache the formats
   // available on the clipboard. As with CacheExternalDragFormats, the
   // data will only be retrieved when needed.
 
   nsCOMPtr<nsIClipboard> clipboard = do_GetService("@mozilla.org/widget/clipboard;1");
@@ -1002,17 +1196,17 @@ nsDOMDataTransfer::CacheExternalClipboar
     // the data. When retrieved, GetRealData will read the data.
     if (supported) {
       CacheExternalData(formats[f], 0, sysPrincipal);
     }
   }
 }
 
 void
-nsDOMDataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
+DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
 {
   NS_PRECONDITION(mIsExternal, "Not an external data transfer");
 
   if (aItem.mData) {
     return;
   }
 
   // only drag and paste events should be calling FillInExternalData
@@ -1076,8 +1270,11 @@ nsDOMDataTransfer::FillInExternalData(Tr
       variant->SetAsAString(str);
     }
     else {
       variant->SetAsISupports(data);
     }
 
     aItem.mData = variant;
   }
+
+} // namespace dom
+} // namespace mozilla
rename from dom/events/nsDOMDataTransfer.h
rename to dom/events/DataTransfer.h
--- a/dom/events/nsDOMDataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -1,102 +1,182 @@
 /* -*- 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 nsDOMDataTransfer_h__
-#define nsDOMDataTransfer_h__
+#ifndef mozilla_dom_DataTransfer_h
+#define mozilla_dom_DataTransfer_h
 
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIVariant.h"
 #include "nsIPrincipal.h"
 #include "nsIDOMDataTransfer.h"
 #include "nsIDOMElement.h"
+#include "nsIDragService.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsAutoPtr.h"
 #include "nsDOMFile.h"
 #include "mozilla/Attributes.h"
 
+class nsEventStateManager;
+class nsINode;
 class nsITransferable;
 class nsISupportsArray;
 class nsILoadContext;
 
+namespace mozilla {
+namespace dom {
+
+class Element;
+template<typename T> class Optional;
+
 /**
  * TransferItem is used to hold data for a particular format. Each piece of
  * data has a principal set from the caller which added it. This allows a
  * caller that wishes to retrieve the data to only be able to access the data
  * it is allowed to, yet still allow a chrome caller to retrieve any of the
  * data.
  */
 struct TransferItem {
   nsString mFormat;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIVariant> mData;
 };
 
-class nsDOMDataTransfer MOZ_FINAL : public nsIDOMDataTransfer
+#define NS_DATATRANSFER_IID \
+{ 0x43ee0327, 0xde5d, 0x463d, \
+  { 0x9b, 0xd0, 0xf1, 0x79, 0x09, 0x69, 0xf2, 0xfb } }
+
+class DataTransfer MOZ_FINAL : public nsIDOMDataTransfer,
+                               public nsWrapperCache
 {
 public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATATRANSFER_IID)
+
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMDATATRANSFER
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMDataTransfer, nsIDOMDataTransfer)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DataTransfer)
 
-  friend class nsEventStateManager;
+  friend class ::nsEventStateManager;
 
 protected:
 
   // hide the default constructor
-  nsDOMDataTransfer();
+  DataTransfer();
 
   // this constructor is used only by the Clone method to copy the fields as
   // needed to a new data transfer.
-  nsDOMDataTransfer(uint32_t aEventType,
-                    const uint32_t aEffectAllowed,
-                    bool aCursorState,
-                    bool aIsExternal,
-                    bool aUserCancelled,
-                    bool aIsCrossDomainSubFrameDrop,
-                    int32_t aClipboardType,
-                    nsTArray<nsTArray<TransferItem> >& aItems,
-                    nsIDOMElement* aDragImage,
-                    uint32_t aDragImageX,
-                    uint32_t aDragImageY);
+  DataTransfer(nsISupports* aParent,
+               uint32_t aEventType,
+               const uint32_t aEffectAllowed,
+               bool aCursorState,
+               bool aIsExternal,
+               bool aUserCancelled,
+               bool aIsCrossDomainSubFrameDrop,
+               int32_t aClipboardType,
+               nsTArray<nsTArray<TransferItem> >& aItems,
+               Element* aDragImage,
+               uint32_t aDragImageX,
+               uint32_t aDragImageY);
 
-  ~nsDOMDataTransfer()
-  {
-    if (mFiles) {
-      mFiles->Disconnect();
-    }
-  }
+  ~DataTransfer();
 
   static const char sEffects[8][9];
 
 public:
 
-  // Constructor for nsDOMDataTransfer.
+  // Constructor for DataTransfer.
   //
   // aEventType is an event constant (such as NS_DRAGDROP_START)
   //
   // aIsExternal must only be true when used to create a dataTransfer for a
   // paste or a drag that was started without using a data transfer. The
   // latter will occur when an external drag occurs, that is, a drag where the
   // source is another application, or a drag is started by calling the drag
   // service directly. For clipboard operations, aClipboardType indicates
   // which clipboard to use, from nsIClipboard, or -1 for non-clipboard operations,
   // or if access to the system clipboard should not be allowed.
-  nsDOMDataTransfer(uint32_t aEventType, bool aIsExternal, int32_t aClipboardType);
+  DataTransfer(nsISupports* aParent, uint32_t aEventType, bool aIsExternal,
+               int32_t aClipboardType);
+
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope);
+  nsISupports* GetParentObject()
+  {
+    return mParent;
+  }
+
+  void SetParentObject(nsISupports* aNewParent)
+  {
+    MOZ_ASSERT(aNewParent);
+    // Setting the parent after we've been wrapped is pointless, so
+    // make sure we aren't wrapped yet.
+    MOZ_ASSERT(!GetWrapperPreserveColor());
+    mParent = aNewParent;
+  }
+
+  static already_AddRefed<DataTransfer>
+  Constructor(const GlobalObject& aGlobal, const nsAString& aEventType,
+              bool aIsExternal, ErrorResult& aRv);
 
-  void GetDragTarget(nsIDOMElement** aDragTarget)
+  void GetDropEffect(nsString& aDropEffect)
+  {
+    aDropEffect.AssignASCII(sEffects[mDropEffect]);
+  }
+  void GetEffectAllowed(nsString& aEffectAllowed)
+  {
+    if (mEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) {
+      aEffectAllowed.AssignLiteral("uninitialized");
+    } else {
+      aEffectAllowed.AssignASCII(sEffects[mEffectAllowed]);
+    }
+  }
+  void SetDragImage(Element& aElement, int32_t aX, int32_t aY,
+                    ErrorResult& aRv);
+  already_AddRefed<nsIDOMDOMStringList> Types();
+  void GetData(const nsAString& aFormat, nsAString& aData, ErrorResult& aRv);
+  void SetData(const nsAString& aFormat, const nsAString& aData,
+               ErrorResult& aRv);
+  void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
+                 mozilla::ErrorResult& aRv);
+  nsDOMFileList* GetFiles(mozilla::ErrorResult& aRv);
+  void AddElement(Element& aElement, mozilla::ErrorResult& aRv);
+  uint32_t MozItemCount()
   {
-    *aDragTarget = mDragTarget;
-    NS_IF_ADDREF(*aDragTarget);
+    return mItems.Length();
+  }
+  void GetMozCursor(nsString& aCursor)
+  {
+    if (mCursorState) {
+      aCursor.AssignLiteral("default");
+    } else {
+      aCursor.AssignLiteral("auto");
+    }
+  }
+  already_AddRefed<nsIDOMDOMStringList> MozTypesAt(uint32_t aIndex,
+                                                   mozilla::ErrorResult& aRv);
+  void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
+                      mozilla::ErrorResult& aRv);
+  void MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
+                    JS::Handle<JS::Value> aData, uint32_t aIndex,
+                    mozilla::ErrorResult& aRv);
+  JS::Value MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
+                         uint32_t aIndex, mozilla::ErrorResult& aRv);
+  bool MozUserCancelled()
+  {
+    return mUserCancelled;
+  }
+  already_AddRefed<nsINode> GetMozSourceNode();
+
+  mozilla::dom::Element* GetDragTarget()
+  {
+    return mDragTarget;
   }
 
   // a readonly dataTransfer cannot have new data added or existing data removed.
   // Only the dropEffect and effectAllowed may be modified.
   void SetReadOnly() { mReadOnly = true; }
 
   // converts the data into an array of nsITransferable objects to be used for
   // drag and drop or clipboard operations.
@@ -118,26 +198,29 @@ public:
   // Similar to SetData except also specifies the principal to store.
   // aData may be null when called from CacheExternalDragFormats or
   // CacheExternalClipboardFormats.
   nsresult SetDataWithPrincipal(const nsAString& aFormat,
                                 nsIVariant* aData,
                                 uint32_t aIndex,
                                 nsIPrincipal* aPrincipal);
 
-protected:
-
   // returns a weak reference to the drag image
-  nsIDOMElement* GetDragImage(int32_t* aX, int32_t* aY)
+  Element* GetDragImage(int32_t* aX, int32_t* aY)
   {
     *aX = mDragImageX;
     *aY = mDragImageY;
     return mDragImage;
   }
 
+  nsresult Clone(nsISupports* aParent, uint32_t aEventType, bool aUserCancelled,
+                 bool aIsCrossDomainSubFrameDrop, DataTransfer** aResult);
+
+protected:
+
   // returns a weak reference to the current principal
   nsIPrincipal* GetCurrentPrincipal(nsresult* rv);
 
   // converts some formats used for compatibility in aInFormat into aOutFormat.
   // Text and text/unicode become text/plain, and URL becomes text/uri-list
   void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat);
 
   // caches text and uri-list data formats that exist in the drag service or
@@ -150,16 +233,21 @@ protected:
 
   // caches the formats that exist in the clipboard
   void CacheExternalClipboardFormats();
 
   // fills in the data field of aItem with the data from the drag service or
   // clipboard for a given index.
   void FillInExternalData(TransferItem& aItem, uint32_t aIndex);
 
+  void MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
+                            mozilla::ErrorResult& aRv);
+
+  nsCOMPtr<nsISupports> mParent;
+
   // the event type this data transfer is for. This will correspond to an
   // event->message value.
   uint32_t mEventType;
 
   // the drop effect and effect allowed
   uint32_t mDropEffect;
   uint32_t mEffectAllowed;
 
@@ -187,19 +275,24 @@ protected:
 
   // array of items, each containing an array of format->data pairs
   nsTArray<nsTArray<TransferItem> > mItems;
 
   // array of files, containing only the files present in the dataTransfer
   nsRefPtr<nsDOMFileList> mFiles;
 
   // the target of the drag. The drag and dragend events will fire at this.
-  nsCOMPtr<nsIDOMElement> mDragTarget;
+  nsCOMPtr<mozilla::dom::Element> mDragTarget;
 
   // the custom drag image and coordinates within the image. If mDragImage is
   // null, the default image is created from the drag target.
-  nsCOMPtr<nsIDOMElement> mDragImage;
+  nsCOMPtr<mozilla::dom::Element> mDragImage;
   uint32_t mDragImageX;
   uint32_t mDragImageY;
 };
 
-#endif // nsDOMDataTransfer_h__
+NS_DEFINE_STATIC_IID_ACCESSOR(DataTransfer, NS_DATATRANSFER_IID)
 
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_DataTransfer_h */
+
--- a/dom/events/Touch.h
+++ b/dom/events/Touch.h
@@ -3,29 +3,31 @@
  * 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_Touch_h
 #define mozilla_dom_Touch_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
+#include "mozilla/MouseEvents.h"
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 #include "Units.h"
 
 class nsPresContext;
 
 namespace mozilla {
 namespace dom {
 
 class EventTarget;
 
 class Touch MOZ_FINAL : public nsISupports
                       , public nsWrapperCache
+                      , public WidgetPointerHelper
 {
 public:
   static bool PrefEnabled(JSContext* aCx, JSObject* aGlobal);
 
   Touch(mozilla::dom::EventTarget* aTarget,
         int32_t aIdentifier,
         int32_t aPageX,
         int32_t aPageY,
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -37,36 +37,37 @@ EXPORTS.mozilla += [
 
 EXPORTS.mozilla.dom += [
     'AnimationEvent.h',
     'BeforeUnloadEvent.h',
     'ClipboardEvent.h',
     'CommandEvent.h',
     'CompositionEvent.h',
     'DataContainerEvent.h',
+    'DataTransfer.h',
     'EventTarget.h',
     'PointerEvent.h',
     'Touch.h',
     'WheelEvent.h',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     EXPORTS.mozilla.dom += ['SpeechRecognitionError.h']
 
 UNIFIED_SOURCES += [
     'AnimationEvent.cpp',
     'BeforeUnloadEvent.cpp',
     'ClipboardEvent.cpp',
     'CommandEvent.cpp',
     'CompositionEvent.cpp',
     'DataContainerEvent.cpp',
+    'DataTransfer.cpp',
     'EventTarget.cpp',
     'nsAsyncDOMEvent.cpp',
     'nsContentEventHandler.cpp',
-    'nsDOMDataTransfer.cpp',
     'nsDOMDeviceMotionEvent.cpp',
     'nsDOMDragEvent.cpp',
     'nsDOMEventTargetHelper.cpp',
     'nsDOMFocusEvent.cpp',
     'nsDOMKeyboardEvent.cpp',
     'nsDOMMessageEvent.cpp',
     'nsDOMMouseEvent.cpp',
     'nsDOMMouseScrollEvent.cpp',
--- a/dom/events/nsDOMDragEvent.cpp
+++ b/dom/events/nsDOMDragEvent.cpp
@@ -1,22 +1,22 @@
 /* -*- 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 "nsDOMDragEvent.h"
 #include "nsContentUtils.h"
-#include "nsIDOMDataTransfer.h"
 #include "prtime.h"
 #include "mozilla/MouseEvents.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
-nsDOMDragEvent::nsDOMDragEvent(mozilla::dom::EventTarget* aOwner,
+nsDOMDragEvent::nsDOMDragEvent(EventTarget* aOwner,
                                nsPresContext* aPresContext,
                                WidgetDragEvent* aEvent)
   : nsDOMMouseEvent(aOwner, aPresContext, aEvent ? aEvent :
                     new WidgetDragEvent(false, 0, nullptr))
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
@@ -30,48 +30,76 @@ nsDOMDragEvent::nsDOMDragEvent(mozilla::
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDragEvent, nsDOMMouseEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMDragEvent, nsDOMMouseEvent)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMDragEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDragEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMMouseEvent)
 
+void
+nsDOMDragEvent::InitDragEvent(const nsAString& aType, bool aCanBubble,
+                              bool aCancelable, nsIDOMWindow* aView,
+                              int32_t aDetail, int32_t aScreenX,
+                              int32_t aScreenY, int32_t aClientX,
+                              int32_t aClientY, bool aCtrlKey, bool aAltKey,
+                              bool aShiftKey, bool aMetaKey, uint16_t aButton,
+                              EventTarget* aRelatedTarget,
+                              DataTransfer* aDataTransfer, ErrorResult& aError)
+{
+  aError =
+    nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
+                                    aView, aDetail, aScreenX, aScreenY,
+                                    aClientX, aClientY, aCtrlKey, aAltKey,
+                                    aShiftKey, aMetaKey, aButton,
+                                    aRelatedTarget);
+  if (aError.Failed()) {
+    return;
+  }
+
+  if (mEventIsInternal && mEvent) {
+    mEvent->AsDragEvent()->dataTransfer = aDataTransfer;
+  }
+}
+
 NS_IMETHODIMP
 nsDOMDragEvent::InitDragEvent(const nsAString & aType,
                               bool aCanBubble, bool aCancelable,
                               nsIDOMWindow* aView, int32_t aDetail,
                               int32_t aScreenX, int32_t aScreenY,
                               int32_t aClientX, int32_t aClientY, 
                               bool aCtrlKey, bool aAltKey, bool aShiftKey,
                               bool aMetaKey, uint16_t aButton,
                               nsIDOMEventTarget *aRelatedTarget,
                               nsIDOMDataTransfer* aDataTransfer)
 {
+  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDataTransfer);
+  NS_ENSURE_ARG(dataTransfer);
+
   nsresult rv = nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
                   aView, aDetail, aScreenX, aScreenY, aClientX, aClientY,
                   aCtrlKey, aAltKey, aShiftKey, aMetaKey, aButton,
                   aRelatedTarget);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mEventIsInternal && mEvent) {
-    mEvent->AsDragEvent()->dataTransfer = aDataTransfer;
+    mEvent->AsDragEvent()->dataTransfer = dataTransfer;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDragEvent::GetDataTransfer(nsIDOMDataTransfer** aDataTransfer)
 {
   NS_IF_ADDREF(*aDataTransfer = GetDataTransfer());
   return NS_OK;
 }
 
-nsIDOMDataTransfer*
+DataTransfer*
 nsDOMDragEvent::GetDataTransfer()
 {
   // the dataTransfer field of the event caches the DataTransfer associated
   // with the drag. It is initialized when an attempt is made to retrieve it
   // rather that when the event is created to avoid duplicating the data when
   // no listener ever uses it.
   if (!mEvent || mEvent->eventStructType != NS_DRAG_EVENT) {
     NS_WARNING("Tried to get dataTransfer from non-drag event!");
@@ -84,15 +112,15 @@ nsDOMDragEvent::GetDataTransfer()
     nsresult rv = nsContentUtils::SetDataTransferInEvent(dragEvent);
     NS_ENSURE_SUCCESS(rv, nullptr);
   }
 
   return dragEvent->dataTransfer;
 }
 
 nsresult NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult,
-                            mozilla::dom::EventTarget* aOwner,
+                            EventTarget* aOwner,
                             nsPresContext* aPresContext,
                             WidgetDragEvent* aEvent) 
 {
   nsDOMDragEvent* event = new nsDOMDragEvent(aOwner, aPresContext, aEvent);
   return CallQueryInterface(event, aInstancePtrResult);
 }
--- a/dom/events/nsDOMDragEvent.h
+++ b/dom/events/nsDOMDragEvent.h
@@ -6,16 +6,22 @@
 #ifndef nsDOMDragEvent_h__
 #define nsDOMDragEvent_h__
 
 #include "nsIDOMDragEvent.h"
 #include "nsDOMMouseEvent.h"
 #include "mozilla/dom/DragEventBinding.h"
 #include "mozilla/EventForwards.h"
 
+namespace mozilla {
+namespace dom {
+class DataTransfer;
+}
+}
+
 class nsDOMDragEvent : public nsDOMMouseEvent,
                        public nsIDOMDragEvent
 {
 public:
   nsDOMDragEvent(mozilla::dom::EventTarget* aOwner,
                  nsPresContext* aPresContext,
                  mozilla::WidgetDragEvent* aEvent);
 
@@ -26,34 +32,28 @@ public:
   NS_FORWARD_TO_NSDOMMOUSEEVENT
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
   {
     return mozilla::dom::DragEventBinding::Wrap(aCx, aScope, this);
   }
 
-  nsIDOMDataTransfer* GetDataTransfer();
+  mozilla::dom::DataTransfer* GetDataTransfer();
 
   void InitDragEvent(const nsAString& aType,
                      bool aCanBubble, bool aCancelable,
                      nsIDOMWindow* aView, int32_t aDetail,
                      int32_t aScreenX, int32_t aScreenY,
-                     int32_t aClientX, int32_t aClientY, 
+                     int32_t aClientX, int32_t aClientY,
                      bool aCtrlKey, bool aAltKey, bool aShiftKey,
                      bool aMetaKey, uint16_t aButton,
                      mozilla::dom::EventTarget* aRelatedTarget,
-                     nsIDOMDataTransfer* aDataTransfer,
-                     mozilla::ErrorResult& aRv)
-  {
-    aRv = InitDragEvent(aType, aCanBubble, aCancelable,
-                        aView, aDetail, aScreenX, aScreenY, aClientX, aClientY,
-                        aCtrlKey, aAltKey, aShiftKey, aMetaKey, aButton,
-                        aRelatedTarget, aDataTransfer);
-  }
+                     mozilla::dom::DataTransfer* aDataTransfer,
+                     mozilla::ErrorResult& aError);
 };
 
 nsresult NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult,
                             mozilla::dom::EventTarget* aOwner,
                             nsPresContext* aPresContext,
                             mozilla::WidgetDragEvent* aEvent);
 
 #endif // nsDOMDragEvent_h__
--- a/dom/events/nsEventStateManager.cpp
+++ b/dom/events/nsEventStateManager.cpp
@@ -65,17 +65,17 @@
 #include "nsEventDispatcher.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsITimer.h"
 #include "nsFontMetrics.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
-#include "nsDOMDataTransfer.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "nsContentAreaDragDrop.h"
 #ifdef MOZ_XUL
 #include "nsTreeBodyFrame.h"
 #endif
 #include "nsIController.h"
 #include "nsICommandParams.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/HTMLLabelElement.h"
@@ -1089,16 +1089,21 @@ nsEventStateManager::PreHandleEvent(nsPr
         // then fall through...
       case WidgetMouseEvent::eRightButton:
       case WidgetMouseEvent::eMiddleButton:
         SetClickCount(aPresContext, mouseEvent, aStatus);
         break;
     }
     break;
   }
+  case NS_POINTER_CANCEL:
+  {
+    GenerateMouseEnterExit(mouseEvent);
+    break;
+  }
   case NS_MOUSE_EXIT:
     // If the event is not a top-level window exit, then it's not
     // really an exit --- we may have traversed widget boundaries but
     // we're still in our toplevel window.
     if (mouseEvent->exit != WidgetMouseEvent::eTopLevel) {
       // Treat it as a synthetic move so we don't generate spurious
       // "exit" or "move" events.  Any necessary "out" or "over" events
       // will be generated by GenerateMouseEnterExit
@@ -2101,35 +2106,42 @@ nsEventStateManager::GenerateDragGesture
     if (DeprecatedAbs(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
         DeprecatedAbs(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
       if (Prefs::ClickHoldContextMenu()) {
         // stop the click-hold before we fire off the drag gesture, in case
         // it takes a long time
         KillClickHoldTimer();
       }
 
-      nsRefPtr<nsDOMDataTransfer> dataTransfer =
-        new nsDOMDataTransfer(NS_DRAGDROP_START, false, -1);
-      if (!dataTransfer)
+      nsCOMPtr<nsISupports> container = aPresContext->GetContainerWeak();
+      nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(container);
+      if (!window)
         return;
 
+      nsRefPtr<DataTransfer> dataTransfer =
+        new DataTransfer(window, NS_DRAGDROP_START, false, -1);
+
       nsCOMPtr<nsISelection> selection;
       nsCOMPtr<nsIContent> eventContent, targetContent;
       mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent));
       if (eventContent)
-        DetermineDragTarget(aPresContext, eventContent, dataTransfer,
+        DetermineDragTarget(window, eventContent, dataTransfer,
                             getter_AddRefs(selection), getter_AddRefs(targetContent));
 
       // Stop tracking the drag gesture now. This should stop us from
       // reentering GenerateDragGesture inside DOM event processing.
       StopTrackingDragGesture();
 
       if (!targetContent)
         return;
 
+      // Use our targetContent, now that we've determined it, as the
+      // parent object of the DataTransfer.
+      dataTransfer->SetParentObject(targetContent);
+
       sLastDragOverFrame = nullptr;
       nsCOMPtr<nsIWidget> widget = mCurrentTarget->GetNearestWidget();
 
       // get the widget from the target frame
       WidgetDragEvent startEvent(aEvent->mFlags.mIsTrusted,
                                  NS_DRAGDROP_START, widget);
       FillInEventFromGestureDown(&startEvent);
 
@@ -2203,38 +2215,33 @@ nsEventStateManager::GenerateDragGesture
 
     // Now flush all pending notifications, for better responsiveness
     // while dragging.
     FlushPendingEvents(aPresContext);
   }
 } // GenerateDragGesture
 
 void
-nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
+nsEventStateManager::DetermineDragTarget(nsPIDOMWindow* aWindow,
                                          nsIContent* aSelectionTarget,
-                                         nsDOMDataTransfer* aDataTransfer,
+                                         DataTransfer* aDataTransfer,
                                          nsISelection** aSelection,
                                          nsIContent** aTargetNode)
 {
   *aTargetNode = nullptr;
 
-  nsCOMPtr<nsISupports> container = aPresContext->GetContainerWeak();
-  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(container);
-  if (!window)
-    return;
-
   // GetDragData determines if a selection, link or image in the content
   // should be dragged, and places the data associated with the drag in the
   // data transfer.
   // mGestureDownContent is the node where the mousedown event for the drag
   // occurred, and aSelectionTarget is the node to use when a selection is used
   bool canDrag;
   nsCOMPtr<nsIContent> dragDataNode;
   bool wasAlt = (mGestureModifiers & MODIFIER_ALT) != 0;
-  nsresult rv = nsContentAreaDragDrop::GetDragData(window, mGestureDownContent,
+  nsresult rv = nsContentAreaDragDrop::GetDragData(aWindow, mGestureDownContent,
                                                    aSelectionTarget, wasAlt,
                                                    aDataTransfer, &canDrag, aSelection,
                                                    getter_AddRefs(dragDataNode));
   if (NS_FAILED(rv) || !canDrag)
     return;
 
   // if GetDragData returned a node, use that as the node being dragged.
   // Otherwise, if a selection is being dragged, use the node within the
@@ -2292,17 +2299,17 @@ nsEventStateManager::DetermineDragTarget
     *aTargetNode = dragContent;
     NS_ADDREF(*aTargetNode);
   }
 }
 
 bool
 nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
                                         WidgetDragEvent* aDragEvent,
-                                        nsDOMDataTransfer* aDataTransfer,
+                                        DataTransfer* aDataTransfer,
                                         nsIContent* aDragTarget,
                                         nsISelection* aSelection)
 {
   nsCOMPtr<nsIDragService> dragService =
     do_GetService("@mozilla.org/widget/dragservice;1");
   if (!dragService)
     return false;
 
@@ -2325,49 +2332,46 @@ nsEventStateManager::DoDefaultDragStart(
     aDataTransfer->GetMozItemCount(&count);
   if (!count)
     return false;
 
   // Get the target being dragged, which may not be the same as the
   // target of the mouse event. If one wasn't set in the
   // aDataTransfer during the event handler, just use the original
   // target instead.
-  nsCOMPtr<nsIDOMNode> dragTarget;
-  nsCOMPtr<nsIDOMElement> dragTargetElement;
-  aDataTransfer->GetDragTarget(getter_AddRefs(dragTargetElement));
-  dragTarget = do_QueryInterface(dragTargetElement);
+  nsCOMPtr<Element> dragTarget = aDataTransfer->GetDragTarget();
   if (!dragTarget) {
     dragTarget = do_QueryInterface(aDragTarget);
     if (!dragTarget)
       return false;
   }
-  nsCOMPtr<nsIContent> content = do_QueryInterface(dragTarget);
 
   // check which drag effect should initially be used. If the effect was not
   // set, just use all actions, otherwise Windows won't allow a drop.
   uint32_t action;
   aDataTransfer->GetEffectAllowedInt(&action);
   if (action == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
     action = nsIDragService::DRAGDROP_ACTION_COPY |
              nsIDragService::DRAGDROP_ACTION_MOVE |
              nsIDragService::DRAGDROP_ACTION_LINK;
 
   // get any custom drag image that was set
   int32_t imageX, imageY;
-  nsIDOMElement* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
-
-  nsCOMPtr<nsISupportsArray> transArray = aDataTransfer->GetTransferables(dragTarget);
+  Element* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
+
+  nsCOMPtr<nsISupportsArray> transArray =
+    aDataTransfer->GetTransferables(dragTarget->AsDOMNode());
   if (!transArray)
     return false;
 
   // XXXndeakin don't really want to create a new drag DOM event
   // here, but we need something to pass to the InvokeDragSession
   // methods.
   nsCOMPtr<nsIDOMEvent> domEvent;
-  NS_NewDOMDragEvent(getter_AddRefs(domEvent), content,
+  NS_NewDOMDragEvent(getter_AddRefs(domEvent), dragTarget,
                      aPresContext, aDragEvent);
 
   nsCOMPtr<nsIDOMDragEvent> domDragEvent = do_QueryInterface(domEvent);
   // if creating a drag event failed, starting a drag session will
   // just fail.
 
   // Use InvokeDragSessionWithSelection if a selection is being dragged,
   // such that the image can be generated from the selected text. However,
@@ -2382,29 +2386,33 @@ nsEventStateManager::DoDefaultDragStart(
     // if dragging within a XUL tree and no custom drag image was
     // set, the region argument to InvokeDragSessionWithImage needs
     // to be set to the area encompassing the selected rows of the
     // tree to ensure that the drag feedback gets clipped to those
     // rows. For other content, region should be null.
     nsCOMPtr<nsIScriptableRegion> region;
 #ifdef MOZ_XUL
     if (dragTarget && !dragImage) {
-      if (content->NodeInfo()->Equals(nsGkAtoms::treechildren,
-                                      kNameSpaceID_XUL)) {
-        nsTreeBodyFrame* treeBody = do_QueryFrame(content->GetPrimaryFrame());
+      if (dragTarget->NodeInfo()->Equals(nsGkAtoms::treechildren,
+                                         kNameSpaceID_XUL)) {
+        nsTreeBodyFrame* treeBody =
+          do_QueryFrame(dragTarget->GetPrimaryFrame());
         if (treeBody) {
           treeBody->GetSelectionRegion(getter_AddRefs(region));
         }
       }
     }
 #endif
 
-    dragService->InvokeDragSessionWithImage(dragTarget, transArray,
-                                            region, action, dragImage,
-                                            imageX, imageY, domDragEvent,
+    dragService->InvokeDragSessionWithImage(dragTarget->AsDOMNode(), transArray,
+                                            region, action,
+                                            dragImage ? dragImage->AsDOMNode() :
+                                                        nullptr,
+                                            imageX,
+                                            imageY, domDragEvent,
                                             aDataTransfer);
   }
 
   return true;
 }
 
 nsresult
 nsEventStateManager::GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv)
@@ -4435,16 +4443,17 @@ nsEventStateManager::GenerateMouseEnterE
         targetElement = mDocument->GetRootElement();
       }
       if (targetElement) {
         NotifyMouseOver(aMouseEvent, targetElement);
       }
     }
     break;
   case NS_POINTER_LEAVE:
+  case NS_POINTER_CANCEL:
   case NS_MOUSE_EXIT:
     {
       // This is actually the window mouse exit or pointer leave event. We're not moving
       // into any new element.
 
       OverOutElementsWrapper* helper = GetWrapperByEventID(aMouseEvent);
       if (helper->mLastOverFrame &&
           nsContentUtils::GetTopLevelWidget(aMouseEvent->widget) !=
--- a/dom/events/nsEventStateManager.h
+++ b/dom/events/nsEventStateManager.h
@@ -19,24 +19,24 @@
 #include "Units.h"
 
 class nsFrameLoader;
 class nsIContent;
 class nsIDocument;
 class nsIDocShell;
 class nsIDocShellTreeItem;
 class imgIContainer;
-class nsDOMDataTransfer;
 class EnterLeaveDispatcher;
 class nsIMarkupDocumentViewer;
 class nsIScrollableFrame;
 class nsITimer;
 
 namespace mozilla {
 namespace dom {
+class DataTransfer;
 class TabParent;
 }
 }
 
 class OverOutElementsWrapper MOZ_FINAL : public nsISupports
 {
 public:
   OverOutElementsWrapper() : mLastOverFrame(nullptr) {}
@@ -732,35 +732,35 @@ protected:
    * This is either the node clicked when there is a selection, or, for HTML,
    * the element with a draggable property set to true.
    *
    * aSelectionTarget - target to check for selection
    * aDataTransfer - data transfer object that will contain the data to drag
    * aSelection - [out] set to the selection to be dragged
    * aTargetNode - [out] the draggable node, or null if there isn't one
    */
-  void DetermineDragTarget(nsPresContext* aPresContext,
+  void DetermineDragTarget(nsPIDOMWindow* aWindow,
                            nsIContent* aSelectionTarget,
-                           nsDOMDataTransfer* aDataTransfer,
+                           mozilla::dom::DataTransfer* aDataTransfer,
                            nsISelection** aSelection,
                            nsIContent** aTargetNode);
 
   /*
    * Perform the default handling for the dragstart/draggesture event and set up a
    * drag for aDataTransfer if it contains any data. Returns true if a drag has
    * started.
    *
    * aDragEvent - the dragstart/draggesture event
    * aDataTransfer - the data transfer that holds the data to be dragged
    * aDragTarget - the target of the drag
    * aSelection - the selection to be dragged
    */
   bool DoDefaultDragStart(nsPresContext* aPresContext,
                           mozilla::WidgetDragEvent* aDragEvent,
-                          nsDOMDataTransfer* aDataTransfer,
+                          mozilla::dom::DataTransfer* aDataTransfer,
                           nsIContent* aDragTarget,
                           nsISelection* aSelection);
 
   bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nullptr; }
   /**
    * Set the fields of aEvent to reflect the mouse position and modifier keys
    * that were set when the user first pressed the mouse button (stored by
    * BeginTrackingDragGesture). aEvent->widget must be
--- a/dom/interfaces/events/nsIDOMDataTransfer.idl
+++ b/dom/interfaces/events/nsIDOMDataTransfer.idl
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
 interface nsIVariant;
 interface nsIDOMFileList;
 
-[scriptable, uuid(7D73CFBF-EC30-4F8E-B6A4-BB31EB943580)]
+[scriptable, builtinclass, uuid(4ba241dd-a964-4077-bc30-515a657772e4)]
 interface nsIDOMDataTransfer : nsISupports
 {
   /**
    * The actual effect that will be used, and should always be one of the
    * possible values of effectAllowed.
    *
    * For dragstart, drag and dragleave events, the dropEffect is initialized
    * to none. Any value assigned to the dropEffect will be set, but the value
@@ -224,19 +224,9 @@ interface nsIDOMDataTransfer : nsISuppor
    */
   [noscript] attribute unsigned long dropEffectInt;
 
   /*
    * Integer version of effectAllowed, set to one or a combination of the
    * constants in nsIDragService.
    */
   [noscript] attribute unsigned long effectAllowedInt;
-
-  /**
-   * Creates a copy of the data transfer object, for the given event type and
-   * user cancelled flag. If isCrossDomainSubFrameDrop is set, then this is a
-   * cross-domain drop from a subframe where access to the data should be
-   * prevented.
-   */
-  [noscript] nsIDOMDataTransfer clone(in uint32_t aEventType,
-                                      in boolean aUserCancelled,
-                                      in boolean isCrossDomainSubFrameDrop);
 };
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -93,17 +93,17 @@
 #include "ProcessPriorityManager.h"
 #include "SandboxHal.h"
 #include "StructuredCloneUtils.h"
 #include "TabParent.h"
 #include "URIUtils.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIDocShell.h"
 #include "mozilla/net/NeckoMessageUtils.h"
-#include "gfxPlatform.h"
+#include "gfxPrefs.h"
 
 #if defined(ANDROID) || defined(LINUX)
 #include "nsSystemInfo.h"
 #endif
 
 #ifdef ANDROID
 # include "gfxAndroidPlatform.h"
 #endif
@@ -1547,17 +1547,17 @@ ContentParent::InitInternal(ProcessPrior
         // PBrowsers are created, because they rely on the Compositor
         // already being around.  (Creation is async, so can't happen
         // on demand.)
         bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
         if (useOffMainThreadCompositing) {
             DebugOnly<bool> opened = PCompositor::Open(this);
             MOZ_ASSERT(opened);
 
-            if (gfxPlatform::AsyncVideoEnabled()) {
+            if (gfxPrefs::AsyncVideoEnabled()) {
                 opened = PImageBridge::Open(this);
                 MOZ_ASSERT(opened);
             }
         }
     }
 
     if (aSendRegisteredChrome) {
         nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
--- a/dom/plugins/base/nsPluginNativeWindow.h
+++ b/dom/plugins/base/nsPluginNativeWindow.h
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsPluginNativeWindow_h_
 #define _nsPluginNativeWindow_h_
 
 #include "nscore.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
+#include "nsISupportsImpl.h"
 #include "nsNPAPIPluginInstance.h"
 #include "npapi.h"
 #include "nsIWidget.h"
-#include "nsTraceRefcnt.h"
 
 /**
  * base class for native plugin window implementations
  */
 class nsPluginNativeWindow : public NPWindow
 {
 public: 
   nsPluginNativeWindow() : NPWindow() {
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -69,16 +69,17 @@ var ecmaGlobals =
     {name: "NaN", xbl: false},
     "Number",
     "Object",
     "Proxy",
     "RangeError",
     "ReferenceError",
     "RegExp",
     "Set",
+    {name: "SharedArrayBuffer", nightly: true},
     {name: "SIMD", nightly: true},
     "StopIteration",
     "String",
     "SyntaxError",
     {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
--- a/dom/webidl/ClipboardEvent.webidl
+++ b/dom/webidl/ClipboardEvent.webidl
@@ -5,18 +5,16 @@
  *
  * For more information on this interface please see
  * http://dev.w3.org/2006/webapi/clipops/#x5-clipboard-event-interfaces
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-interface DataTransfer;
-
 [Constructor(DOMString type, optional ClipboardEventInit eventInitDict)]
 interface ClipboardEvent : Event
 {
   readonly attribute DataTransfer? clipboardData;
 };
 
 dictionary ClipboardEventInit : EventInit
 {
new file mode 100644
--- /dev/null
+++ b/dom/webidl/DataTransfer.webidl
@@ -0,0 +1,137 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is:
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-datatransfer-interface
+ */
+
+[ChromeConstructor(DOMString eventType, boolean isExternal)]
+interface DataTransfer {
+           attribute DOMString dropEffect;
+           attribute DOMString effectAllowed;
+
+  //readonly attribute DataTransferItemList items;
+
+  [Throws]
+  void setDragImage(Element image, long x, long y);
+
+  readonly attribute DOMStringList types;
+  [Throws]
+  DOMString getData(DOMString format);
+  [Throws]
+  void setData(DOMString format, DOMString data);
+  [Throws]
+  void clearData(optional DOMString format);
+  [Throws]
+  readonly attribute FileList files;
+};
+
+// Mozilla specific stuff
+partial interface DataTransfer {
+  /*
+   * Set the drag source. Usually you would not change this, but it will
+   * affect which node the drag and dragend events are fired at. The
+   * default target is the node that was dragged.
+   *
+   * @param element drag source to use
+   * @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
+   */
+  [Throws]
+  void addElement(Element element);
+
+  /**
+   * The number of items being dragged.
+   */
+  readonly attribute unsigned long mozItemCount;
+
+  /**
+   * Sets the drag cursor state. Primarily used to control the cursor during
+   * tab drags, but could be expanded to other uses. XXX Currently implemented
+   * on Win32 only.
+   *
+   * Possible values:
+   *  auto - use default system behavior.
+   *  default - set the cursor to an arrow during the drag operation.
+   *
+   * Values other than 'default' are indentical to setting mozCursor to
+   * 'auto'.
+   */
+  attribute DOMString mozCursor;
+
+  /**
+   * Holds a list of the format types of the data that is stored for an item
+   * at the specified index. If the index is not in the range from 0 to
+   * itemCount - 1, an empty string list is returned.
+   */
+  [Throws]
+  DOMStringList mozTypesAt(unsigned long index);
+
+  /**
+   * Remove the data associated with the given format for an item at the
+   * specified index. The index is in the range from zero to itemCount - 1.
+   *
+   * If the last format for the item is removed, the entire item is removed,
+   * reducing the itemCount by one.
+   *
+   * If format is empty, then the data associated with all formats is removed.
+   * If the format is not found, then this method has no effect.
+   *
+   * @param format the format to remove
+   * @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
+   * @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
+   */
+  [Throws]
+  void mozClearDataAt(DOMString format, unsigned long index);
+
+  /*
+   * A data transfer may store multiple items, each at a given zero-based
+   * index. setDataAt may only be called with an index argument less than
+   * itemCount in which case an existing item is modified, or equal to
+   * itemCount in which case a new item is added, and the itemCount is
+   * incremented by one.
+   *
+   * Data should be added in order of preference, with the most specific
+   * format added first and the least specific format added last. If data of
+   * the given format already exists, it is replaced in the same position as
+   * the old data.
+   *
+   * The data should be either a string, a primitive boolean or number type
+   * (which will be converted into a string) or an nsISupports.
+   *
+   * @param format the format to add
+   * @param data the data to add
+   * @throws NS_ERROR_NULL_POINTER if the data is null
+   * @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater than itemCount
+   * @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
+   */
+  [Throws]
+  void mozSetDataAt(DOMString format, any data, unsigned long index);
+
+  /**
+   * Retrieve the data associated with the given format for an item at the
+   * specified index, or null if it does not exist. The index should be in the
+   * range from zero to itemCount - 1.
+   *
+   * @param format the format of the data to look up
+   * @returns the data of the given format, or null if it doesn't exist.
+   * @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
+   */
+  [Throws]
+  any mozGetDataAt(DOMString format, unsigned long index);
+
+  /**
+   * Will be true when the user has cancelled the drag (typically by pressing
+   * Escape) and when the drag has been cancelled unexpectedly.  This will be
+   * false otherwise, including when the drop has been rejected by its target.
+   * This property is only relevant for the dragend event.
+   */
+  readonly attribute boolean mozUserCancelled;
+
+  /**
+   * The node that the mouse was pressed over to begin the drag. For external
+   * drags, or if the caller cannot access this node, this will be null.
+   */
+  readonly attribute Node? mozSourceNode;
+};
--- a/dom/webidl/DragEvent.webidl
+++ b/dom/webidl/DragEvent.webidl
@@ -1,16 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 interface WindowProxy;
-interface DataTransfer;
 
 interface DragEvent : MouseEvent
 {
   readonly attribute DataTransfer? dataTransfer;
 
   [Throws]
   void initDragEvent(DOMString type,
                      boolean canBubble,
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -61,16 +61,17 @@ WEBIDL_FILES = [
     'CSS.webidl',
     'CSSPrimitiveValue.webidl',
     'CSSStyleDeclaration.webidl',
     'CSSStyleSheet.webidl',
     'CSSValue.webidl',
     'CSSValueList.webidl',
     'DataContainerEvent.webidl',
     'DataStore.webidl',
+    'DataTransfer.webidl',
     'DedicatedWorkerGlobalScope.webidl',
     'DelayNode.webidl',
     'DesktopNotification.webidl',
     'DeviceMotionEvent.webidl',
     'DeviceStorage.webidl',
     'Document.webidl',
     'DocumentFragment.webidl',
     'DocumentType.webidl',
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -35,22 +35,22 @@
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/WorkerBinding.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Navigator.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollector.h"
 #include "nsDOMJSUtils.h"
+#include "nsISupportsImpl.h"
 #include "nsLayoutStatics.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
-#include "nsTraceRefcnt.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMPrivate.h"
 #include "OSFileConstants.h"
 #include "xpcpublic.h"
 
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
--- a/dom/xslt/base/txCore.h
+++ b/dom/xslt/base/txCore.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __txCore_h__
 #define __txCore_h__
 
 #include "nscore.h"
 #include "nsDebug.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 class nsAString;
 
 class txObject
 {
 public:
     txObject()
     {
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -16,17 +16,17 @@
 #include "nsEventListenerManager.h"     // for nsEventListenerManager
 #include "nsFocusManager.h"             // for nsFocusManager
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::input
 #include "nsIClipboard.h"               // for nsIClipboard, etc
 #include "nsIContent.h"                 // for nsIContent
 #include "nsIController.h"              // for nsIController
 #include "nsID.h"
 #include "nsIDOMDOMStringList.h"        // for nsIDOMDOMStringList
-#include "nsIDOMDataTransfer.h"         // for nsIDOMDataTransfer
+#include "mozilla/dom/DataTransfer.h"
 #include "nsIDOMDocument.h"             // for nsIDOMDocument
 #include "nsIDOMDragEvent.h"            // for nsIDOMDragEvent
 #include "nsIDOMElement.h"              // for nsIDOMElement
 #include "nsIDOMEvent.h"                // for nsIDOMEvent
 #include "nsIDOMEventTarget.h"          // for nsIDOMEventTarget
 #include "nsIDOMKeyEvent.h"             // for nsIDOMKeyEvent
 #include "nsIDOMMouseEvent.h"           // for nsIDOMMouseEvent
 #include "nsIDOMNode.h"                 // for nsIDOMNode
--- a/editor/libeditor/html/TypeInState.cpp
+++ b/editor/libeditor/html/TypeInState.cpp
@@ -11,19 +11,19 @@
 #include "nsAString.h"
 #include "nsDebug.h"
 #include "nsEditProperty.h"
 #include "nsEditor.h"
 #include "nsError.h"
 #include "nsIDOMNode.h"
 #include "nsISelection.h"
 #include "nsISupportsBase.h"
+#include "nsISupportsImpl.h"
 #include "nsReadableUtils.h"
 #include "nsStringFwd.h"
-#include "nsTraceRefcnt.h"
 
 class nsIAtom;
 class nsIDOMDocument;
 
 /********************************************************************
  *                     XPCOM cruft 
  *******************************************************************/
 
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -30,17 +30,17 @@
 #include "nsGkAtoms.h"
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLEditor.h"
 #include "nsIClipboard.h"
 #include "nsIContent.h"
 #include "nsIContentFilter.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMDOMStringList.h"
-#include "nsIDOMDataTransfer.h"
+#include "mozilla/dom/DataTransfer.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLEmbedElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMHTMLIFrameElement.h"
 #include "nsIDOMHTMLImageElement.h"
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -12,17 +12,16 @@
 #include "nsEditor.h"
 #include "nsIEditActionListener.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
 #include "nsISupportsImpl.h"
 #include "nsSelectionState.h"
 #include "nsTArray.h"
 #include "nsTextEditRules.h"
-#include "nsTraceRefcnt.h"
 #include "nscore.h"
 
 class nsHTMLEditor;
 class nsIAtom;
 class nsIDOMCharacterData;
 class nsIDOMDocument;
 class nsIDOMElement;
 class nsIDOMNode;
--- a/editor/txmgr/src/nsTransactionItem.cpp
+++ b/editor/txmgr/src/nsTransactionItem.cpp
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/mozalloc.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
+#include "nsISupportsImpl.h"
 #include "nsITransaction.h"
-#include "nsTraceRefcnt.h"
 #include "nsTransactionItem.h"
 #include "nsTransactionManager.h"
 #include "nsTransactionStack.h"
 
 nsTransactionItem::nsTransactionItem(nsITransaction *aTransaction)
     : mTransaction(aTransaction), mUndoStack(0), mRedoStack(0)
 {
 }
--- a/embedding/tests/winEmbed/Makefile.in
+++ b/embedding/tests/winEmbed/Makefile.in
@@ -32,27 +32,8 @@ LIBS = \
 	$(XPCOM_STANDALONE_GLUE_LDOPTS) \
 	$(NULL)
 
 STL_FLAGS=
 
 OS_LIBS		+= $(call EXPAND_LIBNAME,ole32 comdlg32 shell32 version)
 
 include $(topsrcdir)/config/rules.mk
-
-#
-# Control the default heap size.
-# This is the heap returned by GetProcessHeap().
-# As we use the CRT heap, the default size is too large and wastes VM.
-#
-# The default heap size is 1MB on Win32.
-# The heap will grow if need be.
-#
-# Set it to 256k.  See bug 127069.
-#
-ifndef GNU_CC
-LDFLAGS += /HEAP:0x40000
-endif
-
-# Get rid of console window
-ifdef GNU_CC
-LDFLAGS += -mwindows
-endif
--- a/embedding/tests/winEmbed/moz.build
+++ b/embedding/tests/winEmbed/moz.build
@@ -12,8 +12,22 @@ SOURCES += [
     'winEmbed.cpp',
 ]
 
 XPI_NAME = 'winembed'
 
 DEFINES['XPCOM_GLUE'] = True
 
 RESFILE = 'winEmbed.res'
+
+if CONFIG['GNU_CC']:
+    # Get rid of console window
+    LDFLAGS += ['-mwindows']
+else:
+    # Control the default heap size.
+    # This is the heap returned by GetProcessHeap().
+    # As we use the CRT heap, the default size is too large and wastes VM.
+    #
+    # The default heap size is 1MB on Win32.
+    # The heap will grow if need be.
+    #
+    # Set it to 256k.  See bug 127069.
+    LDFLAGS += ['/HEAP:0x40000']
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -7,17 +7,17 @@
 #include "GLContextCGL.h"
 #include "TextureImageCGL.h"
 #include "nsDebug.h"
 #include "nsIWidget.h"
 #include <OpenGL/gl.h>
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
 #include "gfxQuartzSurface.h"
-#include "gfxPlatform.h"
+#include "gfxPrefs.h"
 #include "gfxFailure.h"
 #include "prenv.h"
 #include "mozilla/Preferences.h"
 #include "GeckoProfiler.h"
 #include "mozilla/gfx/MacIOSurface.h"
 
 using namespace mozilla::gfx;
 
@@ -134,17 +134,17 @@ GLContextCGL::MakeCurrentImpl(bool aForc
     if (mContext) {
         [mContext makeCurrentContext];
         // Use non-blocking swap in "ASAP mode".
         // ASAP mode means that rendering is iterated as fast as possible.
         // ASAP mode is entered when layout.frame_rate=0 (requires restart).
         // If swapInt is 1, then glSwapBuffers will block and wait for a vblank signal.
         // When we're iterating as fast as possible, however, we want a non-blocking
         // glSwapBuffers, which will happen when swapInt==0.
-        GLint swapInt = gfxPlatform::GetPrefLayoutFrameRate() == 0 ? 0 : 1;
+        GLint swapInt = gfxPrefs::LayoutFrameRate() == 0 ? 0 : 1;
         [mContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
     }
     return true;
 }
 
 bool
 GLContextCGL::IsCurrent() {
     return [NSOpenGLContext currentContext] == mContext;
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -9,17 +9,17 @@
 #include "Units.h"                      // for ScreenPoint
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefCounted
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"
 #include <vector>
 
 /**
  * Different elements of a web pages are rendered into separate "layers" before
  * they are flattened into the final image that is brought to the screen.
  * See Layers.h for more informations about layers and why we use retained
  * structures.
--- a/gfx/layers/CopyableCanvasLayer.h
+++ b/gfx/layers/CopyableCanvasLayer.h
@@ -14,17 +14,17 @@
 #include "gfxTypes.h"
 #include "gfxPlatform.h"                // for gfxImageFormat
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 class CanvasClientWebGL;
 
 /**
  * A shared CanvasLayer implementation that supports copying
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -20,17 +20,16 @@
 #include "nsAutoPtr.h"                  // for nsRefPtr, nsAutoPtr, etc
 #include "nsDataHashtable.h"            // for nsDataHashtable
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsHashKeys.h"                 // for nsPtrHashKey
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray_Impl
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 struct LayerPropertiesBase;
 LayerPropertiesBase* CloneLayerTreePropertiesInternal(Layer* aRoot);
 
 static nsIntRect
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -14,17 +14,16 @@
 #include "LayerSorter.h"                // for SortLayersBy3DZOrder
 #include "LayersLogging.h"              // for AppendToString
 #include "ReadbackLayer.h"              // for ReadbackLayer
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "gfx2DGlue.h"
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/Telemetry.h"          // for Accumulate
-#include "mozilla/TelemetryHistogramEnums.h"
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/layers/AsyncPanZoomController.h"
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite
 #include "mozilla/layers/LayersMessages.h"  // for TransformFunction, etc
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -7,16 +7,17 @@
 #include <sys/types.h>                  // for int32_t
 #include <algorithm>                    // for max
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayersImpl.h"            // for ToData
 #include "BufferUnrotate.h"             // for BufferUnrotate
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
 #include "Layers.h"                     // for ThebesLayer, Layer, etc
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxUtils.h"                   // for gfxUtils
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Matrix.h"         // for Matrix
 #include "mozilla/gfx/Point.h"          // for Point, IntPoint
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
@@ -447,17 +448,17 @@ RotatedContentBuffer::BeginPaint(ThebesL
 #if defined(MOZ_GFX_OPTIMIZE_MOBILE) || defined(MOZ_WIDGET_GONK)
       mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
 #else
       if (!aLayer->GetParent() ||
           !aLayer->GetParent()->SupportsComponentAlphaChildren() ||
           !aLayer->Manager()->IsCompositingCheap() ||
           !aLayer->AsShadowableLayer() ||
           !aLayer->AsShadowableLayer()->HasShadow() ||
-          !gfxPlatform::ComponentAlphaEnabled()) {
+          !gfxPrefs::ComponentAlphaEnabled()) {
         mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
       } else {
         result.mContentType = gfxContentType::COLOR;
       }
 #endif
     }
 
     if ((aFlags & PAINT_WILL_RESAMPLE) &&
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -10,20 +10,20 @@
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
 #include "mozilla/gfx/2D.h"             // for DrawTarget, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "LayersTypes.h"
 
 struct nsIntSize;
 
 namespace mozilla {
 namespace gfx {
 class Matrix;
 }
--- a/gfx/layers/basic/BasicColorLayer.cpp
+++ b/gfx/layers/basic/BasicColorLayer.cpp
@@ -12,17 +12,16 @@
 #include "gfx2DGlue.h"
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 class BasicColorLayer : public ColorLayer, public BasicImplData {
 public:
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -11,16 +11,17 @@
 #include "nsIWidget.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Helpers.h"
 #include "gfxUtils.h"
 #include "YCbCrUtils.h"
 #include <algorithm>
 #include "ImageContainer.h"
+#include "gfxPrefs.h"
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"                     // for pixman_f_transform, etc
 
 namespace mozilla {
 using namespace mozilla::gfx;
 
 namespace layers {
 
@@ -613,17 +614,17 @@ BasicCompositor::BeginFrame(const nsIntR
 }
 
 void
 BasicCompositor::EndFrame()
 {
   // Pop aClipRectIn/bounds rect
   mRenderTarget->mDrawTarget->PopClip();
 
-  if (gfxPlatform::GetPlatform()->WidgetUpdateFlashing()) {
+  if (gfxPrefs::WidgetUpdateFlashing()) {
     float r = float(rand()) / RAND_MAX;
     float g = float(rand()) / RAND_MAX;
     float b = float(rand()) / RAND_MAX;
     // We're still clipped to mInvalidRegion, so just fill the bounds.
     mRenderTarget->mDrawTarget->FillRect(ToRect(mInvalidRegion.GetBounds()),
                                          ColorPattern(Color(r, g, b, 0.2f)));
   }
 
--- a/gfx/layers/basic/BasicContainerLayer.h
+++ b/gfx/layers/basic/BasicContainerLayer.h
@@ -5,18 +5,18 @@
 
 #ifndef GFX_BASICCONTAINERLAYER_H
 #define GFX_BASICCONTAINERLAYER_H
 
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "Layers.h"                     // for Layer, ContainerLayer
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR
 struct nsIntRect;
 
 namespace mozilla {
 namespace layers {
 
 class BasicContainerLayer : public ContainerLayer, public BasicImplData {
 public:
   BasicContainerLayer(BasicLayerManager* aManager) :
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -18,17 +18,16 @@
 #endif
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsAutoPtr.h"                  // for nsRefPtr, getter_AddRefs, etc
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for gfxPattern::Release, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "mozilla/gfx/Point.h"          // for IntSize
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 class BasicImageLayer : public ImageLayer, public BasicImplData {
--- a/gfx/layers/basic/BasicImplData.h
+++ b/gfx/layers/basic/BasicImplData.h
@@ -3,17 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_BASICIMPLDATA_H
 #define GFX_BASICIMPLDATA_H
 
 #include "Layers.h"                     // for Layer (ptr only), etc
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "nsDebug.h"                    // for NS_ASSERTION
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "mozilla/gfx/Types.h"
 
 class gfxASurface;
 
 namespace mozilla {
 namespace layers {
 
 class ReadbackProcessor;
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -19,16 +19,17 @@
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxCachedTempSurface.h"       // for gfxCachedTempSurface
 #include "gfxColor.h"                   // for gfxRGBA
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxPoint.h"                   // for gfxIntSize, gfxPoint
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxUtils.h"                   // for gfxUtils
 #include "gfx2DGlue.h"                  // for thebes --> moz2d transition
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/WidgetUtils.h"        // for ScreenRotation
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
@@ -40,17 +41,16 @@
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION, etc
 #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion, etc
 #include "nsTArray.h"                   // for nsAutoTArray
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"                     // for pixman_f_transform, etc
 
 class nsIWidget;
 
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
@@ -538,17 +538,17 @@ BasicLayerManager::AbortTransaction()
   mUsingDefaultTarget = false;
   mInTransaction = false;
 }
 
 static uint16_t sFrameCount = 0;
 void
 BasicLayerManager::RenderDebugOverlay()
 {
-  if (!gfxPlatform::DrawFrameCounter()) {
+  if (!gfxPrefs::DrawFrameCounter()) {
     return;
   }
 
   profiler_set_frame_number(sFrameCount);
 
   uint16_t frameNumber = sFrameCount;
   const uint16_t bitWidth = 3;
   for (size_t i = 0; i < 16; i++) {
@@ -659,17 +659,17 @@ BasicLayerManager::EndTransactionInterna
   // out target is the default target.
 
   return !mTransactionIncomplete;
 }
 
 void
 BasicLayerManager::FlashWidgetUpdateArea(gfxContext *aContext)
 {
-  if (gfxPlatform::GetPlatform()->WidgetUpdateFlashing()) {
+  if (gfxPrefs::WidgetUpdateFlashing()) {
     float r = float(rand()) / RAND_MAX;
     float g = float(rand()) / RAND_MAX;
     float b = float(rand()) / RAND_MAX;
     aContext->SetColor(gfxRGBA(r, g, b, 0.2));
     aContext->Paint();
   }
 }
 
--- a/gfx/layers/basic/BasicLayersImpl.h
+++ b/gfx/layers/basic/BasicLayersImpl.h
@@ -13,17 +13,16 @@
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "ipc/AutoOpenSurface.h"        // for AutoOpenSurface
 #include "mozilla/Attributes.h"         // for MOZ_DELETE, MOZ_STACK_CLASS
 #include "mozilla/Maybe.h"              // for Maybe
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 class AutoMaskData;
 class BasicContainerLayer;
 class Layer;
 
--- a/gfx/layers/basic/BasicThebesLayer.h
+++ b/gfx/layers/basic/BasicThebesLayer.h
@@ -11,18 +11,18 @@
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "gfxPoint.h"                   // for gfxPoint
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/layers/ContentClient.h"  // for ContentClientBasic
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 class gfxContext;
 
 namespace mozilla {
 namespace layers {
 
 class ReadbackProcessor;
 
 class BasicThebesLayer : public ThebesLayer, public BasicImplData {
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -11,18 +11,18 @@
 #include "CopyableCanvasLayer.h"        // for CopyableCanvasLayer
 #include "Layers.h"                     // for CanvasLayer, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/layers/LayersMessages.h"  // for CanvasLayerAttributes, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
 class ShadowableLayer;
 
 class ClientCanvasLayer : public CopyableCanvasLayer,
--- a/gfx/layers/client/ClientColorLayer.cpp
+++ b/gfx/layers/client/ClientColorLayer.cpp
@@ -7,17 +7,16 @@
 #include "Layers.h"                     // for ColorLayer, etc
 #include "mozilla/layers/LayersMessages.h"  // for ColorLayerAttributes, etc
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 class ClientColorLayer : public ColorLayer, 
                          public ClientLayer {
--- a/gfx/layers/client/ClientContainerLayer.h
+++ b/gfx/layers/client/ClientContainerLayer.h
@@ -4,22 +4,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_CLIENTCONTAINERLAYER_H
 #define GFX_CLIENTCONTAINERLAYER_H
 
 #include <stdint.h>                     // for uint32_t
 #include "ClientLayerManager.h"         // for ClientLayerManager, etc
 #include "Layers.h"                     // for Layer, ContainerLayer, etc
-#include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsAutoTArray
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 class ShadowableLayer;
 
 class ClientContainerLayer : public ContainerLayer,
                              public ClientLayer
@@ -53,17 +53,17 @@ public:
       if (GetEffectiveVisibleRegion().GetNumRects() != 1 ||
           !(GetContentFlags() & Layer::CONTENT_OPAQUE))
       {
         gfx::Matrix transform;
         if (HasOpaqueAncestorLayer(this) &&
             GetEffectiveTransform().Is2D(&transform) &&
             !gfx::ThebesMatrix(transform).HasNonIntegerTranslation()) {
           SetSupportsComponentAlphaChildren(
-            gfxPlatform::ComponentAlphaEnabled());
+            gfxPrefs::ComponentAlphaEnabled());
         }
       }
     } else {
       SetSupportsComponentAlphaChildren(
         (GetContentFlags() & Layer::CONTENT_OPAQUE) ||
         (GetParent() && GetParent()->SupportsComponentAlphaChildren()));
     }
 
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -13,17 +13,16 @@
 #include "mozilla/layers/ImageClient.h"  // for ImageClient, etc
 #include "mozilla/layers/LayersMessages.h"  // for ImageLayerAttributes, etc
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr, getter_AddRefs, etc
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 class ClientImageLayer : public ImageLayer, 
                          public ClientLayer {
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -16,17 +16,16 @@
 #include "mozilla/layers/LayersTypes.h"  // for BufferMode, LayersBackend, etc
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ABORT_IF_FALSE
 #include "nsISupportsImpl.h"            // for Layer::Release, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsTArray.h"                   // for nsTArray
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR
 #include "nscore.h"                     // for nsAString
 
 class nsIWidget;
 
 namespace mozilla {
 namespace layers {
 
 class ClientThebesLayer;
--- a/gfx/layers/client/ClientThebesLayer.cpp
+++ b/gfx/layers/client/ClientThebesLayer.cpp
@@ -6,16 +6,17 @@
 #include "ClientThebesLayer.h"
 #include "ClientTiledThebesLayer.h"     // for ClientTiledThebesLayer
 #include <stdint.h>                     // for uint32_t
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
 #include "client/ClientLayerManager.h"  // for ClientLayerManager, etc
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxContext.h"                 // for gfxContext
 #include "gfxRect.h"                    // for gfxRect
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/Matrix.h"         // for Matrix
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float, etc
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/Preferences.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
@@ -166,17 +167,17 @@ ClientLayerManager::CreateThebesLayer()
 already_AddRefed<ThebesLayer>
 ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint)
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   if (
 #ifdef MOZ_B2G
       aHint == SCROLLABLE &&
 #endif
-      gfxPlatform::GetPrefLayersEnableTiles() && AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL) {
+      gfxPrefs::LayersTilesEnabled() && AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL) {
     nsRefPtr<ClientTiledThebesLayer> layer =
       new ClientTiledThebesLayer(this);
     CREATE_SHADOW(Thebes);
     return layer.forget();
   } else
   {
     nsRefPtr<ClientThebesLayer> layer =
       new ClientThebesLayer(this);
--- a/gfx/layers/client/ClientThebesLayer.h
+++ b/gfx/layers/client/ClientThebesLayer.h
@@ -9,18 +9,18 @@
 #include "ClientLayerManager.h"         // for ClientLayerManager, etc
 #include "Layers.h"                     // for ThebesLayer, etc
 #include "RotatedBuffer.h"              // for RotatedContentBuffer, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/layers/ContentClient.h"  // for ContentClient
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "mozilla/layers/PLayerTransaction.h" // for ThebesLayerAttributes
 
 class gfxContext;
 
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
--- a/gfx/layers/client/ClientTiledThebesLayer.cpp
+++ b/gfx/layers/client/ClientTiledThebesLayer.cpp
@@ -3,24 +3,25 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ClientTiledThebesLayer.h"
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for ScreenIntRect, CSSPoint, etc
 #include "ClientLayerManager.h"         // for ClientLayerManager, etc
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxRect.h"                    // for gfxRect
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Rect.h"           // for Rect, RectTyped
 #include "mozilla/layers/LayersMessages.h"
 #include "mozilla/mozalloc.h"           // for operator delete, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRect.h"                     // for nsIntRect
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 
 ClientTiledThebesLayer::ClientTiledThebesLayer(ClientLayerManager* const aManager)
   : ThebesLayer(aManager,
                 static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
@@ -171,18 +172,18 @@ ClientTiledThebesLayer::RenderLayer()
   // Only paint the mask layer on the first transaction.
   if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
 
   // Fast path for no progressive updates, no low-precision updates and no
   // critical display-port set, or no display-port set.
   const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();
-  if ((!gfxPlatform::UseProgressiveTilePainting() &&
-       !gfxPlatform::UseLowPrecisionBuffer() &&
+  if ((!gfxPrefs::UseProgressiveTilePainting() &&
+       !gfxPrefs::UseLowPrecisionBuffer() &&
        parentMetrics.mCriticalDisplayPort.IsEmpty()) ||
        parentMetrics.mDisplayPort.IsEmpty()) {
     mValidRegion = mVisibleRegion;
 
     NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
 
     mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
                                              callback, data);
@@ -207,17 +208,17 @@ ClientTiledThebesLayer::RenderLayer()
       // Make sure that tiles that fall outside of the critical displayport are
       // discarded on the first update.
       mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
     }
   }
 
   nsIntRegion lowPrecisionInvalidRegion;
   if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
-    if (gfxPlatform::UseLowPrecisionBuffer()) {
+    if (gfxPrefs::UseLowPrecisionBuffer()) {
       // Calculate the invalid region for the low precision buffer
       lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
 
       // Remove the valid region from the low precision valid region (we don't
       // validate this part of the low precision buffer).
       lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
     }
 
@@ -227,17 +228,17 @@ ClientTiledThebesLayer::RenderLayer()
       EndPaint(true);
       return;
     }
   }
 
   if (!invalidRegion.IsEmpty() && mPaintData.mLowPrecisionPaintCount == 0) {
     bool updatedBuffer = false;
     // Only draw progressively when the resolution is unchanged.
-    if (gfxPlatform::UseProgressiveTilePainting() &&
+    if (gfxPrefs::UseProgressiveTilePainting() &&
         !ClientManager()->HasShadowTarget() &&
         mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
       // Store the old valid region, then clear it before painting.
       // We clip the old valid region to the visible region, as it only gets
       // used to decide stale content (currently valid and previously visible)
       nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
       oldValidRegion.And(oldValidRegion, mVisibleRegion);
       if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -10,17 +10,17 @@
 #include <vector>                       // for vector
 #include <map>                          // for map
 #include "mozilla/Assertions.h"         // for MOZ_CRASH
 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefCounted
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "gfxASurface.h"                // for gfxContentType
 
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
 class DeprecatedTextureClient;
 class TextureClient;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -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/. */
 
 #include "mozilla/layers/ContentClient.h"
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "gfxColor.h"                   // for gfxRGBA
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxPoint.h"                   // for gfxIntSize, gfxPoint
 #include "gfxTeeSurface.h"              // for gfxTeeSurface
 #include "gfxUtils.h"                   // for gfxUtils
 #include "ipc/ShadowLayers.h"           // for ShadowLayerForwarder
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/gfx/2D.h"             // for DrawTarget, Factory
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
@@ -1095,17 +1096,17 @@ ContentClientIncremental::BeginPaintBuff
         // going to be visible. We'll move it.
         destBufferRect = nsIntRect(neededRegion.GetBounds().TopLeft(), mBufferRect.Size());
       }
     } else {
       destBufferRect = neededRegion.GetBounds();
     }
 
     if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
-      if (!gfxPlatform::ComponentAlphaEnabled() ||
+      if (!gfxPrefs::ComponentAlphaEnabled() ||
           !aLayer->GetParent() ||
           !aLayer->GetParent()->SupportsComponentAlphaChildren()) {
         mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
       } else {
         contentType = gfxContentType::COLOR;
       }
     }
 
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -16,17 +16,17 @@
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "ImageContainer.h"             // for PlanarYCbCrImage, etc
 #include "mozilla/gfx/2D.h"
 
 #ifdef MOZ_ANDROID_OMTC
 #  include "gfxReusableImageSurfaceWrapper.h"
 #  include "gfxImageSurface.h"
 #else
 #  include "gfxReusableSharedImageSurfaceWrapper.h"
@@ -103,17 +103,17 @@ private:
     AddRef();
   }
   void ReleaseIPDLReference() {
     MOZ_ASSERT(mIPCOpen == true);
     mIPCOpen = false;
     Release();
   }
 
-  CompositableForwarder* mForwarder;
+  RefPtr<CompositableForwarder> mForwarder;
   TextureClientData* mTextureData;
   TextureClient* mTextureClient;
   bool mIPCOpen;
 
   friend class TextureClient;
 };
 
 void
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -6,16 +6,17 @@
 #include "mozilla/layers/TiledContentClient.h"
 #include <math.h>                       // for ceil, ceilf, floor
 #include "ClientTiledThebesLayer.h"     // for ClientTiledThebesLayer
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
 #include "ClientLayerManager.h"         // for ClientLayerManager
 #include "CompositorChild.h"            // for CompositorChild
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxRect.h"                    // for gfxRect
 #include "mozilla/MathAlgorithms.h"     // for Abs
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for gfxContext::AddRef, etc
@@ -78,17 +79,18 @@ namespace layers {
 TiledContentClient::TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
                                        ClientLayerManager* aManager)
   : CompositableClient(aManager->AsShadowForwarder())
   , mTiledBuffer(aThebesLayer, aManager, &mSharedFrameMetricsHelper)
   , mLowPrecisionTiledBuffer(aThebesLayer, aManager, &mSharedFrameMetricsHelper)
 {
   MOZ_COUNT_CTOR(TiledContentClient);
 
-  mLowPrecisionTiledBuffer.SetResolution(gfxPlatform::GetLowPrecisionResolution());
+  // The preference is int in "thousands", so adjust:
+  mLowPrecisionTiledBuffer.SetResolution(gfxPrefs::LowPrecisionResolution()/1000.f);
 }
 
 void
 TiledContentClient::LockCopyAndWrite(TiledBufferType aType)
 {
   BasicTiledLayerBuffer* buffer = aType == LOW_PRECISION_TILED_BUFFER
     ? &mLowPrecisionTiledBuffer
     : &mTiledBuffer;
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -16,21 +16,21 @@
 #include "gfxTypes.h"
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_DTOR
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_DTOR
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "gfxReusableSurfaceWrapper.h"
 
 class gfxImageSurface;
 
 namespace mozilla {
 namespace layers {
 
--- a/gfx/layers/composite/APZCTreeManager.h
+++ b/gfx/layers/composite/APZCTreeManager.h
@@ -11,18 +11,17 @@
 #include "Units.h"                      // for CSSPoint, CSSRect, etc
 #include "gfxPoint.h"                   // for gfxPoint
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
 #include "mozilla/EventForwards.h"      // for WidgetInputEvent, nsEventStatus
 #include "mozilla/Monitor.h"            // for Monitor
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
-#include "nsISupportsImpl.h"
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "mozilla/Vector.h"             // for mozilla::Vector
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 
 class gfx3DMatrix;
 template <class E> class nsTArray;
 
 namespace mozilla {
 class InputData;
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -12,17 +12,16 @@
 #include "mozilla/Attributes.h"         // for MOZ_DELETE, MOZ_FINAL, etc
 #include "mozilla/RefPtr.h"             // for RefCounted
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 #include "mozilla/dom/ScreenOrientation.h"  // for ScreenOrientation
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"            // for LayerManager::AddRef, etc
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 class Layer;
 class LayerManagerComposite;
 class AutoResolveRefLayers;
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -11,19 +11,19 @@
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsString.h"                   // for nsAutoCString
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 
 CanvasLayerComposite::CanvasLayerComposite(LayerManagerComposite* aManager)
   : CanvasLayer(aManager, nullptr)
   , LayerComposite(aManager)
--- a/gfx/layers/composite/ColorLayerComposite.h
+++ b/gfx/layers/composite/ColorLayerComposite.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_ColorLayerComposite_H
 #define GFX_ColorLayerComposite_H
 
 #include "Layers.h"                     // for ColorLayer, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite, etc
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 
 struct nsIntPoint;
 struct nsIntRect;
 
 namespace mozilla {
 namespace layers {
 
 class CompositableHost;
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -9,17 +9,17 @@
 #include "ContentHost.h"                // for ContentHostDoubleBuffered, etc
 #include "Effects.h"                    // for EffectMask, Effect, etc
 #include "ImageHost.h"                  // for DeprecatedImageHostBuffered, etc
 #include "TiledContentHost.h"           // for TiledContentHost
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_WARNING
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "gfxPlatform.h"                // for gfxPlatform
 
 namespace mozilla {
 namespace layers {
 
 class Matrix4x4;
 class Compositor;
 
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -5,37 +5,37 @@
 
 #include "ContainerLayerComposite.h"
 #include <algorithm>                    // for min
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for LayerRect, LayerPixel, etc
 #include "gfx2DGlue.h"                  // for ToMatrix4x4
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxImageSurface.h"            // for gfxImageSurface
-#include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point, IntPoint
 #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor, etc
 #include "mozilla/layers/CompositorTypes.h"  // for DIAGNOSTIC_CONTAINER
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsAutoTArray
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include <vector>
 
 namespace mozilla {
 namespace layers {
 
 // HasOpaqueAncestorLayer and ContainerRender are shared between RefLayer and ContainerLayer
 static bool
 HasOpaqueAncestorLayer(Layer* aLayer)
@@ -266,21 +266,21 @@ ContainerRender(ContainerT* aContainer,
       const gfx::Matrix4x4& transform3D = aContainer->GetEffectiveTransform();
       gfx::Matrix transform;
       // If we have an opaque ancestor layer, then we can be sure that
       // all the pixels we draw into are either opaque already or will be
       // covered by something opaque. Otherwise copying up the background is
       // not safe.
       if (HasOpaqueAncestorLayer(aContainer) &&
           transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) {
-        surfaceCopyNeeded = gfxPlatform::ComponentAlphaEnabled();
+        surfaceCopyNeeded = gfxPrefs::ComponentAlphaEnabled();
         sourcePoint.x += transform._31;
         sourcePoint.y += transform._32;
         aContainer->mSupportsComponentAlphaChildren
-          = gfxPlatform::ComponentAlphaEnabled();
+          = gfxPrefs::ComponentAlphaEnabled();
       }
     }
 
     sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin();
     if (surfaceCopyNeeded) {
       surface = compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint);
     } else {
       surface = compositor->CreateRenderTarget(surfaceRect, mode);
@@ -343,17 +343,17 @@ ContainerRender(ContainerT* aContainer,
         gfx::Rect aRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
         compositor->clearFBRect(&aRect);
         layerToRender->SetClearFB(false);
       }
     } else {
       layerToRender->RenderLayer(clipRect);
     }
 
-    if (gfxPlatform::GetPrefLayersScrollGraph()) {
+    if (gfxPrefs::LayersScrollGraph()) {
       DrawVelGraph(clipRect, aManager, layerToRender->GetLayer());
     }
     // invariant: our GL context should be current here, I don't think we can
     // assert it though
   }
 
   if (needsSurface) {
     // Unbind the current surface and rebind the previous one.
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -21,21 +21,21 @@
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/LayersTypes.h"  // for etc
 #include "mozilla/layers/TextureHost.h"  // for DeprecatedTextureHost
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsAutoPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsTArray
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nscore.h"                     // for nsACString
 
 namespace mozilla {
 namespace gfx {
 class Matrix4x4;
 }
 namespace layers {
 class Compositor;
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -15,20 +15,20 @@
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/layers/TextureHost.h"  // for DeprecatedTextureHost, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsString.h"                   // for nsAutoCString
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 ImageLayerComposite::ImageLayerComposite(LayerManagerComposite* aManager)
   : ImageLayer(aManager, nullptr)
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -16,17 +16,17 @@
 #include "GeckoProfiler.h"              // for profiler_set_frame_number, etc
 #include "ImageLayerComposite.h"        // for ImageLayerComposite
 #include "Layers.h"                     // for Layer, ContainerLayer, etc
 #include "ThebesLayerComposite.h"       // for ThebesLayerComposite
 #include "TiledLayerBuffer.h"           // for TiledLayerComposer
 #include "Units.h"                      // for ScreenIntRect
 #include "gfx2DGlue.h"                  // for ToMatrix4x4
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
-#include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #ifdef XP_MACOSX
 #include "gfxPlatformMac.h"
 #endif
 #include "gfxRect.h"                    // for gfxRect
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
@@ -384,28 +384,28 @@ void FPSState::DrawFPS(TimeStamp aNow,
   DrawDigits(txnFps, FontWidth * 4, 0, aCompositor, effectChain);
   DrawDigits(aFillRatio, FontWidth * 8, 0, aCompositor, effectChain);
 }
 
 static uint16_t sFrameCount = 0;
 void
 LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
 {
-  if (gfxPlatform::GetPrefLayersDrawFPS()) {
+  if (gfxPrefs::LayersDrawFPS()) {
     if (!mFPS) {
       mFPS = new FPSState();
     }
 
     float fillRatio = mCompositor->GetFillRatio();
     mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mCompositor);
   } else {
     mFPS = nullptr;
   }
 
-  if (gfxPlatform::DrawFrameCounter()) {
+  if (gfxPrefs::DrawFrameCounter()) {
     profiler_set_frame_number(sFrameCount);
 
     uint16_t frameNumber = sFrameCount;
     const uint16_t bitWidth = 3;
     float opacity = 1.0;
     gfx::Rect clip(0,0, bitWidth*16, bitWidth);
     for (size_t i = 0; i < 16; i++) {
 
@@ -432,27 +432,27 @@ void
 LayerManagerComposite::Render()
 {
   PROFILER_LABEL("LayerManagerComposite", "Render");
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
-  if (gfxPlatform::GetPrefLayersDump()) {
+  if (gfxPrefs::LayersDump()) {
     this->Dump();
   }
 
   /** Our more efficient but less powerful alter ego, if one is available. */
   nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
 
   if (composer2D && composer2D->TryRender(mRoot, mWorldMatrix)) {
     if (mFPS) {
       double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
-      if (gfxPlatform::GetPrefLayersDrawFPS()) {
+      if (gfxPrefs::LayersDrawFPS()) {
         printf_stderr("HWComposer: FPS is %g\n", fps);
       }
     }
     mCompositor->EndFrameForExternalComposition(mWorldMatrix);
     return;
   }
 
   {
@@ -650,17 +650,17 @@ GetDisplayportCoverage(const CSSRect& aD
 }
 #endif // MOZ_ANDROID_OMTC
 
 float
 LayerManagerComposite::ComputeRenderIntegrity()
 {
   // We only ever have incomplete rendering when progressive tiles are enabled.
   Layer* root = GetRoot();
-  if (!gfxPlatform::UseProgressiveTilePainting() || !root) {
+  if (!gfxPrefs::UseProgressiveTilePainting() || !root) {
     return 1.f;
   }
 
   const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
   nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
                        rootMetrics.mCompositionBounds.y,
                        rootMetrics.mCompositionBounds.width,
                        rootMetrics.mCompositionBounds.height);
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -15,18 +15,18 @@
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface
 #include "mozilla/gfx/Point.h"          // for IntSize, IntPoint
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayerRenderState, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nscore.h"                     // for nsACString
 #include "mozilla/layers/AtomicRefCountedWithFinalize.h"
 
 class gfxImageSurface;
 class gfxReusableSurfaceWrapper;
 struct nsIntPoint;
 struct nsIntSize;
 struct nsIntRect;
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -15,22 +15,22 @@
 #include "mozilla/gfx/Rect.h"           // for RoundedToInt, Rect
 #include "mozilla/gfx/Types.h"          // for Filter::Filter::LINEAR
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ContentHost.h"  // for ContentHost
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsMathUtils.h"                // for NS_lround
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsSize.h"                     // for nsIntSize
 #include "nsString.h"                   // for nsAutoCString
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "GeckoProfiler.h"
 
 namespace mozilla {
 namespace layers {
 
 class TiledLayerComposer;
 
 ThebesLayerComposite::ThebesLayerComposite(LayerManagerComposite *aManager)
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -9,16 +9,17 @@
 #include "CompositorD3D11Shaders.h"
 
 #include "gfxWindowsPlatform.h"
 #include "nsIWidget.h"
 #include "mozilla/layers/ImageHost.h"
 #include "mozilla/layers/ContentHost.h"
 #include "mozilla/layers/Effects.h"
 #include "nsWindowsHelpers.h"
+#include "gfxPrefs.h"
 
 #ifdef MOZ_METRO
 #include <DXGI1_2.h>
 #endif
 
 namespace mozilla {
 
 using namespace gfx;
@@ -220,17 +221,17 @@ CompositorD3D11::Initialize()
       D3D11_COLOR_WRITE_ENABLE_ALL
     };
     blendDesc.RenderTarget[0] = rtBlendNonPremul;
     hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mNonPremulBlendState));
     if (FAILED(hr)) {
       return false;
     }
 
-    if (gfxPlatform::ComponentAlphaEnabled()) {
+    if (gfxPrefs::ComponentAlphaEnabled()) {
       D3D11_RENDER_TARGET_BLEND_DESC rtBlendComponent = {
         TRUE,
         D3D11_BLEND_ONE,
         D3D11_BLEND_INV_SRC1_COLOR,
         D3D11_BLEND_OP_ADD,
         D3D11_BLEND_ONE,
         D3D11_BLEND_INV_SRC_ALPHA,
         D3D11_BLEND_OP_ADD,
@@ -628,17 +629,17 @@ CompositorD3D11::DrawQuad(const gfx::Rec
                                         nullptr, byRef(views[2]));
 
       ID3D11ShaderResourceView* srViews[3] = { views[0], views[1], views[2] };
       mContext->PSSetShaderResources(0, 3, srViews);
     }
     break;
   case EFFECT_COMPONENT_ALPHA:
     {
-      MOZ_ASSERT(gfxPlatform::ComponentAlphaEnabled());
+      MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       MOZ_ASSERT(mAttachments->mComponentBlendState);
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
 
       TextureSourceD3D11* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D11();
       TextureSourceD3D11* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D11();
 
       if (!sourceOnWhite || !sourceOnBlack) {
@@ -880,17 +881,17 @@ CompositorD3D11::CreateShaders()
   if (FAILED(hr)) { \
     return false; \
   }
 
   LOAD_PIXEL_SHADER(SolidColorShader);
   LOAD_PIXEL_SHADER(RGBShader);
   LOAD_PIXEL_SHADER(RGBAShader);
   LOAD_PIXEL_SHADER(YCbCrShader);
-  if (gfxPlatform::ComponentAlphaEnabled()) {
+  if (gfxPrefs::ComponentAlphaEnabled()) {
     LOAD_PIXEL_SHADER(ComponentAlphaShader);
   }
 
 #undef LOAD_PIXEL_SHADER
 
   hr = mDevice->CreatePixelShader(RGBAShaderMask3D,
                                   sizeof(RGBAShaderMask3D),
                                   nullptr,
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/layers/ImageHost.h"
 #include "mozilla/layers/ContentHost.h"
 #include "mozilla/layers/Effects.h"
 #include "nsWindowsHelpers.h"
 #include "Nv3DVUtils.h"
 #include "gfxFailure.h"
 #include "mozilla/layers/PCompositorParent.h"
 #include "mozilla/layers/LayerManagerComposite.h"
+#include "gfxPrefs.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 CompositorD3D9::CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget)
   : Compositor(aParent)
@@ -398,17 +399,17 @@ CompositorD3D9::DrawQuad(const gfx::Rect
       device()->SetTexture(Y, sourceY->GetD3D9Texture());
       device()->SetTexture(Cb, sourceCb->GetD3D9Texture());
       device()->SetTexture(Cr, sourceCr->GetD3D9Texture());
       maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
     }
     break;
   case EFFECT_COMPONENT_ALPHA:
     {
-      MOZ_ASSERT(gfxPlatform::ComponentAlphaEnabled());
+      MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceD3D9* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D9();
       TextureSourceD3D9* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D9();
 
       Rect textureCoords = effectComponentAlpha->mTextureCoords;
       d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
                                            ShaderConstantRect(
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -10,17 +10,17 @@
 #include "ImageLayerD3D9.h"
 #include "ColorLayerD3D9.h"
 #include "CanvasLayerD3D9.h"
 #include "ReadbackLayerD3D9.h"
 #include "gfxWindowsPlatform.h"
 #include "nsIGfxInfo.h"
 #include "nsServiceManagerUtils.h"
 #include "gfxFailure.h"
-#include "mozilla/Preferences.h"
+#include "gfxPrefs.h"
 
 #include "gfxCrashReporterUtils.h"
 
 namespace mozilla {
 namespace layers {
 
 LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
   : mWidget(aWidget)
@@ -36,17 +36,17 @@ LayerManagerD3D9::~LayerManagerD3D9()
 }
 
 bool
 LayerManagerD3D9::Initialize(bool force)
 {
   ScopedGfxFeatureReporter reporter("D3D9 Layers", force);
 
   /* XXX: this preference and blacklist code should move out of the layer manager */
-  bool forceAccelerate = gfxPlatform::GetPrefLayersAccelerationForceEnabled();
+  bool forceAccelerate = gfxPrefs::LayersAccelerationForceEnabled();
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     int32_t status;
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
       if (status != nsIGfxInfo::FEATURE_NO_INFO && !forceAccelerate)
       {
         NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -14,17 +14,17 @@
 #include "FrameMetrics.h"               // for FrameMetrics, etc
 #include "GestureEventListener.h"       // for GestureEventListener
 #include "InputData.h"                  // for MultiTouchInput, etc
 #include "LayerTransactionParent.h"     // for LayerTransactionParent
 #include "Units.h"                      // for CSSRect, CSSPoint, etc
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/task.h"                  // for NewRunnableMethod, etc
 #include "base/tracked.h"               // for FROM_HERE
-#include "gfxPlatform.h"                // for gfxPlatform::UseProgressiveTilePainting
+#include "gfxPrefs.h"                   // for gfxPrefs::UseProgressiveTilePainting
 #include "gfxTypes.h"                   // for gfxFloat
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/BasicEvents.h"        // for Modifiers, MODIFIER_*
 #include "mozilla/ClearOnShutdown.h"    // for ClearOnShutdown
 #include "mozilla/Constants.h"          // for M_PI
 #include "mozilla/EventForwards.h"      // for nsEventStatus_*
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitorAutoEnter, etc
@@ -44,24 +44,23 @@
 #include "mozilla/layers/TaskThrottler.h"  // for TaskThrottler
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "mozilla/unused.h"             // for unused
 #include "nsAlgorithm.h"                // for clamped
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsIDOMWindowUtils.h"          // for nsIDOMWindowUtils
-#include "nsISupportsImpl.h"
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsMathUtils.h"                // for NS_hypot
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsStyleConsts.h"
 #include "nsStyleStruct.h"              // for nsTimingFunction
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 #include "nsThreadUtils.h"              // for NS_IsMainThread
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "SharedMemoryBasic.h"          // for SharedMemoryBasic
 
 // #define APZC_ENABLE_RENDERTRACE
 
 #define APZC_LOG(...)
 // #define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
 #define APZC_LOG_FM(fm, prefix, ...) \
   APZC_LOG(prefix ":" \
@@ -284,21 +283,16 @@ static int gAsyncScrollTimeout = 300;
 static bool gCrossSlideEnabled = false;
 
 /** 
  * Pref that allows or disallows checkerboarding
  */
 static bool gAllowCheckerboarding = true;
 
 /**
- * Pref that enables progressive tile painting
- */
-static bool gUseProgressiveTilePainting = false;
-
-/**
  * Pref that enables enlarging of the displayport along one axis when its
  * opposite's scrollable rect is within the composition bounds. That is, we
  * don't need to pad the opposite axis.
  */
 static bool gEnlargeDisplayPortWhenOnlyScrollable = false;
 
 /**
  * Is aAngle within the given threshold of the horizontal axis?
@@ -420,17 +414,16 @@ AsyncPanZoomController::InitializeGlobal
   Preferences::AddFloatVarCache(&gYSkateSizeMultiplier, "apz.y_skate_size_multiplier", gYSkateSizeMultiplier);
   Preferences::AddFloatVarCache(&gXStationarySizeMultiplier, "apz.x_stationary_size_multiplier", gXStationarySizeMultiplier);
   Preferences::AddFloatVarCache(&gYStationarySizeMultiplier, "apz.y_stationary_size_multiplier", gYStationarySizeMultiplier);
   Preferences::AddIntVarCache(&gAsyncScrollThrottleTime, "apz.asyncscroll.throttle", gAsyncScrollThrottleTime);
   Preferences::AddIntVarCache(&gAsyncScrollTimeout, "apz.asyncscroll.timeout", gAsyncScrollTimeout);
   Preferences::AddBoolVarCache(&gCrossSlideEnabled, "apz.cross_slide.enabled", gCrossSlideEnabled);
   Preferences::AddIntVarCache(&gAxisLockMode, "apz.axis_lock_mode", gAxisLockMode);
   Preferences::AddBoolVarCache(&gAllowCheckerboarding, "apz.allow-checkerboarding", gAllowCheckerboarding);
-  gUseProgressiveTilePainting = gfxPlatform::UseProgressiveTilePainting();
   Preferences::AddBoolVarCache(&gEnlargeDisplayPortWhenOnlyScrollable, "apz.enlarge_displayport_when_only_scrollable",
     gEnlargeDisplayPortWhenOnlyScrollable);
 
   gComputedTimingFunction = new ComputedTimingFunction();
   gComputedTimingFunction->Init(
     nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
   ClearOnShutdown(&gComputedTimingFunction);
 }
@@ -2051,32 +2044,32 @@ ScrollableLayerGuid AsyncPanZoomControll
 
 void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics()
 {
   mMonitor.AssertCurrentThreadIn();
 
   FrameMetrics* frame = mSharedFrameMetricsBuffer ?
       static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory()) : nullptr;
 
-  if (gUseProgressiveTilePainting && frame && mSharedLock) {
+  if (frame && mSharedLock && gfxPrefs::UseProgressiveTilePainting()) {
     mSharedLock->Lock();
     *frame = mFrameMetrics;
     mSharedLock->Unlock();
   }
 }
 
 void AsyncPanZoomController::ShareCompositorFrameMetrics() {
 
   PCompositorParent* compositor =
     (mCrossProcessCompositorParent ? mCrossProcessCompositorParent : mCompositorParent.get());
 
   // Only create the shared memory buffer if it hasn't already been created,
   // we are using progressive tile painting, and we have a
   // compositor to pass the shared memory back to the content process/thread.
-  if (!mSharedFrameMetricsBuffer && gUseProgressiveTilePainting && compositor) {
+  if (!mSharedFrameMetricsBuffer && compositor && gfxPrefs::UseProgressiveTilePainting()) {
 
     // Create shared memory and initialize it with the current FrameMetrics value
     mSharedFrameMetricsBuffer = new ipc::SharedMemoryBasic;
     FrameMetrics* frame = nullptr;
     mSharedFrameMetricsBuffer->Create(sizeof(FrameMetrics));
     mSharedFrameMetricsBuffer->Map(sizeof(FrameMetrics));
     frame = static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory());
 
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -11,18 +11,18 @@
 #include "base/process_util.h"          // for OpenProcessHandle
 #include "base/task.h"                  // for NewRunnableMethod, etc
 #include "base/tracked.h"               // for FROM_HERE
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/PLayerTransactionChild.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsIObserver.h"                // for nsIObserver
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop, etc
 #include "FrameLayerBuilder.h"
 
 using mozilla::layers::LayerTransactionChild;
 
 namespace mozilla {
 namespace layers {
 
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -15,16 +15,17 @@
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/process.h"               // for ProcessHandle
 #include "base/process_util.h"          // for OpenProcessHandle
 #include "base/task.h"                  // for CancelableTask, etc
 #include "base/thread.h"                // for Thread
 #include "base/tracked.h"               // for FROM_HERE
 #include "gfxContext.h"                 // for gfxContext
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "ipc/ShadowLayersManager.h"    // for ShadowLayersManager
 #include "mozilla/AutoRestore.h"        // for AutoRestore
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/gfx/2D.h"          // for DrawTarget
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/ipc/Transport.h"      // for Transport
 #include "mozilla/layers/APZCTreeManager.h"  // for APZCTreeManager
 #include "mozilla/layers/AsyncCompositionManager.h"
@@ -33,21 +34,21 @@
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/layers/PLayerTransactionParent.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ABORT_IF_FALSE, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsIWidget.h"                  // for nsIWidget
 #include "nsRect.h"                     // for nsIntRect
 #include "nsTArray.h"                   // for nsTArray
 #include "nsThreadUtils.h"              // for NS_IsMainThread
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
 #ifdef XP_WIN
 #include "mozilla/layers/CompositorD3D11.h"
 #include "mozilla/layers/CompositorD3D9.h"
 #endif
 #include "GeckoProfiler.h"
 #include "mozilla/ipc/ProtocolTypes.h"
 
@@ -547,20 +548,20 @@ CompositorParent::NotifyShadowTreeTransa
 
 // Used when layout.frame_rate is -1. Needs to be kept in sync with
 // DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
 static const int32_t kDefaultFrameRate = 60;
 
 static int32_t
 CalculateCompositionFrameRate()
 {
-  int32_t compositionFrameRatePref = gfxPlatform::GetPrefLayersCompositionFrameRate();
+  int32_t compositionFrameRatePref = gfxPrefs::LayersCompositionFrameRate();
   if (compositionFrameRatePref < 0) {
     // Use the same frame rate for composition as for layout.
-    int32_t layoutFrameRatePref = gfxPlatform::GetPrefLayoutFrameRate();
+    int32_t layoutFrameRatePref = gfxPrefs::LayoutFrameRate();
     if (layoutFrameRatePref < 0) {
       // TODO: The main thread frame scheduling code consults the actual
       // monitor refresh rate in this case. We should do the same.
       return kDefaultFrameRate;
     }
     return layoutFrameRatePref;
   }
   return compositionFrameRatePref;
@@ -666,17 +667,17 @@ CompositorParent::CompositeToTarget(Draw
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   if (mExpectedComposeTime + TimeDuration::FromMilliseconds(15) < TimeStamp::Now()) {
     printf_stderr("Compositor: Composite took %i ms.\n",
                   15 + (int)(TimeStamp::Now() - mExpectedComposeTime).ToMilliseconds());
   }
 #endif
 
   // 0 -> Full-tilt composite
-  if (gfxPlatform::GetPrefLayersCompositionFrameRate() == 0) {
+  if (gfxPrefs::LayersCompositionFrameRate() == 0) {
     // Special full-tilt composite mode for performance testing
     ScheduleComposition();
   }
 
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END);
 }
 
 void
@@ -723,17 +724,17 @@ CompositorParent::ShadowLayersUpdated(La
 {
   if (!aIsFirstPaint &&
       !mCompositionManager->IsFirstPaint() &&
       mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
     if (mForceCompositionTask != nullptr) {
       mForceCompositionTask->Cancel();
     }
     mForceCompositionTask = NewRunnableMethod(this, &CompositorParent::ForceComposition);
-    ScheduleTask(mForceCompositionTask, gfxPlatform::GetPlatform()->GetOrientationSyncMillis());
+    ScheduleTask(mForceCompositionTask, gfxPrefs::OrientationSyncMillis());
   }
 
   // Instruct the LayerManager to update its render bounds now. Since all the orientation
   // change, dimension change would be done at the stage, update the size here is free of
   // race condition.
   mLayerManager->UpdateRenderBounds(aTargetConfig.clientBounds());
 
   mCompositionManager->Updated(aIsFirstPaint, aTargetConfig);
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -32,17 +32,16 @@
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsCoord.h"                    // for NSAppUnitsToFloatPixels
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsISupportsImpl.h"            // for Layer::Release, etc
 #include "nsLayoutUtils.h"              // for nsLayoutUtils
 #include "nsMathUtils.h"                // for NS_round
 #include "nsPoint.h"                    // for nsPoint
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "GeckoProfiler.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/AsyncCompositionManager.h"
 
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 using mozilla::layout::RenderFrameParent;
 
@@ -392,17 +391,21 @@ LayerTransactionParent::RecvUpdate(const
         edit.get_OpSetDiagnosticTypes().diagnostics());
       break;
     }
     // Tree ops
     case Edit::TOpSetRoot: {
       MOZ_LAYERS_LOG(("[ParentSide] SetRoot"));
 
       Layer* newRoot = AsLayerComposite(edit.get_OpSetRoot())->AsLayer();
+      if (!newRoot) {
+        return false;
+      }
       if (newRoot->GetParent()) {
+        // newRoot is not a root!
         return false;
       }
       mRoot = newRoot;
       break;
     }
     case Edit::TOpInsertAfter: {
       MOZ_LAYERS_LOG(("[ParentSide] InsertAfter"));
 
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.h
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.h
@@ -5,17 +5,17 @@
 
 #include <stdint.h>                     // for uint8_t, uint32_t
 #include "ImageContainer.h"             // for PlanarYCbCrImage, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/ipc/Shmem.h"          // for Shmem
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR
 
 class gfxASurface;
 
 #ifndef MOZILLA_LAYERS_DeprecatedSharedPlanarYCbCrImage_H
 #define MOZILLA_LAYERS_DeprecatedSharedPlanarYCbCrImage_H
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/ipc/SharedRGBImage.cpp
+++ b/gfx/layers/ipc/SharedRGBImage.cpp
@@ -14,17 +14,16 @@
 #include "mozilla/layers/TextureClient.h"  // for BufferTextureClient, etc
 #include "mozilla/layers/ImageBridgeChild.h"  // for ImageBridgeChild
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Image::AddRef, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsSize.h"                     // for nsIntSize
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 // Just big enough for a 1080p RGBA32 frame
 #define MAX_FRAME_SIZE (16 * 1024 * 1024)
 
 namespace mozilla {
 namespace layers {
 
 DeprecatedSharedRGBImage::DeprecatedSharedRGBImage(ISurfaceAllocator *aAllocator) :
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -15,16 +15,17 @@
 #include "gfx2DGlue.h"                  // for ThebesFilter
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxCrashReporterUtils.h"      // for ScopedGfxFeatureReporter
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "GraphicsFilter.h"             // for GraphicsFilter
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxUtils.h"                   // for NextPowerOfTwo, gfxUtils, etc
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4, Matrix
 #include "mozilla/layers/CompositingRenderTargetOGL.h"
 #include "mozilla/layers/Effects.h"     // for EffectChain, TexturedEffect, etc
@@ -1200,17 +1201,17 @@ CompositorOGL::DrawQuadInternal(const Re
 
       // Drawing is always flipped, but when copying between surfaces we want to avoid
       // this. Pass true for the flip parameter to introduce a second flip
       // that cancels the other one out.
       BindAndDrawQuad(program, true);
     }
     break;
   case EFFECT_COMPONENT_ALPHA: {
-      MOZ_ASSERT(gfxPlatform::ComponentAlphaEnabled());
+      MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceOGL* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceOGL();
       TextureSourceOGL* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceOGL();
 
       if (!sourceOnBlack->IsValid() ||
           !sourceOnWhite->IsValid()) {
         NS_WARNING("Invalid layer texture for component alpha");
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -19,20 +19,20 @@
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float, SurfaceFormat, etc
 #include "mozilla/layers/Compositor.h"  // for SurfaceInitMode, Compositor, etc
 #include "mozilla/layers/CompositorTypes.h"  // for MaskType::NumMaskTypes, etc
 #include "mozilla/layers/LayersTypes.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr, nsAutoPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsSize.h"                     // for nsIntSize
 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray, etc
 #include "nsThreadUtils.h"              // for nsRunnable
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType
 #include "nscore.h"                     // for NS_IMETHOD
 #include "VBOArena.h"                   // for gl::VBOArena
 
 class gfx3DMatrix;
 class nsIWidget;
 
 namespace mozilla {
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -23,17 +23,16 @@
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureHost.h"  // for DeprecatedTextureHost, etc
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for TextureImage::Release, etc
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "OGLShaderProgram.h"           // for ShaderProgramType, etc
 #ifdef MOZ_WIDGET_GONK
 #include <ui/GraphicBuffer.h>
 #if ANDROID_VERSION >= 18
 #include <ui/Fence.h>
 #endif
 #endif
 
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -20,25 +20,25 @@
 #include "nsIAtom.h"                    // for nsIAtom, do_GetAtom
 #include "nsID.h"
 #include "nsIDeviceContextSpec.h"       // for nsIDeviceContextSpec
 #include "nsILanguageAtomService.h"     // for nsILanguageAtomService, etc
 #include "nsIObserver.h"                // for nsIObserver, etc
 #include "nsIObserverService.h"         // for nsIObserverService
 #include "nsIScreen.h"                  // for nsIScreen
 #include "nsIScreenManager.h"           // for nsIScreenManager
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsIWidget.h"                  // for nsIWidget, NS_NATIVE_WINDOW
 #include "nsRect.h"                     // for nsRect
 #include "nsRenderingContext.h"         // for nsRenderingContext
 #include "nsServiceManagerUtils.h"      // for do_GetService
 #include "nsString.h"               // for nsDependentString
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
 #include "nsThreadUtils.h"              // for NS_IsMainThread
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 
 #if !XP_MACOSX
 #include "gfxPDFSurface.h"
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include "gfxPSSurface.h"
 #elif XP_WIN
--- a/gfx/src/nsRect.h
+++ b/gfx/src/nsRect.h
@@ -10,19 +10,19 @@
 #include <stdio.h>                      // for FILE
 #include <stdint.h>                     // for int32_t, int64_t
 #include <algorithm>                    // for min/max
 #include "nsDebug.h"                    // for NS_WARNING
 #include "gfxCore.h"                    // for NS_GFX
 #include "mozilla/Likely.h"             // for MOZ_UNLIKELY
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "nsCoord.h"                    // for nscoord, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsPoint.h"                    // for nsIntPoint, nsPoint
 #include "nsSize.h"                     // for nsIntSize, nsSize
-#include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nscore.h"                     // for NS_BUILD_REFCNT_LOGGING
 
 struct nsIntRect;
 struct nsMargin;
 struct nsIntMargin;
 
 struct NS_GFX nsRect :
   public mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> {
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -5,17 +5,17 @@
 
 #include "nsIMemoryReporter.h"
 #include "nsMemory.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "mozilla/gfx/2D.h"
 
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "gfxRect.h"
 
--- a/gfx/thebes/gfxFontInfoLoader.h
+++ b/gfx/thebes/gfxFontInfoLoader.h
@@ -11,17 +11,17 @@
 #include "nsIObserver.h"
 #include "nsITimer.h"
 #include "nsIThread.h"
 #include "nsRefPtrHashtable.h"
 #include "nsString.h"
 #include "gfxFont.h"
 #include "nsIRunnable.h"
 #include "mozilla/TimeStamp.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 // data retrieved for a given face
 
 struct FontFaceData {
     FontFaceData() : mUVSOffset(0), mSymbolFont(false) {}
 
     FontFaceData(const FontFaceData& aFontFaceData) {
         mFullName = aFontFaceData.mFullName;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -104,18 +104,16 @@ static qcms_transform *gCMSRGBATransform
 
 static bool gCMSInitialized = false;
 static eCMSMode gCMSMode = eCMSMode_Off;
 static int gCMSIntent = -2;
 
 static void ShutdownCMS();
 static void MigratePrefs();
 
-static bool sDrawFrameCounter = false;
-
 #include "mozilla/gfx/2D.h"
 using namespace mozilla::gfx;
 
 /* Class to listen for pref changes so that chrome code can dynamically
    force sRGB as an output profile. See Bug #452125. */
 class SRGBOverrideObserver MOZ_FINAL : public nsIObserver,
                                        public nsSupportsWeakReference
 {
@@ -186,40 +184,16 @@ FontPrefsObserver::Observe(nsISupports *
         return NS_ERROR_UNEXPECTED;
     }
     NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
     gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData).get());
 
     return NS_OK;
 }
 
-class OrientationSyncPrefsObserver MOZ_FINAL : public nsIObserver
-{
-public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIOBSERVER
-};
-
-NS_IMPL_ISUPPORTS1(OrientationSyncPrefsObserver, nsIObserver)
-
-NS_IMETHODIMP
-OrientationSyncPrefsObserver::Observe(nsISupports *aSubject,
-                                      const char *aTopic,
-                                      const char16_t *someData)
-{
-    if (!someData) {
-        NS_ERROR("orientation sync pref observer broken");
-        return NS_ERROR_UNEXPECTED;
-    }
-    NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
-    gfxPlatform::GetPlatform()->OrientationSyncPrefsObserverChanged();
-
-    return NS_OK;
-}
-
 class MemoryPressureObserver MOZ_FINAL : public nsIObserver
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
 };
 
 NS_IMPL_ISUPPORTS1(MemoryPressureObserver, nsIObserver)
@@ -268,19 +242,16 @@ static const char *gPrefLangNames[] = {
     "x-sinh",
     "x-tibt",
     "x-unicode",
 };
 
 gfxPlatform::gfxPlatform()
   : mAzureCanvasBackendCollector(MOZ_THIS_IN_INITIALIZER_LIST(),
                                  &gfxPlatform::GetAzureBackendInfo)
-  , mDrawLayerBorders(false)
-  , mDrawTileBorders(false)
-  , mDrawBigImageBorders(false)
 {
     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
     mWordCacheCharLimit = UNINITIALIZED_VALUE;
     mWordCacheMaxEntries = UNINITIALIZED_VALUE;
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
@@ -288,31 +259,21 @@ gfxPlatform::gfxPlatform()
     mBidiNumeralOption = UNINITIALIZED_VALUE;
 
     mLayersPreferMemoryOverShmem = XRE_GetProcessType() == GeckoProcessType_Default;
 
 #ifdef XP_WIN
     // XXX - When 957560 is fixed, the pref can go away entirely
     mLayersUseDeprecated =
         Preferences::GetBool("layers.use-deprecated-textures", true)
-        && !Preferences::GetBool("layers.prefer-opengl", false);
+        && !gfxPrefs::LayersPreferOpenGL();
 #else
     mLayersUseDeprecated = false;
 #endif
 
-    Preferences::AddBoolVarCache(&mDrawLayerBorders,
-                                 "layers.draw-borders",
-                                 false);
-    Preferences::AddBoolVarCache(&mDrawTileBorders,
-                                 "layers.draw-tile-borders",
-                                 false);
-    Preferences::AddBoolVarCache(&mDrawBigImageBorders,
-                                 "layers.draw-bigimage-borders",
-                                 false);
-
     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA);
     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
     InitBackendPrefs(canvasMask, BackendType::CAIRO,
                      contentMask, BackendType::CAIRO);
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
@@ -405,17 +366,17 @@ gfxPlatform::Init()
                                        GetPrefLayersOffMainThreadCompositionEnabled();
 
     if (!OffMainThreadCompositionRequired()) {
       useOffMainThreadCompositing &= GetPlatform()->SupportsOffMainThreadCompositing();
     }
 
     if (useOffMainThreadCompositing && (XRE_GetProcessType() == GeckoProcessType_Default)) {
         CompositorParent::StartUp();
-        if (AsyncVideoEnabled()) {
+        if (gfxPrefs::AsyncVideoEnabled()) {
             ImageBridgeChild::StartUp();
         }
     }
 
     nsresult rv;
 
 #if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
     rv = gfxPlatformFontList::Init();
@@ -447,42 +408,30 @@ gfxPlatform::Init()
 
     /* Create and register our CMS Override observer. */
     gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
     Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
 
     gPlatform->mFontPrefsObserver = new FontPrefsObserver();
     Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
 
-    gPlatform->mOrientationSyncPrefsObserver = new OrientationSyncPrefsObserver();
-    Preferences::AddStrongObserver(gPlatform->mOrientationSyncPrefsObserver, "layers.orientation.sync.timeout");
-
-    mozilla::Preferences::AddBoolVarCache(&gPlatform->mWidgetUpdateFlashing,
-                                          "nglayout.debug.widget_update_flashing");
-
     mozilla::gl::GLContext::PlatformStartup();
 
 #ifdef MOZ_WIDGET_ANDROID
     // Texture pool init
     mozilla::gl::TexturePoolOGL::Init();
 #endif
 
     // Force registration of the gfx component, thus arranging for
     // ::Shutdown to be called.
     nsCOMPtr<nsISupports> forceReg
         = do_CreateInstance("@mozilla.org/gfx/init;1");
 
     Preferences::RegisterCallbackAndCall(RecordingPrefChanged, "gfx.2d.recording", nullptr);
 
-    gPlatform->mOrientationSyncMillis = Preferences::GetUint("layers.orientation.sync.timeout", (uint32_t)0);
-
-    mozilla::Preferences::AddBoolVarCache(&sDrawFrameCounter,
-                                          "layers.frame-counter",
-                                          false);
-
     CreateCMSOutputProfile();
 
 #ifdef USE_SKIA
     gPlatform->InitializeSkiaCaches();
 #endif
 
     // Listen to memory pressure event so we can purge DrawTarget caches
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
@@ -881,29 +830,28 @@ gfxPlatform::SupportsAzureContentForDraw
   }
 
   return SupportsAzureContentForType(aTarget->GetType());
 }
 
 bool
 gfxPlatform::UseAcceleratedSkiaCanvas()
 {
-  return Preferences::GetBool("gfx.canvas.azure.accelerated", false) &&
+  return gfxPrefs::CanvasAzureAccelerated() &&
          mPreferredCanvasBackend == BackendType::SKIA;
 }
 
 void
 gfxPlatform::InitializeSkiaCaches()
 {
 #ifdef USE_SKIA_GPU
   if (UseAcceleratedSkiaCanvas()) {
-    bool usingDynamicCache = Preferences::GetBool("gfx.canvas.skiagl.dynamic-cache", false);
-
-    int cacheItemLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-items", 256);
-    int cacheSizeLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-size", 96);
+    bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
+    int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
+    int cacheSizeLimit = gfxPrefs::CanvasSkiaGLCacheSize();
 
     // Prefs are in megabytes, but we want the sizes in bytes
     cacheSizeLimit *= 1024*1024;
 
     if (usingDynamicCache) {
       uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory();
 
       if (totalMemory <= 256*1024*1024) {
@@ -1339,34 +1287,28 @@ gfxPlatform::IsLangCJK(eFontPrefLang aLa
             return false;
     }
 }
 
 mozilla::layers::DiagnosticTypes
 gfxPlatform::GetLayerDiagnosticTypes()
 {
   mozilla::layers::DiagnosticTypes type = DIAGNOSTIC_NONE;
-  if (mDrawLayerBorders) {
+  if (gfxPrefs::DrawLayerBorders()) {
     type |= mozilla::layers::DIAGNOSTIC_LAYER_BORDERS;
   }
-  if (mDrawTileBorders) {
+  if (gfxPrefs::DrawTileBorders()) {
     type |= mozilla::layers::DIAGNOSTIC_TILE_BORDERS;
   }
-  if (mDrawBigImageBorders) {
+  if (gfxPrefs::DrawBigImageBorders()) {
     type |= mozilla::layers::DIAGNOSTIC_BIGIMAGE_BORDERS;
   }
   return type;
 }
 
-bool
-gfxPlatform::DrawFrameCounter()
-{
-    return sDrawFrameCounter;
-}
-
 void
 gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
 {
     if (IsLangCJK(aCharLang)) {
         AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
     } else {
         AppendPrefLang(aPrefLangs, aLen, aCharLang);
     }
@@ -1554,64 +1496,16 @@ gfxPlatform::GetBackendPref(const char* 
         }
     }
 
     aBackendBitmask = allowedBackends;
     return result;
 }
 
 bool
-gfxPlatform::UseProgressiveTilePainting()
-{
-    static bool sUseProgressiveTilePainting;
-    static bool sUseProgressiveTilePaintingPrefCached = false;
-
-    if (!sUseProgressiveTilePaintingPrefCached) {
-        sUseProgressiveTilePaintingPrefCached = true;
-        mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
-                                              "layers.progressive-paint",
-                                              false);
-    }
-
-    return sUseProgressiveTilePainting;
-}
-
-bool
-gfxPlatform::UseLowPrecisionBuffer()
-{
-    static bool sUseLowPrecisionBuffer;
-    static bool sUseLowPrecisionBufferPrefCached = false;
-
-    if (!sUseLowPrecisionBufferPrefCached) {
-        sUseLowPrecisionBufferPrefCached = true;
-        mozilla::Preferences::AddBoolVarCache(&sUseLowPrecisionBuffer,
-                                              "layers.low-precision-buffer",
-                                              false);
-    }
-
-    return sUseLowPrecisionBuffer;
-}
-
-float
-gfxPlatform::GetLowPrecisionResolution()
-{
-    static int32_t sLowPrecisionResolutionX1000 = 250;
-    static bool sLowPrecisionResolutionPrefCached = false;
-
-    if (!sLowPrecisionResolutionPrefCached) {
-        sLowPrecisionResolutionPrefCached = true;
-        mozilla::Preferences::AddIntVarCache(&sLowPrecisionResolutionX1000,
-                                             "layers.low-precision-resolution",
-                                             sLowPrecisionResolutionX1000);
-    }
-
-    return sLowPrecisionResolutionX1000/1000.f;
-}
-
-bool
 gfxPlatform::OffMainThreadCompositingEnabled()
 {
   return XRE_GetProcessType() == GeckoProcessType_Default ?
     CompositorParent::CompositorLoop() != nullptr :
     CompositorChild::ChildProcessHasCompositor();
 }
 
 eCMSMode
@@ -2039,86 +1933,44 @@ gfxPlatform::OptimalFormatForContent(gfx
   case gfxContentType::COLOR_ALPHA:
     return gfxImageFormat::ARGB32;
   default:
     NS_NOTREACHED("unknown gfxContentType");
     return gfxImageFormat::ARGB32;
   }
 }
 
-void
-gfxPlatform::OrientationSyncPrefsObserverChanged()
-{
-  mOrientationSyncMillis = Preferences::GetUint("layers.orientation.sync.timeout", (uint32_t)0);
-}
-
-uint32_t
-gfxPlatform::GetOrientationSyncMillis() const
-{
-  return mOrientationSyncMillis;
-}
-
 /**
  * There are a number of layers acceleration (or layers in general) preferences
  * that should be consistent for the lifetime of the application (bug 840967).
  * As such, we will evaluate them all as soon as one of them is evaluated
  * and remember the values.  Changing these preferences during the run will
  * not have any effect until we restart.
  */
-static bool sPrefLayersOffMainThreadCompositionEnabled = false;
-static bool sPrefLayersOffMainThreadCompositionTestingEnabled = false;
-static bool sPrefLayersOffMainThreadCompositionForceEnabled = false;
-static bool sPrefLayersAccelerationForceEnabled = false;
-static bool sPrefLayersAccelerationDisabled = false;
-static bool sPrefLayersPreferOpenGL = false;
-static bool sPrefLayersPreferD3D9 = false;
-static bool sPrefLayersDrawFPS = false;
-static bool sPrefLayersDump = false;
-static bool sPrefLayersScrollGraph = false;
-static bool sPrefLayersEnableTiles = false;
 static bool sLayersSupportsD3D9 = false;
-static int  sPrefLayoutFrameRate = -1;
-static int  sPrefLayersCompositionFrameRate = -1;
-static bool sBufferRotationEnabled = false;
-static bool sComponentAlphaEnabled = true;
+static bool sBufferRotationCheckPref = true;
 static bool sPrefBrowserTabsRemoteAutostart = false;
 
 static bool sLayersAccelerationPrefsInitialized = false;
 
 void
 InitLayersAccelerationPrefs()
 {
   if (!sLayersAccelerationPrefsInitialized)
   {
     // If this is called for the first time on a non-main thread, we're screwed.
     // At the moment there's no explicit guarantee that the main thread calls
     // this before the compositor thread, but let's at least make the assumption
     // explicit.
     MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
 
-    sPrefLayersOffMainThreadCompositionEnabled = Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
-    sPrefLayersOffMainThreadCompositionTestingEnabled = Preferences::GetBool("layers.offmainthreadcomposition.testing.enabled", false);
-    sPrefLayersOffMainThreadCompositionForceEnabled = Preferences::GetBool("layers.offmainthreadcomposition.force-enabled", false);
-    sPrefLayersAccelerationForceEnabled = Preferences::GetBool("layers.acceleration.force-enabled", false);
-    sPrefLayersAccelerationDisabled = Preferences::GetBool("layers.acceleration.disabled", false);
-    sPrefLayersPreferOpenGL = Preferences::GetBool("layers.prefer-opengl", false);
-    sPrefLayersPreferD3D9 = Preferences::GetBool("layers.prefer-d3d9", false);
-    sPrefLayersDump = Preferences::GetBool("layers.dump", false);
-    sPrefLayersScrollGraph = Preferences::GetBool("layers.scroll-graph", false);
-    sPrefLayersEnableTiles = Preferences::GetBool("layers.enable-tiles", false);
-    sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
-    sPrefLayersCompositionFrameRate = Preferences::GetInt("layers.offmainthreadcomposition.frame-rate", -1);
-    sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
-    sComponentAlphaEnabled = Preferences::GetBool("layers.componentalpha.enabled", true);
     sPrefBrowserTabsRemoteAutostart = Preferences::GetBool("browser.tabs.remote.autostart", false);
 
-    Preferences::AddBoolVarCache(&sPrefLayersDrawFPS, "layers.acceleration.draw-fps", false);
-
 #ifdef XP_WIN
-    if (sPrefLayersAccelerationForceEnabled) {
+    if (gfxPrefs::LayersAccelerationForceEnabled()) {
       sLayersSupportsD3D9 = true;
     } else {
       nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
       if (gfxInfo) {
         int32_t status;
         if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
           if (status == nsIGfxInfo::FEATURE_NO_INFO) {
             sLayersSupportsD3D9 = true;
@@ -2131,157 +1983,56 @@ InitLayersAccelerationPrefs()
     sLayersAccelerationPrefsInitialized = true;
   }
 }
 
 bool
 gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
 {
   InitLayersAccelerationPrefs();
-  return sPrefLayersOffMainThreadCompositionEnabled ||
-         sPrefLayersOffMainThreadCompositionForceEnabled ||
-         sPrefLayersOffMainThreadCompositionTestingEnabled;
-}
-
-bool
-gfxPlatform::GetPrefLayersOffMainThreadCompositionForceEnabled()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersOffMainThreadCompositionForceEnabled;
-}
-
-bool
-gfxPlatform::GetPrefLayersAccelerationForceEnabled()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersAccelerationForceEnabled;
+  return gfxPrefs::LayersOffMainThreadCompositionEnabled() ||
+         gfxPrefs::LayersOffMainThreadCompositionForceEnabled() ||
+         gfxPrefs::LayersOffMainThreadCompositionTestingEnabled();
 }
 
 bool gfxPlatform::OffMainThreadCompositionRequired()
 {
   InitLayersAccelerationPrefs();
 #if defined(MOZ_WIDGET_GTK) && defined(NIGHTLY_BUILD)
   // Linux users who chose OpenGL are being grandfathered in to OMTC
   return sPrefBrowserTabsRemoteAutostart ||
-         sPrefLayersAccelerationForceEnabled;
+         gfxPrefs::LayersAccelerationForceEnabled();
 #else
   return sPrefBrowserTabsRemoteAutostart;
 #endif
 }
 
 bool
-gfxPlatform::GetPrefLayersAccelerationDisabled()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersAccelerationDisabled;
-}
-
-bool
-gfxPlatform::GetPrefLayersPreferOpenGL()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersPreferOpenGL;
-}
-
-bool
-gfxPlatform::GetPrefLayersPreferD3D9()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersPreferD3D9;
-}
-
-bool
-gfxPlatform::GetPrefLayersDrawFPS()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersDrawFPS;
-}
-
-bool
 gfxPlatform::CanUseDirect3D9()
 {
   // this function is called from the compositor thread, so it is not
   // safe to init the prefs etc. from here.
   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
   return sLayersSupportsD3D9;
 }
 
-int
-gfxPlatform::GetPrefLayoutFrameRate()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayoutFrameRate;
-}
-
-bool
-gfxPlatform::GetPrefLayersDump()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersDump;
-}
-
-bool
-gfxPlatform::GetPrefLayersScrollGraph()
-{
-  // this function is called from the compositor thread, so it is not
-  // safe to init the prefs etc. from here.
-  MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
-  return sPrefLayersScrollGraph;
-}
-
-bool
-gfxPlatform::GetPrefLayersEnableTiles()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersEnableTiles;
-}
-
-int
-gfxPlatform::GetPrefLayersCompositionFrameRate()
-{
-  InitLayersAccelerationPrefs();
-  return sPrefLayersCompositionFrameRate;
-}
-
 bool
 gfxPlatform::BufferRotationEnabled()
 {
   MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
 
-  InitLayersAccelerationPrefs();
-  return sBufferRotationEnabled;
+  return sBufferRotationCheckPref && gfxPrefs::BufferRotationEnabled();
 }
 
 void
 gfxPlatform::DisableBufferRotation()
 {
   MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
 
-  sBufferRotationEnabled = false;
-}
-
-bool
-gfxPlatform::ComponentAlphaEnabled()
-{
-#ifdef MOZ_GFX_OPTIMIZE_MOBILE
-  return false;
-#endif
-
-  InitLayersAccelerationPrefs();
-  return sComponentAlphaEnabled;
-}
-
-bool
-gfxPlatform::AsyncVideoEnabled()
-{
-#ifdef XP_WIN
-  return false;
-#else
-  return Preferences::GetBool("layers.async-video.enabled", false);
-#endif
+  sBufferRotationCheckPref = false;
 }
 
 TemporaryRef<ScaledFont>
 gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont)
 {
     NativeFont nativeFont;
     if (aTarget->GetType() == BackendType::CAIRO || aTarget->GetType() == BackendType::SKIA) {
         nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -480,60 +480,35 @@ public:
     // these are *possible* matches, no cmap-checking is done at this level
     virtual void GetCommonFallbackFonts(const uint32_t /*aCh*/,
                                         int32_t /*aRunScript*/,
                                         nsTArray<const char*>& /*aFontList*/)
     {
         // platform-specific override, by default do nothing
     }
 
-    // Break large OMTC tiled thebes layer painting into small paints.
-    static bool UseProgressiveTilePainting();
-
-    // When a critical display-port is set, render the visible area outside of
-    // it into a buffer at a lower precision. Requires tiled buffers.
-    static bool UseLowPrecisionBuffer();
-
-    // Retrieve the resolution that a low precision buffer should render at.
-    static float GetLowPrecisionResolution();
-
     static bool OffMainThreadCompositingEnabled();
 
     /** Use gfxPlatform::GetPref* methods instead of direct calls to Preferences
      * to get the values for layers preferences.  These will only be evaluated
      * only once, and remain the same until restart.
      */
     static bool GetPrefLayersOffMainThreadCompositionEnabled();
-    static bool GetPrefLayersOffMainThreadCompositionForceEnabled();
-    static bool GetPrefLayersAccelerationForceEnabled();
-    static bool GetPrefLayersAccelerationDisabled();
-    static bool GetPrefLayersPreferOpenGL();
-    static bool GetPrefLayersPreferD3D9();
     static bool CanUseDirect3D9();
-    static int  GetPrefLayoutFrameRate();
-    static int  GetPrefLayersCompositionFrameRate();
-    static bool GetPrefLayersDump();
-    static bool GetPrefLayersScrollGraph();
-    static bool GetPrefLayersEnableTiles();
-    static bool GetPrefLayersDrawFPS();
 
     static bool OffMainThreadCompositionRequired();
 
     /**
-     * Is it possible to use buffer rotation
+     * Is it possible to use buffer rotation.  Note that these
+     * check the preference, but also allow for the override to
+     * disable it using DisableBufferRotation.
      */
     static bool BufferRotationEnabled();
     static void DisableBufferRotation();
 
-    static bool ComponentAlphaEnabled();
-
-    // Async video is enabled on this platform.
-    // Must only be called from the main thread.
-    static bool AsyncVideoEnabled();
-
     /**
      * Are we going to try color management?
      */
     static eCMSMode GetCMSMode();
 
     /**
      * Determines the rendering intent for color management.
      *
@@ -575,18 +550,16 @@ public:
 
     /**
      * Return sRGBA -> output device transform.
      */
     static qcms_transform* GetCMSRGBATransform();
 
     virtual void FontsPrefsChanged(const char *aPref);
 
-    void OrientationSyncPrefsObserverChanged();
-
     int32_t GetBidiNumeralOption();
 
     /**
      * Returns a 1x1 surface that can be used to create graphics contexts
      * for measuring text etc as if they will be rendered to the screen
      */
     gfxASurface* ScreenReferenceSurface() { return mScreenReferenceSurface; }
     mozilla::gfx::DrawTarget* ScreenReferenceDrawTarget() { return mScreenReferenceDrawTarget; }
@@ -600,26 +573,21 @@ public:
 
     /**
      * Returns a logger if one is available and logging is enabled
      */
     static PRLogModuleInfo* GetLog(eGfxLog aWhichLog);
 
     virtual int GetScreenDepth() const;
 
-    bool WidgetUpdateFlashing() const { return mWidgetUpdateFlashing; }
-
-    uint32_t GetOrientationSyncMillis() const;
-
     /**
      * Return the layer debugging options to use browser-wide.
      */
     mozilla::layers::DiagnosticTypes GetLayerDiagnosticTypes();
 
-    static bool DrawFrameCounter();
     static nsIntRect FrameCounterBounds() {
       int bits = 16;
       int sizeOfBit = 3;
       return nsIntRect(0, 0, bits * sizeOfBit, sizeOfBit);
     }
 
     /**
      * Returns true if we should use raw memory to send data to the compositor
@@ -722,33 +690,27 @@ private:
 
     virtual bool SupportsOffMainThreadCompositing() { return true; }
 
     nsRefPtr<gfxASurface> mScreenReferenceSurface;
     mozilla::RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
     nsTArray<uint32_t> mCJKPrefLangs;
     nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
     nsCOMPtr<nsIObserver> mFontPrefsObserver;
-    nsCOMPtr<nsIObserver> mOrientationSyncPrefsObserver;
     nsCOMPtr<nsIObserver> mMemoryPressureObserver;
 
     // The preferred draw target backend to use for canvas
     mozilla::gfx::BackendType mPreferredCanvasBackend;
     // The fallback draw target backend to use for canvas, if the preferred backend fails
     mozilla::gfx::BackendType mFallbackCanvasBackend;
     // The backend to use for content
     mozilla::gfx::BackendType mContentBackend;
     // Bitmask of backend types we can use to render content
     uint32_t mContentBackendBitmask;
 
     mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
 
     mozilla::RefPtr<mozilla::gfx::DrawEventRecorder> mRecorder;
-    bool mWidgetUpdateFlashing;
-    uint32_t mOrientationSyncMillis;
     bool mLayersPreferMemoryOverShmem;
     bool mLayersUseDeprecated;
-    bool mDrawLayerBorders;
-    bool mDrawTileBorders;
-    bool mDrawBigImageBorders;
 };
 
 #endif /* GFX_PLATFORM_H */
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -93,25 +93,72 @@ private:
         default:
           MOZ_CRASH();
           break;
       }
     }
     T mValue;
   };
 
-public:
   // This is where DECL_GFX_PREF for each of the preferences should go.
   // We will keep these in an alphabetical order to make it easier to see if
   // a method accessing a pref already exists. Just add yours in the list.
 
+  DECL_GFX_PREF(Live, "gfx.canvas.azure.accelerated",          CanvasAzureAccelerated, bool, false);
+  DECL_GFX_PREF(Once, "gfx.canvas.skiagl.dynamic-cache",       CanvasSkiaGLDynamicCache, bool, false);
+  DECL_GFX_PREF(Once, "gfx.canvas.skiagl.cache-size",          CanvasSkiaGLCacheSize, int32_t, 96);
+  DECL_GFX_PREF(Once, "gfx.canvas.skiagl.cache-items",         CanvasSkiaGLCacheItems, int32_t, 256);
+
+  DECL_GFX_PREF(Once, "gfx.direct2d.disabled",                 Direct2DDisabled, bool, false);
+  DECL_GFX_PREF(Once, "gfx.direct2d.force-enabled",            Direct2DForceEnabled, bool, false);
   DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs",           WorkAroundDriverBugs, bool, true);
 
   DECL_GFX_PREF(Live, "gl.msaa-level",                         MSAALevel, uint32_t, 2);
 
+  DECL_GFX_PREF(Once, "layers.acceleration.disabled",          LayersAccelerationDisabled, bool, false);
+  DECL_GFX_PREF(Live, "layers.acceleration.draw-fps",          LayersDrawFPS, bool, true);
+  DECL_GFX_PREF(Once, "layers.acceleration.force-enabled",     LayersAccelerationForceEnabled, bool, false);
+#ifdef XP_WIN
+  // On windows, ignore the preference value, forcing async video to false.
+  DECL_GFX_PREF(Skip, "layers.async-video.enabled",            AsyncVideoEnabled, bool, false);
+#else
+  DECL_GFX_PREF(Once, "layers.async-video.enabled",            AsyncVideoEnabled, bool, false);
+#endif
+  DECL_GFX_PREF(Once, "layers.bufferrotation.enabled",         BufferRotationEnabled, bool, true);
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+  // If MOZ_GFX_OPTIMIZE_MOBILE is defined, we force component alpha off
+  // and ignore the preference.
+  DECL_GFX_PREF(Skip, "layers.componentalpha.enabled",         ComponentAlphaEnabled, bool, false);
+#else
+  // If MOZ_GFX_OPTIMIZE_MOBILE is not defined, we actually take the
+  // preference value, defaulting to true.
+  DECL_GFX_PREF(Once, "layers.componentalpha.enabled",         ComponentAlphaEnabled, bool, true);
+#endif
+  DECL_GFX_PREF(Live, "layers.draw-bigimage-borders",          DrawBigImageBorders, bool, false);
+  DECL_GFX_PREF(Live, "layers.draw-borders",                   DrawLayerBorders, bool, false);
+  DECL_GFX_PREF(Live, "layers.draw-tile-borders",              DrawTileBorders, bool, false);
+  DECL_GFX_PREF(Once, "layers.dump",                           LayersDump, bool, false);
+  DECL_GFX_PREF(Once, "layers.enable-tiles",                   LayersTilesEnabled, bool, false);
+  DECL_GFX_PREF(Live, "layers.frame-counter",                  DrawFrameCounter, bool, false);
+  DECL_GFX_PREF(Live, "layers.low-precision-buffer",           UseLowPrecisionBuffer, bool, false);
+  DECL_GFX_PREF(Live, "layers.low-precision-resolution",       LowPrecisionResolution, int32_t, 250);
+  DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.enabled", LayersOffMainThreadCompositionEnabled, bool, false);
+  DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);
+  DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-enabled", LayersOffMainThreadCompositionForceEnabled, bool, false);
+  DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.testing.enabled", LayersOffMainThreadCompositionTestingEnabled, bool, false);
+  DECL_GFX_PREF(Live, "layers.orientation.sync.timeout",       OrientationSyncMillis, uint32_t, (uint32_t)0);
+  DECL_GFX_PREF(Once, "layers.prefer-d3d9",                    LayersPreferD3D9, bool, false);
+  DECL_GFX_PREF(Once, "layers.prefer-opengl",                  LayersPreferOpenGL, bool, false);
+  DECL_GFX_PREF(Once, "layers.progressive-paint",              UseProgressiveTilePainting, bool, false);
+  DECL_GFX_PREF(Once, "layers.scroll-graph",                   LayersScrollGraph, bool, false);
+
+  DECL_GFX_PREF(Once, "layout.frame_rate",                     LayoutFrameRate, int32_t, -1);
+
+  DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
+
 public:
   // Manage the singleton:
   static gfxPrefs& One()
   {
     if (!sInstance) {
       sInstance = new gfxPrefs;
     }
     return *sInstance;
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -60,16 +60,17 @@
 
 #include <d3d11.h>
 
 #include "nsIMemoryReporter.h"
 #include <winternl.h>
 #include "d3dkmtQueryStatistics.h"
 
 #include "SurfaceCache.h"
+#include "gfxPrefs.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::image;
 
 #ifdef CAIRO_HAS_D2D_SURFACE
@@ -105,39 +106,16 @@ public:
         NS_ENSURE_SUCCESS(rv, rv);
 
         return NS_OK;
     }
 };
 
 NS_IMPL_ISUPPORTS1(GfxD2DSurfaceReporter, nsIMemoryReporter)
 
-namespace
-{
-
-bool OncePreferenceDirect2DDisabled()
-{
-  static int preferenceValue = -1;
-  if (preferenceValue < 0) {
-    preferenceValue = Preferences::GetBool("gfx.direct2d.disabled", false);
-  }
-  return !!preferenceValue;
-}
-
-bool OncePreferenceDirect2DForceEnabled()
-{
-  static int preferenceValue = -1;
-  if (preferenceValue < 0) {
-    preferenceValue = Preferences::GetBool("gfx.direct2d.force-enabled", false);
-  }
-  return !!preferenceValue;
-}
-
-} // anonymous namespace
-
 #endif
 
 class GfxD2DVramReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
@@ -394,20 +372,20 @@ gfxWindowsPlatform::UpdateRenderMode()
             if (status != nsIGfxInfo::FEATURE_NO_INFO) {
                 d2dBlocked = true;
             }
         }
     }
 
     // These will only be evaluated once, and any subsequent changes to
     // the preferences will be ignored until restart.
-    d2dDisabled = OncePreferenceDirect2DDisabled();
-    d2dForceEnabled = OncePreferenceDirect2DForceEnabled();
+    d2dDisabled = gfxPrefs::Direct2DDisabled();
+    d2dForceEnabled = gfxPrefs::Direct2DForceEnabled();
 
-    bool tryD2D = (!d2dBlocked && !GetPrefLayersPreferD3D9()) || d2dForceEnabled;
+    bool tryD2D = d2dForceEnabled || (!d2dBlocked && !gfxPrefs::LayersPreferD3D9());
 
     // Do not ever try if d2d is explicitly disabled,
     // or if we're not using DWrite fonts.
     if (d2dDisabled || mUsingGDIFonts) {
         tryD2D = false;
     }
 
     if (isVistaOrHigher  && !safeMode && tryD2D) {
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -150,17 +150,17 @@ Decoder::Finish(RasterImage::eShutdownIn
                          NS_ConvertUTF8toUTF16(mImage.GetURIString()),
                          EmptyString(), 0, 0, nsIScriptError::errorFlag,
                          "Image", mImage.InnerWindowID()
                        ))) {
         consoleService->LogMessage(errorObject);
       }
     }
 
-    bool usable = true;
+    bool usable = !HasDecoderError();
     if (aShutdownIntent != RasterImage::eShutdownIntent_NotNeeded && !HasDecoderError()) {
       // If we only have a data error, we're usable if we have at least one complete frame.
       if (GetCompleteFrameCount() == 0) {
         usable = false;
       }
     }
 
     // If we're usable, do exactly what we should have when the decoder
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -3355,16 +3355,21 @@ RasterImage::DecodePool::DecodeSomeOfIma
                     "Worker active for uninitialized container!");
   aImg->mDecodingMonitor.AssertCurrentThreadIn();
 
   // If an error is flagged, it probably happened while we were waiting
   // in the event queue.
   if (aImg->mError)
     return NS_OK;
 
+  // If there is an error worker pending (say because the main thread has enqueued
+  // another decode request for us before processing the error worker) then bail out.
+  if (aImg->mPendingError)
+    return NS_OK;
+
   // If mDecoded or we don't have a decoder, we must have finished already (for
   // example, a synchronous decode request came while the worker was pending).
   if (!aImg->mDecoder || aImg->mDecoded)
     return NS_OK;
 
   // If we're doing synchronous decodes, and we're waiting on a new frame for
   // this image, get it now.
   if (aStrategy == DECODE_SYNC && aImg->mDecoder->NeedsNewFrame()) {
--- a/ipc/app/Makefile.in
+++ b/ipc/app/Makefile.in
@@ -33,41 +33,26 @@ endif
 # This switches $(INSTALL) to copy mode, like $(SYSINSTALL), so things that
 # shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall.
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/config.mk
 
 include $(topsrcdir)/config/rules.mk
 
-LDFLAGS += $(MOZ_ALLOW_HEAP_EXECUTE_FLAGS)
-
 ifeq ($(OS_ARCH),WINNT) #{
 
 ifdef MOZ_CONTENT_SANDBOX
 LIBS += ../../security/sandbox/$(LIB_PREFIX)sandbox_s.$(LIB_SUFFIX)
 LIBS += $(NSPR_LIBS)
 endif
 
 # Note the manifest file exists in the tree, so we use the explicit filename
 # here.
 EXTRA_DEPS += plugin-container.exe.manifest
-#
-# Control the default heap size.
-# This is the heap returned by GetProcessHeap().
-# As we use the CRT heap, the default size is too large and wastes VM.
-#
-# The default heap size is 1MB on Win32.
-# The heap will grow if need be.
-#
-# Set it to 256k.  See bug 127069.
-#
-ifndef GNU_CC #{
-LDFLAGS += /HEAP:0x40000
-endif #}
 endif #}
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{
 
 libs::
 	$(NSINSTALL) -D $(DIST)/bin/$(PROGRAM).app
 	rsync -a -C --exclude '*.in' $(srcdir)/macbuild/Contents $(DIST)/bin/$(PROGRAM).app 
 	sed -e 's/%PROGRAM%/$(PROGRAM)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/bin/$(PROGRAM).app/Contents/Info.plist
--- a/ipc/app/moz.build
+++ b/ipc/app/moz.build
@@ -29,8 +29,21 @@ if CONFIG['MOZ_CONTENT_SANDBOX'] and CON
         '/security/sandbox',
         '/security/sandbox/chromium',
     ]
 
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
+
+LDFLAGS += [CONFIG['MOZ_ALLOW_HEAP_EXECUTE_FLAGS']]
+
+# Control the default heap size.
+# This is the heap returned by GetProcessHeap().
+# As we use the CRT heap, the default size is too large and wastes VM.
+#
+# The default heap size is 1MB on Win32.
+# The heap will grow if need be.
+#
+# Set it to 256k.  See bug 127069.
+if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
+    LDFLAGS += ['/HEAP:0x40000']
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -1,14 +1,15 @@
 /* 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 "base/process_util.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ipc/ProtocolTypes.h"
 #include "BackgroundChild.h"
@@ -136,17 +137,17 @@ private:
   // background thread. It is specific to each instance of sBackgroundThread.
   static nsTArray<ParentImpl*>* sLiveActorsForBackgroundThread;
 
   // This is only modified on the main thread.
   static StaticRefPtr<nsITimer> sShutdownTimer;
 
   // This exists so that that [Assert]IsOnBackgroundThread() can continue to
   // work during shutdown.
-  static PRThread* sBackgroundPRThread;
+  static Atomic<PRThread*> sBackgroundPRThread;
 
   // This is only modified on the main thread. It is null if the thread does not
   // exist or is shutting down.
   static MessageLoop* sBackgroundThreadMessageLoop;
 
   // This is only modified on the main thread. It maintains a count of live
   // actors so that the background thread can be shut down when it is no longer
   // needed.
@@ -792,17 +793,17 @@ const ParentImpl::ProcessHandle ParentIm
 #endif
 
 StaticRefPtr<nsIThread> ParentImpl::sBackgroundThread;
 
 nsTArray<ParentImpl*>* ParentImpl::sLiveActorsForBackgroundThread;
 
 StaticRefPtr<nsITimer> ParentImpl::sShutdownTimer;
 
-PRThread* ParentImpl::sBackgroundPRThread = nullptr;
+Atomic<PRThread*> ParentImpl::sBackgroundPRThread;
 
 MessageLoop* ParentImpl::sBackgroundThreadMessageLoop = nullptr;
 
 uint64_t ParentImpl::sLiveActorCount = 0;
 
 bool ParentImpl::sShutdownObserverRegistered = false;
 
 bool ParentImpl::sShutdownHasStarted = false;
@@ -1244,27 +1245,27 @@ ParentImpl::RequestMessageLoopRunnable::
     return NS_OK;
   }
 
   char stackBaseGuess;
   profiler_register_thread("IPDL Background", &stackBaseGuess);
 
 #ifdef DEBUG
   {
-    PRThread* currentPRThread = PR_GetCurrentThread();
-    MOZ_ASSERT(currentPRThread);
-    MOZ_ASSERT_IF(sBackgroundPRThread, currentPRThread != sBackgroundPRThread);
-
     bool correctThread;
     MOZ_ASSERT(NS_SUCCEEDED(mTargetThread->IsOnCurrentThread(&correctThread)));
     MOZ_ASSERT(correctThread);
   }
 #endif
 
-  sBackgroundPRThread = PR_GetCurrentThread();
+  DebugOnly<PRThread*> oldBackgroundThread =
+    sBackgroundPRThread.exchange(PR_GetCurrentThread());
+
+  MOZ_ASSERT_IF(oldBackgroundThread,
+                PR_GetCurrentThread() != oldBackgroundThread);
 
   MOZ_ASSERT(!mMessageLoop);
 
   mMessageLoop = MessageLoop::current();
   MOZ_ASSERT(mMessageLoop);
 
   if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Failed to dispatch RequestMessageLoopRunnable to main thread!");
@@ -1276,17 +1277,21 @@ ParentImpl::RequestMessageLoopRunnable::
 
 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ShutdownBackgroundThreadRunnable,
                              nsRunnable)
 
 NS_IMETHODIMP
 ParentImpl::ShutdownBackgroundThreadRunnable::Run()
 {
   AssertIsInMainProcess();
-  AssertIsOnBackgroundThread();
+
+  // It is possible that another background thread was created while this thread
+  // was shutting down. In that case we can't assert anything about
+  // sBackgroundPRThread and we should not modify it here.
+  sBackgroundPRThread.compareExchange(PR_GetCurrentThread(), nullptr);
 
   profiler_unregister_thread();
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ForceCloseBackgroundActorsRunnable,
                              nsRunnable)
--- a/ipc/glue/CrossProcessMutex_posix.cpp
+++ b/ipc/glue/CrossProcessMutex_posix.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; 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 "CrossProcessMutex.h"
 #include "mozilla/unused.h"
 #include "nsDebug.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 namespace {
 
 struct MutexData {
   pthread_mutex_t mMutex;
   mozilla::Atomic<int32_t> mCount;
 };
 
--- a/ipc/glue/CrossProcessMutex_windows.cpp
+++ b/ipc/glue/CrossProcessMutex_windows.cpp
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <windows.h>
 
 #include "base/process_util.h"
 #include "CrossProcessMutex.h"
 #include "nsDebug.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 using namespace base;
 
 namespace mozilla {
 
 CrossProcessMutex::CrossProcessMutex(const char*)
 {
   // We explicitly share this using DuplicateHandle, we do -not- want this to
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -7,17 +7,17 @@
 
 #include "mozilla/ipc/MessageChannel.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Move.h"
 #include "nsDebug.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 // Undo the damage done by mozzconf.h
 #undef compress
 
 using namespace mozilla;
 using namespace std;
 
 using mozilla::MonitorAutoLock;
--- a/ipc/glue/MessageLink.cpp
+++ b/ipc/glue/MessageLink.cpp
@@ -6,17 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ipc/MessageLink.h"
 #include "mozilla/ipc/MessageChannel.h"
 #include "mozilla/ipc/BrowserProcessSubThread.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 
 #include "nsDebug.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla;
 using namespace std;
 
 template<>
 struct RunnableMethodTraits<mozilla::ipc::ProcessLink>
 {
--- a/ipc/glue/SharedMemory.cpp
+++ b/ipc/glue/SharedMemory.cpp
@@ -43,16 +43,17 @@ public:
 };
 
 NS_IMPL_ISUPPORTS1(ShmemReporter, nsIMemoryReporter)
 
 SharedMemory::SharedMemory()
   : mAllocSize(0)
   , mMappedSize(0)
 {
+  MOZ_COUNT_CTOR(SharedMemory);
   static Atomic<bool> registered;
   if (registered.compareExchange(false, true)) {
     RegisterStrongMemoryReporter(new ShmemReporter());
   }
 }
 
 /*static*/ size_t
 SharedMemory::PageAlignedSize(size_t aSize)
--- a/ipc/glue/SharedMemory.h
+++ b/ipc/glue/SharedMemory.h
@@ -25,24 +25,29 @@ enum Rights {
 }
 
 namespace mozilla {
 namespace ipc {
 
 class SharedMemory
 {
 public:
+  virtual ~SharedMemory()
+  {
+    MOZ_COUNT_DTOR(SharedMemory);
+    Unmapped();
+    Destroyed();
+  }
+
   enum SharedMemoryType {
     TYPE_BASIC,
     TYPE_SYSV,
     TYPE_UNKNOWN
   };
 
-  virtual ~SharedMemory() { Unmapped(); Destroyed(); }
-
   size_t Size() const { return mMappedSize; }
 
   virtual void* memory() const = 0;
 
   virtual bool Create(size_t size) = 0;
   virtual bool Map(size_t nBytes) = 0;
 
   virtual SharedMemoryType Type() const = 0;
--- a/ipc/glue/WindowsMessageLoop.h
+++ b/ipc/glue/WindowsMessageLoop.h
@@ -7,17 +7,17 @@
 
 #ifndef IPC_GLUE_WINDOWSMESSAGELOOP_H
 #define IPC_GLUE_WINDOWSMESSAGELOOP_H
 
 // This file is only meant to compile on windows
 #include <windows.h>
 
 #include "base/basictypes.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace ipc {
 namespace windows {
 
 class DeferredMessage
 {
 public:
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -1196,17 +1196,16 @@ public:
 
     void cmpxchg32(RegisterID src, int offset, RegisterID base)
     {
         // Note that 32-bit CMPXCHG performs comparison against %eax.
         // If %eax == [%base+offset], then %src -> [%base+offset].
         // Otherwise, [%base+offset] -> %eax.
         spew("cmpxchg    %s, %s0x%x(%s)",
              nameIReg(src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
-        m_formatter.oneByteOp(PRE_LOCK);
         m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, src, base, offset);
     }
 
 
     // Comparisons:
 
     void cmpl_rr(RegisterID src, RegisterID dst)
     {
@@ -1401,16 +1400,24 @@ public:
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
             m_formatter.immediate8(imm);
         } else {
             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
             m_formatter.immediate32(imm);
         }
     }
 
+    void cmpw_rr(RegisterID src, RegisterID dst)
+    {
+        spew("cmpw       %s, %s",
+             nameIReg(2, src), nameIReg(2, dst));
+        m_formatter.prefix(PRE_OPERAND_SIZE);
+        m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
+    }
+
     void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
     {
         FIXME_INSN_PRINTING;
         m_formatter.prefix(PRE_OPERAND_SIZE);
         m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
     }
 
     void cmpw_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
@@ -2059,16 +2066,23 @@ public:
     void movsbl_mr(const void* addr, RegisterID dst)
     {
         spew("movsbl     %p, %s",
              addr, nameIReg(4, dst));
         m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, addr);
     }
 #endif
 
+    void movzwl_rr(RegisterID src, RegisterID dst)
+    {
+        spew("movzwl     %s, %s",
+             nameIReg(2, src), nameIReg(4, dst));
+        m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, src);
+    }
+
     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
     {
         spew("movzwl     %s0x%x(%s), %s",
              PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
         m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset);
     }
 
     void movzwl_mr_disp32(int offset, RegisterID base, RegisterID dst)
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -8,20 +8,20 @@ var ignoreIndirectCalls = {
     "aMallocSizeOf" : true,
     "_malloc_message" : true,
     "__conv" : true,
     "__convf" : true,
     "prerrortable.c:callback_newtable" : true,
     "mozalloc_oom.cpp:void (* gAbortHandler)(size_t)" : true,
 
     // I don't know why these are getting truncated
-    "nsTraceRefcntImpl.cpp:void (* leakyLogAddRef)(void*": true,
-    "nsTraceRefcntImpl.cpp:void (* leakyLogAddRef)(void*, int, int)": true,
-    "nsTraceRefcntImpl.cpp:void (* leakyLogRelease)(void*": true,
-    "nsTraceRefcntImpl.cpp:void (* leakyLogRelease)(void*, int, int)": true,
+    "nsTraceRefcnt.cpp:void (* leakyLogAddRef)(void*": true,
+    "nsTraceRefcnt.cpp:void (* leakyLogAddRef)(void*, int, int)": true,
+    "nsTraceRefcnt.cpp:void (* leakyLogRelease)(void*": true,
+    "nsTraceRefcnt.cpp:void (* leakyLogRelease)(void*, int, int)": true,
 };
 
 function indirectCallCannotGC(fullCaller, fullVariable)
 {
     var caller = readable(fullCaller);
 
     // This is usually a simple variable name, but sometimes a full name gets
     // passed through. And sometimes that name is truncated. Examples:
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -427,16 +427,17 @@ Is##base##AboutToBeFinalized(BarrieredPt
 }
 
 DeclMarkerImpl(BaseShape, BaseShape)
 DeclMarkerImpl(BaseShape, UnownedBaseShape)
 DeclMarkerImpl(JitCode, jit::JitCode)
 DeclMarkerImpl(Object, ArgumentsObject)
 DeclMarkerImpl(Object, ArrayBufferObject)
 DeclMarkerImpl(Object, ArrayBufferViewObject)
+DeclMarkerImpl(Object, SharedArrayBufferObject)
 DeclMarkerImpl(Object, DebugScopeObject)
 DeclMarkerImpl(Object, GlobalObject)
 DeclMarkerImpl(Object, JSObject)
 DeclMarkerImpl(Object, JSFunction)
 DeclMarkerImpl(Object, ObjectImpl)
 DeclMarkerImpl(Object, ScopeObject)
 DeclMarkerImpl(Script, JSScript)
 DeclMarkerImpl(LazyScript, LazyScript)
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -12,16 +12,17 @@
 class JSAtom;
 class JSLinearString;
 
 namespace js {
 
 class ArgumentsObject;
 class ArrayBufferObject;
 class ArrayBufferViewObject;
+class SharedArrayBufferObject;
 class BaseShape;
 class DebugScopeObject;
 struct GCMarker;
 class GlobalObject;
 class LazyScript;
 class ScopeObject;
 class Shape;
 class UnownedBaseShape;
@@ -92,16 +93,17 @@ bool Is##base##AboutToBeFinalized(type *
 bool Is##base##AboutToBeFinalized(BarrieredPtr<type> *thingp);                                 \
 
 DeclMarker(BaseShape, BaseShape)
 DeclMarker(BaseShape, UnownedBaseShape)
 DeclMarker(JitCode, jit::JitCode)
 DeclMarker(Object, ArgumentsObject)
 DeclMarker(Object, ArrayBufferObject)
 DeclMarker(Object, ArrayBufferViewObject)
+DeclMarker(Object, SharedArrayBufferObject)
 DeclMarker(Object, DebugScopeObject)
 DeclMarker(Object, GlobalObject)
 DeclMarker(Object, JSObject)
 DeclMarker(Object, JSFunction)
 DeclMarker(Object, ScopeObject)
 DeclMarker(Script, JSScript)
 DeclMarker(LazyScript, LazyScript)
 DeclMarker(Shape, Shape)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/sharedbuf/asm-link.js
@@ -0,0 +1,10 @@
+// Don't assert.
+function $(stdlib, foreign, heap) {
+    "use asm";
+    var Float64ArrayView = new stdlib.Float64Array(heap);
+    function f() {}
+    return f
+}
+
+if (typeof SharedArrayBuffer !== "undefined")
+    $(this, {}, new SharedArrayBuffer(4096));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/sharedbuf/gc-one-view.js
@@ -0,0 +1,10 @@
+// Test tracing of a single linked ArrayBufferViewObject.
+
+function f() {
+    var x = new SharedArrayBuffer(0x1000);
+    var y = new Int32Array(x);
+    gc();
+}
+
+if (typeof SharedArrayBuffer !== "undefined")
+    f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/sharedbuf/gc-two-views.js
@@ -0,0 +1,11 @@
+// Test tracing of two views of a SharedArrayBuffer. Uses a different path.
+
+function f() {
+    var x = new SharedArrayBuffer(0x1000);
+    var y = new Int32Array(x);
+    var z = new Int8Array(x);
+    gc();
+}
+
+if (typeof SharedArrayBuffer !== "undefined")
+    f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/sharedbuf/is-zeroed.js
@@ -0,0 +1,12 @@
+// Test that the SharedArrayBuffer memory is properly zeroed.
+
+function f() {
+    var x = new SharedArrayBuffer(4096);
+    var y = new Int32Array(x);
+    assertEq(y[0], 0);
+    assertEq(y[1], 0);
+    assertEq(y[1023], 0);
+}
+
+if (typeof SharedArrayBuffer !== "undefined")
+    f();
--- a/js/src/jit/AsmJS.h
+++ b/js/src/jit/AsmJS.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_AsmJS_h
 #define jit_AsmJS_h
 
 #include <stddef.h>
 
 #include "js/TypeDecls.h"
+#include "vm/ObjectImpl.h"
 
 namespace js {
 
 class ExclusiveContext;
 class AsmJSModule;
 class SPSProfiler;
 namespace frontend {
     template <typename ParseHandler> struct Parser;
@@ -86,17 +87,39 @@ RoundUpToNextValidAsmJSHeapLength(uint32
 extern bool
 IsValidAsmJSHeapLength(uint32_t length);
 
 #ifdef JS_CODEGEN_X64
 // On x64, the internal ArrayBuffer data array is inflated to 4GiB (only the
 // byteLength portion of which is accessible) so that out-of-bounds accesses
 // (made using a uint32 index) are guaranteed to raise a SIGSEGV.
 static const size_t AsmJSBufferProtectedSize = 4 * 1024ULL * 1024ULL * 1024ULL;
-#endif
+
+// To avoid dynamically checking bounds on each load/store, asm.js code relies
+// on the SIGSEGV handler in AsmJSSignalHandlers.cpp. However, this only works
+// if we can guarantee that *any* out-of-bounds access generates a fault. This
+// isn't generally true since an out-of-bounds access could land on other
+// Mozilla data. To overcome this on x64, we reserve an entire 4GB space,
+// making only the range [0, byteLength) accessible, and use a 32-bit unsigned
+// index into this space. (x86 and ARM require different tricks.)
+//
+// One complication is that we need to put an ObjectElements struct immediately
+// before the data array (as required by the general JSObject data structure).
+// Thus, we must stick a page before the elements to hold ObjectElements.
+//
+//   |<------------------------------ 4GB + 1 pages --------------------->|
+//           |<--- sizeof --->|<------------------- 4GB ----------------->|
+//
+//   | waste | ObjectElements | data array | inaccessible reserved memory |
+//                            ^            ^                              ^
+//                            |            \                             /
+//                      obj->elements       required to be page boundaries
+//
+static const size_t AsmJSMappedSize = AsmJSPageSize + AsmJSBufferProtectedSize;
+#endif // JS_CODEGEN_X64
 
 #ifdef JS_ION
 
 // Return whether asm.js optimization is inhibitted by the platform or
 // dynamically disabled:
 extern bool
 IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, JS::Value *vp);
 
--- a/js/src/jit/AsmJSLink.cpp
+++ b/js/src/jit/AsmJSLink.cpp
@@ -219,16 +219,48 @@ ValidateConstant(JSContext *cx, AsmJSMod
         if (v.toNumber() != global.constantValue())
             return LinkFail(cx, "global constant value mismatch");
     }
 
     return true;
 }
 
 static bool
+LinkModuleToHeap(JSContext *cx, AsmJSModule &module, Handle<ArrayBufferObject*> heap)
+{
+    if (!IsValidAsmJSHeapLength(heap->byteLength())) {
+        ScopedJSFreePtr<char> msg(
+            JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next "
+                        "valid length is 0x%x",
+                        heap->byteLength(),
+                        RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
+        return LinkFail(cx, msg.get());
+    }
+
+    // This check is sufficient without considering the size of the loaded datum because heap
+    // loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
+    JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
+    if (heap->byteLength() < module.minHeapLength()) {
+        ScopedJSFreePtr<char> msg(
+            JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the"
+                        "largest constant heap access offset rounded up to the next valid "
+                        "heap size).",
+                        heap->byteLength(),
+                        module.minHeapLength()));
+        return LinkFail(cx, msg.get());
+    }
+
+    if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
+        return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
+
+    module.initHeap(heap, cx);
+    return true;
+}
+
+static bool
 DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
 {
     module.setIsDynamicallyLinked();
 
     RootedValue globalVal(cx);
     if (args.length() > 0)
         globalVal = args[0];
 
@@ -240,44 +272,19 @@ DynamicallyLinkModule(JSContext *cx, Cal
     if (args.length() > 2)
         bufferVal = args[2];
 
     Rooted<ArrayBufferObject*> heap(cx);
     if (module.hasArrayView()) {
         if (!IsTypedArrayBuffer(bufferVal))
             return LinkFail(cx, "bad ArrayBuffer argument");
 
-        heap = &bufferVal.toObject().as<ArrayBufferObject>();
-
-        if (!IsValidAsmJSHeapLength(heap->byteLength())) {
-            ScopedJSFreePtr<char> msg(
-                JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next "
-                            "valid length is 0x%x",
-                            heap->byteLength(),
-                            RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
-            return LinkFail(cx, msg.get());
-        }
-
-        // This check is sufficient without considering the size of the loaded datum because heap
-        // loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
-        JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
-        if (heap->byteLength() < module.minHeapLength()) {
-            ScopedJSFreePtr<char> msg(
-                JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the"
-                            "largest constant heap access offset rounded up to the next valid "
-                            "heap size).",
-                            heap->byteLength(),
-                            module.minHeapLength()));
-            return LinkFail(cx, msg.get());
-        }
-
-        if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
-            return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
-
-        module.initHeap(heap, cx);
+        heap = &AsTypedArrayBuffer(bufferVal);
+        if (!LinkModuleToHeap(cx, module, heap))
+            return false;
     }
 
     AutoObjectVector ffis(cx);
     if (!ffis.resize(module.numFFIs()))
         return false;
 
     for (unsigned i = 0; i < module.numGlobals(); i++) {
         AsmJSModule::Global &global = module.global(i);
@@ -414,17 +421,16 @@ CallAsmJS(JSContext *cx, unsigned argc, 
         // pushed on a stack maintained by the runtime. This record is used for
         // to handle a variety of exceptional things that can happen in asm.js
         // code.
         AsmJSActivation activation(cx, module);
 
         // Eagerly push an IonContext+JitActivation so that the optimized
         // asm.js-to-Ion FFI call path (which we want to be very fast) can
         // avoid doing so.
-        jit::IonContext ictx(cx, nullptr);
         JitActivation jitActivation(cx, /* firstFrameIsConstructing = */ false, /* active */ false);
 
         // Call the per-exported-function trampoline created by GenerateEntry.
         AsmJSModule::CodePtr enter = module.entryTrampoline(func);
         if (!CALL_GENERATED_ASMJS(enter, coercedArgs.begin(), module.globalData()))
             return false;
     }
 
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -44,33 +44,34 @@ SnapshotIterator::SnapshotIterator(const
     ionScript_(iter.ionScript())
 {
 }
 
 void
 IonBailoutIterator::dump() const
 {
     if (type_ == IonFrame_OptimizedJS) {
-        InlineFrameIterator frames(GetIonContext()->cx, this);
+        InlineFrameIterator frames(GetJSContextFromJitCode(), this);
         for (;;) {
             frames.dump();
             if (!frames.more())
                 break;
             ++frames;
         }
     } else {
         IonFrameIterator::dump();
     }
 }
 
 uint32_t
 jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
 {
+    JSContext *cx = GetJSContextFromJitCode();
     JS_ASSERT(bailoutInfo);
-    JSContext *cx = GetIonContext()->cx;
+
     // We don't have an exit frame.
     cx->mainThread().ionTop = nullptr;
     JitActivationIterator jitActivations(cx->runtime());
     IonBailoutIterator iter(jitActivations, sp);
     JitActivation *activation = jitActivations.activation()->asJit();
 
     IonSpew(IonSpew_Bailouts, "Took bailout! Snapshot offset: %d", iter.snapshotOffset());
 
@@ -90,17 +91,17 @@ jit::Bailout(BailoutStack *sp, BaselineB
 }
 
 uint32_t
 jit::InvalidationBailout(InvalidationBailoutStack *sp, size_t *frameSizeOut,
                          BaselineBailoutInfo **bailoutInfo)
 {
     sp->checkInvariants();
 
-    JSContext *cx = GetIonContext()->cx;
+    JSContext *cx = GetJSContextFromJitCode();
 
     // We don't have an exit frame.
     cx->mainThread().ionTop = nullptr;
     JitActivationIterator jitActivations(cx->runtime());
     IonBailoutIterator iter(jitActivations, sp);
     JitActivation *activation = jitActivations.activation()->asJit();
 
     IonSpew(IonSpew_Bailouts, "Took invalidation bailout! Snapshot offset: %d", iter.snapshotOffset());
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1411,17 +1411,17 @@ HandleBaselineInfoBailout(JSContext *cx,
     return Invalidate(cx, outerScript);
 }
 
 uint32_t
 jit::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
 {
     // The caller pushes R0 and R1 on the stack without rooting them.
     // Since GC here is very unlikely just suppress it.
-    JSContext *cx = GetIonContext()->cx;
+    JSContext *cx = GetJSContextFromJitCode();
     js::gc::AutoSuppressGC suppressGC(cx);
 
     IonSpew(IonSpew_BaselineBailouts, "  Done restoring frames");
 
     // Check that we can get the current script's PC.
 #ifdef DEBUG
     jsbytecode *pc;
     cx->currentScript(&pc);
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -450,17 +450,17 @@ BaselineCompiler::emitIC(ICStub *stub, b
 typedef bool (*CheckOverRecursedWithExtraFn)(JSContext *, BaselineFrame *, uint32_t, uint32_t);
 static const VMFunction CheckOverRecursedWithExtraInfo =
     FunctionInfo<CheckOverRecursedWithExtraFn>(CheckOverRecursedWithExtra);
 
 bool
 BaselineCompiler::emitStackCheck(bool earlyCheck)
 {
     Label skipCall;
-    uintptr_t *limitAddr = &cx->runtime()->mainThread.ionStackLimit;
+    uintptr_t *limitAddr = &cx->runtime()->mainThread.jitStackLimit;
     uint32_t slotsSize = script->nslots() * sizeof(Value);
     uint32_t tolerance = earlyCheck ? slotsSize : 0;
 
     masm.movePtr(BaselineStackReg, R1.scratchReg());
 
     // If this is the early stack check, locals haven't been pushed yet.  Adjust the
     // stack pointer to account for the locals that would be pushed before performing
     // the guard around the vmcall to the stack check.
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -178,17 +178,17 @@ BaselineFrame::initForOsr(StackFrame *fp
         BaselineFrame::Size() +
         numStackValues * sizeof(Value);
 
     JS_ASSERT(numValueSlots() == numStackValues);
 
     for (uint32_t i = 0; i < numStackValues; i++)
         *valueSlot(i) = fp->slots()[i];
 
-    JSContext *cx = GetIonContext()->cx;
+    JSContext *cx = GetJSContextFromJitCode();
     if (cx->compartment()->debugMode()) {
         // In debug mode, update any Debugger.Frame objects for the StackFrame to
         // point to the BaselineFrame.
 
         // The caller pushed a fake return address. ScriptFrameIter, used by the
         // debugger, wants a valid return address, but it's okay to just pick one.
         // In debug mode there's always at least 1 ICEntry (since there are always
         // debug prologue/epilogue calls).
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -572,16 +572,17 @@ ICStubCompiler::getStubCode()
 
     // Check for existing cached stubcode.
     uint32_t stubKey = getKey();
     JitCode *stubCode = comp->getStubCode(stubKey);
     if (stubCode)
         return stubCode;
 
     // Compile new stubcode.
+    IonContext ictx(cx, nullptr);
     MacroAssembler masm;
 #ifdef JS_CODEGEN_ARM
     masm.setSecondScratchReg(BaselineSecondScratchReg);
 #endif
 
     AutoFlushCache afc("ICStubCompiler::getStubCode", cx->runtime()->jitRuntime());
     if (!generateStubCode(masm))
         return nullptr;
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -103,17 +103,16 @@ EnterBaseline(JSContext *cx, EnterJitDat
     EnterJitCode enter = cx->runtime()->jitRuntime()->enterBaseline();
 
     // Caller must construct |this| before invoking the Ion function.
     JS_ASSERT_IF(data.constructing, data.maxArgv[0].isObject());
 
     data.result.setInt32(data.numActualArgs);
     {
         AssertCompartmentUnchanged pcc(cx);
-        IonContext ictx(cx, nullptr);
         JitActivation activation(cx, data.constructing);
         JSAutoResolveFlags rf(cx, RESOLVE_INFER);
         AutoFlushInhibitor afi(cx->runtime()->jitRuntime());
 
         if (data.osrFrame)
             data.osrFrame->setRunningInJit();
 
         JS_ASSERT_IF(data.osrFrame, !IsJSDEnabled(cx));
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2736,17 +2736,17 @@ CodeGenerator::visitCheckOverRecursed(LC
     // crossed, an error must be thrown, which requires more frames.
     //
     // It must always be possible to trespass past the stack limit.
     // Ion may legally place frames very close to the limit. Calling additional
     // C functions may then violate the limit without any checking.
 
     // Since Ion frames exist on the C stack, the stack limit may be
     // dynamically set by JS_SetThreadStackLimit() and JS_SetNativeStackQuota().
-    const void *limitAddr = GetIonContext()->runtime->addressOfIonStackLimit();
+    const void *limitAddr = GetIonContext()->runtime->addressOfJitStackLimit();
 
     CheckOverRecursedFailure *ool = new(alloc()) CheckOverRecursedFailure(lir);
     if (!addOutOfLineCode(ool))
         return false;
 
     // Conditional forward (unlikely) branch to failure.
     masm.branchPtr(Assembler::AboveOrEqual, AbsoluteAddress(limitAddr), StackPointer, ool->entry());
     masm.bind(ool->rejoin());
@@ -2829,27 +2829,27 @@ class CheckOverRecursedFailurePar : publ
         return lir_;
     }
 };
 
 bool
 CodeGenerator::visitCheckOverRecursedPar(LCheckOverRecursedPar *lir)
 {
     // See above: unlike visitCheckOverRecursed(), this code runs in
-    // parallel mode and hence uses the ionStackLimit from the current
+    // parallel mode and hence uses the jitStackLimit from the current
     // thread state.  Also, we must check the interrupt flags because
     // on interrupt or abort, only the stack limit for the main thread
     // is reset, not the worker threads.  See comment in vm/ForkJoin.h
     // for more details.
 
     Register cxReg = ToRegister(lir->forkJoinContext());
     Register tempReg = ToRegister(lir->getTempReg());
 
     masm.loadPtr(Address(cxReg, offsetof(ForkJoinContext, perThreadData)), tempReg);
-    masm.loadPtr(Address(tempReg, offsetof(PerThreadData, ionStackLimit)), tempReg);
+    masm.loadPtr(Address(tempReg, offsetof(PerThreadData, jitStackLimit)), tempReg);
 
     // Conditional forward (unlikely) branch to failure.
     CheckOverRecursedFailurePar *ool = new(alloc()) CheckOverRecursedFailurePar(lir);
     if (!addOutOfLineCode(ool))
         return false;
     masm.branchPtr(Assembler::BelowOrEqual, StackPointer, tempReg, ool->entry());
     masm.checkInterruptFlagPar(tempReg, ool->entry());
     masm.bind(ool->rejoin());
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -29,25 +29,25 @@ CompileRuntime::onMainThread()
 
 const void *
 CompileRuntime::addressOfIonTop()
 {
     return &runtime()->mainThread.ionTop;
 }
 
 const void *
-CompileRuntime::addressOfIonStackLimit()
+CompileRuntime::addressOfJitStackLimit()
 {
-    return &runtime()->mainThread.ionStackLimit;
+    return &runtime()->mainThread.jitStackLimit;
 }
 
 const void *
 CompileRuntime::addressOfJSContext()
 {
-    return &runtime()->mainThread.ionJSContext;
+    return &runtime()->mainThread.jitJSContext;
 }
 
 const void *
 CompileRuntime::addressOfActivation()
 {
     return runtime()->mainThread.addressOfActivation();
 }
 
@@ -74,16 +74,22 @@ CompileRuntime::addressOfInterrupt()
 #ifdef JS_THREADSAFE
 const void *
 CompileRuntime::addressOfInterruptPar()
 {
     return &runtime()->interruptPar;
 }
 #endif
 
+const void *
+CompileRuntime::addressOfThreadPool()
+{
+    return &runtime()->threadPool;
+}
+
 const JitRuntime *
 CompileRuntime::jitRuntime()
 {
     return runtime()->jitRuntime();
 }
 
 SPSProfiler &
 CompileRuntime::spsProfiler()
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -29,18 +29,18 @@ class CompileRuntime
   public:
     static CompileRuntime *get(JSRuntime *rt);
 
     bool onMainThread();
 
     // &mainThread.ionTop
     const void *addressOfIonTop();
 
-    // rt->mainThread.ionStackLimit;
-    const void *addressOfIonStackLimit();
+    // rt->mainThread.jitStackLimit;
+    const void *addressOfJitStackLimit();
 
     // &mainThread.ionJSContext
     const void *addressOfJSContext();
 
     // &mainThread.activation_
     const void *addressOfActivation();
 
     // &GetIonContext()->runtime->nativeIterCache.last
@@ -51,16 +51,18 @@ class CompileRuntime
 #endif
 
     const void *addressOfInterrupt();
 
 #ifdef JS_THREADSAFE
     const void *addressOfInterruptPar();
 #endif
 
+    const void *addressOfThreadPool();
+
     const JitRuntime *jitRuntime();
 
     // Compilation does not occur off thread when the SPS profiler is enabled.
     SPSProfiler &spsProfiler();
 
     bool signalHandlersInstalled();
     bool jitSupportsFloatingPoint();
     bool hadOutOfMemory();
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -152,16 +152,17 @@ JitRuntime::JitRuntime()
     bailoutTail_(nullptr),
     enterJIT_(nullptr),
     bailoutHandler_(nullptr),
     argumentsRectifier_(nullptr),
     argumentsRectifierReturnAddr_(nullptr),
     parallelArgumentsRectifier_(nullptr),
     invalidator_(nullptr),
     debugTrapHandler_(nullptr),
+    forkJoinGetSliceStub_(nullptr),
     functionWrappers_(nullptr),
     osrTempData_(nullptr),
     flusher_(nullptr),
     ionCodeProtected_(false)
 {
 }
 
 JitRuntime::~JitRuntime()
@@ -283,16 +284,28 @@ JitRuntime::debugTrapHandler(JSContext *
         // be allocated in the atoms compartment.
         AutoLockForExclusiveAccess lock(cx);
         AutoCompartment ac(cx, cx->runtime()->atomsCompartment());
         debugTrapHandler_ = generateDebugTrapHandler(cx);
     }
     return debugTrapHandler_;
 }
 
+bool
+JitRuntime::ensureForkJoinGetSliceStubExists(JSContext *cx)
+{
+    if (!forkJoinGetSliceStub_) {
+        IonSpew(IonSpew_Codegen, "# Emitting ForkJoinGetSlice stub");
+        AutoLockForExclusiveAccess lock(cx);
+        AutoCompartment ac(cx, cx->runtime()->atomsCompartment());
+        forkJoinGetSliceStub_ = generateForkJoinGetSliceStub(cx);
+    }
+    return !!forkJoinGetSliceStub_;
+}
+
 uint8_t *
 JitRuntime::allocateOsrTempData(size_t size)
 {
     osrTempData_ = (uint8_t *)js_realloc(osrTempData_, size);
     return osrTempData_;
 }
 
 void
@@ -1662,16 +1675,23 @@ IonCompile(JSContext *cx, JSScript *scri
     types::AutoEnterAnalysis enter(cx);
 
     if (!cx->compartment()->ensureJitCompartmentExists(cx))
         return AbortReason_Alloc;
 
     if (!cx->compartment()->jitCompartment()->ensureIonStubsExist(cx))
         return AbortReason_Alloc;
 
+    if (executionMode == ParallelExecution &&
+        LIRGenerator::allowInlineForkJoinGetSlice() &&
+        !cx->runtime()->jitRuntime()->ensureForkJoinGetSliceStubExists(cx))
+    {
+        return AbortReason_Alloc;
+    }
+
     MIRGraph *graph = alloc->new_<MIRGraph>(temp);
     if (!graph)
         return AbortReason_Alloc;
 
     CompileInfo *info = alloc->new_<CompileInfo>(script, script->functionNonDelazifying(), osrPc,
                                                  constructing, executionMode,
                                                  script->needsArgsObj());
     if (!info)
@@ -2222,17 +2242,16 @@ EnterIon(JSContext *cx, EnterJitData &da
     EnterJitCode enter = cx->runtime()->jitRuntime()->enterIon();
 
     // Caller must construct |this| before invoking the Ion function.
     JS_ASSERT_IF(data.constructing, data.maxArgv[0].isObject());
 
     data.result.setInt32(data.numActualArgs);
     {
         AssertCompartmentUnchanged pcc(cx);
-        IonContext ictx(cx, nullptr);
         JitActivation activation(cx, data.constructing);
         JSAutoResolveFlags rf(cx, RESOLVE_INFER);
         AutoFlushInhibitor afi(cx->runtime()->jitRuntime());
 
         CALL_GENERATED_CODE(enter, data.jitcode, data.maxArgc, data.maxArgv, /* osrFrame = */nullptr, data.calleeToken,
                             /* scopeChain = */ nullptr, 0, data.result.address());
     }
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -669,16 +669,19 @@ class IonBuilder : public MIRGenerator
     InliningStatus inlineNewDenseArray(CallInfo &callInfo);
     InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
     InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo);
 
     // Slot intrinsics.
     InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo);
     InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo);
 
+    // ForkJoin intrinsics
+    InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo);
+
     // Utility intrinsics.
     InliningStatus inlineIsCallable(CallInfo &callInfo);
     InliningStatus inlineHaveSameClass(CallInfo &callInfo);
     InliningStatus inlineToObject(CallInfo &callInfo);
     InliningStatus inlineDump(CallInfo &callInfo);
     InliningStatus inlineHasClass(CallInfo &callInfo, const Class *clasp);
 
     // Testing functions.
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -566,17 +566,17 @@ HandleExceptionBaseline(JSContext *cx, c
         }
     }
 
 }
 
 void
 HandleException(ResumeFromException *rfe)
 {
-    JSContext *cx = GetIonContext()->cx;
+    JSContext *cx = GetJSContextFromJitCode();
 
     rfe->kind = ResumeFromException::RESUME_ENTRY_FRAME;
 
     IonSpew(IonSpew_Invalidate, "handling exception");
 
     // Clear any Ion return override that's been set.
     // This may happen if a callVM function causes an invalidation (setting the
     // override), and then fails, bypassing the bailout handlers that would
@@ -1646,17 +1646,17 @@ MachineState::FromBailout(mozilla::Array
 }
 
 template <AllowGC allowGC>
 bool
 InlineFrameIteratorMaybeGC<allowGC>::isConstructing() const
 {
     // Skip the current frame and look at the caller's.
     if (more()) {
-        InlineFrameIteratorMaybeGC<allowGC> parent(GetIonContext()->cx, this);
+        InlineFrameIteratorMaybeGC<allowGC> parent(GetJSContextFromJitCode(), this);
         ++parent;
 
         // Inlined Getters and Setters are never constructing.
         if (IsGetPropPC(parent.pc()) || IsSetPropPC(parent.pc()))
             return false;
 
         // In the case of a JS frame, look up the pc from the snapshot.
         JS_ASSERT(IsCallPC(parent.pc()));
@@ -1676,17 +1676,17 @@ IonFrameIterator::isConstructing() const
 
     // Skip the current frame and look at the caller's.
     do {
         ++parent;
     } while (!parent.done() && !parent.isScripted());
 
     if (parent.isOptimizedJS()) {
         // In the case of a JS frame, look up the pc from the snapshot.
-        InlineFrameIterator inlinedParent(GetIonContext()->cx, &parent);
+        InlineFrameIterator inlinedParent(GetJSContextFromJitCode(), &parent);
 
         //Inlined Getters and Setters are never constructing.
         if (IsGetPropPC(inlinedParent.pc()) || IsSetPropPC(inlinedParent.pc()))
             return false;
 
         JS_ASSERT(IsCallPC(inlinedParent.pc()));
 
         return (JSOp)*inlinedParent.pc() == JSOP_NEW;
@@ -1756,17 +1756,17 @@ IonFrameIterator::dumpBaseline() const
 #endif
     } else {
         fprintf(stderr, "  global frame, no callee\n");
     }
 
     fprintf(stderr, "  file %s line %u\n",
             script()->filename(), (unsigned) script()->lineno());
 
-    JSContext *cx = GetIonContext()->cx;
+    JSContext *cx = GetJSContextFromJitCode();
     RootedScript script(cx);
     jsbytecode *pc;
     baselineScriptAndPc(script.address(), &pc);
 
     fprintf(stderr, "  script = %p, pc = %p (offset %u)\n", (void *)script, pc, uint32_t(script->pcToOffset(pc)));
     fprintf(stderr, "  current op: %s\n", js_CodeName[*pc]);
 
     fprintf(stderr, "  actual args: %d\n", numActualArgs());
@@ -1824,17 +1824,17 @@ InlineFrameIteratorMaybeGC<allowGC>::dum
                 fprintf(stderr, "  scope chain: ");
             else if (i == 1)
                 fprintf(stderr, "  this: ");
             else if (i - 2 < callee()->nargs())
                 fprintf(stderr, "  formal (arg %d): ", i - 2);
             else {
                 if (i - 2 == callee()->nargs() && numActualArgs() > callee()->nargs()) {
                     DumpOp d(callee()->nargs());
-                    forEachCanonicalActualArg(GetIonContext()->cx, d, d.i_, numActualArgs() - d.i_);
+                    forEachCanonicalActualArg(GetJSContextFromJitCode(), d, d.i_, numActualArgs() - d.i_);
                 }
 
                 fprintf(stderr, "  slot %d: ", int(i - 2 - callee()->nargs()));
             }
         } else
             fprintf(stderr, "  slot %u: ", i);
 #ifdef DEBUG
         js_DumpValue(si.maybeRead());
@@ -1861,17 +1861,17 @@ IonFrameIterator::dump() const
         break;
       case IonFrame_BaselineStub:
       case IonFrame_Unwound_BaselineStub:
         fprintf(stderr, " Baseline stub frame\n");
         fprintf(stderr, "  Frame size: %u\n", unsigned(current()->prevFrameLocalSize()));
         break;
       case IonFrame_OptimizedJS:
       {
-        InlineFrameIterator frames(GetIonContext()->cx, this);
+        InlineFrameIterator frames(GetJSContextFromJitCode(), this);
         for (;;) {
             frames.dump();
             if (!frames.more())
                 break;
             ++frames;
         }
         break;
       }
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -372,16 +372,20 @@ class MacroAssembler : public MacroAssem
         loadPtr(Address(dest, types::TypeObject::offsetOfProto()), dest);
     }
 
     void loadStringLength(Register str, Register dest) {
         loadPtr(Address(str, JSString::offsetOfLengthAndFlags()), dest);
         rshiftPtr(Imm32(JSString::LENGTH_SHIFT), dest);
     }
 
+    void loadSliceBounds(Register worker, Register dest) {
+        loadPtr(Address(worker, ThreadPoolWorker::offsetOfSliceBounds()), dest);
+    }
+
     void loadJSContext(const Register &dest) {
         loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfJSContext()), dest);
     }
     void loadJitActivation(const Register &dest) {
         loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfActivation()), dest);
     }
 
     template<typename T>
@@ -828,16 +832,22 @@ class MacroAssembler : public MacroAssem
         Push(ImmPtr(f));
     }
     void enterFakeExitFrame(JitCode *codeVal = nullptr) {
         linkExitFrame();
         Push(ImmPtr(codeVal));
         Push(ImmPtr(nullptr));
     }
 
+    void loadThreadPool(Register pool) {
+        // JitRuntimes are tied to JSRuntimes and there is one ThreadPool per
+        // JSRuntime, so we can hardcode the ThreadPool address here.
+        movePtr(ImmPtr(GetIonContext()->runtime->addressOfThreadPool()), pool);
+    }
+
     void loadForkJoinContext(Register cx, Register scratch);
     void loadContext(Register cxReg, Register scratch, ExecutionMode executionMode);
 
     void enterParallelExitFrameAndLoadContext(const VMFunction *f, Register cx,
                                               Register scratch);
 
     void enterExitFrameAndLoadContext(const VMFunction *f, Register cxReg, Register scratch,
                                       ExecutionMode executionMode);
--- a/js/src/jit/JitCompartment.h
+++ b/js/src/jit/JitCompartment.h
@@ -184,16 +184,19 @@ class JitRuntime
 
     // Thunk that calls the GC pre barrier.
     JitCode *valuePreBarrier_;
     JitCode *shapePreBarrier_;
 
     // Thunk used by the debugger for breakpoint and step mode.
     JitCode *debugTrapHandler_;
 
+    // Stub used to inline the ForkJoinGetSlice intrinsic.
+    JitCode *forkJoinGetSliceStub_;
+
     // Map VMFunction addresses to the JitCode of the wrapper.
     typedef WeakCache<const VMFunction *, JitCode *> VMWrapperMap;
     VMWrapperMap *functionWrappers_;
 
     // Buffer for OSR from baseline to Ion. To avoid holding on to this for
     // too long, it's also freed in JitCompartment::mark and in EnterBaseline
     // (after returning from JIT code).
     uint8_t *osrTempData_;
@@ -214,16 +217,17 @@ class JitRuntime
     JitCode *generateBailoutTailStub(JSContext *cx);
     JitCode *generateEnterJIT(JSContext *cx, EnterJitType type);
     JitCode *generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut);
     JitCode *generateBailoutTable(JSContext *cx, uint32_t frameClass);
     JitCode *generateBailoutHandler(JSContext *cx);
     JitCode *generateInvalidator(JSContext *cx);
     JitCode *generatePreBarrier(JSContext *cx, MIRType type);
     JitCode *generateDebugTrapHandler(JSContext *cx);
+    JitCode *generateForkJoinGetSliceStub(JSContext *cx);
     JitCode *generateVMWrapper(JSContext *cx, const VMFunction &f);
 
     JSC::ExecutableAllocator *createIonAlloc(JSContext *cx);
 
   public:
     JitRuntime();
     ~JitRuntime();
     bool initialize(JSContext *cx);
@@ -316,16 +320,21 @@ class JitRuntime
 
     JitCode *valuePreBarrier() const {
         return valuePreBarrier_;
     }
 
     JitCode *shapePreBarrier() const {
         return shapePreBarrier_;
     }
+
+    bool ensureForkJoinGetSliceStubExists(JSContext *cx);
+    JitCode *forkJoinGetSliceStub() const {
+        return forkJoinGetSliceStub_;
+    }
 };
 
 class JitCompartment
 {
     friend class JitActivation;
 
     // Ion state for the compartment's runtime.
     JitRuntime *rt;
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -4780,16 +4780,48 @@ class LForkJoinContext : public LCallIns
         setTemp(0, temp1);
     }
 
     const LDefinition *getTempReg() {
         return getTemp(0);
     }
 };
 
+class LForkJoinGetSlice : public LInstructionHelper<1, 1, 4>
+{
+  public:
+    LIR_HEADER(ForkJoinGetSlice);
+
+    LForkJoinGetSlice(const LAllocation &cx,
+                      const LDefinition &temp1, const LDefinition &temp2,
+                      const LDefinition &temp3, const LDefinition &temp4) {
+        setOperand(0, cx);
+        setTemp(0, temp1);
+        setTemp(1, temp2);
+        setTemp(2, temp3);
+        setTemp(3, temp4);
+    }
+
+    const LAllocation *forkJoinContext() {
+        return getOperand(0);
+    }
+    const LDefinition *temp1() {
+        return getTemp(0);
+    }
+    const LDefinition *temp2() {
+        return getTemp(1);
+    }
+    const LDefinition *temp3() {
+        return getTemp(2);
+    }
+    const LDefinition *temp4() {
+        return getTemp(3);
+    }
+};
+
 class LCallGetProperty : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallGetProperty)
 
     static const size_t Value = 0;
 
     MCallGetProperty *mir() const {
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -209,16 +209,17 @@
     _(ClampDToUint8)                \
     _(ClampVToUint8)                \
     _(LoadFixedSlotV)               \
     _(LoadFixedSlotT)               \
     _(StoreFixedSlotV)              \
     _(StoreFixedSlotT)              \
     _(FunctionEnvironment)          \
     _(ForkJoinContext)              \
+    _(ForkJoinGetSlice)             \
     _(GetPropertyCacheV)            \
     _(GetPropertyCacheT)            \
     _(GetPropertyPolymorphicV)      \
     _(GetPropertyPolymorphicT)      \
     _(GetElementCacheV)             \
     _(GetElementCacheT)             \
     _(BindNameCache)                \
     _(CallGetProperty)              \
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -141,16 +141,18 @@ IonBuilder::inlineNativeCall(CallInfo &c
         return inlineUnsafeSetReservedSlot(callInfo);
     if (native == intrinsic_UnsafeGetReservedSlot)
         return inlineUnsafeGetReservedSlot(callInfo);
 
     // Parallel intrinsics.
     if (native == intrinsic_ShouldForceSequential ||
         native == intrinsic_InParallelSection)
         return inlineForceSequentialOrInParallelSection(callInfo);
+    if (native == intrinsic_ForkJoinGetSlice)
+        return inlineForkJoinGetSlice(callInfo);
 
     // Utility intrinsics.
     if (native == intrinsic_IsCallable)
         return inlineIsCallable(callInfo);
     if (native == intrinsic_HaveSameClass)
         return inlineHaveSameClass(callInfo);
     if (native == intrinsic_ToObject)
         return inlineToObject(callInfo);
@@ -1385,16 +1387,50 @@ IonBuilder::inlineForceSequentialOrInPar
         return InliningStatus_Inlined;
       }
     }
 
     MOZ_ASSUME_UNREACHABLE("Invalid execution mode");
 }
 
 IonBuilder::InliningStatus
+IonBuilder::inlineForkJoinGetSlice(CallInfo &callInfo)
+{
+    if (info().executionMode() != ParallelExecution)
+        return InliningStatus_NotInlined;
+
+    // Assert the way the function is used instead of testing, as it is a
+    // self-hosted function which must be used in a particular fashion.
+    MOZ_ASSERT(callInfo.argc() == 1 && !callInfo.constructing());
+    MOZ_ASSERT(callInfo.getArg(0)->type() == MIRType_Int32);
+    MOZ_ASSERT(getInlineReturnType() == MIRType_Int32);
+
+    callInfo.setImplicitlyUsedUnchecked();
+
+    switch (info().executionMode()) {
+      case SequentialExecution:
+      case DefinitePropertiesAnalysis:
+        // ForkJoinGetSlice acts as identity for sequential execution.
+        current->push(callInfo.getArg(0));
+        return InliningStatus_Inlined;
+      case ParallelExecution:
+        if (LIRGenerator::allowInlineForkJoinGetSlice()) {
+            MForkJoinGetSlice *getSlice = MForkJoinGetSlice::New(alloc(),
+                                                                 graph().forkJoinContext());
+            current->add(getSlice);
+            current->push(getSlice);
+            return InliningStatus_Inlined;
+        }
+        return InliningStatus_NotInlined;
+    }
+
+    MOZ_ASSUME_UNREACHABLE("Invalid execution mode");
+}
+
+IonBuilder::InliningStatus
 IonBuilder::inlineNewDenseArray(CallInfo &callInfo)
 {
     if (callInfo.constructing() || callInfo.argc() != 1)
         return InliningStatus_NotInlined;
 
     // For now, in seq. mode we just call the C function.  In
     // par. mode we use inlined MIR.
     ExecutionMode executionMode = info().executionMode();
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7484,16 +7484,43 @@ class MForkJoinContext
         return AliasSet::None();
     }
 
     bool possiblyCalls() const {
         return true;
     }
 };
 
+// Calls the ForkJoinGetSlice stub, used for inlining the eponymous intrinsic.
+// Only applicable in ParallelExecution.
+class MForkJoinGetSlice
+  : public MUnaryInstruction
+{
+    MForkJoinGetSlice(MDefinition *cx)
+      : MUnaryInstruction(cx)
+    {
+        setResultType(MIRType_Int32);
+    }
+
+  public:
+    INSTRUCTION_HEADER(ForkJoinGetSlice);
+
+    static MForkJoinGetSlice *New(TempAllocator &alloc, MDefinition *cx) {
+        return new(alloc) MForkJoinGetSlice(cx);
+    }
+
+    MDefinition *forkJoinContext() {
+        return getOperand(0);
+    }
+
<