merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 30 May 2016 15:29:19 +0200
changeset 372909 3435dd7ad71fe9003bdeee18fd38d815e033beef
parent 372838 cad514ad49c199e823a92e8c8d27e16c22c3cac7 (current diff)
parent 372908 e0d0d87fb7d3e2d60a0bd552fadcad7640c58a35 (diff)
child 372910 7dcc890c12a81ad6ce5ae9ff5a29eccf9137112b
child 372925 373d3a3e1b27b66faeea09747ce9404e9775ae3b
child 372927 481b1c001f7df0a005e7095b12d11439c9ca87fe
child 372995 392b592c2fe40d176119896cf87daa81dd38fc85
child 373018 5b5d3c73e3801ba10d7c5f553d8d2ff096c37a16
child 373019 a01391c6fed694806f383ec3c877e9433f0e9304
child 373020 1567d188400f3b4424fe27467b20f4406a857e6a
child 373026 39be5603ac9b49661d3e825e137152ae462826a3
child 373029 4a337690902d1c8d7f064281790d440e9b6ddc68
child 373054 b1bcde9bfa290b05a435661b8774dd0c9f3f82bb
child 373055 0f79e820a9e1728254c7d84c2874740e009041d8
child 373056 635efa0b0ce8807099899dccd0d810bfe0da1a36
child 373057 ef74bcafe720a23ed69ed351e2e4301429d61f8c
child 373059 c410afedc8ddfe63f9d7b7685d6ca085d0f908fb
child 373061 3e4ee4b583e09a481ec4ff80ebe87890c70a28e0
child 373067 bd94d427edb34d80ae495f5198b9cb85867d2f4f
child 373068 f08656a34ae1fa55c36d7d8d38707541ac360ba2
child 373080 e02d7da544dfe0813f6137526a28567f4f343057
child 373082 c7b690b20854d42c2ae90c930795a78e811a58b1
child 373087 31e80760afaba343f66ea699aa1716d6295db457
child 373091 cb4c4c64730a28ecb40a81ad807c740a461f17be
child 373115 44ebc6a88ab95413bbff8bef18478e4b6bc2c9c4
child 373172 3c1da36b0a4aa9fe36ccf6179365d9e0311f76b8
child 373175 b48b8a75e128e37f3d80da771c50dfce56a8f100
child 373176 7bc309aa7ef90e8ced68ff961fe5c1748caed11f
child 373180 3b7f487f4204677453a4475c013e50c5cd33ce43
child 373217 4c7d65243dd9a1b029b962919b3f57ace6107880
child 373231 9ff2973f162d2753fc9135e44b39f4e01eace722
child 373235 4b58ee68c789bffdfb7ae7f461460cb9cf7bb726
child 373248 8fb095b5cb10a17d97bd864b6833285679d997ce
child 373292 3495d1857f3984010abf75922e0e63bfec7ad8fe
child 373308 2f06237f96ef2b1cb2becfa27b2377766452936c
child 373322 9c69f52c434f365b35cc370f472d1dd69baf26d2
child 373350 7852964305f20d42f47219553e69fe14e49a741c
child 373351 200021a2aaf1d4fc540dfe75b444c269b8ff06b2
child 373352 321c1837843bf3e3824c6a74966b74ed91fd8a74
child 373492 0f8cfe6c204aeaa8083a2601bcfe5f3513215e10
child 373646 c1fb512d8497e7f5a02cf553b16cb830859fcae7
child 373753 9b7082c5a38e6ab444450ea9a431cef26fbd1c41
child 373836 527369a342787ec4a9a8674768637de71191539f
child 373864 af87caac8c6a4dbe008d9cc1a9e84540f30cba4c
child 373943 fea1a0fbae1bf11956ad5bf5e4bd21190e5ba53c
child 373999 d6e6d81c6f030e24e59b320aee1944e3cff65b4e
child 374207 da950d23f132265820b36bb53a7d38b6e1c9f65e
child 374254 089b794b4d63c14110232e920073bc4b98ae84b7
child 374277 c8186e96a8e1298be725331e6da56417301cd20b
child 374369 47d5dedb29e4e45479001d0ad4ef4070f4b17db1
child 374940 4223bc836af5d342ef3e8105a371281bcf3a2ab2
child 375264 908c5469bcf1211bcced8542835570836b8a7e8a
child 375410 4572b110fe1c7da0f6ea24bdcf6120322d2b7765
child 375411 505ec796021ac22e4dd0f32d4839a15f6cc04810
push id19630
push userpbrosset@mozilla.com
push dateMon, 30 May 2016 15:41:42 +0000
reviewersmerge
milestone49.0a1
merge mozilla-inbound to mozilla-central a=merge
dom/media/FlushableTaskQueue.cpp
dom/media/FlushableTaskQueue.h
ipc/chromium/src/base/buffer.cc
ipc/chromium/src/base/buffer.h
js/src/jit-test/tests/basic/save-frame-chain.js
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.h
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.mm
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.h
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.mm
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info_objc.h
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info_objc.mm
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.h
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.mm
media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h
mfbt/Endian.h
modules/libpref/init/all.js
testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/meta-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/meta-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
--- a/accessible/tests/browser/.eslintrc
+++ b/accessible/tests/browser/.eslintrc
@@ -9,16 +9,17 @@
 
     // Defined in accessible/tests/mochitest/ common.js, name.js, states.js
     "prettyName": true,
     "statesToString": true,
     "eventTypeToString": true,
     "testName": true,
     "testDescr": true,
     "testStates": true,
+    "testRelation": true,
     "testAccessibleTree": true,
     "isAccessible": true,
     "getAccessibleDOMNodeID": true,
 
     // Defined for all accessibility browser tests.
     "addAccessibleTask": true,
     "BrowserTestUtils": true,
     "ContentTask": true,
--- a/accessible/tests/browser/browser.ini
+++ b/accessible/tests/browser/browser.ini
@@ -12,16 +12,18 @@ support-files =
   !/accessible/tests/mochitest/*.js
   !/accessible/tests/mochitest/letters.gif
   !/accessible/tests/mochitest/moz.png
 
 # Caching tests
 [browser_caching_description.js]
 [browser_caching_name.js]
 skip-if = e10s
+[browser_caching_relations.js]
+[browser_caching_states.js]
 
 # Events tests
 [browser_events_caretmove.js]
 [browser_events_hide.js]
 [browser_events_show.js]
 [browser_events_statechange.js]
 [browser_events_textchange.js]
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/browser_caching_relations.js
@@ -0,0 +1,86 @@
+/* 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/. */
+
+'use strict';
+
+/* global RELATION_LABELLED_BY, RELATION_LABEL_FOR, RELATION_DESCRIBED_BY,
+          RELATION_DESCRIPTION_FOR, RELATION_CONTROLLER_FOR,
+          RELATION_CONTROLLED_BY, RELATION_FLOWS_TO, RELATION_FLOWS_FROM */
+
+loadScripts({ name: 'relations.js', dir: MOCHITESTS_DIR });
+
+/**
+ * A test specification that has the following format:
+ * [
+ *   attr                 relevant aria attribute
+ *   hostRelation         corresponding host relation type
+ *   dependantRelation    corresponding dependant relation type
+ * ]
+ */
+const attrRelationsSpec = [
+  ['aria-labelledby', RELATION_LABELLED_BY, RELATION_LABEL_FOR],
+  ['aria-describedby', RELATION_DESCRIBED_BY, RELATION_DESCRIPTION_FOR],
+  ['aria-controls', RELATION_CONTROLLER_FOR, RELATION_CONTROLLED_BY],
+  ['aria-flowto', RELATION_FLOWS_TO, RELATION_FLOWS_FROM]
+];
+
+function* testRelated(browser, accDoc, attr, hostRelation, dependantRelation) {
+  let host = findAccessibleChildByID(accDoc, 'host');
+  let dependant1 = findAccessibleChildByID(accDoc, 'dependant1');
+  let dependant2 = findAccessibleChildByID(accDoc, 'dependant2');
+
+  /**
+   * Test data has the format of:
+   * {
+   *   desc      {String}   description for better logging
+   *   attrs     {?Array}   an optional list of attributes to update
+   *   expected  {Array}    expected relation values for dependant1, dependant2
+   *                        and host respectively.
+   * }
+   */
+  const tests = [{
+    desc: 'No attribute',
+    expected: [ null, null, null ]
+  }, {
+    desc: 'Set attribute',
+    attrs: [{ key: attr, value: 'dependant1' }],
+    expected: [ host, null, dependant1 ]
+  }, {
+    desc: 'Change attribute',
+    attrs: [{ key: attr, value: 'dependant2' }],
+    expected: [ null, host, dependant2 ]
+  }, {
+    desc: 'Remove attribute',
+    attrs: [{ key: attr }],
+    expected: [ null, null, null ]
+  }];
+
+  for (let { desc, attrs, expected } of tests) {
+    info(desc);
+
+    if (attrs) {
+      for (let { key, value } of attrs) {
+        yield invokeSetAttribute(browser, 'host', key, value);
+      }
+    }
+
+    testRelation(dependant1, dependantRelation, expected[0]);
+    testRelation(dependant2, dependantRelation, expected[1]);
+    testRelation(host, hostRelation, expected[2]);
+  }
+}
+
+/**
+ * Test caching of relations between accessible objects.
+ */
+addAccessibleTask(`
+  <div id="dependant1">label</div>
+  <div id="dependant2">label2</div>
+  <div role="checkbox" id="host"></div>`,
+  function* (browser, accDoc) {
+    for (let spec of attrRelationsSpec) {
+      yield testRelated(browser, accDoc, ...spec);
+    }
+  }
+);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/browser_caching_states.js
@@ -0,0 +1,120 @@
+/* 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/. */
+
+'use strict';
+
+/* global EVENT_STATE_CHANGE, STATE_CHECKED, STATE_BUSY, STATE_REQUIRED,
+          STATE_INVALID, EXT_STATE_ENABLED */
+
+loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR },
+            { name: 'states.js', dir: MOCHITESTS_DIR });
+
+/**
+ * Test data has the format of:
+ * {
+ *   desc      {String}   description for better logging
+ *   expected  {Array}    expected states for a given accessible that have the
+ *                        following format:
+ *                          [
+ *                            expected state,
+ *                            expected extra state,
+ *                            absent state,
+ *                            absent extra state
+ *                          ]
+ *   attrs     {?Array}   an optional list of attributes to update
+ * }
+ */
+
+// State caching tests for attribute changes
+const attributeTests = [{
+  desc: 'Checkbox with @checked attribute set to true should have checked ' +
+        'state',
+  attrs: [{
+    attr: 'checked',
+    value: 'true'
+  }],
+  expected: [STATE_CHECKED, 0]
+}, {
+  desc: 'Checkbox with no @checked attribute should not have checked state',
+  attrs: [{
+    attr: 'checked'
+  }],
+  expected: [0, 0, STATE_CHECKED]
+}];
+
+// State caching tests for ARIA changes
+const ariaTests = [{
+  desc: 'File input has busy state when @aria-busy attribute is set to true',
+  attrs: [{
+    attr: 'aria-busy',
+    value: 'true'
+  }],
+  expected: [STATE_BUSY, 0, STATE_REQUIRED | STATE_INVALID]
+}, {
+  desc: 'File input has required state when @aria-required attribute is set ' +
+        'to true',
+  attrs: [{
+    attr: 'aria-required',
+    value: 'true'
+  }],
+  expected: [STATE_REQUIRED, 0, STATE_INVALID]
+}, {
+  desc: 'File input has invalid state when @aria-invalid attribute is set to ' +
+        'true',
+  attrs: [{
+    attr: 'aria-invalid',
+    value: 'true'
+  }],
+  expected: [STATE_INVALID, 0]
+}];
+
+// Extra state caching tests
+const extraStateTests = [{
+  desc: 'Input has no extra enabled state when aria and native disabled ' +
+        'attributes are set at once',
+  attrs: [{
+    attr: 'aria-disabled',
+    value: 'true'
+  }, {
+    attr: 'disabled',
+    value: 'true'
+  }],
+  expected: [0, 0, 0, EXT_STATE_ENABLED]
+}, {
+  desc: 'Input has an extra enabled state when aria and native disabled ' +
+        'attributes are unset at once',
+  attrs: [{
+    attr: 'aria-disabled'
+  }, {
+    attr: 'disabled'
+  }],
+  expected: [0, EXT_STATE_ENABLED]
+}];
+
+function* runStateTests(browser, accDoc, id, tests) {
+  let acc = findAccessibleChildByID(accDoc, id);
+  for (let { desc, attrs, expected } of tests) {
+    info(desc);
+    let onUpdate = waitForEvent(EVENT_STATE_CHANGE, id);
+    for (let { attr, value } of attrs) {
+      yield invokeSetAttribute(browser, id, attr, value);
+    }
+    yield onUpdate;
+    testStates(acc, ...expected);
+  }
+}
+
+/**
+ * Test caching of accessible object states
+ */
+addAccessibleTask(`
+  <input id="checkbox" type="checkbox">
+  <input id="file" type="file">
+  <input id="text">`,
+  function* (browser, accDoc) {
+    yield runStateTests(browser, accDoc, 'checkbox', attributeTests);
+    yield runStateTests(browser, accDoc, 'file', ariaTests);
+    yield runStateTests(browser, accDoc, 'text', extraStateTests);
+  }
+);
--- a/accessible/xpcom/nsAccessibleRelation.cpp
+++ b/accessible/xpcom/nsAccessibleRelation.cpp
@@ -19,16 +19,28 @@ nsAccessibleRelation::nsAccessibleRelati
   mType(aType)
 {
   mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
   Accessible* targetAcc = nullptr;
   while ((targetAcc = aRel->Next()))
     mTargets->AppendElement(static_cast<nsIAccessible*>(ToXPC(targetAcc)), false);
 }
 
+nsAccessibleRelation::nsAccessibleRelation(uint32_t aType,
+                                           const nsTArray<ProxyAccessible*>* aTargets) :
+  mType(aType)
+{
+  mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  for (uint32_t idx = 0; idx < aTargets->Length(); ++idx) {
+    mTargets->AppendElement(
+      static_cast<nsIAccessible*>(ToXPC(aTargets->ElementAt(idx))),
+      false);
+  }
+}
+
 nsAccessibleRelation::~nsAccessibleRelation()
 {
 }
 
 // nsISupports
 NS_IMPL_ISUPPORTS(nsAccessibleRelation, nsIAccessibleRelation)
 
 // nsIAccessibleRelation
--- a/accessible/xpcom/nsAccessibleRelation.h
+++ b/accessible/xpcom/nsAccessibleRelation.h
@@ -4,42 +4,47 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsAccessibleRelation_H_
 #define _nsAccessibleRelation_H_
 
 #include "nsIAccessibleRelation.h"
 
 #include "nsCOMPtr.h"
+#include "nsTArray.h"
 #include "nsIMutableArray.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/a11y/ProxyAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 class Relation;
 
 /**
  * Class represents an accessible relation.
  */
 class nsAccessibleRelation final : public nsIAccessibleRelation
 {
 public:
   nsAccessibleRelation(uint32_t aType, Relation* aRel);
 
+  nsAccessibleRelation(uint32_t aType,
+                       const nsTArray<ProxyAccessible*>* aTargets);
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSIACCESSIBLERELATION
 
 private:
   nsAccessibleRelation();
   ~nsAccessibleRelation();
 
   nsAccessibleRelation(const nsAccessibleRelation&);
   nsAccessibleRelation& operator = (const nsAccessibleRelation&);
-  
+
   uint32_t mType;
   nsCOMPtr<nsIMutableArray> mTargets;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/xpcom/xpcAccessible.cpp
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -464,22 +464,31 @@ NS_IMETHODIMP
 xpcAccessible::GetRelationByType(uint32_t aType,
                                  nsIAccessibleRelation** aRelation)
 {
   NS_ENSURE_ARG_POINTER(aRelation);
   *aRelation = nullptr;
 
   NS_ENSURE_ARG(aType <= static_cast<uint32_t>(RelationType::LAST));
 
-  if (!Intl())
+  if (IntlGeneric().IsNull())
     return NS_ERROR_FAILURE;
 
-  Relation rel = Intl()->RelationByType(static_cast<RelationType>(aType));
-  NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
-  return *aRelation ? NS_OK : NS_ERROR_FAILURE;
+  if (IntlGeneric().IsAccessible()) {
+    Relation rel = Intl()->RelationByType(static_cast<RelationType>(aType));
+    NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
+    return NS_OK;
+  }
+
+  ProxyAccessible* proxy = IntlGeneric().AsProxy();
+  nsTArray<ProxyAccessible*> targets =
+    proxy->RelationByType(static_cast<RelationType>(aType));
+  NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &targets));
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessible::GetRelations(nsIArray** aRelations)
 {
   NS_ENSURE_ARG_POINTER(aRelations);
   *aRelations = nullptr;
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2681,17 +2681,17 @@ var gMenuButtonUpdateBadge = {
 };
 
 // Values for telemtery bins: see TLS_ERROR_REPORT_UI in Histograms.json
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_CHECKED   = 2;
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_UNCHECKED = 3;
 const TLS_ERROR_REPORT_TELEMETRY_MANUAL_SEND    = 4;
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_SEND      = 5;
 
-const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.min", "security.tls.version.max", "security.ssl3."];
+const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
 
 const PREF_SSL_IMPACT = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => {
   return prefs.concat(Services.prefs.getChildList(root));
 }, []);
 
 /**
  * Handle command events bubbling up from error page content
  * or from about:newtab or from remote error pages that invoke
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -228,17 +228,17 @@ const SEC_ERROR_EXPIRED_CERTIFICATE     
 const SEC_ERROR_UNKNOWN_ISSUER                     = SEC_ERROR_BASE + 13;
 const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE         = SEC_ERROR_BASE + 30;
 const SEC_ERROR_OCSP_FUTURE_RESPONSE               = SEC_ERROR_BASE + 131;
 const SEC_ERROR_OCSP_OLD_RESPONSE                  = SEC_ERROR_BASE + 132;
 const MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE = MOZILLA_PKIX_ERROR_BASE + 5;
 
 const PREF_BLOCKLIST_CLOCK_SKEW_SECONDS = "services.blocklist.clock_skew_seconds";
 
-const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.min", "security.tls.version.max", "security.ssl3."];
+const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
 
 const PREF_SSL_IMPACT = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => {
   return prefs.concat(Services.prefs.getChildList(root));
 }, []);
 
 
 var AboutNetAndCertErrorListener = {
   init: function(chromeGlobal) {
--- a/browser/components/feeds/FeedWriter.js
+++ b/browser/components/feeds/FeedWriter.js
@@ -5,16 +5,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
 
 const FEEDWRITER_CID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
 const FEEDWRITER_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
 
 function LOG(str) {
   let prefB = Cc["@mozilla.org/preferences-service;1"].
               getService(Ci.nsIPrefBranch);
 
@@ -884,26 +885,24 @@ FeedWriter.prototype = {
     let chan = docShell.currentDocumentChannel;
 
     // We probably need to call InheritFromDocShellToDoc for this, but right now
     // we can't call it from JS.
     let attrs = docShell.getOriginAttributes();
     let ssm = Services.scriptSecurityManager;
     let nullPrincipal = ssm.createNullPrincipal(attrs);
 
-    let resolvedURI = Cc["@mozilla.org/network/io-service;1"].
-                      getService(Ci.nsIIOService).
-                      newChannel2("about:feeds",
-                                  null,
-                                  null,
-                                  null, // aLoadingNode
-                                  nullPrincipal,
-                                  null, // aTriggeringPrincipal
-                                  Ci.nsILoadInfo.SEC_NORMAL,
-                                  Ci.nsIContentPolicy.TYPE_OTHER).URI;
+    // this channel is not going to be openend, use a nullPrincipal
+    // and the most restrctive securityFlag.
+    let resolvedURI = NetUtil.newChannel({
+      uri: "about:feeds",
+      loadingPrincipal: nullPrincipal,
+      securityFlags: Ci.nsILoadInfo.SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
+      contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
+    }).URI;
 
     if (resolvedURI.equals(chan.URI))
       return chan.originalURI;
 
     return null;
   },
 
   _window: null,
--- a/browser/config/tooltool-manifests/linux32/releng.manifest
+++ b/browser/config/tooltool-manifests/linux32/releng.manifest
@@ -11,19 +11,19 @@
 "size": 11189216,
 "digest": "18bc52b0599b1308b667e282abb45f47597bfc98a5140cfcab8da71dacf89dd76d0dee22a04ce26fe7ad1f04e2d6596991f9e5b01fd2aaaab5542965f596b0e6",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
 "setup": "setup.sh",
 "unpack": true
 },
 {
-"version": "rustc 1.8.0 (db2939409 2016-04-11)",
-"size": 123218320,
-"digest": "7afcd7b39c4d5277db6b28951602aff4c698102ba45d3d811b353ca7446074beceebf03a2a529e323af19d73db4acbe96ec2bdad44def2e218ed36f55e82cab2",
+"version": "gecko rust 1.9.0 (commit e4e8b666850a763fdf1c3c2c142856ab51e32779)",
+"size": 96854912,
+"digest": "d613d5528e83bb73917372948c05a766912a9dd0ec4e8a5fab69161a515c1545d52e9ed3394716df96a9dcdf1c086b6f970413e97c2df78a11e5f9151573921a",
 "algorithm": "sha512",
 "filename": "rustc.tar.xz",
 "unpack": true
 },
 {
 "size": 167175,
 "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
 "algorithm": "sha512",
--- a/browser/config/tooltool-manifests/linux64/releng.manifest
+++ b/browser/config/tooltool-manifests/linux64/releng.manifest
@@ -11,19 +11,19 @@
 "size": 12072532,
 "digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
 "setup": "setup.sh",
 "unpack": true
 },
 {
-"version": "rustc 1.8.0 (db2939409 2016-04-11)",
-"size": 123218320,
-"digest": "7afcd7b39c4d5277db6b28951602aff4c698102ba45d3d811b353ca7446074beceebf03a2a529e323af19d73db4acbe96ec2bdad44def2e218ed36f55e82cab2",
+"version": "gecko rust 1.9.0 (commit e4e8b666850a763fdf1c3c2c142856ab51e32779)",
+"size": 96854912,
+"digest": "d613d5528e83bb73917372948c05a766912a9dd0ec4e8a5fab69161a515c1545d52e9ed3394716df96a9dcdf1c086b6f970413e97c2df78a11e5f9151573921a",
 "algorithm": "sha512",
 "filename": "rustc.tar.xz",
 "unpack": true
 },
 {
 "size": 167175,
 "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
 "algorithm": "sha512",
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -121,21 +121,16 @@ interface nsIScriptSecurityManager : nsI
      * hence will check whether fixed-up versions of the URI are allowed to
      * load as well); if any of the versions of this URI is not allowed, this
      * function will return error code NS_ERROR_DOM_BAD_URI.
      */
     void checkLoadURIStrWithPrincipal(in nsIPrincipal aPrincipal,
                                       in AUTF8String uri,
                                       in unsigned long flags);
 
-    /**
-     * Return true if scripts may be executed in the scope of the given global.
-     */
-    [noscript,notxpcom] boolean scriptAllowed(in JSObjectPtr aGlobal);
-
     ///////////////// Principals ///////////////////////
 
     /**
      * Return the all-powerful system principal.
      */
     nsIPrincipal getSystemPrincipal();
 
     /**
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -222,30 +222,16 @@ public:
 private:
     nsIClassInfo *mClassInfo; // WEAK
     uint32_t mFlags;
     char *mName;
     bool mDidGetFlags;
     bool mMustFreeName;
 };
 
-JSContext *
-nsScriptSecurityManager::GetCurrentJSContext()
-{
-    // Get JSContext from stack.
-    return nsXPConnect::XPConnect()->GetCurrentJSContext();
-}
-
-JSContext *
-nsScriptSecurityManager::GetSafeJSContext()
-{
-    // Get JSContext from stack.
-    return nsXPConnect::XPConnect()->GetSafeJSContext();
-}
-
 /* static */
 bool
 nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
                                              nsIURI* aTargetURI)
 {
     return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
 }
 
@@ -1107,26 +1093,16 @@ nsScriptSecurityManager::CheckLoadURIStr
             return rv;
         }
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return rv;
 }
 
-bool
-nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
-{
-    MOZ_ASSERT(aGlobal);
-    MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsWindowProxy(aGlobal));
-
-    // Check the bits on the compartment private.
-    return xpc::Scriptability::Get(aGlobal).Allowed();
-}
-
 ///////////////// Principals ///////////////////////
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
 {
     NS_ADDREF(*result = mSystemPrincipal);
 
     return NS_OK;
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -53,20 +53,16 @@ public:
     GetScriptSecurityManager();
 
     // Invoked exactly once, by XPConnect.
     static void InitStatics();
 
     static nsSystemPrincipal*
     SystemPrincipalSingletonConstructor();
 
-    JSContext* GetCurrentJSContext();
-
-    JSContext* GetSafeJSContext();
-
     /**
      * Utility method for comparing two URIs.  For security purposes, two URIs
      * are equivalent if their schemes, hosts, and ports (if any) match.  This
      * method returns true if aSubjectURI and aObjectURI have the same origin,
      * false otherwise.
      */
     static bool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
     static uint32_t SecurityHashURI(nsIURI* aURI);
--- a/chrome/RegistryMessageUtils.h
+++ b/chrome/RegistryMessageUtils.h
@@ -73,17 +73,17 @@ struct ParamTraits<SerializedURI>
   typedef SerializedURI paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.spec);
     WriteParam(aMsg, aParam.charset);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     nsCString spec, charset;
     if (ReadParam(aMsg, aIter, &spec) &&
         ReadParam(aMsg, aIter, &charset)) {
       aResult->spec = spec;
       aResult->charset = charset;
       return true;
     }
@@ -100,17 +100,17 @@ struct ParamTraits<ChromePackage>
   {
     WriteParam(aMsg, aParam.package);
     WriteParam(aMsg, aParam.contentBaseURI);
     WriteParam(aMsg, aParam.localeBaseURI);
     WriteParam(aMsg, aParam.skinBaseURI);
     WriteParam(aMsg, aParam.flags);
   }
   
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     nsCString package;
     SerializedURI contentBaseURI, localeBaseURI, skinBaseURI;
     uint32_t flags;
     
     if (ReadParam(aMsg, aIter, &package) &&
         ReadParam(aMsg, aIter, &contentBaseURI) &&
         ReadParam(aMsg, aIter, &localeBaseURI) &&
@@ -142,17 +142,17 @@ struct ParamTraits<SubstitutionMapping>
   
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.scheme);
     WriteParam(aMsg, aParam.path);
     WriteParam(aMsg, aParam.resolvedURI);
   }
   
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     nsCString scheme, path;
     SerializedURI resolvedURI;
     
     if (ReadParam(aMsg, aIter, &scheme) &&
         ReadParam(aMsg, aIter, &path) &&
         ReadParam(aMsg, aIter, &resolvedURI)) {
       aResult->scheme = scheme;
@@ -178,17 +178,17 @@ struct ParamTraits<OverrideMapping>
   typedef OverrideMapping paramType;
   
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.originalURI);
     WriteParam(aMsg, aParam.overrideURI);
   }
   
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     SerializedURI originalURI;
     SerializedURI overrideURI;
     
     if (ReadParam(aMsg, aIter, &originalURI) &&
         ReadParam(aMsg, aIter, &overrideURI)) {
       aResult->originalURI = originalURI;
       aResult->overrideURI = overrideURI;
--- a/devtools/client/responsivedesign/responsivedesign.jsm
+++ b/devtools/client/responsivedesign/responsivedesign.jsm
@@ -182,16 +182,22 @@ function ResponsiveUI(aWindow, aTab)
   this.bound_stopResizing = this.stopResizing.bind(this);
   this.bound_onDrag = this.onDrag.bind(this);
   this.bound_changeUA = this.changeUA.bind(this);
   this.bound_onContentResize = this.onContentResize.bind(this);
 
   this.mm.addMessageListener("ResponsiveMode:OnContentResize",
                              this.bound_onContentResize);
 
+  // We must be ready to handle window or tab close now that we have saved
+  // ourselves in ActiveTabs.  Otherwise we risk leaking the window.
+  this.mainWindow.addEventListener("unload", this);
+  this.tab.addEventListener("TabClose", this);
+  this.tabContainer.addEventListener("TabSelect", this);
+
   ActiveTabs.set(this.tab, this);
 
   this.inited = this.init();
 }
 
 ResponsiveUI.prototype = {
   _transitionsEnabled: true,
   get transitionsEnabled() {
@@ -221,20 +227,16 @@ ResponsiveUI.prototype = {
       // Tests expect events on resize to yield on various size changes
       notifyOnResize: DevToolsUtils.testing,
     });
     yield started;
 
     // Load Presets
     this.loadPresets();
 
-    // Events
-    this.tab.addEventListener("TabClose", this);
-    this.tabContainer.addEventListener("TabSelect", this);
-
     // Setup the UI
     this.container.setAttribute("responsivemode", "true");
     this.stack.setAttribute("responsivemode", "true");
     this.buildUI();
     this.checkMenus();
 
     // Rotate the responsive mode if needed
     try {
@@ -338,35 +340,38 @@ ResponsiveUI.prototype = {
     debug(`CURRENT SIZE: ${this.stack.getAttribute("style")}`);
     let style = "max-width: none;" +
                 "min-width: 0;" +
                 "max-height: none;" +
                 "min-height: 0;";
     debug("RESET STACK SIZE");
     this.stack.setAttribute("style", style);
 
-    // Wait for resize message before stopping in the child when testing
-    if (DevToolsUtils.testing) {
+    // Wait for resize message before stopping in the child when testing,
+    // but only if we should expect to still get a message.
+    if (DevToolsUtils.testing && this.tab.linkedBrowser.messageManager) {
       yield this.waitForMessage("ResponsiveMode:OnContentResize");
     }
 
     if (this.isResizing)
       this.stopResizing();
 
     // Remove listeners.
     this.menulist.removeEventListener("select", this.bound_presetSelected, true);
     this.menulist.removeEventListener("change", this.bound_handleManualInput, true);
+    this.mainWindow.removeEventListener("unload", this);
     this.tab.removeEventListener("TabClose", this);
     this.tabContainer.removeEventListener("TabSelect", this);
     this.rotatebutton.removeEventListener("command", this.bound_rotate, true);
     this.screenshotbutton.removeEventListener("command", this.bound_screenshot, true);
     this.closebutton.removeEventListener("command", this.bound_close, true);
     this.addbutton.removeEventListener("command", this.bound_addPreset, true);
     this.removebutton.removeEventListener("command", this.bound_removePreset, true);
     this.touchbutton.removeEventListener("command", this.bound_touch, true);
+    this.userAgentInput.removeEventListener("blur", this.bound_changeUA, true);
 
     // Removed elements.
     this.container.removeChild(this.toolbar);
     if (this.bottomToolbar) {
       this.bottomToolbar.remove();
       delete this.bottomToolbar;
     }
     this.stack.removeChild(this.resizer);
@@ -386,19 +391,21 @@ ResponsiveUI.prototype = {
 
     yield new Promise((resolve, reject) => {
       this.client.close(resolve);
       this.client = this.tabClient = null;
     });
 
     this._telemetry.toolClosed("responsive");
 
-    let stopped = this.waitForMessage("ResponsiveMode:Stop:Done");
-    this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
-    yield stopped;
+    if (this.tab.linkedBrowser.messageManager) {
+      let stopped = this.waitForMessage("ResponsiveMode:Stop:Done");
+      this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
+      yield stopped;
+    }
 
     this.inited = null;
     ResponsiveUIManager.emit("off", { tab: this.tab });
   }),
 
   waitForMessage(message) {
     return new Promise(resolve => {
       let listener = () => {
@@ -421,16 +428,17 @@ ResponsiveUI.prototype = {
   },
 
   /**
    * Handle events
    */
   handleEvent: function (aEvent) {
     switch (aEvent.type) {
       case "TabClose":
+      case "unload":
         this.close();
         break;
       case "TabSelect":
         if (this.tab.selected) {
           this.checkMenus();
         } else if (!this.mainWindow.gBrowser.selectedTab.responsiveUI) {
           this.unCheckMenus();
         }
@@ -444,17 +452,20 @@ ResponsiveUI.prototype = {
   checkMenus: function RUI_checkMenus() {
     this.chromeDoc.getElementById("menu_responsiveUI").setAttribute("checked", "true");
   },
 
   /**
    * Uncheck the menu items.
    */
   unCheckMenus: function RUI_unCheckMenus() {
-    this.chromeDoc.getElementById("menu_responsiveUI").setAttribute("checked", "false");
+    let el = this.chromeDoc.getElementById("menu_responsiveUI");
+    if (el) {
+      el.setAttribute("checked", "false");
+    }
   },
 
   /**
    * Build the toolbar and the resizers.
    *
    * <vbox class="browserContainer"> From tabbrowser.xml
    *  <toolbar class="devtools-responsiveui-toolbar">
    *    <menulist class="devtools-responsiveui-menulist"/> // presets
--- a/devtools/client/responsivedesign/test/browser.ini
+++ b/devtools/client/responsivedesign/test/browser.ini
@@ -12,8 +12,9 @@ support-files =
 skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
 [browser_responsiveruleview.js]
 skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
 [browser_responsiveui.js]
 [browser_responsiveui_touch.js]
 [browser_responsiveuiaddcustompreset.js]
 [browser_responsive_devicewidth.js]
 [browser_responsiveui_customuseragent.js]
+[browser_responsiveui_window_close.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/responsivedesign/test/browser_responsiveui_window_close.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(function* () {
+  let newWindowPromise = BrowserTestUtils.waitForNewWindow();
+  window.open("about:blank", "_blank");
+  let newWindow = yield newWindowPromise;
+
+  newWindow.focus();
+  yield once(newWindow.gBrowser, "load", true);
+
+  let tab = newWindow.gBrowser.selectedTab;
+  yield ResponsiveUIManager.runIfNeeded(newWindow, tab);
+
+  // Close the window on a tab with an active responsive design UI and
+  // wait for the UI to gracefully shutdown.  This has leaked the window
+  // in the past.
+  ok(ResponsiveUIManager.isActiveForTab(tab),
+     "ResponsiveUI should be active for tab when the window is closed");
+  let offPromise = once(ResponsiveUIManager, "off");
+  yield BrowserTestUtils.closeWindow(newWindow);
+  yield offPromise;
+});
--- a/devtools/shared/gcli/commands/cookie.js
+++ b/devtools/shared/gcli/commands/cookie.js
@@ -36,23 +36,29 @@ XPCOMUtils.defineLazyGetter(this, "cooki
 function sanitizeHost(host) {
   if (host == null || host == "") {
     throw new Error(l10n.lookup("cookieListOutNonePage"));
   }
   return host.split(":")[0];
 }
 
 /**
- * The cookie 'expires' value needs converting into something more readable
+ * The cookie 'expires' value needs converting into something more readable.
+ *
+ * And the unit of expires is sec, the unit that in argument of Date() needs 
+ * millisecond.
  */
 function translateExpires(expires) {
   if (expires == 0) {
     return l10n.lookup("cookieListOutSession");
   }
-  return new Date(expires).toLocaleString();
+
+  let expires_msec = expires * 1000;
+
+  return (new Date(expires_msec)).toLocaleString();
 }
 
 /**
  * Check if a given cookie matches a given host
  */
 function isCookieAtHost(cookie, host) {
   if (cookie.host == null) {
     return host == null;
--- a/docshell/base/SerializedLoadContext.h
+++ b/docshell/base/SerializedLoadContext.h
@@ -71,17 +71,17 @@ struct ParamTraits<SerializedLoadContext
     WriteParam(aMsg, aParam.mIsNotNull);
     WriteParam(aMsg, aParam.mIsContent);
     WriteParam(aMsg, aParam.mIsPrivateBitValid);
     WriteParam(aMsg, aParam.mUsePrivateBrowsing);
     WriteParam(aMsg, aParam.mUseRemoteTabs);
     WriteParam(aMsg, suffix);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     nsAutoCString suffix;
     if (!ReadParam(aMsg, aIter, &aResult->mIsNotNull) ||
         !ReadParam(aMsg, aIter, &aResult->mIsContent) ||
         !ReadParam(aMsg, aIter, &aResult->mIsPrivateBitValid) ||
         !ReadParam(aMsg, aIter, &aResult->mUsePrivateBrowsing) ||
         !ReadParam(aMsg, aIter, &aResult->mUseRemoteTabs) ||
         !ReadParam(aMsg, aIter, &suffix)) {
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Animation.h"
 #include "AnimationUtils.h"
 #include "mozilla/dom/AnimationBinding.h"
 #include "mozilla/dom/AnimationPlaybackEvent.h"
+#include "mozilla/dom/DocumentTimeline.h"
 #include "mozilla/AnimationTarget.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/AsyncEventDispatcher.h" // For AsyncEventDispatcher
 #include "mozilla/Maybe.h" // For Maybe
 #include "nsAnimationManager.h" // For CSSAnimation
 #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
 #include "nsIDocument.h" // For nsIDocument
 #include "nsIPresShell.h" // For nsIPresShell
@@ -82,29 +83,42 @@ namespace {
 // ---------------------------------------------------------------------------
 //
 // Animation interface:
 //
 // ---------------------------------------------------------------------------
 /* static */ already_AddRefed<Animation>
 Animation::Constructor(const GlobalObject& aGlobal,
                        KeyframeEffectReadOnly* aEffect,
-                       AnimationTimeline* aTimeline,
+                       const Optional<AnimationTimeline*>& aTimeline,
                        ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
   RefPtr<Animation> animation = new Animation(global);
 
   if (!aEffect) {
     // Bug 1049975: We do not support null effect yet.
     aRv.Throw(NS_ERROR_DOM_ANIM_NO_EFFECT_ERR);
     return nullptr;
   }
 
-  animation->SetTimeline(aTimeline);
+  AnimationTimeline* timeline;
+  if (aTimeline.WasPassed()) {
+    timeline = aTimeline.Value();
+  } else {
+    nsIDocument* document =
+      AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
+    if (!document) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+    timeline = document->Timeline();
+  }
+
+  animation->SetTimeline(timeline);
   animation->SetEffect(aEffect);
 
   return animation.forget();
 }
 
 void
 Animation::SetId(const nsAString& aId)
 {
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -88,17 +88,17 @@ public:
     AutoRewind,
     Continue
   };
 
   // Animation interface methods
   static already_AddRefed<Animation>
   Constructor(const GlobalObject& aGlobal,
               KeyframeEffectReadOnly* aEffect,
-              AnimationTimeline* aTimeline,
+              const Optional<AnimationTimeline*>& aTimeline,
               ErrorResult& aRv);
   void GetId(nsAString& aResult) const { aResult = mId; }
   void SetId(const nsAString& aId);
   KeyframeEffectReadOnly* GetEffect() const { return mEffect; }
   void SetEffect(KeyframeEffectReadOnly* aEffect);
   AnimationTimeline* GetTimeline() const { return mTimeline; }
   void SetTimeline(AnimationTimeline* aTimeline);
   Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -1843,17 +1843,17 @@ ParamTraits<Metadata>::Write(Message* aM
     WriteParam(aMsg, entry.mFastHash);
     WriteParam(aMsg, entry.mNumChars);
     WriteParam(aMsg, entry.mFullHash);
     WriteParam(aMsg, entry.mModuleIndex);
   }
 }
 
 bool
-ParamTraits<Metadata>::Read(const Message* aMsg, void** aIter,
+ParamTraits<Metadata>::Read(const Message* aMsg, PickleIterator* aIter,
                             paramType* aResult)
 {
   for (unsigned i = 0; i < Metadata::kNumEntries; i++) {
     Metadata::Entry& entry = aResult->mEntries[i];
     if (!ReadParam(aMsg, aIter, &entry.mFastHash) ||
         !ReadParam(aMsg, aIter, &entry.mNumChars) ||
         !ReadParam(aMsg, aIter, &entry.mFullHash) ||
         !ReadParam(aMsg, aIter, &entry.mModuleIndex))
@@ -1882,17 +1882,17 @@ ParamTraits<WriteParams>::Write(Message*
   WriteParam(aMsg, aParam.mSize);
   WriteParam(aMsg, aParam.mFastHash);
   WriteParam(aMsg, aParam.mNumChars);
   WriteParam(aMsg, aParam.mFullHash);
   WriteParam(aMsg, aParam.mInstalled);
 }
 
 bool
-ParamTraits<WriteParams>::Read(const Message* aMsg, void** aIter,
+ParamTraits<WriteParams>::Read(const Message* aMsg, PickleIterator* aIter,
                                paramType* aResult)
 {
   return ReadParam(aMsg, aIter, &aResult->mSize) &&
          ReadParam(aMsg, aIter, &aResult->mFastHash) &&
          ReadParam(aMsg, aIter, &aResult->mNumChars) &&
          ReadParam(aMsg, aIter, &aResult->mFullHash) &&
          ReadParam(aMsg, aIter, &aResult->mInstalled);
 }
--- a/dom/asmjscache/AsmJSCache.h
+++ b/dom/asmjscache/AsmJSCache.h
@@ -164,26 +164,26 @@ struct ParamTraits<mozilla::dom::asmjsca
                                   mozilla::dom::asmjscache::NUM_OPEN_MODES>
 { };
 
 template <>
 struct ParamTraits<mozilla::dom::asmjscache::Metadata>
 {
   typedef mozilla::dom::asmjscache::Metadata paramType;
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
   static void Log(const paramType& aParam, std::wstring* aLog);
 };
 
 template <>
 struct ParamTraits<mozilla::dom::asmjscache::WriteParams>
 {
   typedef mozilla::dom::asmjscache::WriteParams paramType;
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
   static void Log(const paramType& aParam, std::wstring* aLog);
 };
 
 template <>
 struct ParamTraits<JS::AsmJSCacheResult> :
   public ContiguousEnumSerializer<JS::AsmJSCacheResult,
                                   JS::AsmJSCache_MIN,
                                   JS::AsmJSCache_LIMIT>
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3329,19 +3329,20 @@ Element::Animate(const Nullable<ElementO
   }
 
   RefPtr<KeyframeEffect> effect =
     KeyframeEffect::Constructor(global, aTarget, keyframes, aOptions, aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
+  AnimationTimeline* timeline = referenceElement->OwnerDoc()->Timeline();
   RefPtr<Animation> animation =
     Animation::Constructor(global, effect,
-                           referenceElement->OwnerDoc()->Timeline(), aError);
+                           Optional<AnimationTimeline*>(timeline), aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   if (aOptions.IsKeyframeAnimationOptions()) {
     animation->SetId(aOptions.GetAsKeyframeAnimationOptions().mId);
   }
 
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -776,19 +776,17 @@ danger::AutoCxPusher::AutoCxPusher(JSCon
 
   // Hold a strong ref to the nsIScriptContext, if any. This ensures that we
   // only destroy the mContext of an nsJSContext when it is not on the cx stack
   // (and therefore not in use). See nsJSContext::DestroyJSContext().
   if (cx)
     mScx = GetScriptContextFromJSContext(cx);
 
   XPCJSContextStack *stack = XPCJSRuntime::Get()->GetJSContextStack();
-  if (!stack->Push(cx)) {
-    MOZ_CRASH();
-  }
+  stack->Push(cx);
   mStackDepthAfterPush = stack->Count();
 
 #ifdef DEBUG
   mPushedContext = cx;
   mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
 #endif
 
   // Enter a request and a compartment for the duration that the cx is on the
--- a/dom/base/contentAreaDropListener.js
+++ b/dom/base/contentAreaDropListener.js
@@ -115,16 +115,18 @@ ContentAreaDropListener.prototype =
     let sourceDocument = sourceNode.ownerDocument;
     let eventDocument = aEvent.originalTarget.ownerDocument;
     if (sourceDocument == eventDocument)
       return false;
 
     // also check for nodes in other child or sibling frames by checking
     // if both have the same top window.
     if (sourceDocument && eventDocument) {
+      if (sourceDocument.defaultView == null)
+        return true;
       let sourceRoot = sourceDocument.defaultView.top;
       if (sourceRoot && sourceRoot == eventDocument.defaultView.top)
         return false;
     }
 
     return true;
   },
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7419,17 +7419,18 @@ nsContentUtils::TransferableToIPCTransfe
             RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
               surface->GetDataSurface();
             if (!dataSurface) {
               continue;
             }
             size_t length;
             int32_t stride;
             mozilla::UniquePtr<char[]> surfaceData =
-              nsContentUtils::GetSurfaceData(dataSurface, &length, &stride);
+              nsContentUtils::GetSurfaceData(WrapNotNull(dataSurface), &length,
+                                             &stride);
 
             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
             item->flavor() = flavorStr;
             // Turn item->data() into an nsCString prior to accessing it.
             item->data() = EmptyCString();
             item->data().get_nsCString().Adopt(surfaceData.release(), length);
 
             IPCDataTransferImage& imageDetails = item->imageDetails();
@@ -7523,18 +7524,19 @@ nsContentUtils::TransferableToIPCTransfe
           }
         }
       }
     }
   }
 }
 
 mozilla::UniquePtr<char[]>
-nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
-                               size_t* aLength, int32_t* aStride)
+nsContentUtils::GetSurfaceData(
+  NotNull<mozilla::gfx::DataSourceSurface*> aSurface,
+  size_t* aLength, int32_t* aStride)
 {
   mozilla::gfx::DataSourceSurface::MappedSurface map;
   if (NS_WARN_IF(!aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map))) {
     return nullptr;
   }
   mozilla::gfx::IntSize size = aSurface->GetSize();
   mozilla::CheckedInt32 requiredBytes =
     mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -27,16 +27,17 @@
 #include "nsMathUtils.h"
 #include "nsTArrayForwardDeclare.h"
 #include "Units.h"
 #include "mozilla/dom/AutocompleteInfoBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/net/ReferrerPolicy.h"
 #include "mozilla/Logging.h"
+#include "mozilla/NotNull.h"
 #include "nsIContentPolicy.h"
 
 #if defined(XP_WIN)
 // Undefine LoadImage to prevent naming conflict with Windows.
 #undef LoadImage
 #endif
 
 class imgICache;
@@ -2427,18 +2428,19 @@ public:
                                             bool aInSyncMessage,
                                             mozilla::dom::nsIContentChild* aChild,
                                             mozilla::dom::nsIContentParent* aParent);
 
   /*
    * Get the pixel data from the given source surface and return it as a buffer.
    * The length and stride will be assigned from the surface.
    */
-  static mozilla::UniquePtr<char[]> GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
-                                                   size_t* aLength, int32_t* aStride);
+  static mozilla::UniquePtr<char[]> GetSurfaceData(
+    mozilla::NotNull<mozilla::gfx::DataSourceSurface*> aSurface,
+    size_t* aLength, int32_t* aStride);
 
   // Helpers shared by the implementations of nsContentUtils methods and
   // nsIDOMWindowUtils methods.
   static mozilla::Modifiers GetWidgetModifiers(int32_t aModifiers);
   static nsIWidget* GetWidget(nsIPresShell* aPresShell, nsPoint* aOffset);
   static int16_t GetButtonsFlagForButton(int32_t aButton);
   static mozilla::LayoutDeviceIntPoint ToWidgetPoint(const mozilla::CSSPoint& aPoint,
                                                      const nsPoint& aOffset,
--- a/dom/base/nsDOMJSUtils.h
+++ b/dom/base/nsDOMJSUtils.h
@@ -25,18 +25,16 @@ GetScriptContextFromJSContext(JSContext 
     do_QueryInterface(static_cast<nsISupports *>
                                  (::JS_GetContextPrivate(cx)));
 
   // This will return a pointer to something that's about to be
   // released, but that's ok here.
   return scx;
 }
 
-JSObject* GetDefaultScopeFromJSContext(JSContext *cx);
-
 // A factory function for turning a JS::Value argv into an nsIArray
 // but also supports an effecient way of extracting the original argv.
 // The resulting object will take a copy of the array, and ensure each
 // element is rooted.
 // Optionally, aArgv may be nullptr, in which case the array is allocated and
 // rooted, but all items remain nullptr.  This presumably means the caller
 // will then QI us for nsIJSArgArray, and set our array elements.
 nsresult NS_CreateJSArgv(JSContext *aContext, uint32_t aArgc,
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -133,16 +133,17 @@
 #include "nsIDateTimeFormat.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "nsDOMCID.h"
 
 #include "jsapi.h"
 #include "nsIXPConnect.h"
+#include "xpcpublic.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIDocumentLoader.h"
 #include "nsIContentViewer.h"
 #include "nsIXMLContentSink.h"
@@ -8467,28 +8468,25 @@ bool
 nsDocument::IsScriptEnabled()
 {
   // If this document is sandboxed without 'allow-scripts'
   // script is not enabled
   if (mSandboxFlags & SANDBOXED_SCRIPTS) {
     return false;
   }
 
-  nsCOMPtr<nsIScriptSecurityManager> sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
-  NS_ENSURE_TRUE(sm, false);
-
   nsCOMPtr<nsIScriptGlobalObject> globalObject = do_QueryInterface(GetInnerWindow());
   if (!globalObject && mMasterDocument) {
     globalObject = do_QueryInterface(mMasterDocument->GetInnerWindow());
   }
   if (!globalObject || !globalObject->GetGlobalJSObject()) {
     return false;
   }
 
-  return sm->ScriptAllowed(globalObject->GetGlobalJSObject());
+  return xpc::Scriptability::Get(globalObject->GetGlobalJSObject()).Allowed();
 }
 
 nsRadioGroupStruct*
 nsDocument::GetRadioGroupInternal(const nsAString& aName) const
 {
 #ifdef DEBUG
   if (IsHTMLDocument()) {
     nsAutoString lcName;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8106,33 +8106,31 @@ nsGlobalWindow::Open(const nsAString& aU
                    NS_ERROR_NOT_INITIALIZED);
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       true,           // aCalledNoScript
                       false,          // aDoJSFixups
                       true,           // aNavigate
                       nullptr, nullptr,  // No args
-                      nullptr,           // aJSCallerContext
                       _retval);
 }
 
 nsresult
 nsGlobalWindow::OpenJS(const nsAString& aUrl, const nsAString& aName,
                        const nsAString& aOptions, nsPIDOMWindowOuter **_retval)
 {
   MOZ_ASSERT(IsOuterWindow());
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       false,          // aCalledNoScript
                       true,           // aDoJSFixups
                       true,           // aNavigate
                       nullptr, nullptr,  // No args
-                      nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
                       _retval);
 }
 
 // like Open, but attaches to the new window any extra parameters past
 // [features] as a JS property named "arguments"
 nsresult
 nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
                            const nsAString& aOptions,
@@ -8142,17 +8140,16 @@ nsGlobalWindow::OpenDialog(const nsAStri
   MOZ_ASSERT(IsOuterWindow());
   return OpenInternal(aUrl, aName, aOptions,
                       true,                    // aDialog
                       false,                   // aContentModal
                       true,                    // aCalledNoScript
                       false,                   // aDoJSFixups
                       true,                    // aNavigate
                       nullptr, aExtraArgument,    // Arguments
-                      nullptr,                    // aJSCallerContext
                       _retval);
 }
 
 // Like Open, but passes aNavigate=false.
 /* virtual */ nsresult
 nsGlobalWindow::OpenNoNavigate(const nsAString& aUrl,
                                const nsAString& aName,
                                const nsAString& aOptions,
@@ -8161,17 +8158,16 @@ nsGlobalWindow::OpenNoNavigate(const nsA
   MOZ_ASSERT(IsOuterWindow());
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       true,           // aCalledNoScript
                       false,          // aDoJSFixups
                       false,          // aNavigate
                       nullptr, nullptr,  // No args
-                      nullptr,           // aJSCallerContext
                       _retval);
 
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindow::OpenDialogOuter(JSContext* aCx, const nsAString& aUrl,
                                 const nsAString& aName, const nsAString& aOptions,
                                 const Sequence<JS::Value>& aExtraArgument,
@@ -8190,17 +8186,16 @@ nsGlobalWindow::OpenDialogOuter(JSContex
   nsCOMPtr<nsPIDOMWindowOuter> dialog;
   aError = OpenInternal(aUrl, aName, aOptions,
                         true,             // aDialog
                         false,            // aContentModal
                         false,            // aCalledNoScript
                         false,            // aDoJSFixups
                         true,                // aNavigate
                         argvArray, nullptr,  // Arguments
-                        aCx,                 // aJSCallerContext
                         getter_AddRefs(dialog));
   return dialog.forget();
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindow::OpenDialog(JSContext* aCx, const nsAString& aUrl,
                            const nsAString& aName, const nsAString& aOptions,
                            const Sequence<JS::Value>& aExtraArgument,
@@ -8628,23 +8623,24 @@ nsGlobalWindow::FinalClose()
   // This stuff is non-sensical but incredibly fragile. The reasons for the
   // behavior here don't make sense today and may not have ever made sense,
   // but various bits of frontend code break when you change them. If you need
   // to fix up this behavior, feel free to. It's a righteous task, but involves
   // wrestling with various download manager tests, frontend code, and possible
   // broken addons. The chrome tests in toolkit/mozapps/downloads are a good
   // testing ground.
   //
-  // In particular, if |win|'s JSContext is at the top of the stack, we must
+  // In particular, if some inner of |win| is the entry global, we must
   // complete _two_ round-trips to the event loop before the call to
   // ReallyCloseWindow. This allows setTimeout handlers that are set after
   // FinalClose() is called to run before the window is torn down.
-  bool indirect = GetContextInternal() && // Occasionally null. See bug 877390.
-                  (nsContentUtils::GetCurrentJSContext() ==
-                   GetContextInternal()->GetNativeContext());
+  nsCOMPtr<nsPIDOMWindowInner> entryWindow =
+    do_QueryInterface(GetEntryGlobal());
+  bool indirect =
+    entryWindow && entryWindow->GetOuterWindow() == this->AsOuter();
   if (NS_FAILED(nsCloseEvent::PostCloseEvent(this, indirect))) {
     ReallyCloseWindow();
   } else {
     mHavePendingClose = true;
   }
 }
 
 
@@ -9270,17 +9266,16 @@ nsGlobalWindow::ShowModalDialogOuter(con
   nsContentUtils::SetMicroTaskLevel(0);
   aError = OpenInternal(aUrl, EmptyString(), options,
                         false,          // aDialog
                         true,           // aContentModal
                         true,           // aCalledNoScript
                         true,           // aDoJSFixups
                         true,           // aNavigate
                         nullptr, argHolder, // args
-                        nullptr,            // aJSCallerContext
                         getter_AddRefs(dlgWin));
   nsContentUtils::SetMicroTaskLevel(oldMicroTaskLevel);
   LeaveModalState();
   if (aError.Failed()) {
     return nullptr;
   }
 
   nsCOMPtr<nsIDOMModalContentWindow> dialog = do_QueryInterface(dlgWin);
@@ -11739,32 +11734,29 @@ public:
 
 nsresult
 nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
                              const nsAString& aOptions, bool aDialog,
                              bool aContentModal, bool aCalledNoScript,
                              bool aDoJSFixups, bool aNavigate,
                              nsIArray *argv,
                              nsISupports *aExtraArgument,
-                             JSContext *aJSCallerContext,
                              nsPIDOMWindowOuter **aReturn)
 {
   MOZ_ASSERT(IsOuterWindow());
 
 #ifdef DEBUG
   uint32_t argc = 0;
   if (argv)
       argv->GetLength(&argc);
 #endif
   NS_PRECONDITION(!aExtraArgument || (!argv && argc == 0),
                   "Can't pass in arguments both ways");
   NS_PRECONDITION(!aCalledNoScript || (!argv && argc == 0),
                   "Can't pass JS args when called via the noscript methods");
-  NS_PRECONDITION(!aJSCallerContext || !aCalledNoScript,
-                  "Shouldn't have caller context when called noscript");
 
   mozilla::Maybe<AutoUnblockScriptClosing> closeUnblocker;
 
   // Calls to window.open from script should navigate.
   MOZ_ASSERT(aCalledNoScript || aNavigate);
 
   *aReturn = nullptr;
 
@@ -11815,23 +11807,28 @@ nsGlobalWindow::OpenInternal(const nsASt
 
   if (NS_FAILED(rv))
     return rv;
 
   PopupControlState abuseLevel = gPopupControlState;
   if (checkForPopup) {
     abuseLevel = RevisePopupAbuseLevel(abuseLevel);
     if (abuseLevel >= openAbused) {
-      if (aJSCallerContext) {
+      if (!aCalledNoScript) {
         // If script in some other window is doing a window.open on us and
         // it's being blocked, then it's OK to close us afterwards, probably.
         // But if we're doing a window.open on ourselves and block the popup,
         // prevent this window from closing until after this script terminates
         // so that whatever popup blocker UI the app has will be visible.
-        if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) {
+        nsCOMPtr<nsPIDOMWindowInner> entryWindow =
+          do_QueryInterface(GetEntryGlobal());
+        // Note that entryWindow can be null here if some JS component was the
+        // place where script was entered for this JS execution.
+        if (entryWindow &&
+            entryWindow->GetOuterWindow() == this->AsOuter()) {
           mBlockScriptedClosingFlag = true;
           closeUnblocker.emplace(this);
         }
       }
 
       FireAbuseEvents(aUrl, aName, aOptions);
       return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
     }
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1426,34 +1426,30 @@ private:
    *        three args, if present, will be aUrl, aName, and aOptions.  So this
    *        param only matters if there are more than 3 arguments.
    *
    * @param argc The number of arguments in argv.
    *
    * @param aExtraArgument Another way to pass arguments in.  This is mutually
    *        exclusive with the argv/argc approach.
    *
-   * @param aJSCallerContext The calling script's context. This must be null
-   *        when aCalledNoScript is true.
-   *
    * @param aReturn [out] The window that was opened, if any.
    *
    * Outer windows only.
    */
   nsresult OpenInternal(const nsAString& aUrl,
                         const nsAString& aName,
                         const nsAString& aOptions,
                         bool aDialog,
                         bool aContentModal,
                         bool aCalledNoScript,
                         bool aDoJSFixups,
                         bool aNavigate,
                         nsIArray *argv,
                         nsISupports *aExtraArgument,
-                        JSContext *aJSCallerContext,
                         nsPIDOMWindowOuter **aReturn);
 
 public:
   // Timeout Functions
   // Language agnostic timeout function (all args passed).
   // |interval| is in milliseconds.
   nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
                                 int32_t interval,
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -169,18 +169,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
   // cases.  So we need to be explicitly told whether the caller cares about the
   // return value.  Callers can do this by calling the other overload of
   // EvaluateString() which calls this function with
   // aCompileOptions.noScriptRval set to true.
   aRetValue.setUndefined();
 
   nsresult rv = NS_OK;
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
 
   bool ok = true;
   // Scope the JSAutoCompartment so that we can later wrap the return value
   // into the caller's cx.
   {
     JSAutoCompartment ac(aCx, aEvaluationGlobal);
 
     // Now make sure to wrap the scope chain into the right compartment.
@@ -289,18 +288,17 @@ nsJSUtils::CompileModule(JSContext* aCx,
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(aSrcBuf.get());
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) ==
              aEvaluationGlobal);
   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
 
   if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -311,19 +309,17 @@ nsJSUtils::ModuleDeclarationInstantiatio
     js::ProfileEntry::Category::JS);
 
   MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(),
              "Caller must own error reporting");
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  JSObject* global = JS_GetGlobalForObject(aCx, aModule);
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(global), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
 
   if (!JS::ModuleDeclarationInstantiation(aCx, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -334,19 +330,17 @@ nsJSUtils::ModuleEvaluation(JSContext* a
     js::ProfileEntry::Category::JS);
 
   MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(),
              "Caller must own error reporting");
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  JSObject* global = JS_GetGlobalForObject(aCx, aModule);
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(global), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
 
   if (!JS::ModuleEvaluation(aCx, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -376,25 +370,16 @@ nsJSUtils::ResetTimeZone()
 {
   JS::ResetTimeZone();
 }
 
 //
 // nsDOMJSUtils.h
 //
 
-JSObject* GetDefaultScopeFromJSContext(JSContext *cx)
-{
-  // DOM JSContexts don't store their default compartment object on
-  // the cx, so in those cases we need to fetch it via the scx
-  // instead.
-  nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
-  return  scx ? scx->GetWindowProxy() : nullptr;
-}
-
 bool nsAutoJSString::init(const JS::Value &v)
 {
   JSContext* cx = nsContentUtils::RootingCxForThread();
   if (!init(nsContentUtils::RootingCxForThread(), v)) {
     JS_ClearPendingException(cx);
     return false;
   }
 
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -1997,17 +1997,17 @@ nsScriptLoader::EvaluateScript(nsScriptL
       // execution currentScript of the master should refer to this
       // script. So let's update the mCurrentScript of the ScriptLoader
       // of the master document too.
       masterScriptUpdater.emplace(master->ScriptLoader(),
                                   aRequest->mElement);
     }
 
     if (aRequest->IsModuleRequest()) {
-      rv = EnsureModuleResolveHook(context->GetNativeContext());
+      rv = EnsureModuleResolveHook(aes.cx());
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsModuleLoadRequest* request = aRequest->AsModuleRequest();
       MOZ_ASSERT(request->mModuleScript);
       MOZ_ASSERT(!request->mOffThreadToken);
       JS::Rooted<JSObject*> module(aes.cx(),
                                    request->mModuleScript->ModuleRecord());
       MOZ_ASSERT(module);
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -168,17 +168,17 @@ ErrorResult::SerializeMessage(IPC::Messa
   using namespace IPC;
   MOZ_ASSERT(mUnionState == HasMessage);
   MOZ_ASSERT(mMessage);
   WriteParam(aMsg, mMessage->mArgs);
   WriteParam(aMsg, mMessage->mErrorNumber);
 }
 
 bool
-ErrorResult::DeserializeMessage(const IPC::Message* aMsg, void** aIter)
+ErrorResult::DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter)
 {
   using namespace IPC;
   nsAutoPtr<Message> readMessage(new Message());
   if (!ReadParam(aMsg, aIter, &readMessage->mArgs) ||
       !ReadParam(aMsg, aIter, &readMessage->mErrorNumber)) {
     return false;
   }
   if (!readMessage->HasCorrectNumberOfArguments()) {
@@ -290,17 +290,17 @@ ErrorResult::SerializeDOMExceptionInfo(I
   using namespace IPC;
   MOZ_ASSERT(mDOMExceptionInfo);
   MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
   WriteParam(aMsg, mDOMExceptionInfo->mMessage);
   WriteParam(aMsg, mDOMExceptionInfo->mRv);
 }
 
 bool
-ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, void** aIter)
+ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterator* aIter)
 {
   using namespace IPC;
   nsCString message;
   nsresult rv;
   if (!ReadParam(aMsg, aIter, &message) ||
       !ReadParam(aMsg, aIter, &rv)) {
     return false;
   }
@@ -2177,17 +2177,17 @@ InterfaceHasInstance(JSContext* cx, JS::
   if (domClass &&
       domClass->mInterfaceChain[clasp->mDepth] == clasp->mPrototypeID) {
     *bp = true;
     return true;
   }
 
   if (jsipc::IsWrappedCPOW(instance)) {
     bool boolp = false;
-    if (!jsipc::DOMInstanceOf(cx, js::CheckedUnwrap(instance), clasp->mPrototypeID,
+    if (!jsipc::DOMInstanceOf(cx, js::UncheckedUnwrap(instance), clasp->mPrototypeID,
                               clasp->mDepth, &boolp)) {
       return false;
     }
     *bp = boolp;
     return true;
   }
 
   JS::Rooted<JS::Value> protov(cx);
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -7,17 +7,16 @@
 #include "mozilla/dom/CallbackObject.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "jsfriendapi.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #include "nsJSUtils.h"
-#include "nsIScriptSecurityManager.h"
 #include "xpcprivate.h"
 #include "WorkerPrivate.h"
 #include "nsGlobalWindow.h"
 #include "WorkerScope.h"
 #include "jsapi.h"
 #include "nsJSPrincipals.h"
 
 namespace mozilla {
@@ -172,18 +171,17 @@ CallbackObject::CallSetup::CallSetup(Cal
   }
 
   // JS-implemented WebIDL is always OK to run, since it runs with Chrome
   // privileges anyway.
   if (mIsMainThread && !aIsJSImplementedWebIDL) {
     // Check that it's ok to run this callback at all.
     // Make sure to use realCallback to get the global of the callback object,
     // not the wrapper.
-    bool allowed = nsContentUtils::GetSecurityManager()->
-      ScriptAllowed(js::GetGlobalForObjectCrossCompartment(realCallback));
+    bool allowed = xpc::Scriptability::Get(realCallback).Allowed();
 
     if (!allowed) {
       aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
         NS_LITERAL_CSTRING("Refusing to execute function from global in which "
                            "script is disabled."));
       return;
     }
   }
--- a/dom/bindings/ErrorIPCUtils.h
+++ b/dom/bindings/ErrorIPCUtils.h
@@ -45,17 +45,17 @@ struct ParamTraits<mozilla::ErrorResult>
     WriteParam(aMsg, aParam.IsDOMException());
     if (aParam.IsErrorWithMessage()) {
       aParam.SerializeMessage(aMsg);
     } else if (aParam.IsDOMException()) {
       aParam.SerializeDOMExceptionInfo(aMsg);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     paramType readValue;
     if (!ReadParam(aMsg, aIter, &readValue.mResult)) {
       return false;
     }
     bool hasMessage = false;
     if (!ReadParam(aMsg, aIter, &hasMessage)) {
       return false;
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -31,16 +31,17 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Move.h"
 #include "nsTArray.h"
 
 namespace IPC {
 class Message;
 template <typename> struct ParamTraits;
 } // namespace IPC
+class PickleIterator;
 
 namespace mozilla {
 
 namespace dom {
 
 enum ErrNum {
 #define MSG_DEF(_name, _argc, _exn, _str) \
   _name,
@@ -302,20 +303,20 @@ private:
     HasDOMExceptionInfo,
     HasJSException,
     HasNothing
   };
 #endif // DEBUG
 
   friend struct IPC::ParamTraits<ErrorResult>;
   void SerializeMessage(IPC::Message* aMsg) const;
-  bool DeserializeMessage(const IPC::Message* aMsg, void** aIter);
+  bool DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter);
 
   void SerializeDOMExceptionInfo(IPC::Message* aMsg) const;
-  bool DeserializeDOMExceptionInfo(const IPC::Message* aMsg, void** aIter);
+  bool DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterator* aIter);
 
   // Helper method that creates a new Message for this ErrorResult,
   // and returns the arguments array from that Message.
   nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType);
 
   template<dom::ErrNum errorNumber, typename... Ts>
   void ThrowErrorWithMessage(nsresult errorType, Ts&&... messageArgs)
   {
--- a/dom/bluetooth/bluedroid/BluetoothMapSmsManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothMapSmsManager.cpp
@@ -10,17 +10,17 @@
 #include "BluetoothService.h"
 #include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuidHelper.h"
 #include "ObexBase.h"
 
 #include "mozilla/dom/BluetoothMapParametersBinding.h"
 #include "mozilla/dom/ipc/BlobParent.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/dom/File.h"
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIInputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
--- a/dom/bluetooth/bluedroid/BluetoothPbapManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothPbapManager.cpp
@@ -8,17 +8,17 @@
 #include "BluetoothPbapManager.h"
 
 #include "BluetoothService.h"
 #include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuidHelper.h"
 
 #include "mozilla/dom/BluetoothPbapParametersBinding.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIInputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
--- a/dom/bluetooth/bluedroid/BluetoothSocketMessageWatcher.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocketMessageWatcher.cpp
@@ -4,17 +4,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 "BluetoothSocketMessageWatcher.h"
 #include <errno.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include "BluetoothInterface.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "nsClassHashtable.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 //
 // SocketMessageWatcherWrapper
 //
 
--- a/dom/bluetooth/common/BluetoothCommon.h
+++ b/dom/bluetooth/common/BluetoothCommon.h
@@ -4,17 +4,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 mozilla_dom_bluetooth_BluetoothCommon_h
 #define mozilla_dom_bluetooth_BluetoothCommon_h
 
 #include <algorithm>
 #include "mozilla/Compiler.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/Observer.h"
 #include "mozilla/UniquePtr.h"
 #include "nsPrintfCString.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 extern bool gBluetoothDebugFlag;
 
--- a/dom/bluetooth/common/ObexBase.h
+++ b/dom/bluetooth/common/ObexBase.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_ObexBase_h
 #define mozilla_dom_bluetooth_ObexBase_h
 
 #include "BluetoothCommon.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/UniquePtr.h"
 #include "nsTArray.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 const char FINAL_BIT = 0x80;
 
 /**
--- a/dom/bluetooth/ipc/BluetoothMessageUtils.h
+++ b/dom/bluetooth/ipc/BluetoothMessageUtils.h
@@ -19,17 +19,17 @@ struct ParamTraits<mozilla::dom::bluetoo
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aParam.mAddr); ++i) {
       WriteParam(aMsg, aParam.mAddr[i]);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aResult->mAddr); ++i) {
       if (!ReadParam(aMsg, aIter, aResult->mAddr + i)) {
         return false;
       }
     }
     return true;
   }
@@ -56,17 +56,17 @@ struct ParamTraits<mozilla::dom::bluetoo
     }
 
     WriteParam(aMsg, length);
     for (uint8_t i = 0; i < length; ++i) {
       WriteParam(aMsg, aParam.mPinCode[i]);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &aResult->mLength)) {
       return false;
     }
 
     auto maxLength = MOZ_ARRAY_LENGTH(aResult->mPinCode);
 
     if (aResult->mLength > maxLength) {
@@ -92,17 +92,17 @@ struct ParamTraits<mozilla::dom::bluetoo
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mLength);
     for (size_t i = 0; i < aParam.mLength; ++i) {
       WriteParam(aMsg, aParam.mName[i]);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &aResult->mLength)) {
       return false;
     }
     if (aResult->mLength > MOZ_ARRAY_LENGTH(aResult->mName)) {
       return false;
     }
     for (uint8_t i = 0; i < aResult->mLength; ++i) {
@@ -153,17 +153,17 @@ struct ParamTraits<mozilla::dom::bluetoo
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     for (uint8_t i = 0; i < 16; i++) {
       WriteParam(aMsg, aParam.mUuid[i]);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     for (uint8_t i = 0; i < 16; i++) {
       if (!ReadParam(aMsg, aIter, &(aResult->mUuid[i]))) {
         return false;
       }
     }
 
     return true;
@@ -176,17 +176,17 @@ struct ParamTraits<mozilla::dom::bluetoo
   typedef mozilla::dom::bluetooth::BluetoothGattId paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mUuid);
     WriteParam(aMsg, aParam.mInstanceId);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mUuid)) ||
         !ReadParam(aMsg, aIter, &(aResult->mInstanceId))) {
       return false;
     }
 
     return true;
   }
@@ -198,17 +198,17 @@ struct ParamTraits<mozilla::dom::bluetoo
   typedef mozilla::dom::bluetooth::BluetoothGattServiceId paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mId);
     WriteParam(aMsg, aParam.mIsPrimary);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIsPrimary))) {
       return false;
     }
 
     return true;
   }
@@ -221,17 +221,17 @@ struct ParamTraits<mozilla::dom::bluetoo
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mId);
     WriteParam(aMsg, aParam.mProperties);
     WriteParam(aMsg, aParam.mWriteType);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mProperties)) ||
         !ReadParam(aMsg, aIter, &(aResult->mWriteType))) {
       return false;
     }
 
     return true;
@@ -243,17 +243,17 @@ struct ParamTraits<mozilla::dom::bluetoo
 {
   typedef mozilla::dom::bluetooth::BluetoothAttributeHandle paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mHandle);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mHandle))) {
       return false;
     }
 
     return true;
   }
 };
@@ -274,17 +274,17 @@ struct ParamTraits<mozilla::dom::bluetoo
     WriteParam(aMsg, aParam.mOffset);
     WriteParam(aMsg, length);
     WriteParam(aMsg, aParam.mAuthReq);
     for (uint16_t i = 0; i < length; i++) {
       WriteParam(aMsg, aParam.mValue[i]);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mHandle)) ||
         !ReadParam(aMsg, aIter, &(aResult->mOffset)) ||
         !ReadParam(aMsg, aIter, &(aResult->mLength)) ||
         !ReadParam(aMsg, aIter, &(aResult->mAuthReq))) {
       return false;
     }
 
@@ -307,17 +307,17 @@ struct ParamTraits<mozilla::dom::bluetoo
 {
   typedef mozilla::dom::bluetooth::ControlPlayStatus paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<uint8_t>(aParam));
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     uint8_t value;
     if (!ReadParam(aMsg, aIter, &value)) {
       return false;
     }
 
     mozilla::dom::bluetooth::ControlPlayStatus result =
       static_cast<mozilla::dom::bluetooth::ControlPlayStatus>(value);
@@ -347,17 +347,17 @@ struct ParamTraits<mozilla::dom::bluetoo
     WriteParam(aMsg, aParam.mAppearance);
     WriteParam(aMsg, aParam.mIncludeDevName);
     WriteParam(aMsg, aParam.mIncludeTxPower);
     WriteParam(aMsg, aParam.mManufacturerData);
     WriteParam(aMsg, aParam.mServiceData);
     WriteParam(aMsg, aParam.mServiceUuids);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mAppearance)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIncludeDevName)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIncludeTxPower)) ||
         !ReadParam(aMsg, aIter, &(aResult->mManufacturerData)) ||
         !ReadParam(aMsg, aIter, &(aResult->mServiceData)) ||
         !ReadParam(aMsg, aIter, &(aResult->mServiceUuids))) {
       return false;
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -77,17 +77,17 @@
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageBitmap.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/TypedArray.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Helpers.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/gfx/PatternHelpers.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/PDocumentRendererParent.h"
 #include "mozilla/layers/PersistentBufferProvider.h"
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -45,17 +45,17 @@
 #if defined(MOZ_WIDGET_COCOA)
 #include "nsCocoaFeatures.h"
 #endif
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtrExtensions.h"
 
 namespace mozilla {
 
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
--- a/dom/canvas/WebGLContextTextures.cpp
+++ b/dom/canvas/WebGLContextTextures.cpp
@@ -42,17 +42,17 @@
 #if defined(MOZ_WIDGET_COCOA)
 #include "nsCocoaFeatures.h"
 #endif
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 namespace mozilla {
 
 static bool
 IsValidTexTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexTarget,
                  TexTarget* const out)
 {
     uint8_t targetDims;
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -1164,17 +1164,17 @@ Event::Serialize(IPC::Message* aMsg, boo
   IPC::WriteParam(aMsg, Bubbles());
   IPC::WriteParam(aMsg, Cancelable());
   IPC::WriteParam(aMsg, IsTrusted());
 
   // No timestamp serialization for now!
 }
 
 NS_IMETHODIMP_(bool)
-Event::Deserialize(const IPC::Message* aMsg, void** aIter)
+Event::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
 {
   nsString type;
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &type), false);
 
   bool bubbles = false;
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &bubbles), false);
 
   bool cancelable = false;
--- a/dom/events/NotifyPaintEvent.cpp
+++ b/dom/events/NotifyPaintEvent.cpp
@@ -135,17 +135,17 @@ NotifyPaintEvent::Serialize(IPC::Message
   IPC::WriteParam(aMsg, length);
   for (uint32_t i = 0; i < length; ++i) {
     IPC::WriteParam(aMsg, mInvalidateRequests[i].mRect);
     IPC::WriteParam(aMsg, mInvalidateRequests[i].mFlags);
   }
 }
 
 NS_IMETHODIMP_(bool)
-NotifyPaintEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+NotifyPaintEvent::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
 {
   NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false);
 
   uint32_t length = 0;
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &length), false);
   mInvalidateRequests.SetCapacity(length);
   for (uint32_t i = 0; i < length; ++i) {
     nsInvalidateRequestList::Request req;
--- a/dom/events/NotifyPaintEvent.h
+++ b/dom/events/NotifyPaintEvent.h
@@ -38,17 +38,17 @@ public:
 
   // Forward to base class
   NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION
   NS_IMETHOD DuplicatePrivateData() override
   {
     return Event::DuplicatePrivateData();
   }
   NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) override;
-  NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) override;
+  NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, PickleIterator* aIter) override;
 
   virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
   {
     return NotifyPaintEventBinding::Wrap(aCx, this, aGivenProto);
   }
 
   already_AddRefed<DOMRectList> ClientRects();
 
--- a/dom/events/ScrollAreaEvent.cpp
+++ b/dom/events/ScrollAreaEvent.cpp
@@ -55,17 +55,17 @@ ScrollAreaEvent::Serialize(IPC::Message*
 
   IPC::WriteParam(aMsg, X());
   IPC::WriteParam(aMsg, Y());
   IPC::WriteParam(aMsg, Width());
   IPC::WriteParam(aMsg, Height());
 }
 
 NS_IMETHODIMP_(bool)
-ScrollAreaEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+ScrollAreaEvent::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
 {
   NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false);
 
   float x, y, width, height;
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &x), false);
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &y), false);
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &width), false);
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &height), false);
--- a/dom/events/ScrollAreaEvent.h
+++ b/dom/events/ScrollAreaEvent.h
@@ -28,17 +28,17 @@ public:
   NS_FORWARD_NSIDOMUIEVENT(UIEvent::)
 
   NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION
   NS_IMETHOD DuplicatePrivateData() override
   {
     return Event::DuplicatePrivateData();
   }
   NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) override;
-  NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) override;
+  NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, PickleIterator* aIter) override;
 
   virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
   {
     return ScrollAreaEventBinding::Wrap(aCx, this, aGivenProto);
   }
 
   float X() const
   {
--- a/dom/events/UIEvent.cpp
+++ b/dom/events/UIEvent.cpp
@@ -393,17 +393,17 @@ UIEvent::Serialize(IPC::Message* aMsg, b
   Event::Serialize(aMsg, false);
 
   int32_t detail = 0;
   GetDetail(&detail);
   IPC::WriteParam(aMsg, detail);
 }
 
 NS_IMETHODIMP_(bool)
-UIEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
+UIEvent::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
 {
   NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false);
   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &mDetail), false);
   return true;
 }
 
 // XXX Following struct and array are used only in
 //     UIEvent::ComputeModifierState(), but if we define them in it,
--- a/dom/events/UIEvent.h
+++ b/dom/events/UIEvent.h
@@ -33,17 +33,17 @@ public:
 
   // nsIDOMUIEvent Interface
   NS_DECL_NSIDOMUIEVENT
 
   // Forward to Event
   NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION
   NS_IMETHOD DuplicatePrivateData() override;
   NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) override;
-  NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) override;
+  NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, PickleIterator* aIter) override;
 
 
   static already_AddRefed<UIEvent> Constructor(const GlobalObject& aGlobal,
                                                const nsAString& aType,
                                                const UIEventInit& aParam,
                                                ErrorResult& aRv);
 
   virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
@@ -134,17 +134,17 @@ protected:
   }                                                         \
   NS_IMETHOD_(void) Serialize(IPC::Message* aMsg,           \
                               bool aSerializeInterfaceType) \
     override                                                \
   {                                                         \
     UIEvent::Serialize(aMsg, aSerializeInterfaceType);      \
   }                                                         \
   NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg,   \
-                                void** aIter) override      \
+                                PickleIterator* aIter) override \
   {                                                         \
     return UIEvent::Deserialize(aMsg, aIter);               \
   }
 
 already_AddRefed<mozilla::dom::UIEvent>
 NS_NewDOMUIEvent(mozilla::dom::EventTarget* aOwner,
                  nsPresContext* aPresContext,
                  mozilla::WidgetGUIEvent* aEvent);
--- a/dom/geolocation/nsGeoPositionIPCSerialiser.h
+++ b/dom/geolocation/nsGeoPositionIPCSerialiser.h
@@ -48,17 +48,17 @@ struct ParamTraits<nsIDOMGeoPositionCoor
     aParam->GetHeading(&coordData);
     WriteParam(aMsg, coordData);
 
     aParam->GetSpeed(&coordData);
     WriteParam(aMsg, coordData);
   }
 
   // Function to de-serialize a geoposition
-  static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if it is the null pointer we have transfered
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) return false;
 
     if (isNull) {
       *aResult = 0;
       return true;
@@ -114,17 +114,17 @@ struct ParamTraits<nsIDOMGeoPosition*>
     WriteParam(aMsg, timeStamp);
 
     nsCOMPtr<nsIDOMGeoPositionCoords> coords;
     aParam->GetCoords(getter_AddRefs(coords));
     WriteParam(aMsg, coords.get());
   }
 
   // Function to de-serialize a geoposition
-  static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if it is the null pointer we have transfered
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) return false;
 
     if (isNull) {
       *aResult = 0;
       return true;
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -16,17 +16,17 @@
 #include "IndexedDatabaseManager.h"
 #include "js/StructuredClone.h"
 #include "js/Value.h"
 #include "jsapi.h"
 #include "KeyPath.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/AppProcessChecker.h"
 #include "mozilla/AutoRestore.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/storage.h"
 #include "mozilla/unused.h"
 #include "mozilla/UniquePtrExtensions.h"
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -18,17 +18,17 @@
 #include "IDBTransaction.h"
 #include "IndexedDatabase.h"
 #include "IndexedDatabaseInlines.h"
 #include "IndexedDatabaseManager.h"
 #include "js/Class.h"
 #include "js/Date.h"
 #include "js/StructuredClone.h"
 #include "KeyPath.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Move.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/IDBMutableFileBinding.h"
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -7,17 +7,17 @@
 
 #include "Key.h"
 
 #include <algorithm>
 #include "IndexedDatabaseManager.h"
 #include "js/Date.h"
 #include "js/Value.h"
 #include "jsfriendapi.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageValueArray.h"
 #include "nsAlgorithm.h"
 #include "nsJSUtils.h"
 #include "ReportInternalError.h"
 #include "xpcpublic.h"
 
--- a/dom/indexedDB/SerializationHelpers.h
+++ b/dom/indexedDB/SerializationHelpers.h
@@ -21,17 +21,17 @@ struct ParamTraits<mozilla::dom::indexed
 {
   typedef mozilla::dom::indexedDB::Key paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mBuffer);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->mBuffer);
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
     LogParam(aParam.mBuffer, aLog);
   }
@@ -50,17 +50,17 @@ struct ParamTraits<mozilla::dom::indexed
   typedef mozilla::dom::indexedDB::KeyPath paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mType);
     WriteParam(aMsg, aParam.mStrings);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->mType) &&
            ReadParam(aMsg, aIter, &aResult->mStrings);
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
     LogParam(aParam.mStrings, aLog);
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -6,28 +6,30 @@
 #include "domstubs.idl"
 
 interface nsIDOMEventTarget;
 
 [ptr] native WidgetEvent(mozilla::WidgetEvent);
 [ptr] native DOMEventPtr(mozilla::dom::Event);
 [ptr] native IPCMessagePtr(IPC::Message);
 [ptr] native ConstIPCMessagePtr(const IPC::Message);
+[ptr] native PickleIterator(PickleIterator);
 [ptr] native EventTargetPtr(mozilla::dom::EventTarget);
 %{C++
 #ifdef ERROR
 #undef ERROR
 #endif
 
 #include "mozilla/EventForwards.h"
 class nsPresContext;
 class nsInvalidateRequestList;
 namespace IPC {
 class Message;
 }
+class PickleIterator;
 namespace mozilla {
 namespace dom {
 class Event;
 class EventTarget;
 } // namespace dom
 } // namespace mozilla
 %}
 
@@ -206,13 +208,13 @@ interface nsIDOMEvent : nsISupports
 
   [noscript] void duplicatePrivateData();
   [noscript] void setTarget(in nsIDOMEventTarget aTarget);
   [notxpcom] boolean IsDispatchStopped();
   [notxpcom] WidgetEvent WidgetEventPtr();
   [noscript,notxpcom] void SetTrusted(in boolean aTrusted);
   [notxpcom] void Serialize(in IPCMessagePtr aMsg,
                             in boolean aSerializeInterfaceType);
-  [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, out voidPtr aIter);
+  [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, in PickleIterator aIter);
   [noscript,notxpcom] void SetOwner(in EventTargetPtr aOwner);
   [notxpcom] DOMEventPtr InternalDOMEvent();
   [noscript] void stopCrossProcessForwarding();
 };
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -638,16 +638,18 @@ ContentChild::Init(MessageLoop* aIOLoop,
   // to use, and when starting under XWayland, it may choose to start with
   // the wayland backend instead of the x11 backend.
   // The DISPLAY environment variable is normally set by the parent process.
   char* display_name = PR_GetEnv("DISPLAY");
   if (display_name) {
     int argc = 3;
     char option_name[] = "--display";
     char* argv[] = {
+      // argv0 is unused because g_set_prgname() was called in
+      // XRE_InitChildProcess().
       nullptr,
       option_name,
       display_name,
       nullptr
     };
     char** argvp = argv;
     gtk_init(&argc, &argvp);
   } else {
--- a/dom/ipc/IdType.h
+++ b/dom/ipc/IdType.h
@@ -57,17 +57,17 @@ struct ParamTraits<mozilla::dom::IdType<
 {
   typedef mozilla::dom::IdType<T> paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mId);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->mId);
   }
 };
 
 } // namespace IPC
 
 #endif // mozilla_dom_IdType_h
--- a/dom/ipc/PermissionMessageUtils.cpp
+++ b/dom/ipc/PermissionMessageUtils.cpp
@@ -32,17 +32,17 @@ ParamTraits<Principal>::Write(Message* a
     NS_RUNTIMEABORT("Unable to serialize principal.");
     return;
   }
 
   WriteParam(aMsg, principalString);
 }
 
 bool
-ParamTraits<Principal>::Read(const Message* aMsg, void** aIter, paramType* aResult)
+ParamTraits<Principal>::Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
 {
   bool isNull;
   if (!ReadParam(aMsg, aIter, &isNull)) {
     return false;
   }
 
   if (isNull) {
     aResult->mPrincipal = nullptr;
--- a/dom/ipc/PermissionMessageUtils.h
+++ b/dom/ipc/PermissionMessageUtils.h
@@ -34,15 +34,15 @@ private:
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
 template <>
 struct ParamTraits<Principal>
 {
   typedef Principal paramType;
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
 };
 
 } // namespace IPC
 
 #endif // mozilla_dom_permission_message_utils_h__
 
--- a/dom/ipc/StructuredCloneData.cpp
+++ b/dom/ipc/StructuredCloneData.cpp
@@ -93,48 +93,43 @@ StructuredCloneData::Write(JSContext* aC
 }
 
 void
 StructuredCloneData::WriteIPCParams(IPC::Message* aMsg) const
 {
   WriteParam(aMsg, DataLength());
 
   if (DataLength()) {
-    // Structured clone data must be 64-bit aligned.
-    aMsg->WriteBytes(Data(), DataLength(), sizeof(uint64_t));
+    aMsg->WriteBytes(Data(), DataLength());
   }
 }
 
 bool
 StructuredCloneData::ReadIPCParams(const IPC::Message* aMsg,
-                                   void** aIter)
+                                   PickleIterator* aIter)
 {
   MOZ_ASSERT(!Data());
 
   size_t dataLength = 0;
   if (!ReadParam(aMsg, aIter, &dataLength)) {
     return false;
   }
 
   if (!dataLength) {
     return true;
   }
 
-  uint64_t* dataBuffer = nullptr;
-  const char** buffer =
-    const_cast<const char**>(reinterpret_cast<char**>(&dataBuffer));
-  // Structured clone data must be 64-bit aligned.
-  if (!aMsg->ReadBytes(aIter, buffer, dataLength, sizeof(uint64_t))) {
+  mSharedData = SharedJSAllocatedData::AllocateForExternalData(dataLength);
+  NS_ENSURE_TRUE(mSharedData, false);
+
+  if (!aMsg->ReadBytesInto(aIter, mSharedData->Data(), dataLength)) {
+    mSharedData = nullptr;
     return false;
   }
 
-  mSharedData = SharedJSAllocatedData::CreateFromExternalData(dataBuffer,
-                                                              dataLength);
-  NS_ENSURE_TRUE(mSharedData, false);
-
   return true;
 }
 
 bool
 StructuredCloneData::CopyExternalData(const void* aData,
                                       size_t aDataLength)
 {
   MOZ_ASSERT(!Data());
--- a/dom/ipc/StructuredCloneData.h
+++ b/dom/ipc/StructuredCloneData.h
@@ -10,44 +10,53 @@
 #include <algorithm>
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/StructuredCloneHolder.h"
 #include "nsISupportsImpl.h"
 
 namespace IPC {
 class Message;
 }
+class PickleIterator;
 
 namespace mozilla {
 namespace dom {
 namespace ipc {
 
 class SharedJSAllocatedData final
 {
 public:
   SharedJSAllocatedData(uint64_t* aData, size_t aDataLength)
   : mData(aData), mDataLength(aDataLength)
   {
     MOZ_ASSERT(mData);
   }
 
   static already_AddRefed<SharedJSAllocatedData>
-  CreateFromExternalData(const void* aData, size_t aDataLength)
+  AllocateForExternalData(size_t aDataLength)
   {
     uint64_t* data = Allocate64bitSafely(aDataLength);
     if (!data) {
       return nullptr;
     }
 
-    memcpy(data, aData, aDataLength);
     RefPtr<SharedJSAllocatedData> sharedData =
       new SharedJSAllocatedData(data, aDataLength);
     return sharedData.forget();
   }
 
+  static already_AddRefed<SharedJSAllocatedData>
+  CreateFromExternalData(const void* aData, size_t aDataLength)
+  {
+    RefPtr<SharedJSAllocatedData> sharedData =
+      AllocateForExternalData(aDataLength);
+    memcpy(sharedData->Data(), aData, aDataLength);
+    return sharedData.forget();
+  }
+
   NS_INLINE_DECL_REFCOUNTING(SharedJSAllocatedData)
 
   uint64_t* Data() const { return mData; }
   size_t DataLength() const { return mDataLength; }
 
 private:
   ~SharedJSAllocatedData()
   {
@@ -132,17 +141,17 @@ public:
 
   SharedJSAllocatedData* SharedData() const
   {
     return mSharedData;
   }
 
   // For IPC serialization
   void WriteIPCParams(IPC::Message* aMessage) const;
-  bool ReadIPCParams(const IPC::Message* aMessage, void** aIter);
+  bool ReadIPCParams(const IPC::Message* aMessage, PickleIterator* aIter);
 
 private:
   uint64_t* MOZ_NON_OWNING_REF mExternalData;
   size_t mExternalDataLength;
 
   RefPtr<SharedJSAllocatedData> mSharedData;
 };
 
--- a/dom/ipc/TabMessageUtils.cpp
+++ b/dom/ipc/TabMessageUtils.cpp
@@ -8,17 +8,17 @@
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/TabMessageUtils.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
 
 bool
-ReadRemoteEvent(const IPC::Message* aMsg, void** aIter,
+ReadRemoteEvent(const IPC::Message* aMsg, PickleIterator* aIter,
                 RemoteDOMEvent* aResult)
 {
   aResult->mEvent = nullptr;
   nsString type;
   NS_ENSURE_TRUE(ReadParam(aMsg, aIter, &type), false);
 
   aResult->mEvent = EventDispatcher::CreateEvent(nullptr, nullptr, nullptr,
                                                  type);
--- a/dom/ipc/TabMessageUtils.h
+++ b/dom/ipc/TabMessageUtils.h
@@ -19,17 +19,17 @@
 namespace mozilla {
 namespace dom {
 struct RemoteDOMEvent
 {
   // Make sure to set the owner after deserializing.
   nsCOMPtr<nsIDOMEvent> mEvent;
 };
 
-bool ReadRemoteEvent(const IPC::Message* aMsg, void** aIter,
+bool ReadRemoteEvent(const IPC::Message* aMsg, PickleIterator* aIter,
                      mozilla::dom::RemoteDOMEvent* aResult);
 
 #ifdef MOZ_CRASHREPORTER
 typedef CrashReporter::ThreadId NativeThreadId;
 #else
 // unused in this case
 typedef int32_t NativeThreadId;
 #endif
@@ -44,17 +44,17 @@ struct ParamTraits<mozilla::dom::RemoteD
 {
   typedef mozilla::dom::RemoteDOMEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     aParam.mEvent->Serialize(aMsg, true);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return mozilla::dom::ReadRemoteEvent(aMsg, aIter, aResult);
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
   }
 };
@@ -70,17 +70,17 @@ struct ParamTraits<mozilla::dom::AudioCh
   }
 
   static void Write(Message* aMsg, const paramType& aValue)
   {
     MOZ_ASSERT(IsLegalValue(aValue));
     WriteParam(aMsg, (uint32_t)aValue);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     uint32_t value;
     if(!ReadParam(aMsg, aIter, &value) ||
        !IsLegalValue(paramType(value))) {
       return false;
     }
     *aResult = paramType(value);
     return true;
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -376,17 +376,17 @@ nsMathMLElement::ParseNumericValue(const
   int32_t stringLength = str.Length();
   if (!stringLength) {
     if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) {
       ReportLengthParseError(aString, aDocument);
     }
     return false;
   }
 
-  if (ParseNamedSpaceValue(aString, aCSSValue, aFlags)) {
+  if (ParseNamedSpaceValue(str, aCSSValue, aFlags)) {
     return true;
   }
 
   nsAutoString number, unit;
 
   // see if the negative sign is there
   int32_t i = 0;
   char16_t c = str[0];
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -136,17 +136,17 @@ Benchmark::Init()
 
   MediaPrefs::GetSingleton();
 }
 
 BenchmarkPlayback::BenchmarkPlayback(Benchmark* aMainThreadState,
                                      MediaDataDemuxer* aDemuxer)
   : QueueObject(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
   , mMainThreadState(aMainThreadState)
-  , mDecoderTaskQueue(new FlushableTaskQueue(GetMediaThreadPool(
+  , mDecoderTaskQueue(new TaskQueue(GetMediaThreadPool(
                         MediaThreadType::PLATFORM_DECODER)))
   , mDemuxer(aDemuxer)
   , mSampleIndex(0)
   , mFrameCount(0)
   , mFinished(false)
 {
   MOZ_ASSERT(static_cast<Benchmark*>(mMainThreadState)->OnThread());
 }
--- a/dom/media/Benchmark.h
+++ b/dom/media/Benchmark.h
@@ -12,17 +12,17 @@
 #include "PlatformDecoderModule.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TaskQueue.h"
 #include "mozilla/TimeStamp.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 
-class FlushableTaskQueue;
+class TaskQueue;
 class Benchmark;
 
 class BenchmarkPlayback : public QueueObject, private MediaDataDecoderCallback
 {
   friend class Benchmark;
   explicit BenchmarkPlayback(Benchmark* aMainThreadState, MediaDataDemuxer* aDemuxer);
   void DemuxSamples();
   void DemuxNextSample();
@@ -34,17 +34,17 @@ class BenchmarkPlayback : public QueueOb
   void Output(MediaData* aData) override;
   void Error() override;
   void InputExhausted() override;
   void DrainComplete() override;
   bool OnReaderTaskQueue() override;
 
   Atomic<Benchmark*> mMainThreadState;
 
-  RefPtr<FlushableTaskQueue> mDecoderTaskQueue;
+  RefPtr<TaskQueue> mDecoderTaskQueue;
   RefPtr<MediaDataDecoder> mDecoder;
 
   // Object only accessed on Thread()
   RefPtr<MediaDataDemuxer> mDemuxer;
   RefPtr<MediaTrackDemuxer> mTrackDemuxer;
   nsTArray<RefPtr<MediaRawData>> mSamples;
   size_t mSampleIndex;
   TimeStamp mDecodeStartTime;
--- a/dom/media/FileBlockCache.cpp
+++ b/dom/media/FileBlockCache.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/SharedThreadPool.h"
 #include "FileBlockCache.h"
 #include "VideoUtils.h"
 #include "prio.h"
 #include <algorithm>
 
 namespace mozilla {
 
 nsresult FileBlockCache::Open(PRFileDesc* aFD)
deleted file mode 100644
--- a/dom/media/FlushableTaskQueue.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "FlushableTaskQueue.h"
-
-namespace mozilla {
-
-void
-FlushableTaskQueue::Flush()
-{
-  MonitorAutoLock mon(mQueueMonitor);
-  AutoSetFlushing autoFlush(this);
-  FlushLocked();
-  AwaitIdleLocked();
-}
-
-nsresult
-FlushableTaskQueue::FlushAndDispatch(already_AddRefed<nsIRunnable> aRunnable)
-{
-  nsCOMPtr<nsIRunnable> r = aRunnable;
-  {
-    MonitorAutoLock mon(mQueueMonitor);
-    AutoSetFlushing autoFlush(this);
-    FlushLocked();
-    nsresult rv = DispatchLocked(/* passed by ref */r, IgnoreFlushing, AssertDispatchSuccess);
-    NS_ENSURE_SUCCESS(rv, rv);
-    AwaitIdleLocked();
-  }
-  // If the ownership of |r| is not transferred in DispatchLocked() due to
-  // dispatch failure, it will be deleted here outside the lock. We do so
-  // since the destructor of the runnable might access TaskQueue and result
-  // in deadlocks.
-  return NS_OK;
-}
-
-void
-FlushableTaskQueue::FlushLocked()
-{
-  // Make sure there are no tasks for this queue waiting in the caller's tail
-  // dispatcher.
-  MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
-                !AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
-
-  mQueueMonitor.AssertCurrentThreadOwns();
-  MOZ_ASSERT(mIsFlushing);
-
-  // Clear the tasks. If this strikes you as awful, stop using a
-  // FlushableTaskQueue.
-  while (!mTasks.empty()) {
-    mTasks.pop();
-  }
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/media/FlushableTaskQueue.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef FlushableTaskQueue_h_
-#define FlushableTaskQueue_h_
-
-#include "mozilla/TaskQueue.h"
-
-//
-// WARNING: THIS CLASS IS DEPRECATED AND GOING AWAY. DO NOT USE IT!
-//
-
-namespace mozilla {
-
-class FlushableTaskQueue : public TaskQueue
-{
-public:
-  explicit FlushableTaskQueue(already_AddRefed<SharedThreadPool> aPool) : TaskQueue(Move(aPool)) {}
-  nsresult FlushAndDispatch(already_AddRefed<nsIRunnable> aRunnable);
-  void Flush();
-
-  bool IsDispatchReliable() override { return false; }
-
-private:
-
-  class MOZ_STACK_CLASS AutoSetFlushing
-  {
-  public:
-    explicit AutoSetFlushing(FlushableTaskQueue* aTaskQueue) : mTaskQueue(aTaskQueue)
-    {
-      mTaskQueue->mQueueMonitor.AssertCurrentThreadOwns();
-      mTaskQueue->mIsFlushing = true;
-    }
-    ~AutoSetFlushing()
-    {
-      mTaskQueue->mQueueMonitor.AssertCurrentThreadOwns();
-      mTaskQueue->mIsFlushing = false;
-    }
-
-  private:
-    FlushableTaskQueue* mTaskQueue;
-  };
-
-  void FlushLocked();
-
-};
-
-}  // namespace mozilla
-
-#endif // FlushableTaskQueue_h_
--- a/dom/media/MP3Demuxer.cpp
+++ b/dom/media/MP3Demuxer.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MP3Demuxer.h"
 
 #include <inttypes.h>
 #include <algorithm>
 
 #include "mozilla/Assertions.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "VideoUtils.h"
 #include "TimeUnits.h"
 #include "prenv.h"
 
 #ifdef PR_LOGGING
 mozilla::LazyLogModule gMP3DemuxerLog("MP3Demuxer");
 #define MP3LOG(msg, ...) \
   MOZ_LOG(gMP3DemuxerLog, LogLevel::Debug, ("MP3Demuxer " msg, ##__VA_ARGS__))
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -167,19 +167,19 @@ MediaFormatReader::InitLayersBackendType
 nsresult
 MediaFormatReader::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
 
   InitLayersBackendType();
 
   mAudio.mTaskQueue =
-    new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
+    new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   mVideo.mTaskQueue =
-    new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
+    new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
 
   return NS_OK;
 }
 
 #ifdef MOZ_EME
 class DispatchKeyNeededEvent : public Runnable {
 public:
   DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
@@ -1099,16 +1099,21 @@ MediaFormatReader::Update(TrackType aTra
   bool needOutput = false;
   auto& decoder = GetDecoderData(aTrack);
   decoder.mUpdateScheduled = false;
 
   if (!mInitDone) {
     return;
   }
 
+  if (aTrack == TrackType::kVideoTrack && mSkipRequest.Exists()) {
+    LOGV("Skipping in progress, nothing more to do");
+    return;
+  }
+
   if (UpdateReceivedNewData(aTrack)) {
     LOGV("Nothing more to do");
     return;
   }
 
   if (decoder.mSeekRequest.Exists()) {
     LOGV("Seeking hasn't completed, nothing more to do");
     return;
@@ -1413,38 +1418,68 @@ MediaFormatReader::Reset(TrackType aTrac
 
   decoder.ResetState();
   decoder.Flush();
 
   LOG("Reset(%s) END", TrackTypeToStr(aTrack));
 }
 
 void
+MediaFormatReader::DropDecodedSamples(TrackType aTrack)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  auto& decoder = GetDecoderData(aTrack);
+  size_t lengthDecodedQueue = decoder.mOutput.Length();
+  if (lengthDecodedQueue && decoder.mTimeThreshold.isSome()) {
+    TimeUnit time =
+      TimeUnit::FromMicroseconds(decoder.mOutput.LastElement()->mTime);
+    if (time >= decoder.mTimeThreshold.ref().Time()) {
+      // We would have reached our internal seek target.
+      decoder.mTimeThreshold.reset();
+    }
+  }
+  decoder.mOutput.Clear();
+  decoder.mSizeOfQueue -= lengthDecodedQueue;
+  if (aTrack == TrackInfo::kVideoTrack && mDecoder) {
+    mDecoder->NotifyDecodedFrames(0, 0, lengthDecodedQueue);
+  }
+}
+
+void
 MediaFormatReader::SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(mVideo.HasPromise());
   LOG("Skipping up to %lld", aTimeThreshold.ToMicroseconds());
 
+  // We've reached SkipVideoDemuxToNextKeyFrame when our decoding is late.
+  // As such we can drop all already decoded samples and discard all pending
+  // samples.
+  // TODO: Ideally we should set mOutputRequested to false so that all pending
+  // frames are dropped too. However, we can't do such thing as the code assumes
+  // that the decoder just got flushed. Once bug 1257107 land, we could set the
+  // decoder threshold to the value of currentTime.
+  DropDecodedSamples(TrackInfo::kVideoTrack);
+
   mSkipRequest.Begin(mVideo.mTrackDemuxer->SkipToNextRandomAccessPoint(aTimeThreshold)
                           ->Then(OwnerThread(), __func__, this,
                                  &MediaFormatReader::OnVideoSkipCompleted,
                                  &MediaFormatReader::OnVideoSkipFailed));
   return;
 }
 
 void
 MediaFormatReader::VideoSkipReset(uint32_t aSkipped)
 {
   MOZ_ASSERT(OnTaskQueue());
-  // I think it's still possible for an output to have been sent from the decoder
-  // and is currently sitting in our event queue waiting to be processed. The following
-  // flush won't clear it, and when we return to the event loop it'll be added to our
-  // output queue and be used.
-  // This code will count that as dropped, which was the intent, but not quite true.
+
+  // Some frames may have been output by the decoder since we initiated the
+  // videoskip process and we know they would be late.
+  DropDecodedSamples(TrackInfo::kVideoTrack);
+  // Report the pending frames as dropped.
   if (mDecoder) {
     mDecoder->NotifyDecodedFrames(0, 0, SizeOfVideoQueueInFrames());
   }
 
   // Cancel any pending demux request and pending demuxed samples.
   mVideo.mDemuxRequest.DisconnectIfExists();
   Reset(TrackType::kVideoTrack);
 
@@ -1473,16 +1508,19 @@ MediaFormatReader::OnVideoSkipFailed(Med
   MOZ_ASSERT(OnTaskQueue());
   LOG("Skipping failed, skipped %u frames", aFailure.mSkipped);
   mSkipRequest.Complete();
 
   MOZ_ASSERT(mVideo.HasPromise());
   switch (aFailure.mFailure) {
     case DemuxerFailureReason::END_OF_STREAM: MOZ_FALLTHROUGH;
     case DemuxerFailureReason::WAITING_FOR_DATA:
+      // Some frames may have been output by the decoder since we initiated the
+      // videoskip process and we know they would be late.
+      DropDecodedSamples(TrackInfo::kVideoTrack);
       // We can't complete the skip operation, will just service a video frame
       // normally.
       NotifyDecodingRequested(TrackInfo::kVideoTrack);
       break;
     case DemuxerFailureReason::CANCELED: MOZ_FALLTHROUGH;
     case DemuxerFailureReason::SHUTDOWN:
       if (mVideo.HasPromise()) {
         mVideo.RejectPromise(CANCELED, __func__);
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -174,16 +174,17 @@ private:
 
   // DecoderCallback proxies the MediaDataDecoderCallback calls to these
   // functions.
   void Output(TrackType aType, MediaData* aSample);
   void InputExhausted(TrackType aTrack);
   void Error(TrackType aTrack);
   void Reset(TrackType aTrack);
   void DrainComplete(TrackType aTrack);
+  void DropDecodedSamples(TrackType aTrack);
 
   bool ShouldSkip(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
 
   size_t SizeOfQueue(TrackType aTrack);
 
   RefPtr<PDMFactory> mPlatform;
 
   class DecoderCallback : public MediaDataDecoderCallback {
@@ -249,17 +250,17 @@ private:
     {}
 
     MediaFormatReader* mOwner;
     // Disambiguate Audio vs Video.
     MediaData::Type mType;
     RefPtr<MediaTrackDemuxer> mTrackDemuxer;
     // TaskQueue on which decoder can choose to decode.
     // Only non-null up until the decoder is created.
-    RefPtr<FlushableTaskQueue> mTaskQueue;
+    RefPtr<TaskQueue> mTaskQueue;
     // Callback that receives output and error notifications from the decoder.
     nsAutoPtr<DecoderCallback> mCallback;
 
     // Monitor protecting mDescription and mDecoder.
     Monitor mMonitor;
     // The platform decoder.
     RefPtr<MediaDataDecoder> mDecoder;
     const char* mDescription;
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -307,24 +307,16 @@ GenerateRandomPathName(nsCString& aOutSa
 already_AddRefed<TaskQueue>
 CreateMediaDecodeTaskQueue()
 {
   RefPtr<TaskQueue> queue = new TaskQueue(
     GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   return queue.forget();
 }
 
-already_AddRefed<FlushableTaskQueue>
-CreateFlushableMediaDecodeTaskQueue()
-{
-  RefPtr<FlushableTaskQueue> queue = new FlushableTaskQueue(
-    GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
-  return queue.forget();
-}
-
 void
 SimpleTimer::Cancel() {
   if (mTimer) {
 #ifdef DEBUG
     nsCOMPtr<nsIEventTarget> target;
     mTimer->GetTarget(getter_AddRefs(target));
     nsCOMPtr<nsIThread> thread(do_QueryInterface(target));
     MOZ_ASSERT(NS_GetCurrentThread() == thread);
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -2,17 +2,16 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef VideoUtils_h
 #define VideoUtils_h
 
-#include "FlushableTaskQueue.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/RefPtr.h"
 
 #include "nsIThread.h"
 #include "nsSize.h"
@@ -263,19 +262,16 @@ GenerateRandomName(nsCString& aOutSalt, 
 // This version returns a string suitable for use as a file or URL
 // path. This is based on code from nsExternalAppHandler::SetUpTempFile.
 nsresult
 GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength);
 
 already_AddRefed<TaskQueue>
 CreateMediaDecodeTaskQueue();
 
-already_AddRefed<FlushableTaskQueue>
-CreateFlushableMediaDecodeTaskQueue();
-
 // Iteratively invokes aWork until aCondition returns true, or aWork returns false.
 // Use this rather than a while loop to avoid bogarting the task queue.
 template<class Work, class Condition>
 RefPtr<GenericPromise> InvokeUntil(Work aWork, Condition aCondition) {
   RefPtr<GenericPromise::Private> p = new GenericPromise::Private(__func__);
 
   if (aCondition()) {
     p->Resolve(true, __func__);
--- a/dom/media/encoder/fmp4_muxer/ISOControl.h
+++ b/dom/media/encoder/fmp4_muxer/ISOControl.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ISOCOMPOSITOR_H_
 #define ISOCOMPOSITOR_H_
 
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "nsTArray.h"
 #include "ISOTrackMetadata.h"
 #include "EncodedFrameContainer.h"
 
 namespace mozilla {
 
 class Box;
 class ISOControl;
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -213,17 +213,17 @@ static const uint8_t sTestH264ExtraData[
   0xc0, 0x1e, 0xbb, 0x40, 0x50, 0x17, 0xfc, 0xb8, 0x08, 0x80,
   0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, 0xb5, 0x07, 0x8b, 0x17,
   0x50, 0x01, 0x00, 0x04, 0x68, 0xce, 0x32, 0xc8
 };
 
 static already_AddRefed<MediaDataDecoder>
 CreateTestH264Decoder(layers::LayersBackend aBackend,
                       VideoInfo& aConfig,
-                      FlushableTaskQueue* aTaskQueue)
+                      TaskQueue* aTaskQueue)
 {
   aConfig.mMimeType = "video/avc";
   aConfig.mId = 1;
   aConfig.mDuration = 40000;
   aConfig.mMediaTime = 0;
   aConfig.mImage = aConfig.mDisplay = nsIntSize(640, 360);
   aConfig.mExtraData = new MediaByteBuffer();
   aConfig.mExtraData->AppendElements(sTestH264ExtraData,
@@ -246,18 +246,18 @@ MP4Decoder::IsVideoAccelerated(layers::L
   ErrorResult rv;
   RefPtr<dom::Promise> promise;
   promise = dom::Promise::Create(aParent, rv);
   if (rv.Failed()) {
     rv.SuppressException();
     return nullptr;
   }
 
-  RefPtr<FlushableTaskQueue> taskQueue =
-    new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
+  RefPtr<TaskQueue> taskQueue =
+    new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   VideoInfo config;
   RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config, taskQueue));
   if (!decoder) {
     taskQueue->BeginShutdown();
     taskQueue->AwaitShutdownAndIdle();
     promise->MaybeResolve(NS_LITERAL_STRING("No; Failed to create H264 decoder"));
     return promise.forget();
   }
--- a/dom/media/gmp/GMPDiskStorage.cpp
+++ b/dom/media/gmp/GMPDiskStorage.cpp
@@ -5,17 +5,17 @@
 
 #include "plhash.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "GMPParent.h"
 #include "gmp-storage.h"
 #include "mozilla/unused.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "nsClassHashtable.h"
 #include "prio.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "nsContentCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsISimpleEnumerator.h"
 
 namespace mozilla {
--- a/dom/media/gmp/GMPMessageUtils.h
+++ b/dom/media/gmp/GMPMessageUtils.h
@@ -127,17 +127,17 @@ struct ParamTraits<GMPSimulcastStream>
     WriteParam(aMsg, aParam.mHeight);
     WriteParam(aMsg, aParam.mNumberOfTemporalLayers);
     WriteParam(aMsg, aParam.mMaxBitrate);
     WriteParam(aMsg, aParam.mTargetBitrate);
     WriteParam(aMsg, aParam.mMinBitrate);
     WriteParam(aMsg, aParam.mQPMax);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (ReadParam(aMsg, aIter, &(aResult->mWidth)) &&
         ReadParam(aMsg, aIter, &(aResult->mHeight)) &&
         ReadParam(aMsg, aIter, &(aResult->mNumberOfTemporalLayers)) &&
         ReadParam(aMsg, aIter, &(aResult->mMaxBitrate)) &&
         ReadParam(aMsg, aIter, &(aResult->mTargetBitrate)) &&
         ReadParam(aMsg, aIter, &(aResult->mMinBitrate)) &&
         ReadParam(aMsg, aIter, &(aResult->mQPMax))) {
@@ -176,17 +176,17 @@ struct ParamTraits<GMPVideoCodec>
     WriteParam(aMsg, aParam.mQPMax);
     WriteParam(aMsg, aParam.mNumberOfSimulcastStreams);
     for (uint32_t i = 0; i < aParam.mNumberOfSimulcastStreams; i++) {
       WriteParam(aMsg, aParam.mSimulcastStream[i]);
     }
     WriteParam(aMsg, aParam.mMode);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // NOTE: make sure this matches any versions supported
     if (!ReadParam(aMsg, aIter, &(aResult->mGMPApiVersion)) ||
       aResult->mGMPApiVersion != kGMPVersion33) {
         return false;
     }
     if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) {
       return false;
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -2,17 +2,17 @@
 /* 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 "ContainerParser.h"
 
 #include "WebMBufferedParser.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/ErrorResult.h"
 #include "mp4_demuxer/MoofParser.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Maybe.h"
 #include "MediaData.h"
 #ifdef MOZ_FMP4
 #include "MP4Stream.h"
 #include "mp4_demuxer/AtomType.h"
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -98,17 +98,16 @@ EXPORTS += [
     'Benchmark.h',
     'BufferMediaResource.h',
     'CubebUtils.h',
     'DecoderDoctorDiagnostics.h',
     'DecoderTraits.h',
     'DOMMediaStream.h',
     'EncodedBufferCache.h',
     'FileBlockCache.h',
-    'FlushableTaskQueue.h',
     'FrameStatistics.h',
     'Intervals.h',
     'Latency.h',
     'MediaCache.h',
     'MediaCallbackID.h',
     'MediaData.h',
     'MediaDataDemuxer.h',
     'MediaDecoder.h',
@@ -210,17 +209,16 @@ UNIFIED_SOURCES += [
     'AudioTrackList.cpp',
     'Benchmark.cpp',
     'CanvasCaptureMediaStream.cpp',
     'CubebUtils.cpp',
     'DecoderDoctorDiagnostics.cpp',
     'DOMMediaStream.cpp',
     'EncodedBufferCache.cpp',
     'FileBlockCache.cpp',
-    'FlushableTaskQueue.cpp',
     'GetUserMediaRequest.cpp',
     'GraphDriver.cpp',
     'Latency.cpp',
     'MediaCache.cpp',
     'MediaCallbackID.cpp',
     'MediaData.cpp',
     'MediaDecoder.cpp',
     'MediaDecoderReader.cpp',
--- a/dom/media/ogg/OggCodecState.cpp
+++ b/dom/media/ogg/OggCodecState.cpp
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <string.h>
 
 #include "mozilla/DebugOnly.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include <stdint.h>
 
 #include "nsDebug.h"
 #include "MediaDecoderReader.h"
 #include "OggCodecState.h"
 #include "OggDecoder.h"
 #include "nsISupportsImpl.h"
 #include "VideoUtils.h"
--- a/dom/media/ogg/OpusParser.cpp
+++ b/dom/media/ogg/OpusParser.cpp
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <string.h>
 
 #include "mozilla/DebugOnly.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include <stdint.h>
 
 #include "OpusParser.h"
 
 #include "nsDebug.h"
 #include "MediaDecoderReader.h"
 #include "VideoUtils.h"
 #include <algorithm>
--- a/dom/media/platforms/agnostic/OpusDecoder.cpp
+++ b/dom/media/platforms/agnostic/OpusDecoder.cpp
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "OpusDecoder.h"
 #include "TimeUnits.h"
 #include "VorbisUtils.h"
 #include "VorbisDecoder.h" // For VorbisLayout
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/SyncRunnable.h"
 
 #include <stdint.h>
 #include <inttypes.h>  // For PRId64
 
 #define OPUS_DEBUG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \
     ("OpusDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPVideoDecoder.h"
 #include "GMPVideoHost.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "prsystem.h"
 #include "MediaData.h"
 #include "GMPDecoderModule.h"
 
 namespace mozilla {
 
 #if defined(DEBUG)
 extern bool IsOnGMPThread();
--- a/dom/media/wave/WaveDemuxer.cpp
+++ b/dom/media/wave/WaveDemuxer.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WaveDemuxer.h"
 
 #include <inttypes.h>
 #include <algorithm>
 
 #include "mozilla/Assertions.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "VideoUtils.h"
 #include "TimeUnits.h"
 #include "prenv.h"
 
 using mozilla::media::TimeUnit;
 using mozilla::media::TimeIntervals;
 using mp4_demuxer::ByteReader;
 
--- a/dom/media/wave/WaveReader.cpp
+++ b/dom/media/wave/WaveReader.cpp
@@ -8,17 +8,17 @@
 #include "WaveReader.h"
 #include "MediaDecoderStateMachine.h"
 #include "VideoUtils.h"
 #include "nsISeekableStream.h"
 
 #include <stdint.h>
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/CheckedInt.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/UniquePtr.h"
 #include <algorithm>
 
 using namespace mozilla::media;
 
 namespace mozilla {
 
 // Un-comment to enable logging of seek bisections.
--- a/dom/media/webm/EbmlComposer.cpp
+++ b/dom/media/webm/EbmlComposer.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 "EbmlComposer.h"
 #include "mozilla/UniquePtr.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "libmkv/EbmlIDs.h"
 #include "libmkv/EbmlWriter.h"
 #include "libmkv/WebMElement.h"
 #include "prtime.h"
 
 namespace mozilla {
 
 // Timecode scale in nanoseconds
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -7,17 +7,17 @@
 #include "nsError.h"
 #include "MediaDecoderStateMachine.h"
 #include "AbstractMediaDecoder.h"
 #include "MediaResource.h"
 #include "WebMDemuxer.h"
 #include "WebMBufferedParser.h"
 #include "gfx2DGlue.h"
 #include "mozilla/Atomics.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/SharedThreadPool.h"
 #include "MediaDataDemuxer.h"
 #include "nsAutoRef.h"
 #include "NesteggPacketHolder.h"
 #include "XiphExtradata.h"
 #include "prprf.h"           // leaving it for PR_vsnprintf()
 #include "mozilla/Snprintf.h"
 
--- a/dom/media/webrtc/WebrtcGlobal.h
+++ b/dom/media/webrtc/WebrtcGlobal.h
@@ -26,17 +26,17 @@ struct ParamTraits<mozilla::dom::Optiona
       WriteParam(aMsg, true);
       WriteParam(aMsg, aParam.Value());
       return;
     }
 
     WriteParam(aMsg, false);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     bool was_passed = false;
 
     if (!ReadParam(aMsg, aIter, &was_passed)) {
       return false;
     }
 
     aResult->Reset(); //XXX Optional_base seems to reach this point with isSome true.
@@ -56,17 +56,17 @@ struct ParamTraits<mozilla::dom::Sequenc
 {
   typedef mozilla::dom::Sequence<T> paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<const FallibleTArray<T>&>(aParam));
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, dynamic_cast<FallibleTArray<T>*>(aResult));
   }
 };
 
 template<>
 struct ParamTraits<mozilla::dom::RTCStatsType> :
   public ContiguousEnumSerializer<
@@ -109,17 +109,17 @@ struct ParamTraits<mozilla::dom::RTCStat
     WriteParam(aMsg, aParam.mMediaStreamTrackStats);
     WriteParam(aMsg, aParam.mOutboundRTPStreamStats);
     WriteParam(aMsg, aParam.mPcid);
     WriteParam(aMsg, aParam.mRemoteSdp);
     WriteParam(aMsg, aParam.mTimestamp);
     WriteParam(aMsg, aParam.mTransportStats);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mClosed)) ||
         !ReadParam(aMsg, aIter, &(aResult->mCodecStats)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIceCandidatePairStats)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIceCandidateStats)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIceComponentStats)) ||
         !ReadParam(aMsg, aIter, &(aResult->mInboundRTPStreamStats)) ||
         !ReadParam(aMsg, aIter, &(aResult->mLocalSdp)) ||
@@ -142,17 +142,17 @@ typedef mozilla::dom::RTCStats RTCStats;
 static void WriteRTCStats(Message* aMsg, const RTCStats& aParam)
 {
   // RTCStats base class
   WriteParam(aMsg, aParam.mId);
   WriteParam(aMsg, aParam.mTimestamp);
   WriteParam(aMsg, aParam.mType);
 }
 
-static bool ReadRTCStats(const Message* aMsg, void** aIter, RTCStats* aResult)
+static bool ReadRTCStats(const Message* aMsg, PickleIterator* aIter, RTCStats* aResult)
 {
   // RTCStats base class
   if (!ReadParam(aMsg, aIter, &(aResult->mId)) ||
       !ReadParam(aMsg, aIter, &(aResult->mTimestamp)) ||
       !ReadParam(aMsg, aIter, &(aResult->mType))) {
     return false;
   }
 
@@ -169,17 +169,17 @@ struct ParamTraits<mozilla::dom::RTCCode
     WriteParam(aMsg, aParam.mChannels);
     WriteParam(aMsg, aParam.mClockRate);
     WriteParam(aMsg, aParam.mCodec);
     WriteParam(aMsg, aParam.mParameters);
     WriteParam(aMsg, aParam.mPayloadType);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mChannels)) ||
         !ReadParam(aMsg, aIter, &(aResult->mClockRate)) ||
         !ReadParam(aMsg, aIter, &(aResult->mCodec)) ||
         !ReadParam(aMsg, aIter, &(aResult->mParameters)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPayloadType)) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
       return false;
@@ -202,17 +202,17 @@ struct ParamTraits<mozilla::dom::RTCIceC
     WriteParam(aMsg, aParam.mNominated);
     WriteParam(aMsg, aParam.mReadable);
     WriteParam(aMsg, aParam.mRemoteCandidateId);
     WriteParam(aMsg, aParam.mSelected);
     WriteParam(aMsg, aParam.mState);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mComponentId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mLocalCandidateId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPriority)) ||
         !ReadParam(aMsg, aIter, &(aResult->mNominated)) ||
         !ReadParam(aMsg, aIter, &(aResult->mReadable)) ||
         !ReadParam(aMsg, aIter, &(aResult->mRemoteCandidateId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mSelected)) ||
@@ -237,17 +237,17 @@ struct ParamTraits<mozilla::dom::RTCIceC
     WriteParam(aMsg, aParam.mComponentId);
     WriteParam(aMsg, aParam.mIpAddress);
     WriteParam(aMsg, aParam.mMozLocalTransport);
     WriteParam(aMsg, aParam.mPortNumber);
     WriteParam(aMsg, aParam.mTransport);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mCandidateId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mCandidateType)) ||
         !ReadParam(aMsg, aIter, &(aResult->mComponentId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIpAddress)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozLocalTransport)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPortNumber)) ||
         !ReadParam(aMsg, aIter, &(aResult->mTransport)) ||
@@ -269,17 +269,17 @@ struct ParamTraits<mozilla::dom::RTCIceC
     WriteParam(aMsg, aParam.mActiveConnection);
     WriteParam(aMsg, aParam.mBytesReceived);
     WriteParam(aMsg, aParam.mBytesSent);
     WriteParam(aMsg, aParam.mComponent);
     WriteParam(aMsg, aParam.mTransportId);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mActiveConnection)) ||
         !ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
         !ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
         !ReadParam(aMsg, aIter, &(aResult->mComponent)) ||
         !ReadParam(aMsg, aIter, &(aResult->mTransportId)) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
       return false;
@@ -302,17 +302,17 @@ static void WriteRTCRTPStreamStats(
     WriteParam(aMsg, aParam.mMediaTrackId);
     WriteParam(aMsg, aParam.mMediaType);
     WriteParam(aMsg, aParam.mRemoteId);
     WriteParam(aMsg, aParam.mSsrc);
     WriteParam(aMsg, aParam.mTransportId);
 }
 
 static bool ReadRTCRTPStreamStats(
-              const Message* aMsg, void** aIter,
+              const Message* aMsg, PickleIterator* aIter,
               mozilla::dom::RTCRTPStreamStats* aResult)
 {
   if (!ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) ||
       !ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) ||
       !ReadParam(aMsg, aIter, &(aResult->mCodecId)) ||
       !ReadParam(aMsg, aIter, &(aResult->mFramerateMean)) ||
       !ReadParam(aMsg, aIter, &(aResult->mFramerateStdDev)) ||
       !ReadParam(aMsg, aIter, &(aResult->mIsRemote)) ||
@@ -341,17 +341,17 @@ struct ParamTraits<mozilla::dom::RTCInbo
     WriteParam(aMsg, aParam.mMozJitterBufferDelay);
     WriteParam(aMsg, aParam.mMozRtt);
     WriteParam(aMsg, aParam.mPacketsLost);
     WriteParam(aMsg, aParam.mPacketsReceived);
     WriteRTCRTPStreamStats(aMsg, aParam);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) ||
         !ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozRtt)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
@@ -375,17 +375,17 @@ struct ParamTraits<mozilla::dom::RTCOutb
     WriteParam(aMsg, aParam.mBytesSent);
     WriteParam(aMsg, aParam.mDroppedFrames);
     WriteParam(aMsg, aParam.mPacketsSent);
     WriteParam(aMsg, aParam.mTargetBitrate);
     WriteRTCRTPStreamStats(aMsg, aParam);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDroppedFrames)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPacketsSent)) ||
         !ReadParam(aMsg, aIter, &(aResult->mTargetBitrate)) ||
         !ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
       return false;
@@ -402,17 +402,17 @@ struct ParamTraits<mozilla::dom::RTCMedi
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mStreamIdentifier);
     WriteParam(aMsg, aParam.mTrackIds);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mStreamIdentifier)) ||
         !ReadParam(aMsg, aIter, &(aResult->mTrackIds)) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
       return false;
     }
 
     return true;
@@ -426,17 +426,17 @@ struct ParamTraits<mozilla::dom::RTCTran
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mBytesReceived);
     WriteParam(aMsg, aParam.mBytesSent);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
         !ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
       return false;
     }
 
     return true;
@@ -462,17 +462,17 @@ struct ParamTraits<mozilla::dom::RTCMedi
     WriteParam(aMsg, aParam.mFramesReceived);
     WriteParam(aMsg, aParam.mFramesSent);
     WriteParam(aMsg, aParam.mRemoteSource);
     WriteParam(aMsg, aParam.mSsrcIds);
     WriteParam(aMsg, aParam.mTrackIdentifier);
     WriteRTCStats(aMsg, aParam);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mAudioLevel)) ||
         !ReadParam(aMsg, aIter, &(aResult->mEchoReturnLoss)) ||
         !ReadParam(aMsg, aIter, &(aResult->mEchoReturnLossEnhancement)) ||
         !ReadParam(aMsg, aIter, &(aResult->mFrameHeight)) ||
         !ReadParam(aMsg, aIter, &(aResult->mFrameWidth)) ||
         !ReadParam(aMsg, aIter, &(aResult->mFramesCorrupted)) ||
         !ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) ||
--- a/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h
+++ b/dom/mobileconnection/ipc/MobileConnectionIPCSerializer.h
@@ -92,17 +92,17 @@ struct ParamTraits<nsIMobileCallForwardi
     aParam->GetTimeSeconds(&pShort);
     WriteParam(aMsg, pShort);
 
     aParam->GetServiceClass(&pShort);
     WriteParam(aMsg, pShort);
   }
 
   // Function to de-serialize a MobileCallForwardingOptions.
-  static bool Read(const Message *aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message *aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if is the null pointer we have transfered.
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) {
       return false;
     }
 
     if (isNull) {
@@ -171,17 +171,17 @@ struct ParamTraits<nsIMobileNetworkInfo*
     aParam->GetState(pString);
     WriteParam(aMsg, pString);
 
     // We release the ref here given that ipdl won't handle reference counting.
     aParam->Release();
   }
 
   // Function to de-serialize a MobileNetworkInfo.
-  static bool Read(const Message *aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message *aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if is the null pointer we have transfered.
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) {
       return false;
     }
 
     if (isNull) {
@@ -258,17 +258,17 @@ struct ParamTraits<nsIMobileCellInfo*>
     aParam->GetCdmaNetworkId(&pLong);
     WriteParam(aMsg, pLong);
 
     // We release the ref here given that ipdl won't handle reference counting.
     aParam->Release();
   }
 
   // Function to de-serialize a MobileCellInfo.
-  static bool Read(const Message *aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message *aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if is the null pointer we have transfered.
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) {
       return false;
     }
 
     if (isNull) {
@@ -373,17 +373,17 @@ struct ParamTraits<nsIMobileConnectionIn
       WriteParam(aMsg, pInt32);
     }
 
     // We release the ref here given that ipdl won't handle reference counting.
     aParam->Release();
   }
 
   // Function to de-serialize a MobileConectionInfo.
-  static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if is the null pointer we have transfered.
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) {
       return false;
     }
 
     if (isNull) {
@@ -536,17 +536,17 @@ struct ParamTraits<MozCallForwardingOpti
       WriteParam(aMsg, isNull);
       if (!isNull) {
         WriteParam(aMsg, aParam.mServiceClass.Value().Value());
       }
     }
   }
 
   // Function to de-serialize a MozCallForwardingOptions.
-  static bool Read(const Message *aMsg, void **aIter, paramType* aResult)
+  static bool Read(const Message *aMsg, PickleIterator* aIter, paramType* aResult)
   {
     bool wasPassed = false;
     bool isNull = false;
 
     // Read mActive
     if (!ReadParam(aMsg, aIter, &wasPassed)) {
       return false;
     }
--- a/dom/nfc/gonk/NfcService.cpp
+++ b/dom/nfc/gonk/NfcService.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "NfcService.h"
 #include <binder/Parcel.h>
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/NfcOptionsBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/RootedDictionary.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/Hal.h"
 #include "mozilla/ipc/ListenSocket.h"
 #include "mozilla/ipc/ListenSocketConsumer.h"
 #include "mozilla/ipc/NfcConnector.h"
 #include "mozilla/ipc/StreamSocket.h"
 #include "mozilla/ipc/StreamSocketConsumer.h"
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/UniquePtr.h"
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -467,28 +467,16 @@ GetGlobalObject(NPP npp)
 
   nsCOMPtr<nsIDocument> doc;
   owner->GetDocument(getter_AddRefs(doc));
   NS_ENSURE_TRUE(doc, nullptr);
 
   return doc->GetScopeObject();
 }
 
-JSContext *
-GetJSContext(NPP npp)
-{
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetGlobalObject(npp));
-  NS_ENSURE_TRUE(sgo, nullptr);
-
-  nsIScriptContext *scx = sgo->GetContext();
-  NS_ENSURE_TRUE(scx, nullptr);
-
-  return scx->GetNativeContext();
-}
-
 } // namespace parent
 } // namespace plugins
 } // namespace mozilla
 
 static NPP
 LookupNPP(NPObject *npobj);
 
 
@@ -605,17 +593,17 @@ JSValToNPVariant(NPP npp, JSContext *cx,
   // legitimate cases where a security wrapper ends up here (for example,
   // Location objects, which are _always_ behind security wrappers).
   JS::Rooted<JSObject*> obj(cx, val.toObjectOrNull());
   obj = js::CheckedUnwrap(obj);
   if (!obj) {
     obj = val.toObjectOrNull();
   }
 
-  NPObject *npobj = nsJSObjWrapper::GetNewOrUsed(npp, cx, obj);
+  NPObject* npobj = nsJSObjWrapper::GetNewOrUsed(npp, obj);
   if (!npobj) {
     return false;
   }
 
   // Pass over ownership of npobj to *variant
   OBJECT_TO_NPVARIANT(npobj, *variant);
 
   return true;
@@ -1098,17 +1086,17 @@ nsJSObjWrapper::NP_Construct(NPObject *n
 {
   return doInvoke(npobj, NPIdentifier_VOID, args, argCount, true, result);
 }
 
 // Look up or create an NPObject that wraps the JSObject obj.
 
 // static
 NPObject *
-nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JS::Handle<JSObject*> obj)
+nsJSObjWrapper::GetNewOrUsed(NPP npp, JS::Handle<JSObject*> obj)
 {
   if (!npp) {
     NS_ERROR("Null NPP passed to nsJSObjWrapper::GetNewOrUsed()!");
 
     return nullptr;
   }
 
   // If we're running out-of-process and initializing asynchronously, and if
@@ -1117,26 +1105,16 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JS
   nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
   if (inst->GetPlugin()->GetLibrary()->IsOOP()) {
     PluginAsyncSurrogate* surrogate = PluginAsyncSurrogate::Cast(npp);
     if (surrogate && surrogate->IsDestroyPending()) {
       return nullptr;
     }
   }
 
-  if (!cx) {
-    cx = GetJSContext(npp);
-
-    if (!cx) {
-      NS_ERROR("Unable to find a JSContext in nsJSObjWrapper::GetNewOrUsed()!");
-
-      return nullptr;
-    }
-  }
-
   // No need to enter the right compartment here as we only get the
   // class and private from the JSObject, neither of which cares about
   // compartments.
 
   if (nsNPObjWrapper::IsWrapper(obj)) {
     // obj is one of our own, its private data is the NPObject we're
     // looking for.
 
--- a/dom/plugins/base/nsJSNPRuntime.h
+++ b/dom/plugins/base/nsJSNPRuntime.h
@@ -53,18 +53,17 @@ public:
 
 class nsJSObjWrapper : public NPObject
 {
 public:
   JS::Heap<JSObject *> mJSObj;
   const NPP mNpp;
   bool mDestroyPending;
 
-  static NPObject *GetNewOrUsed(NPP npp, JSContext *cx,
-                                JS::Handle<JSObject*> obj);
+  static NPObject* GetNewOrUsed(NPP npp, JS::Handle<JSObject*> obj);
   static bool HasOwnProperty(NPObject* npobj, NPIdentifier npid);
 
   void trace(JSTracer* trc) {
       JS::TraceEdge(trc, &mJSObj, "nsJSObjWrapper");
   }
 
 protected:
   explicit nsJSObjWrapper(NPP npp);
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -1057,19 +1057,19 @@ NPObject*
 
   // The window want to return here is the outer window, *not* the inner (since
   // we don't know what the plugin will do with it).
   nsIDocument* doc = GetDocumentFromNPP(npp);
   NS_ENSURE_TRUE(doc, nullptr);
   nsCOMPtr<nsPIDOMWindowOuter> outer = doc->GetWindow();
   NS_ENSURE_TRUE(outer, nullptr);
 
-  AutoJSContext cx;
-  JS::Rooted<JSObject*> global(cx, nsGlobalWindow::Cast(outer)->GetGlobalJSObject());
-  return nsJSObjWrapper::GetNewOrUsed(npp, cx, global);
+  JS::Rooted<JSObject*> global(nsContentUtils::RootingCx(),
+                               nsGlobalWindow::Cast(outer)->GetGlobalJSObject());
+  return nsJSObjWrapper::GetNewOrUsed(npp, global);
 }
 
 NPObject*
 _getpluginelement(NPP npp)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getpluginelement called from the wrong thread\n"));
     return nullptr;
@@ -1099,17 +1099,17 @@ NPObject*
   nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
   NS_ENSURE_TRUE(xpc, nullptr);
 
   JS::RootedObject obj(cx);
   xpc->WrapNative(cx, ::JS::CurrentGlobalOrNull(cx), element,
                   NS_GET_IID(nsIDOMElement), obj.address());
   NS_ENSURE_TRUE(obj, nullptr);
 
-  return nsJSObjWrapper::GetNewOrUsed(npp, cx, obj);
+  return nsJSObjWrapper::GetNewOrUsed(npp, obj);
 }
 
 NPIdentifier
 _getstringidentifier(const NPUTF8* name)
 {
   if (!name) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifier: passed null name"));
     return nullptr;
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -1542,45 +1542,16 @@ nsNPAPIPluginInstance::GetMIMEType(const
   if (!mMIMEType)
     *result = "";
   else
     *result = mMIMEType;
 
   return NS_OK;
 }
 
-nsresult
-nsNPAPIPluginInstance::GetJSContext(JSContext* *outContext)
-{
-  if (!mOwner)
-    return NS_ERROR_FAILURE;
-
-  RefPtr<nsPluginInstanceOwner> deathGrip(mOwner);
-
-  *outContext = nullptr;
-  nsCOMPtr<nsIDocument> document;
-
-  nsresult rv = mOwner->GetDocument(getter_AddRefs(document));
-
-  if (NS_SUCCEEDED(rv) && document) {
-    nsCOMPtr<nsIScriptGlobalObject> global =
-      do_QueryInterface(document->GetWindow());
-
-    if (global) {
-      nsIScriptContext *context = global->GetContext();
-
-      if (context) {
-        *outContext = context->GetNativeContext();
-      }
-    }
-  }
-
-  return rv;
-}
-
 nsPluginInstanceOwner*
 nsNPAPIPluginInstance::GetOwner()
 {
   return mOwner;
 }
 
 void
 nsNPAPIPluginInstance::SetOwner(nsPluginInstanceOwner *aOwner)
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -116,17 +116,16 @@ public:
   nsresult IsTransparent(bool* isTransparent);
   nsresult GetFormValue(nsAString& aValue);
   nsresult PushPopupsEnabledState(bool aEnabled);
   nsresult PopPopupsEnabledState();
   nsresult GetPluginAPIVersion(uint16_t* version);
   nsresult InvalidateRect(NPRect *invalidRect);
   nsresult InvalidateRegion(NPRegion invalidRegion);
   nsresult GetMIMEType(const char* *result);
-  nsresult GetJSContext(JSContext* *outContext);
 #if defined(XP_WIN)
   nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer **aContainer);
   nsresult UpdateScrollState(bool aIsScrolling);
 #endif
   nsresult HandledWindowedPluginKeyEvent(
              const mozilla::NativeEventData& aKeyEventData,
              bool aIsConsumed);
   nsPluginInstanceOwner* GetOwner();
--- a/dom/plugins/ipc/NPEventAndroid.h
+++ b/dom/plugins/ipc/NPEventAndroid.h
@@ -32,26 +32,19 @@ struct ParamTraits<mozilla::plugins::NPR
 {
     typedef mozilla::plugins::NPRemoteEvent paramType;
 
     static void Write(Message* aMsg, const paramType& aParam)
     {
         aMsg->WriteBytes(&aParam, sizeof(paramType));
     }
 
-    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
     {
-        const char* bytes = 0;
-
-        if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
-            return false;
-        }
-
-        memcpy(aResult, bytes, sizeof(paramType));
-        return true;
+        return aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType));
     }
 
     static void Log(const paramType& aParam, std::wstring* aLog)
     {
         // TODO
         aLog->append(L"(AndroidEvent)");
     }
 };
--- a/dom/plugins/ipc/NPEventOSX.h
+++ b/dom/plugins/ipc/NPEventOSX.h
@@ -77,17 +77,17 @@ struct ParamTraits<mozilla::plugins::NPR
                 break;
             default:
                 NS_NOTREACHED("Attempted to serialize unknown event type.");
                 return;
         }
         aMsg->WriteDouble(aParam.contentsScaleFactor);
     }
 
-    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
     {
         int type = 0;
         if (!aMsg->ReadInt(aIter, &type)) {
             return false;
         }
         aResult->event.type = static_cast<NPCocoaEventType>(type);
 
         if (!aMsg->ReadUInt32(aIter, &aResult->event.version)) {
--- a/dom/plugins/ipc/NPEventUnix.h
+++ b/dom/plugins/ipc/NPEventUnix.h
@@ -50,26 +50,22 @@ struct ParamTraits<mozilla::plugins::NPR
 {
     typedef mozilla::plugins::NPRemoteEvent paramType;
 
     static void Write(Message* aMsg, const paramType& aParam)
     {
         aMsg->WriteBytes(&aParam, sizeof(paramType));
     }
 
-    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
     {
-        const char* bytes = 0;
-
-        if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
+        if (!aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType))) {
             return false;
         }
 
-        memcpy(aResult, bytes, sizeof(paramType));
-
 #ifdef MOZ_X11
         SetXDisplay(aResult->event);
 #endif
         return true;
     }
 
     static void Log(const paramType& aParam, std::wstring* aLog)
     {
--- a/dom/plugins/ipc/NPEventWindows.h
+++ b/dom/plugins/ipc/NPEventWindows.h
@@ -125,24 +125,21 @@ struct ParamTraits<mozilla::plugins::NPR
                 // entirely.
                 paramCopy.event.event = WM_NULL;
                 break;
         }
 
         aMsg->WriteBytes(&paramCopy, sizeof(paramType));
     }
 
-    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
     {
-        const char* bytes = 0;
-
-        if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
+        if (!aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType))) {
             return false;
         }
-        memcpy(aResult, bytes, sizeof(paramType));
 
         if (aResult->event.event == WM_PAINT) {
             // restore the lParam to point at the RECT
             aResult->event.lParam = reinterpret_cast<LPARAM>(&aResult->lParamData.rect);
         } else if (aResult->event.event == WM_WINDOWPOSCHANGED) {
             // restore the lParam to point at the WINDOWPOS
             aResult->event.lParam = reinterpret_cast<LPARAM>(&aResult->lParamData.windowpos);
         }
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -275,17 +275,17 @@ struct ParamTraits<NPRect>
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.top);
     WriteParam(aMsg, aParam.left);
     WriteParam(aMsg, aParam.bottom);
     WriteParam(aMsg, aParam.right);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     uint16_t top, left, bottom, right;
     if (ReadParam(aMsg, aIter, &top) &&
         ReadParam(aMsg, aIter, &left) &&
         ReadParam(aMsg, aIter, &bottom) &&
         ReadParam(aMsg, aIter, &right)) {
       aResult->top = top;
       aResult->left = left;
@@ -308,17 +308,17 @@ struct ParamTraits<NPWindowType>
 {
   typedef NPWindowType paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     aMsg->WriteInt16(int16_t(aParam));
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     int16_t result;
     if (aMsg->ReadInt16(aIter, &result)) {
       *aResult = paramType(result);
       return true;
     }
     return false;
   }
@@ -347,17 +347,17 @@ struct ParamTraits<mozilla::plugins::NPR
     aMsg->WriteULong(aParam.visualID);
     aMsg->WriteULong(aParam.colormap);
 #endif
 #if defined(XP_MACOSX)
     aMsg->WriteDouble(aParam.contentsScaleFactor);
 #endif
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     uint64_t window;
     int32_t x, y;
     uint32_t width, height;
     NPRect clipRect;
     NPWindowType type;
     if (!(aMsg->ReadUInt64(aIter, &window) &&
           ReadParam(aMsg, aIter, &x) &&
@@ -438,41 +438,45 @@ struct ParamTraits<NPNSString*>
     } else {
       UniChar *buffer = (UniChar*)moz_xmalloc(length * sizeof(UniChar));
       ::CFStringGetCharacters(cfString, ::CFRangeMake(0, length), buffer);
       aMsg->WriteBytes(buffer, length * sizeof(UniChar));
       free(buffer);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     bool haveString = false;
     if (!aMsg->ReadBool(aIter, &haveString)) {
       return false;
     }
     if (!haveString) {
       *aResult = nullptr;
       return true;
     }
 
     long length;
     if (!ReadParam(aMsg, aIter, &length)) {
       return false;
     }
 
-    UniChar* buffer = nullptr;
+    // Avoid integer multiplication overflow.
+    if (length > INT_MAX / static_cast<long>(sizeof(UniChar))) {
+      return false;
+    }
+
+    auto chars = mozilla::MakeUnique<UniChar[]>(length);
     if (length != 0) {
-      if (!aMsg->ReadBytes(aIter, (const char**)&buffer, length * sizeof(UniChar)) ||
-          !buffer) {
+      if (!aMsg->ReadBytesInto(aIter, chars.get(), length * sizeof(UniChar))) {
         return false;
       }
     }
 
-    *aResult = (NPNSString*)::CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*)buffer,
+    *aResult = (NPNSString*)::CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*)chars.get(),
                                                       length * sizeof(UniChar),
                                                       kCFStringEncodingUTF16, false);
     if (!*aResult) {
       return false;
     }
 
     return true;
   }
@@ -502,17 +506,17 @@ struct ParamTraits<NSCursorInfo>
     }
 
     uint8_t* buffer = (uint8_t*)moz_xmalloc(dataLength);
     memcpy(buffer, aParam.GetCustomImageData(), dataLength);
     aMsg->WriteBytes(buffer, dataLength);
     free(buffer);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     NSCursorInfo::Type type;
     if (!aMsg->ReadInt(aIter, (int*)&type)) {
       return false;
     }
 
     nscoord hotSpotX, hotSpotY;
     if (!ReadParam(aMsg, aIter, &hotSpotX) ||
@@ -520,26 +524,26 @@ struct ParamTraits<NSCursorInfo>
       return false;
     }
 
     uint32_t dataLength;
     if (!ReadParam(aMsg, aIter, &dataLength)) {
       return false;
     }
 
-    uint8_t* data = nullptr;
+    auto data = mozilla::MakeUnique<uint8_t[]>(dataLength);
     if (dataLength != 0) {
-      if (!aMsg->ReadBytes(aIter, (const char**)&data, dataLength) || !data) {
+      if (!aMsg->ReadBytesInto(aIter, data.get(), dataLength)) {
         return false;
       }
     }
 
     aResult->SetType(type);
     aResult->SetHotSpot(nsPoint(hotSpotX, hotSpotY));
-    aResult->SetCustomImageData(data, dataLength);
+    aResult->SetCustomImageData(data.get(), dataLength);
 
     return true;
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
     const char* typeName = aParam.GetTypeName();
     nsPoint hotSpot = aParam.GetHotSpot();
@@ -561,17 +565,17 @@ struct ParamTraits<NSCursorInfo>
 #else
 template<>
 struct ParamTraits<NSCursorInfo>
 {
   typedef NSCursorInfo paramType;
   static void Write(Message* aMsg, const paramType& aParam) {
     NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform");
   }
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
     NS_RUNTIMEABORT("NSCursorInfo isn't meaningful on this platform");
     return false;
   }
 };
 #endif // #ifdef XP_MACOSX
 
 template <>
 struct ParamTraits<mozilla::plugins::IPCByteRange>
@@ -579,17 +583,17 @@ struct ParamTraits<mozilla::plugins::IPC
   typedef mozilla::plugins::IPCByteRange paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.offset);
     WriteParam(aMsg, aParam.length);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     paramType p;
     if (ReadParam(aMsg, aIter, &p.offset) &&
         ReadParam(aMsg, aIter, &p.length)) {
       *aResult = p;
       return true;
     }
     return false;
@@ -601,17 +605,17 @@ struct ParamTraits<NPNVariable>
 {
   typedef NPNVariable paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, int(aParam));
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     int intval;
     if (ReadParam(aMsg, aIter, &intval)) {
       *aResult = paramType(intval);
       return true;
     }
     return false;
   }
@@ -622,17 +626,17 @@ struct ParamTraits<NPNURLVariable>
 {
   typedef NPNURLVariable paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, int(aParam));
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     int intval;
     if (ReadParam(aMsg, aIter, &intval)) {
       switch (intval) {
       case NPNURLVCookie:
       case NPNURLVProxy:
         *aResult = paramType(intval);
         return true;
@@ -648,17 +652,17 @@ struct ParamTraits<NPCoordinateSpace>
 {
   typedef NPCoordinateSpace paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, int32_t(aParam));
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     int32_t intval;
     if (ReadParam(aMsg, aIter, &intval)) {
       switch (intval) {
       case NPCoordinateSpacePlugin:
       case NPCoordinateSpaceWindow:
       case NPCoordinateSpaceFlippedWindow:
       case NPCoordinateSpaceScreen:
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -80,50 +80,35 @@ static bool IsImageLoadInEditorAppType(n
 static nsresult
 DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
 {
   // Bug 1228117: determine the correct security policy for DTD loads
   if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DTD) {
     return NS_OK;
   }
 
-  nsresult rv = NS_OK;
+  if (IsImageLoadInEditorAppType(aLoadInfo)) {
+    return NS_OK;
+  }
 
-  nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
   uint32_t flags = nsIScriptSecurityManager::STANDARD;
   if (aLoadInfo->GetAllowChrome()) {
     flags |= nsIScriptSecurityManager::ALLOW_CHROME;
   }
   if (aLoadInfo->GetDisallowScript()) {
     flags |= nsIScriptSecurityManager::DISALLOW_SCRIPT;
   }
 
-  bool isImageInEditorType = IsImageLoadInEditorAppType(aLoadInfo);
-
-  // We don't have a loadingPrincipal for TYPE_DOCUMENT
-  if (aLoadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT &&
-      !isImageInEditorType) {
-    rv = nsContentUtils::GetSecurityManager()->
-      CheckLoadURIWithPrincipal(loadingPrincipal,
-                                aURI,
-                                flags);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  // If the loadingPrincipal and the triggeringPrincipal are different, then make
-  // sure the triggeringPrincipal is allowed to access that URI.
-  nsCOMPtr<nsIPrincipal> triggeringPrincipal = aLoadInfo->TriggeringPrincipal();
-  if (loadingPrincipal != triggeringPrincipal && !isImageInEditorType) {
-    rv = nsContentUtils::GetSecurityManager()->
-           CheckLoadURIWithPrincipal(triggeringPrincipal,
+  // Only call CheckLoadURIWithPrincipal() using the TriggeringPrincipal and not
+  // the LoadingPrincipal when SEC_ALLOW_CROSS_ORIGIN_* security flags are set,
+  // to allow, e.g. user stylesheets to load chrome:// URIs.
+  return nsContentUtils::GetSecurityManager()->
+           CheckLoadURIWithPrincipal(aLoadInfo->TriggeringPrincipal(),
                                      aURI,
                                      flags);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  return NS_OK;
 }
 
 static bool
 URIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
 {
   bool hasFlags;
   nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
   NS_ENSURE_SUCCESS(rv, false);
--- a/dom/svg/SVGContentUtils.cpp
+++ b/dom/svg/SVGContentUtils.cpp
@@ -92,18 +92,18 @@ GetStrokeDashData(SVGContentUtils::AutoS
     for (size_t i = 0; i < dashArrayLength; i++) {
       if (dashSrc[i] < 0.0) {
         return eContinuousStroke; // invalid
       }
       dashPattern[i] = Float(dashSrc[i]);
       (i % 2 ? totalLengthOfGaps : totalLengthOfDashes) += dashSrc[i];
     }
   } else {
-    const nsStyleCoord *dasharray = aStyleSVG->mStrokeDasharray;
-    dashArrayLength = aStyleSVG->mStrokeDasharrayLength;
+    const nsTArray<nsStyleCoord>& dasharray = aStyleSVG->mStrokeDasharray;
+    dashArrayLength = aStyleSVG->mStrokeDasharray.Length();
     if (dashArrayLength <= 0) {
       return eContinuousStroke;
     }
     if (aElement->IsSVGElement(nsGkAtoms::path)) {
       pathScale = static_cast<SVGPathElement*>(aElement)->
         GetPathLengthScale(SVGPathElement::eForStroking);
       if (pathScale <= 0) {
         return eContinuousStroke;
--- a/dom/telephony/ipc/TelephonyIPCSerializer.h
+++ b/dom/telephony/ipc/TelephonyIPCSerializer.h
@@ -78,17 +78,17 @@ struct ParamTraits<nsITelephonyCallInfo*
 
     WriteParam(aMsg, isOutgoing);
     WriteParam(aMsg, isEmergency);
     WriteParam(aMsg, isConference);
     WriteParam(aMsg, isSwitchable);
     WriteParam(aMsg, isMergeable);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     // Check if is the null pointer we have transfered.
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) {
       return false;
     }
 
     if (isNull) {
--- a/dom/tests/mochitest/fetch/fetch_test_framework.js
+++ b/dom/tests/mochitest/fetch/fetch_test_framework.js
@@ -1,9 +1,16 @@
 function testScript(script) {
+
+  // The framework runs the entire test in many different configurations.
+  // On slow platforms and builds this can make the tests likely to
+  // timeout while they are still running.  Lengthen the timeout to
+  // accomodate this.
+  SimpleTest.requestLongerTimeout(2);
+
   // reroute.html should have set this variable if a service worker is present!
   if (!("isSWPresent" in window)) {
     window.isSWPresent = false;
   }
 
   function setupPrefs() {
     return new Promise(function(resolve, reject) {
       SpecialPowers.pushPrefEnv({
--- a/dom/tests/mochitest/fetch/nested_worker_wrapper.js
+++ b/dom/tests/mochitest/fetch/nested_worker_wrapper.js
@@ -1,12 +1,15 @@
+// Hold the nested worker alive until this parent worker closes.
+var worker;
+
 addEventListener('message', function nestedWorkerWrapperOnMessage(evt) {
   removeEventListener('message', nestedWorkerWrapperOnMessage);
 
-  var worker = new Worker('worker_wrapper.js');
+  worker = new Worker('worker_wrapper.js');
 
   worker.addEventListener('message', function(evt) {
     self.postMessage({
       context: 'NestedWorker',
       type: evt.data.type,
       status: evt.data.status,
       msg: evt.data.msg,
     });
--- a/dom/tests/mochitest/fetch/test_fetch_cors.html
+++ b/dom/tests/mochitest/fetch/test_fetch_cors.html
@@ -11,17 +11,13 @@
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none"></div>
 <pre id="test"></pre>
 <script type="text/javascript" src="utils.js"> </script>
 <script type="text/javascript" src="fetch_test_framework.js"> </script>
 <script class="testbody" type="text/javascript">
-
-// XXXcatalinb: this test takes a really long time to run on android debug.
-SimpleTest.requestLongerTimeout(2);
-
 testScript("test_fetch_cors.js");
 </script>
 </body>
 </html>
 
--- a/dom/webidl/Animation.webidl
+++ b/dom/webidl/Animation.webidl
@@ -9,17 +9,17 @@
  * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
 
 [Func="nsDocument::IsElementAnimateEnabled",
  Constructor (optional KeyframeEffectReadOnly? effect = null,
-              optional AnimationTimeline? timeline = null)]
+              optional AnimationTimeline? timeline)]
 interface Animation : EventTarget {
   attribute DOMString id;
   // Bug 1049975: Make 'effect' writeable
   [Func="nsDocument::IsWebAnimationsEnabled", Pure]
   readonly attribute AnimationEffectReadOnly? effect;
   [Func="nsDocument::IsWebAnimationsEnabled"]
   readonly attribute AnimationTimeline? timeline;
   [BinaryName="startTimeAsDouble"]
--- a/dom/wifi/WifiCertService.cpp
+++ b/dom/wifi/WifiCertService.cpp
@@ -2,17 +2,17 @@
 /* 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 "WifiCertService.h"
 
 #include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "cert.h"
 #include "certdb.h"
 #include "CryptoTask.h"
 #include "nsIDOMBlob.h"
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3577,33 +3577,16 @@ WorkerPrivateParent<Derived>::SetPrincip
   mLoadInfo.mPrincipalInfo = new PrincipalInfo();
   mLoadInfo.mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(aLoadGroup);
 
   MOZ_ALWAYS_SUCCEEDS(
     PrincipalToPrincipalInfo(aPrincipal, mLoadInfo.mPrincipalInfo));
 }
 
 template <class Derived>
-JSContext*
-WorkerPrivateParent<Derived>::ParentJSContext() const
-{
-  AssertIsOnParentThread();
-
-  if (mParent) {
-    return mParent->GetJSContext();
-  }
-
-  AssertIsOnMainThread();
-
-  return mLoadInfo.mScriptContext ?
-         mLoadInfo.mScriptContext->GetNativeContext() :
-         nsContentUtils::GetSafeJSContext();
-}
-
-template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup)
 {
   AssertIsOnMainThread();
 
   // The load group should have been overriden at init time.
   mLoadInfo.mInterfaceRequestor->MaybeAddTabChild(aBaseLoadGroup);
 }
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -434,19 +434,16 @@ public:
 
   Status
   ParentStatus() const
   {
     mMutex.AssertCurrentThreadOwns();
     return mParentStatus;
   }
 
-  JSContext*
-  ParentJSContext() const;
-
   nsIScriptContext*
   GetScriptContext() const
   {
     AssertIsOnMainThread();
     return mLoadInfo.mScriptContext;
   }
 
   const nsString&
--- a/dom/xbl/builtin/android/platformHTMLBindings.xml
+++ b/dom/xbl/builtin/android/platformHTMLBindings.xml
@@ -22,18 +22,16 @@
       <handler event="keypress" keycode="VK_LEFT" modifiers="shift,alt" command="cmd_selectBeginLine"/>
       <handler event="keypress" keycode="VK_RIGHT" modifiers="shift,alt" command="cmd_selectEndLine"/>
 
       <handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
 
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
       <handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
       <handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
     </handlers>
   </binding>
 
   <binding id="textAreas" bindToUntrustedContent="true">
     <handlers>
 #include ../textareas-base.inc
@@ -66,18 +64,16 @@
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
       <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
 
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
       <handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
       <handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
     </handlers>
   </binding>
 
   <binding id="browser">
     <handlers>
 #include ../browser-base.inc
@@ -112,18 +108,16 @@
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
       <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
 
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
       <handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
       <handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
     </handlers>
   </binding>
 
   <binding id="editor">
     <handlers>
 #include ../editor-base.inc
@@ -156,15 +150,13 @@
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
       <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
 
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
-      <handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
       <handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
       <handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
     </handlers>
   </binding>
 </bindings>
--- a/dom/xbl/nsXBLProtoImplMethod.cpp
+++ b/dom/xbl/nsXBLProtoImplMethod.cpp
@@ -311,18 +311,17 @@ nsXBLProtoImplAnonymousMethod::Execute(n
   JS::Rooted<JSObject*> method(cx, JS::CloneFunctionObject(cx, jsMethodObject,
                                                            scopeChain));
   if (!method)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Now call the method
 
   // Check whether script is enabled.
-  bool scriptAllowed = nsContentUtils::GetSecurityManager()->
-                         ScriptAllowed(js::GetGlobalForObjectCrossCompartment(method));
+  bool scriptAllowed = xpc::Scriptability::Get(method).Allowed();
 
   if (scriptAllowed) {
     JS::Rooted<JS::Value> retval(cx);
     JS::Rooted<JS::Value> methodVal(cx, JS::ObjectValue(*method));
     // No need to check the return here as AutoEntryScript has taken ownership
     // of error reporting.
     ::JS::Call(cx, scopeChain[0], methodVal, JS::HandleValueArray::empty(), &retval);
   }
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -88,16 +88,17 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/URL.h"
 #include "nsIContentPolicy.h"
 #include "mozAutoDocUpdate.h"
+#include "xpcpublic.h"
 #include "mozilla/StyleSheetHandle.h"
 #include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 //
@@ -3506,17 +3507,17 @@ XULDocument::ExecuteScript(nsXULPrototyp
     // Execute the precompiled script with the given version
     nsAutoMicroTask mt;
 
     // We're about to run script via JS::CloneAndExecuteScript, so we need an
     // AutoEntryScript. This is Gecko specific and not in any spec.
     AutoEntryScript aes(mScriptGlobalObject, "precompiled XUL <script> element");
     JSContext* cx = aes.cx();
     JS::Rooted<JSObject*> baseGlobal(cx, JS::CurrentGlobalOrNull(cx));
-    NS_ENSURE_TRUE(nsContentUtils::GetSecurityManager()->ScriptAllowed(baseGlobal), NS_OK);
+    NS_ENSURE_TRUE(xpc::Scriptability::Get(baseGlobal).Allowed(), NS_OK);
 
     JSAddonId* addonId = mCurrentPrototype ? MapURIToAddonID(mCurrentPrototype->GetURI()) : nullptr;
     JS::Rooted<JSObject*> global(cx, xpc::GetAddonScope(cx, baseGlobal, addonId));
     NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
 
     JS::ExposeObjectToActiveJS(global);
     xpc_UnmarkGrayScript(scriptObject);
     JSAutoCompartment ac(cx, global);
--- a/dom/xul/templates/tests/chrome/test_bug330010.xul
+++ b/dom/xul/templates/tests/chrome/test_bug330010.xul
@@ -13,28 +13,31 @@ SimpleTest.waitForExplicitFinish();
 function boom()
 {
   const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].
                          getService(Components.interfaces.nsIRDFService);
   var src = window.location.href.replace(/test_bug330010.xul/, "file_bug330010.rdf");
 
   var ds = RDF.GetDataSourceBlocking(src);
 
+  var s = document.getElementById("s");
+  s.setAttribute("datasources", "file_bug330010.rdf");
+
   var x = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "hbox");
-  var generatedShape = document.getElementById("s").childNodes[3];
+  var generatedShape = s.childNodes[3];
   generatedShape.appendChild(x);
   document.documentElement.removeChild(document.getElementById("s"));
   ok(true, "Didn't crash");
   SimpleTest.finish();
 }
 
 ]]>
 </script>
 
-  <html:div datasources="file_bug330010.rdf" ref="urn:root" flex="1" id="s">
+  <html:div datasources="rdf:null" ref="urn:root" flex="1" id="s">
     <template>
       <rule>
         <conditions>
           <content uri="?root"/>
           <triple subject="?root"
                   predicate="urn:croczilla:xulsvg1:shapes"
                   object="?shapes"/>
           <member container="?shapes" child="?shape" id="m"/>
--- a/gfx/2d/BasePoint.h
+++ b/gfx/2d/BasePoint.h
@@ -17,17 +17,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub, class Coord = T>
 struct BasePoint {
-  T x, y;
+  union {
+    struct {
+      T x, y;
+    };
+    T components[2];
+  };
 
   // Constructors
   MOZ_CONSTEXPR BasePoint() : x(0), y(0) {}
   MOZ_CONSTEXPR BasePoint(Coord aX, Coord aY) : x(aX), y(aY) {}
 
   void MoveTo(T aX, T aY) { x = aX; y = aY; }
   void MoveBy(T aDx, T aDy) { x += aDx; y += aDy; }
 
--- a/gfx/2d/BasePoint3D.h
+++ b/gfx/2d/BasePoint3D.h
@@ -13,17 +13,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub>
 struct BasePoint3D {
-  T x, y, z;
+  union {
+    struct {
+      T x, y, z;
+    };
+    T components[3];
+  };
 
   // Constructors
   BasePoint3D() : x(0), y(0), z(0) {}
   BasePoint3D(T aX, T aY, T aZ) : x(aX), y(aY), z(aZ) {}
 
   void MoveTo(T aX, T aY, T aZ) { x = aX; y = aY; z = aZ; }
   void MoveBy(T aDx, T aDy, T aDz) { x += aDx; y += aDy; z += aDz; }
 
--- a/gfx/2d/BasePoint4D.h
+++ b/gfx/2d/BasePoint4D.h
@@ -13,17 +13,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub>
 struct BasePoint4D {
-  T x, y, z, w;
+  union {
+    struct {
+      T x, y, z, w;
+    };
+    T components[4];
+  };
 
   // Constructors
   BasePoint4D() : x(0), y(0), z(0), w(0) {}
   BasePoint4D(T aX, T aY, T aZ, T aW) : x(aX), y(aY), z(aZ), w(aW) {}
 
   void MoveTo(T aX, T aY, T aZ, T aW) { x = aX; y = aY; z = aZ; w = aW; }
   void MoveBy(T aDx, T aDy, T aDz, T aDw) { x += aDx; y += aDy; z += aDz; w += aDw; }
 
--- a/gfx/2d/BaseSize.h
+++ b/gfx/2d/BaseSize.h
@@ -13,17 +13,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub>
 struct BaseSize {
-  T width, height;
+  union {
+    struct {
+      T width, height;
+    };
+    T components[2];
+  };
 
   // Constructors
   MOZ_CONSTEXPR BaseSize() : width(0), height(0) {}
   MOZ_CONSTEXPR BaseSize(T aWidth, T aHeight) : width(aWidth), height(aHeight) {}
 
   void SizeTo(T aWidth, T aHeight) { width = aWidth; height = aHeight; }
 
   bool IsEmpty() const {
--- a/gfx/2d/BigEndianInts.h
+++ b/gfx/2d/BigEndianInts.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_BigEndianInts_h
 #define mozilla_BigEndianInts_h
 
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 namespace mozilla {
 
 #pragma pack(push, 1)
 
 struct BigEndianUint16
 {
 #ifdef __SUNPRO_CC
@@ -72,9 +72,9 @@ struct BigEndianUint32
 private:
   uint32_t  value;
 };
 
 #pragma pack(pop)
 
 } // mozilla
 
-#endif // mozilla_BigEndianInts_h
\ No newline at end of file
+#endif // mozilla_BigEndianInts_h
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -32,19 +32,24 @@ public:
     , _21(0), _22(1.0f)
     , _31(0), _32(0)
   {}
   Matrix(Float a11, Float a12, Float a21, Float a22, Float a31, Float a32)
     : _11(a11), _12(a12)
     , _21(a21), _22(a22)
     , _31(a31), _32(a32)
   {}
-  Float _11, _12;
-  Float _21, _22;
-  Float _31, _32;
+  union {
+    struct {
+      Float _11, _12;
+      Float _21, _22;
+      Float _31, _32;
+    };
+    Float components[6];
+  };
 
   MOZ_ALWAYS_INLINE Matrix Copy() const
   {
     return Matrix(*this);
   }
 
   friend std::ostream& operator<<(std::ostream& aStream, const Matrix& aMatrix);
 
@@ -456,20 +461,25 @@ public:
     , _41(a41), _42(a42), _43(a43), _44(a44)
   {}
 
   Matrix4x4Typed(const Matrix4x4Typed& aOther)
   {
     memcpy(this, &aOther, sizeof(*this));
   }
 
-  Float _11, _12, _13, _14;
-  Float _21, _22, _23, _24;
-  Float _31, _32, _33, _34;
-  Float _41, _42, _43, _44;
+  union {
+    struct {
+      Float _11, _12, _13, _14;
+      Float _21, _22, _23, _24;
+      Float _31, _32, _33, _34;
+      Float _41, _42, _43, _44;
+    };
+    Float components[16];
+  };
 
   friend std::ostream& operator<<(std::ostream& aStream, const Matrix4x4Typed& aMatrix)
   {
     const Float *f = &aMatrix._11;
     aStream << "[ " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
     aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
     aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
     aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ]" << std::endl;
@@ -1613,19 +1623,24 @@ public:
   }
 
   Matrix5x4& operator*=(const Matrix5x4 &aMatrix)
   {
     *this = *this * aMatrix;
     return *this;
   }
 
-  Float _11, _12, _13, _14;
-  Float _21, _22, _23, _24;
-  Float _31, _32, _33, _34;
-  Float _41, _42, _43, _44;
-  Float _51, _52, _53, _54;
+  union {
+    struct {
+      Float _11, _12, _13, _14;
+      Float _21, _22, _23, _24;
+      Float _31, _32, _33, _34;
+      Float _41, _42, _43, _44;
+      Float _51, _52, _53, _54;
+    };
+    Float components[20];
+  };
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_MATRIX_H_ */
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TYPES_H_
 #define MOZILLA_GFX_TYPES_H_
 
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 #include <stddef.h>
 #include <stdint.h>
 
 namespace mozilla {
 namespace gfx {
 
 typedef float Float;
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -49,16 +49,18 @@ EXPORTS.mozilla.gfx += [
     'SourceSurfaceCairo.h',
     'SourceSurfaceRawData.h',
     'StackArray.h',
     'Tools.h',
     'Types.h',
     'UserData.h',
 ]
 
+EXPORTS.mozilla.gfx += ['ssse3-scaler.h']
+
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
     EXPORTS.mozilla.gfx += [
         'MacIOSurface.h',
     ]
     UNIFIED_SOURCES += [
         'DrawTargetCG.cpp',
         'PathCG.cpp',
         'ScaledFontMac.cpp',
@@ -106,27 +108,29 @@ if CONFIG['MOZ_ENABLE_SKIA']:
     ]
 
 # Are we targeting x86 or x64?  If so, build SSE2 files.
 if CONFIG['INTEL_ARCHITECTURE']:
     SOURCES += [
         'BlurSSE2.cpp',
         'FilterProcessingSSE2.cpp',
         'ImageScalingSSE2.cpp',
+        'ssse3-scaler.c',
     ]
     if CONFIG['MOZ_ENABLE_SKIA']:
         SOURCES += [
             'convolverSSE2.cpp',
         ]
     DEFINES['USE_SSE2'] = True
     # The file uses SSE2 intrinsics, so it needs special compile flags on some
     # compilers.
     SOURCES['BlurSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
     SOURCES['FilterProcessingSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
     SOURCES['ImageScalingSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
+    SOURCES['ssse3-scaler.c'].flags += CONFIG['SSSE3_FLAGS']
     if CONFIG['MOZ_ENABLE_SKIA']:
         SOURCES['convolverSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
 elif CONFIG['CPU_ARCH'].startswith('mips'):
     SOURCES += [
         'BlurLS3.cpp',
     ]
     if CONFIG['MOZ_ENABLE_SKIA']:
         SOURCES += [
new file mode 100644
--- /dev/null
+++ b/gfx/2d/ssse3-scaler.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright © 2013 Soren Sandmann Pedersen
+ * Copyright © 2013 Red Hat, Inc.
+ * Copyright © 2016 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Soren Sandmann (soren.sandmann@gmail.com)
+ *         Jeff Muizelaar (jmuizelaar@mozilla.com)
+ */
+
+/* This has been adapted from the ssse3 code from pixman. It's currently
+ * a mess as I want to try it out in practice before finalizing the details.
+ */
+
+#include <stdlib.h>
+#include <mmintrin.h>
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include <tmmintrin.h>
+#include <stdint.h>
+#include <assert.h>
+
+typedef int32_t                 pixman_fixed_16_16_t;
+typedef pixman_fixed_16_16_t    pixman_fixed_t;
+#define pixman_fixed_1                  (pixman_int_to_fixed(1))
+#define pixman_fixed_to_int(f)          ((int) ((f) >> 16))
+#define pixman_int_to_fixed(i)          ((pixman_fixed_t) ((i) << 16))
+#define pixman_double_to_fixed(d)       ((pixman_fixed_t) ((d) * 65536.0))
+typedef struct pixman_vector pixman_vector_t;
+
+typedef int pixman_bool_t;
+typedef int64_t                 pixman_fixed_32_32_t;
+typedef pixman_fixed_32_32_t    pixman_fixed_48_16_t;
+typedef struct { pixman_fixed_48_16_t v[3]; } pixman_vector_48_16_t;
+
+struct pixman_vector
+{
+    pixman_fixed_t      vector[3];
+};
+typedef struct pixman_transform pixman_transform_t;
+
+struct pixman_transform
+{
+    pixman_fixed_t      matrix[3][3];
+};
+
+#ifdef _MSC_VER
+#define force_inline __forceinline
+#else
+#define force_inline __inline__ __attribute__((always_inline))
+#endif
+
+#define BILINEAR_INTERPOLATION_BITS 6
+
+static force_inline int
+pixman_fixed_to_bilinear_weight (pixman_fixed_t x)
+{
+    return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) &
+                               ((1 << BILINEAR_INTERPOLATION_BITS) - 1);
+}
+
+static void
+pixman_transform_point_31_16_3d (const pixman_transform_t    *t,
+                                 const pixman_vector_48_16_t *v,
+                                 pixman_vector_48_16_t       *result)
+{
+    int i;
+    int64_t tmp[3][2];
+
+    /* input vector values must have no more than 31 bits (including sign)
+     * in the integer part */
+    assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
+    assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
+    assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
+    assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
+    assert (v->v[2] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
+    assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
+
+    for (i = 0; i < 3; i++)
+    {
+        tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
+        tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
+        tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
+        tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
+        tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
+        tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
+    }
+
+    result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
+    result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
+    result->v[2] = tmp[2][0] + ((tmp[2][1] + 0x8000) >> 16);
+}
+
+static pixman_bool_t
+pixman_transform_point_3d (const struct pixman_transform *transform,
+                           struct pixman_vector *         vector)
+{
+    pixman_vector_48_16_t tmp;
+    tmp.v[0] = vector->vector[0];
+    tmp.v[1] = vector->vector[1];
+    tmp.v[2] = vector->vector[2];
+
+    pixman_transform_point_31_16_3d (transform, &tmp, &tmp);
+
+    vector->vector[0] = tmp.v[0];
+    vector->vector[1] = tmp.v[1];
+    vector->vector[2] = tmp.v[2];
+
+    return vector->vector[0] == tmp.v[0] &&
+           vector->vector[1] == tmp.v[1] &&
+           vector->vector[2] == tmp.v[2];
+}
+
+
+struct bits_image_t
+{
+    uint32_t *                 bits;
+    int                        rowstride;
+    pixman_transform_t *transform;
+};
+
+typedef struct bits_image_t bits_image_t;
+typedef struct {
+    int unused;
+} pixman_iter_info_t;
+
+typedef struct pixman_iter_t pixman_iter_t;
+typedef void      (* pixman_iter_fini_t)         (pixman_iter_t *iter);
+
+struct pixman_iter_t
+{
+    int x, y;
+    pixman_iter_fini_t          fini;
+    bits_image_t *image;
+    uint32_t *                  buffer;
+    int width;
+    int height;
+    void *                      data;
+};
+
+typedef struct
+{
+    int		y;
+    uint64_t *	buffer;
+} line_t;
+
+typedef struct
+{
+    line_t		lines[2];
+    pixman_fixed_t	y;
+    pixman_fixed_t	x;
+    uint64_t		data[1];
+} bilinear_info_t;
+
+static void
+ssse3_fetch_horizontal (bits_image_t *image, line_t *line,
+			int y, pixman_fixed_t x, pixman_fixed_t ux, int n)
+{
+    uint32_t *bits = image->bits + y * image->rowstride;
+    __m128i vx = _mm_set_epi16 (
+	- (x + 1), x, - (x + 1), x,
+	- (x + ux + 1), x + ux,  - (x + ux + 1), x + ux);
+    __m128i vux = _mm_set_epi16 (
+	- 2 * ux, 2 * ux, - 2 * ux, 2 * ux,
+	- 2 * ux, 2 * ux, - 2 * ux, 2 * ux);
+    __m128i vaddc = _mm_set_epi16 (1, 0, 1, 0, 1, 0, 1, 0);
+    __m128i *b = (__m128i *)line->buffer;
+    __m128i vrl0, vrl1;
+
+    while ((n -= 2) >= 0)
+    {
+        __m128i vw, vr, s;
+#ifdef HACKY_PADDING
+        if (pixman_fixed_to_int(x + ux) >= image->rowstride) {
+            vrl1 = _mm_setzero_si128();
+            printf("overread 2loop\n");
+         } else {
+                 if (pixman_fixed_to_int(x + ux) < 0)
+                         printf("underflow\n");
+        vrl1 = _mm_loadl_epi64(
+            (__m128i *)(bits + (pixman_fixed_to_int(x + ux) < 0 ? 0 : pixman_fixed_to_int(x + ux))));
+        }
+#else
+        vrl1 = _mm_loadl_epi64(
+            (__m128i *)(bits + pixman_fixed_to_int(x + ux)));
+#endif
+	/* vrl1: R1, L1 */
+
+    final_pixel:
+#ifdef HACKY_PADDING
+	vrl0 = _mm_loadl_epi64 (
+	    (__m128i *)(bits + (pixman_fixed_to_int (x) < 0 ? 0 : pixman_fixed_to_int (x))));
+#else
+        vrl0 = _mm_loadl_epi64 (
+	    (__m128i *)(bits + pixman_fixed_to_int (x)));
+#endif
+        /* vrl0: R0, L0 */
+
+	/* The weights are based on vx which is a vector of 
+	 *
+	 *    - (x + 1), x, - (x + 1), x,
+	 *          - (x + ux + 1), x + ux, - (x + ux + 1), x + ux
+	 *
+	 * so the 16 bit weights end up like this:
+	 *
+	 *    iw0, w0, iw0, w0, iw1, w1, iw1, w1
+	 *
+	 * and after shifting and packing, we get these bytes:
+	 *
+	 *    iw0, w0, iw0, w0, iw1, w1, iw1, w1,
+	 *        iw0, w0, iw0, w0, iw1, w1, iw1, w1,
+	 *
+	 * which means the first and the second input pixel 
+	 * have to be interleaved like this:
+	 *
+	 *    la0, ra0, lr0, rr0, la1, ra1, lr1, rr1,
+	 *        lg0, rg0, lb0, rb0, lg1, rg1, lb1, rb1
+	 *
+	 * before maddubsw can be used.
+	 */
+
+	vw = _mm_add_epi16 (
+	    vaddc, _mm_srli_epi16 (vx, 16 - BILINEAR_INTERPOLATION_BITS));
+	/* vw: iw0, w0, iw0, w0, iw1, w1, iw1, w1
+	 */
+
+	vw = _mm_packus_epi16 (vw, vw);
+	/* vw: iw0, w0, iw0, w0, iw1, w1, iw1, w1,
+	 *         iw0, w0, iw0, w0, iw1, w1, iw1, w1
+	 */
+	vx = _mm_add_epi16 (vx, vux);
+
+	x += 2 * ux;
+
+	vr = _mm_unpacklo_epi16 (vrl1, vrl0);
+	/* vr: rar0, rar1, rgb0, rgb1, lar0, lar1, lgb0, lgb1 */
+
+	s = _mm_shuffle_epi32 (vr, _MM_SHUFFLE (1, 0, 3, 2));
+	/* s:  lar0, lar1, lgb0, lgb1, rar0, rar1, rgb0, rgb1 */
+
+	vr = _mm_unpackhi_epi8 (vr, s);
+	/* vr: la0, ra0, lr0, rr0, la1, ra1, lr1, rr1,
+	 *         lg0, rg0, lb0, rb0, lg1, rg1, lb1, rb1
+	 */
+
+	vr = _mm_maddubs_epi16 (vr, vw);
+
+	/* When the weight is 0, the inverse weight is
+	 * 128 which can't be represented in a signed byte.
+	 * As a result maddubsw computes the following:
+	 *
+	 *     r = l * -128 + r * 0
+	 *
+	 * rather than the desired
+	 *
+	 *     r = l * 128 + r * 0
+	 *
+	 * We fix this by taking the absolute value of the
+	 * result.
+	 */
+        // we can drop this if we use lower precision
+
+	vr = _mm_shuffle_epi32 (vr, _MM_SHUFFLE (2, 0, 3, 1));
+	/* vr: A0, R0, A1, R1, G0, B0, G1, B1 */
+	_mm_store_si128 (b++, vr);
+    }
+
+    if (n == -1)
+    {
+	vrl1 = _mm_setzero_si128();
+	goto final_pixel;
+    }
+
+    line->y = y;
+}
+
+// scale a line of destination pixels
+static uint32_t *
+ssse3_fetch_bilinear_cover (pixman_iter_t *iter, const uint32_t *mask)
+{
+    pixman_fixed_t fx, ux;
+    bilinear_info_t *info = iter->data;
+    line_t *line0, *line1;
+    int y0, y1;
+    int32_t dist_y;
+    __m128i vw, uvw;
+    int i;
+
+    fx = info->x;
+    ux = iter->image->transform->matrix[0][0];
+
+    y0 = pixman_fixed_to_int (info->y);
+    if (y0 < 0)
+        *(volatile char*)0 = 9;
+    y1 = y0 + 1;
+
+    // clamping in y direction
+    if (y1 >= iter->height) {
+        y1 = iter->height - 1;
+    }
+
+    line0 = &info->lines[y0 & 0x01];
+    line1 = &info->lines[y1 & 0x01];
+
+    if (line0->y != y0)
+    {
+	ssse3_fetch_horizontal (
+	    iter->image, line0, y0, fx, ux, iter->width);
+    }
+
+    if (line1->y != y1)
+    {
+	ssse3_fetch_horizontal (
+	    iter->image, line1, y1, fx, ux, iter->width);
+    }
+
+#ifdef PIXMAN_STYLE_INTERPOLATION
+    dist_y = pixman_fixed_to_bilinear_weight (info->y);
+    dist_y <<= (16 - BILINEAR_INTERPOLATION_BITS);
+
+    vw = _mm_set_epi16 (
+	dist_y, dist_y, dist_y, dist_y, dist_y, dist_y, dist_y, dist_y);
+
+#else
+    // setup the weights for the top (vw) and bottom (uvw) lines
+    dist_y = pixman_fixed_to_bilinear_weight (info->y);
+    // we use 15 instead of 16 because we need an extra bit to handle when the weights are 0 and 1
+    dist_y <<= (15 - BILINEAR_INTERPOLATION_BITS);
+
+    vw = _mm_set_epi16 (
+	dist_y, dist_y, dist_y, dist_y, dist_y, dist_y, dist_y, dist_y);
+
+
+    dist_y = (1 << BILINEAR_INTERPOLATION_BITS) - pixman_fixed_to_bilinear_weight (info->y);
+    dist_y <<= (15 - BILINEAR_INTERPOLATION_BITS);
+    uvw = _mm_set_epi16 (
+	dist_y, dist_y, dist_y, dist_y, dist_y, dist_y, dist_y, dist_y);
+#endif
+
+    for (i = 0; i + 3 < iter->width; i += 4)
+    {
+	__m128i top0 = _mm_load_si128 ((__m128i *)(line0->buffer + i));
+	__m128i bot0 = _mm_load_si128 ((__m128i *)(line1->buffer + i));
+	__m128i top1 = _mm_load_si128 ((__m128i *)(line0->buffer + i + 2));
+	__m128i bot1 = _mm_load_si128 ((__m128i *)(line1->buffer + i + 2));
+#ifdef PIXMAN_STYLE_INTERPOLATION
+	__m128i r0, r1, tmp, p;
+
+        r0 = _mm_mulhi_epu16 (
+	    _mm_sub_epi16 (bot0, top0), vw);
+	tmp = _mm_cmplt_epi16 (bot0, top0);
+	tmp = _mm_and_si128 (tmp, vw);
+	r0 = _mm_sub_epi16 (r0, tmp);
+	r0 = _mm_add_epi16 (r0, top0);
+	r0 = _mm_srli_epi16 (r0, BILINEAR_INTERPOLATION_BITS);
+	/* r0:  A0 R0 A1 R1 G0 B0 G1 B1 */
+        //r0 = _mm_shuffle_epi32 (r0, _MM_SHUFFLE (2, 0, 3, 1));
+	/* r0:  A1 R1 G1 B1 A0 R0 G0 B0 */
+
+        // tmp = bot1 < top1 ? vw : 0;
+        // r1 = (bot1 - top1)*vw + top1 - tmp
+        // r1 = bot1*vw - vw*top1 + top1 - tmp
+        // r1 = bot1*vw + top1 - vw*top1 - tmp
+        // r1 = bot1*vw + top1*(1 - vw) - tmp
+	r1 = _mm_mulhi_epu16 (
+	    _mm_sub_epi16 (bot1, top1), vw);
+	tmp = _mm_cmplt_epi16 (bot1, top1);
+	tmp = _mm_and_si128 (tmp, vw);
+	r1 = _mm_sub_epi16 (r1, tmp);
+	r1 = _mm_add_epi16 (r1, top1);
+	r1 = _mm_srli_epi16 (r1, BILINEAR_INTERPOLATION_BITS);
+	//r1 = _mm_shuffle_epi32 (r1, _MM_SHUFFLE (2, 0, 3, 1));
+	/* r1: A3 R3 G3 B3 A2 R2 G2 B2 */
+#else
+	__m128i r0, r1, p;
+        top0 = _mm_mulhi_epu16 (top0, uvw);
+        bot0 = _mm_mulhi_epu16 (bot0, vw);
+        r0 = _mm_add_epi16(top0, bot0);
+        r0 = _mm_srli_epi16(r0, BILINEAR_INTERPOLATION_BITS-1);
+
+        top1 = _mm_mulhi_epu16 (top1, uvw);
+        bot1 = _mm_mulhi_epu16 (bot1, vw);
+        r1 = _mm_add_epi16(top1, bot1);
+        r1 = _mm_srli_epi16(r1, BILINEAR_INTERPOLATION_BITS-1);
+#endif
+
+	p = _mm_packus_epi16 (r0, r1);
+	_mm_storeu_si128 ((__m128i *)(iter->buffer + i), p);
+    }
+
+    while (i < iter->width)
+    {
+	__m128i top0 = _mm_load_si128 ((__m128i *)(line0->buffer + i));
+	__m128i bot0 = _mm_load_si128 ((__m128i *)(line1->buffer + i));
+
+#ifdef PIXMAN_STYLE_INTERPOLATION
+	__m128i r0, tmp, p;
+	r0 = _mm_mulhi_epu16 (
+	    _mm_sub_epi16 (bot0, top0), vw);
+	tmp = _mm_cmplt_epi16 (bot0, top0);
+	tmp = _mm_and_si128 (tmp, vw);
+	r0 = _mm_sub_epi16 (r0, tmp);
+	r0 = _mm_add_epi16 (r0, top0);
+	r0 = _mm_srli_epi16 (r0, BILINEAR_INTERPOLATION_BITS);
+	/* r0:  A0 R0 A1 R1 G0 B0 G1 B1 */
+	r0 = _mm_shuffle_epi32 (r0, _MM_SHUFFLE (2, 0, 3, 1));
+	/* r0:  A1 R1 G1 B1 A0 R0 G0 B0 */
+#else
+	__m128i r0, p;
+        top0 = _mm_mulhi_epu16 (top0, uvw);
+        bot0 = _mm_mulhi_epu16 (bot0, vw);
+        r0 = _mm_add_epi16(top0, bot0);
+        r0 = _mm_srli_epi16(r0, BILINEAR_INTERPOLATION_BITS-1);
+#endif
+
+	p = _mm_packus_epi16 (r0, r0);
+
+	if (iter->width - i == 1)
+	{
+	    *(uint32_t *)(iter->buffer + i) = _mm_cvtsi128_si32 (p);
+	    i++;
+	}
+	else
+	{
+	    _mm_storel_epi64 ((__m128i *)(iter->buffer + i), p);
+	    i += 2;
+	}
+    }
+
+    info->y += iter->image->transform->matrix[1][1];
+
+    return iter->buffer;
+}
+
+static void
+ssse3_bilinear_cover_iter_fini (pixman_iter_t *iter)
+{
+    free (iter->data);
+}
+
+static void
+ssse3_bilinear_cover_iter_init (pixman_iter_t *iter)
+{
+    int width = iter->width;
+    bilinear_info_t *info;
+    pixman_vector_t v;
+
+    /* Reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed (iter->x) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed (iter->y) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (!pixman_transform_point_3d (iter->image->transform, &v))
+	goto fail;
+
+    info = malloc (sizeof (*info) + (2 * width - 1) * sizeof (uint64_t) + 64);
+    if (!info)
+	goto fail;
+
+    info->x = v.vector[0] - pixman_fixed_1 / 2;
+    info->y = v.vector[1] - pixman_fixed_1 / 2;
+
+#define ALIGN(addr)							\
+    ((void *)((((uintptr_t)(addr)) + 15) & (~15)))
+
+    /* It is safe to set the y coordinates to -1 initially
+     * because COVER_CLIP_BILINEAR ensures that we will only
+     * be asked to fetch lines in the [0, height) interval
+     */
+    info->lines[0].y = -1;
+    info->lines[0].buffer = ALIGN (&(info->data[0]));
+    info->lines[1].y = -1;
+    info->lines[1].buffer = ALIGN (info->lines[0].buffer + width);
+
+    iter->fini = ssse3_bilinear_cover_iter_fini;
+
+    iter->data = info;
+    return;
+
+fail:
+    /* Something went wrong, either a bad matrix or OOM; in such cases,
+     * we don't guarantee any particular rendering.
+     */
+    iter->fini = NULL;
+}
+
+/* scale the src from src_width/height to dest_width/height drawn
+ * into the rectangle x,y width,height
+ * src_stride and dst_stride are 4 byte units */
+void ssse3_scale_data(uint32_t *src, int src_width, int src_height, int src_stride,
+                      uint32_t *dest, int dest_width, int dest_height,
+                      int dest_stride,
+                      int x, int y,
+                      int width, int height)
+{
+    //XXX: assert(src_width > 1)
+    pixman_transform_t transform = {
+        { { pixman_fixed_1, 0, 0 },
+            { 0, pixman_fixed_1, 0 },
+            { 0, 0, pixman_fixed_1 } }
+    };
+    double width_scale = ((double)src_width)/dest_width;
+    double height_scale = ((double)src_height)/dest_height;
+#define AVOID_PADDING
+#ifdef AVOID_PADDING
+    // scale up by enough that we don't read outside of the bounds of the source surface
+    // currently this is required to avoid reading out of bounds.
+    if (width_scale < 1) {
+        width_scale = (double)(src_width-1)/dest_width;
+        transform.matrix[0][2] = pixman_fixed_1/2;
+    }
+    if (height_scale < 1) {
+        height_scale = (double)(src_height-1)/dest_height;
+        transform.matrix[1][2] = pixman_fixed_1/2;
+    }
+#endif
+    transform.matrix[0][0] = pixman_double_to_fixed(width_scale);
+    transform.matrix[1][1] = pixman_double_to_fixed(height_scale);
+    transform.matrix[2][2] = pixman_fixed_1;
+
+    bits_image_t image;
+    image.bits = src;
+    image.transform = &transform;
+    image.rowstride = src_stride;
+
+    pixman_iter_t iter;
+    iter.image = &image;
+    iter.x = x;
+    iter.y = y;
+    iter.width = width;
+    iter.height = src_height;
+    iter.buffer = dest;
+
+    ssse3_bilinear_cover_iter_init(&iter);
+    for (int iy = 0; iy < height; iy++) {
+        ssse3_fetch_bilinear_cover(&iter, NULL);
+        iter.buffer += dest_stride;
+    }
+    ssse3_bilinear_cover_iter_fini(&iter);
+
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/ssse3-scaler.h
@@ -0,0 +1,22 @@
+#/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_2D_SSSE3_SCALER_H_
+#define MOZILLA_GFX_2D_SSSE3_SCALER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void ssse3_scale_data(uint32_t *src, int src_width, int src_height,
+                int src_stride,
+                uint32_t *dest, int dest_width, int dest_height,
+                int dest_rowstride,
+                int x, int y,
+                int width, int height);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MOZILLA_GFX_2D_SSS3_SCALER_H_
--- a/gfx/ipc/D3DMessageUtils.cpp
+++ b/gfx/ipc/D3DMessageUtils.cpp
@@ -48,24 +48,22 @@ ParamTraits<DxgiAdapterDesc>::Write(Mess
   WriteParam(aMsg, aParam.AdapterLuid.LowPart);
   WriteParam(aMsg, aParam.AdapterLuid.HighPart);
 #else
   MOZ_ASSERT_UNREACHABLE("DxgiAdapterDesc is Windows-only");
 #endif
 }
 
 bool
-ParamTraits<DxgiAdapterDesc>::Read(const Message* aMsg, void** aIter, paramType* aResult)
+ParamTraits<DxgiAdapterDesc>::Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
 {
 #if defined(XP_WIN)
-  const char* description = nullptr;
-  if (!aMsg->ReadBytes(aIter, &description, sizeof(aResult->Description))) {
+  if (!aMsg->ReadBytesInto(aIter, aResult->Description, sizeof(aResult->Description))) {
     return false;
   }
-  memcpy(aResult->Description, description, sizeof(aResult->Description));
 
   if (ReadParam(aMsg, aIter, &aResult->VendorId) &&
       ReadParam(aMsg, aIter, &aResult->DeviceId) &&
       ReadParam(aMsg, aIter, &aResult->SubSysId) &&
       ReadParam(aMsg, aIter, &aResult->Revision) &&
       ReadParam(aMsg, aIter, &aResult->DedicatedVideoMemory) &&
       ReadParam(aMsg, aIter, &aResult->DedicatedSystemMemory) &&
       ReadParam(aMsg, aIter, &aResult->SharedSystemMemory) &&
--- a/gfx/ipc/D3DMessageUtils.h
+++ b/gfx/ipc/D3DMessageUtils.h
@@ -35,14 +35,14 @@ struct DxgiAdapterDesc
 
 namespace IPC {
 
 template <>
 struct ParamTraits<DxgiAdapterDesc>
 {
   typedef DxgiAdapterDesc paramType;
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
 };
 
 } // namespace IPC
 
 #endif // _include_gfx_ipc_D3DMessageUtils_h__
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -49,17 +49,17 @@ struct ParamTraits<mozilla::gfx::Matrix>
     WriteParam(aMsg, aParam._11);
     WriteParam(aMsg, aParam._12);
     WriteParam(aMsg, aParam._21);
     WriteParam(aMsg, aParam._22);
     WriteParam(aMsg, aParam._31);
     WriteParam(aMsg, aParam._32);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (ReadParam(aMsg, aIter, &aResult->_11) &&
         ReadParam(aMsg, aIter, &aResult->_12) &&
         ReadParam(aMsg, aIter, &aResult->_21) &&
         ReadParam(aMsg, aIter, &aResult->_22) &&
         ReadParam(aMsg, aIter, &aResult->_31) &&
         ReadParam(aMsg, aIter, &aResult->_32))
       return true;
@@ -84,17 +84,17 @@ struct ParamTraits<mozilla::gfx::Matrix4
 #define Wr(_f)  WriteParam(msg, param. _f)
     Wr(_11); Wr(_12); Wr(_13); Wr(_14);
     Wr(_21); Wr(_22); Wr(_23); Wr(_24);
     Wr(_31); Wr(_32); Wr(_33); Wr(_34);
     Wr(_41); Wr(_42); Wr(_43); Wr(_44);
 #undef Wr
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
 #define Rd(_f)  ReadParam(msg, iter, &result-> _f)
     return (Rd(_11) && Rd(_12) && Rd(_13) && Rd(_14) &&
             Rd(_21) && Rd(_22) && Rd(_23) && Rd(_24) &&
             Rd(_31) && Rd(_32) && Rd(_33) && Rd(_34) &&
             Rd(_41) && Rd(_42) && Rd(_43) && Rd(_44));
 #undef Rd
   }
@@ -111,17 +111,17 @@ struct ParamTraits<mozilla::gfx::Matrix5
     Wr(_11); Wr(_12); Wr(_13); Wr(_14);
     Wr(_21); Wr(_22); Wr(_23); Wr(_24);
     Wr(_31); Wr(_32); Wr(_33); Wr(_34);
     Wr(_41); Wr(_42); Wr(_43); Wr(_44);
     Wr(_51); Wr(_52); Wr(_53); Wr(_54);
 #undef Wr
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
 #define Rd(_f)  ReadParam(msg, iter, &result-> _f)
     return (Rd(_11) && Rd(_12) && Rd(_13) && Rd(_14) &&
             Rd(_21) && Rd(_22) && Rd(_23) && Rd(_24) &&
             Rd(_31) && Rd(_32) && Rd(_33) && Rd(_34) &&
             Rd(_41) && Rd(_42) && Rd(_43) && Rd(_44) &&
             Rd(_51) && Rd(_52) && Rd(_53) && Rd(_54));
 #undef Rd
@@ -134,17 +134,17 @@ struct ParamTraits<gfxPoint>
   typedef gfxPoint paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.x);
     WriteParam(aMsg, aParam.y);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->x) &&
             ReadParam(aMsg, aIter, &aResult->y));
  }
 };
 
 template<>
 struct ParamTraits<gfxSize>
@@ -152,17 +152,17 @@ struct ParamTraits<gfxSize>
   typedef gfxSize paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.width);
     WriteParam(aMsg, aParam.height);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (ReadParam(aMsg, aIter, &aResult->width) &&
         ReadParam(aMsg, aIter, &aResult->height))
       return true;
 
     return false;
   }
 };
@@ -175,17 +175,17 @@ struct ParamTraits<gfxRect>
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.x);
     WriteParam(aMsg, aParam.y);
     WriteParam(aMsg, aParam.width);
     WriteParam(aMsg, aParam.height);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->x) &&
            ReadParam(aMsg, aIter, &aResult->y) &&
            ReadParam(aMsg, aIter, &aResult->width) &&
            ReadParam(aMsg, aIter, &aResult->height);
   }
 };
 
@@ -292,17 +292,17 @@ struct ParamTraits<mozilla::gfx::Color>
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.r);
     WriteParam(msg, param.g);
     WriteParam(msg, param.b);
     WriteParam(msg, param.a);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->r) &&
             ReadParam(msg, iter, &result->g) &&
             ReadParam(msg, iter, &result->b) &&
             ReadParam(msg, iter, &result->a));
   }
 };
 
@@ -312,17 +312,17 @@ struct ParamTraits<nsPoint>
   typedef nsPoint paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y));
   }
 };
 
 template<>
 struct ParamTraits<nsIntPoint>
@@ -330,17 +330,17 @@ struct ParamTraits<nsIntPoint>
   typedef nsIntPoint paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y));
   }
 };
 
 template<typename T>
 struct ParamTraits<mozilla::gfx::IntSizeTyped<T> >
@@ -348,17 +348,17 @@ struct ParamTraits<mozilla::gfx::IntSize
   typedef mozilla::gfx::IntSizeTyped<T> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
 template<typename Region, typename Rect, typename Iter>
 struct RegionParamTraits
@@ -373,17 +373,17 @@ struct RegionParamTraits
       MOZ_RELEASE_ASSERT(!r.IsEmpty());
       WriteParam(msg, r);
     }
     // empty rects are sentinel values because nsRegions will never
     // contain them
     WriteParam(msg, Rect());
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     RegionBuilder<Region> builder;
     Rect rect;
     while (ReadParam(msg, iter, &rect)) {
       if (rect.IsEmpty()) {
         *result = builder.ToRegion();
         return true;
       }
@@ -407,83 +407,83 @@ struct ParamTraits<mozilla::gfx::IntSize
   typedef mozilla::gfx::IntSize paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
 template<class T>
 struct ParamTraits< mozilla::gfx::CoordTyped<T> >
 {
   typedef mozilla::gfx::CoordTyped<T> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.value);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->value));
   }
 };
 
 template<class T>
 struct ParamTraits< mozilla::gfx::IntCoordTyped<T> >
 {
   typedef mozilla::gfx::IntCoordTyped<T> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.value);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->value));
   }
 };
 
 template<class T, class U>
 struct ParamTraits< mozilla::gfx::ScaleFactor<T, U> >
 {
   typedef mozilla::gfx::ScaleFactor<T, U> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.scale);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->scale));
   }
 };
 
 template<class T, class U>
 struct ParamTraits< mozilla::gfx::ScaleFactors2D<T, U> >
 {
   typedef mozilla::gfx::ScaleFactors2D<T, U> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.xScale);
     WriteParam(msg, param.yScale);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->xScale) &&
             ReadParam(msg, iter, &result->yScale));
   }
 };
 
 template<class T>
 struct ParamTraits< mozilla::gfx::PointTyped<T> >
@@ -491,17 +491,17 @@ struct ParamTraits< mozilla::gfx::PointT
   typedef mozilla::gfx::PointTyped<T> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y));
   }
 };
 
 template<class F, class T>
 struct ParamTraits< mozilla::gfx::Point3DTyped<F, T> >
@@ -510,17 +510,17 @@ struct ParamTraits< mozilla::gfx::Point3
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
     WriteParam(msg, param.z);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y) &&
             ReadParam(msg, iter, &result->z));
   }
 };
 
 template<class T>
@@ -529,17 +529,17 @@ struct ParamTraits< mozilla::gfx::IntPoi
   typedef mozilla::gfx::IntPointTyped<T> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y));
   }
 };
 
 template<class T>
 struct ParamTraits< mozilla::gfx::SizeTyped<T> >
@@ -547,17 +547,17 @@ struct ParamTraits< mozilla::gfx::SizeTy
   typedef mozilla::gfx::SizeTyped<T> paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
 template<class T>
 struct ParamTraits< mozilla::gfx::RectTyped<T> >
@@ -567,17 +567,17 @@ struct ParamTraits< mozilla::gfx::RectTy
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y) &&
             ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
@@ -589,17 +589,17 @@ struct ParamTraits< mozilla::gfx::IntRec
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y) &&
             ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
@@ -611,17 +611,17 @@ struct ParamTraits<mozilla::gfx::Margin>
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.top);
     WriteParam(msg, param.right);
     WriteParam(msg, param.bottom);
     WriteParam(msg, param.left);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->top) &&
             ReadParam(msg, iter, &result->right) &&
             ReadParam(msg, iter, &result->bottom) &&
             ReadParam(msg, iter, &result->left));
   }
 };
 
@@ -633,17 +633,17 @@ struct ParamTraits< mozilla::gfx::Margin
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.top);
     WriteParam(msg, param.right);
     WriteParam(msg, param.bottom);
     WriteParam(msg, param.left);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->top) &&
             ReadParam(msg, iter, &result->right) &&
             ReadParam(msg, iter, &result->bottom) &&
             ReadParam(msg, iter, &result->left));
   }
 };
 
@@ -655,17 +655,17 @@ struct ParamTraits<nsRect>
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
-  static bool Read(const Message* msg, void** iter, paramType* result)
+  static bool Read(const Message* msg, PickleIterator* iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y) &&
             ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
@@ -685,17 +685,17 @@ struct ParamTraits<mozilla::layers::Fram
 // Helper class for reading bitfields.
 // If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>.
 template <typename ParamType>
 struct BitfieldHelper
 {
   // We need this helper because we can't get the address of a bitfield to
   // pass directly to ReadParam. So instead we read it into a temporary bool
   // and set the bitfield using a setter function
-  static bool ReadBoolForBitfield(const Message* aMsg, void** aIter,
+  static bool ReadBoolForBitfield(const Message* aMsg, PickleIterator* aIter,
         ParamType* aResult, void (ParamType::*aSetter)(bool))
   {
     bool value;
     if (ReadParam(aMsg, aIter, &value)) {
       (aResult->*aSetter)(value);
       return true;
     }
     return false;
@@ -730,17 +730,17 @@ struct ParamTraits<mozilla::layers::Fram
     WriteParam(aMsg, aParam.mPaintRequestTime);
     WriteParam(aMsg, aParam.mScrollUpdateType);
     WriteParam(aMsg, aParam.mIsRootContent);
     WriteParam(aMsg, aParam.mDoSmoothScroll);
     WriteParam(aMsg, aParam.mUseDisplayPortMargins);
     WriteParam(aMsg, aParam.mIsScrollInfoLayer);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mScrollId) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellResolution) &&
             ReadParam(aMsg, aIter, &aResult->mCompositionBounds) &&
             ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
             ReadParam(aMsg, aIter, &aResult->mCriticalDisplayPort) &&
             ReadParam(aMsg, aIter, &aResult->mScrollableRect) &&
             ReadParam(aMsg, aIter, &aResult->mCumulativeResolution) &&
@@ -773,17 +773,17 @@ struct ParamTraits<mozilla::layers::Scro
     WriteParam(aMsg, aParam.mScrollSnapTypeX);
     WriteParam(aMsg, aParam.mScrollSnapTypeY);
     WriteParam(aMsg, aParam.mScrollSnapIntervalX);
     WriteParam(aMsg, aParam.mScrollSnapIntervalY);
     WriteParam(aMsg, aParam.mScrollSnapDestination);
     WriteParam(aMsg, aParam.mScrollSnapCoordinates);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mScrollSnapTypeX) &&
             ReadParam(aMsg, aIter, &aResult->mScrollSnapTypeY) &&
             ReadParam(aMsg, aIter, &aResult->mScrollSnapIntervalX) &&
             ReadParam(aMsg, aIter, &aResult->mScrollSnapIntervalY) &&
             ReadParam(aMsg, aIter, &aResult->mScrollSnapDestination) &&
             ReadParam(aMsg, aIter, &aResult->mScrollSnapCoordinates));
   }
@@ -795,17 +795,17 @@ struct ParamTraits<mozilla::layers::Laye
   typedef mozilla::layers::LayerClip paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mClipRect);
     WriteParam(aMsg, aParam.mMaskLayerIndex);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mClipRect) &&
             ReadParam(aMsg, aIter, &aResult->mMaskLayerIndex));
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::ScrollMetadata>
@@ -825,27 +825,27 @@ struct ParamTraits<mozilla::layers::Scro
     WriteParam(aMsg, aParam.mScrollClip);
     WriteParam(aMsg, aParam.mHasScrollgrab);
     WriteParam(aMsg, aParam.mAllowVerticalScrollWithWheel);
     WriteParam(aMsg, aParam.mIsLayersIdRoot);
     WriteParam(aMsg, aParam.mUsesContainerScrolling);
     WriteParam(aMsg, aParam.mForceDisableApz);
   }
 
-  static bool ReadContentDescription(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool ReadContentDescription(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     nsCString str;
     if (!ReadParam(aMsg, aIter, &str)) {
       return false;
     }
     aResult->SetContentDescription(str);
     return true;
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mMetrics) &&
             ReadParam(aMsg, aIter, &aResult->mSnapInfo) &&
             ReadParam(aMsg, aIter, &aResult->mScrollParentId) &&
             ReadParam(aMsg, aIter, &aResult->mBackgroundColor) &&
             ReadContentDescription(aMsg, aIter, aResult) &&
             ReadParam(aMsg, aIter, &aResult->mLineScrollAmount) &&
             ReadParam(aMsg, aIter, &aResult->mPageScrollAmount) &&
@@ -867,17 +867,17 @@ struct ParamTraits<mozilla::layers::Text
   {
     WriteParam(aMsg, aParam.mParentBackend);
     WriteParam(aMsg, aParam.mMaxTextureSize);
     WriteParam(aMsg, aParam.mSupportsTextureBlitting);
     WriteParam(aMsg, aParam.mSupportsPartialUploads);
     WriteParam(aMsg, aParam.mSyncHandle);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     bool result = ReadParam(aMsg, aIter, &aResult->mParentBackend) &&
                   ReadParam(aMsg, aIter, &aResult->mMaxTextureSize) &&
                   ReadParam(aMsg, aIter, &aResult->mSupportsTextureBlitting) &&
                   ReadParam(aMsg, aIter, &aResult->mSupportsPartialUploads) &&
                   ReadParam(aMsg, aIter, &aResult->mSyncHandle);
     return result;
   }
@@ -889,17 +889,17 @@ struct ParamTraits<mozilla::layers::Text
   typedef mozilla::layers::TextureInfo paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mCompositableType);
     WriteParam(aMsg, aParam.mTextureFlags);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->mCompositableType) &&
            ReadParam(aMsg, aIter, &aResult->mTextureFlags);
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::CompositableType>
@@ -932,17 +932,17 @@ struct ParamTraits<mozilla::layers::Scro
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mLayersId);
     WriteParam(aMsg, aParam.mPresShellId);
     WriteParam(aMsg, aParam.mScrollId);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mLayersId) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
             ReadParam(aMsg, aIter, &aResult->mScrollId));
   }
 };
 
 
@@ -954,17 +954,17 @@ struct ParamTraits<mozilla::layers::Zoom
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mAllowZoom);
     WriteParam(aMsg, aParam.mAllowDoubleTapZoom);
     WriteParam(aMsg, aParam.mMinZoom);
     WriteParam(aMsg, aParam.mMaxZoom);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mAllowZoom) &&
             ReadParam(aMsg, aIter, &aResult->mAllowDoubleTapZoom) &&
             ReadParam(aMsg, aIter, &aResult->mMinZoom) &&
             ReadParam(aMsg, aIter, &aResult->mMaxZoom));
   }
 };
 
@@ -977,17 +977,17 @@ struct ParamTraits<mozilla::layers::Even
   {
     WriteParam(aMsg, aParam.mHitRegion);
     WriteParam(aMsg, aParam.mDispatchToContentHitRegion);
     WriteParam(aMsg, aParam.mNoActionRegion);
     WriteParam(aMsg, aParam.mHorizontalPanRegion);
     WriteParam(aMsg, aParam.mVerticalPanRegion);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mHitRegion) &&
             ReadParam(aMsg, aIter, &aResult->mDispatchToContentHitRegion) &&
             ReadParam(aMsg, aIter, &aResult->mNoActionRegion) &&
             ReadParam(aMsg, aIter, &aResult->mHorizontalPanRegion) &&
             ReadParam(aMsg, aIter, &aResult->mVerticalPanRegion));
   }
 };
@@ -1032,17 +1032,17 @@ struct ParamTraits<mozilla::gfx::Attribu
 #undef CASE_TYPE
 
         default:
           MOZ_CRASH("GFX: unhandled attribute type");
       }
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     uint32_t count;
     if (!ReadParam(aMsg, aIter, &count)) {
       return false;
     }
     for (uint32_t i = 0; i < count; i++) {
       mozilla::gfx::AttributeType type;
       if (!ReadParam(aMsg, aIter, &type)) {
@@ -1111,17 +1111,17 @@ struct ParamTraits<mozilla::gfx::FilterP
     WriteParam(aMsg, aParam.NumberOfInputs());
     for (size_t i = 0; i < aParam.NumberOfInputs(); i++) {
       WriteParam(aMsg, aParam.InputPrimitiveIndex(i));
       WriteParam(aMsg, aParam.InputColorSpace(i));
     }
     WriteParam(aMsg, aParam.Attributes());
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     mozilla::gfx::PrimitiveType type;
     mozilla::gfx::IntRect primitiveSubregion;
     mozilla::gfx::IntRect filterSpaceBounds;
     bool isTainted = false;
     mozilla::gfx::ColorSpace outputColorSpace;
     size_t numberOfInputs = 0;
     if (!ReadParam(aMsg, aIter, &type) ||
@@ -1159,17 +1159,17 @@ struct ParamTraits<mozilla::gfx::FilterD
 {
   typedef mozilla::gfx::FilterDescription paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mPrimitives);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mPrimitives));
   }
 };
 
 typedef mozilla::layers::GeckoContentController::APZStateChange APZStateChange;
 
 template <>
@@ -1205,17 +1205,17 @@ struct ParamTraits<mozilla::layers::Asyn
     WriteParam(aMsg, aParam.mViewId);
     WriteParam(aMsg, aParam.mPresShellId);
     WriteParam(aMsg, aParam.mDragStartSequenceNumber);
     WriteParam(aMsg, aParam.mScrollbarDragOffset);
     WriteParam(aMsg, aParam.mScrollTrack);
     WriteParam(aMsg, aParam.mDirection);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mViewId) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
             ReadParam(aMsg, aIter, &aResult->mDragStartSequenceNumber) &&
             ReadParam(aMsg, aIter, &aResult->mScrollbarDragOffset) &&
             ReadParam(aMsg, aIter, &aResult->mScrollTrack) &&
             ReadParam(aMsg, aIter, &aResult->mDirection));
   }
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -61,19 +61,21 @@ enum class TextureFlags : uint32_t {
   // during the transaction, because the producer may want to write
   // to it again.
   IMMEDIATE_UPLOAD   = 1 << 10,
   // The texture is part of a component-alpha pair
   COMPONENT_ALPHA    = 1 << 11,
   // The texture is being allocated for a compositor that no longer exists.
   // This flag is only used in the parent process.
   INVALID_COMPOSITOR = 1 << 12,
+  // The texture was created by converting from YCBCR to RGB
+  RGB_FROM_YCBCR = 1 << 13,
 
   // OR union of all valid bits
-  ALL_BITS           = (1 << 13) - 1,
+  ALL_BITS           = (1 << 14) - 1,
   // the default flags
   DEFAULT = NO_FLAGS
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextureFlags)
 
 static inline bool
 TextureRequiresLocking(TextureFlags aFlags)
 {
--- a/gfx/layers/LayerScope.cpp
+++ b/gfx/layers/LayerScope.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
 #include "LayerScope.h"
 
 #include "nsAppRunner.h"
 #include "Composer2D.h"
 #include "Effects.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TimeStamp.h"
 
 #include "TexturePoolOGL.h"
 #include "mozilla/layers/CompositorOGL.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/LayerManagerComposite.h"
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3144,17 +3144,17 @@ AsyncPanZoomController::ReportCheckerboa
     }
     mCheckerboardEvent = nullptr;
   }
 }
 
 bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
   ReentrantMonitorAutoEnter lock(mMonitor);
 
-  if (!gfxPrefs::APZAllowCheckerboarding()) {
+  if (!gfxPrefs::APZAllowCheckerboarding() || mScrollMetadata.IsApzForceDisabled()) {
     return false;
   }
 
   CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
   CSSRect painted = mLastContentPaintMetrics.GetDisplayPort() + mLastContentPaintMetrics.GetScrollOffset();
   painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1)));   // fuzz for rounding error
   CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
   if (painted.Contains(visible)) {
--- a/gfx/layers/apz/testutil/APZTestData.h
+++ b/gfx/layers/apz/testutil/APZTestData.h
@@ -138,17 +138,17 @@ struct ParamTraits<mozilla::layers::APZT
   typedef mozilla::layers::APZTestData paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mPaints);
     WriteParam(aMsg, aParam.mRepaintRequests);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mPaints) &&
             ReadParam(aMsg, aIter, &aResult->mRepaintRequests));
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::APZTestData::ScrollFrameData>
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -7,16 +7,18 @@
 #include "BasicLayersImpl.h"            // for FillRectWithMask
 #include "TextureHostBasic.h"
 #include "mozilla/layers/Effects.h"
 #include "nsIWidget.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Helpers.h"
 #include "mozilla/gfx/Tools.h"
+#include "mozilla/gfx/ssse3-scaler.h"
+#include "mozilla/SSE.h"
 #include "gfxUtils.h"
 #include "YCbCrUtils.h"
 #include <algorithm>
 #include "ImageContainer.h"
 #include "gfxPrefs.h"
 
 namespace mozilla {
 using namespace mozilla::gfx;
@@ -194,17 +196,20 @@ BasicCompositor::CreateRenderTargetForWi
   }
 
   return rt.forget();
 }
 
 already_AddRefed<DataTextureSource>
 BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
 {
-  RefPtr<DataTextureSource> result = new DataTextureSourceBasic(nullptr);
+  RefPtr<DataTextureSourceBasic> result = new DataTextureSourceBasic(nullptr);
+  if (aFlags & TextureFlags::RGB_FROM_YCBCR) {
+      result->mFromYCBCR = true;
+  }
   return result.forget();
 }
 
 already_AddRefed<DataTextureSource>
 BasicCompositor::CreateDataTextureSourceAround(DataSourceSurface* aSurface)
 {
   RefPtr<DataTextureSource> result = new DataTextureSourceBasic(aSurface);
   return result.forget();
@@ -270,16 +275,79 @@ SetupMask(const EffectChain& aEffectChai
       gfxWarning() << "Invalid sourceMask effect";
     }
     MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
     aMaskTransform = effectMask->mMaskTransform.As2D();
     aMaskTransform.PostTranslate(-aOffset.x, -aOffset.y);
   }
 }
 
+static bool
+AttemptVideoScale(TextureSourceBasic* aSource, const SourceSurface* aSourceMask,
+                       gfx::Float aOpacity, CompositionOp aBlendMode,
+                       const TexturedEffect* aTexturedEffect,
+                       const Matrix& aNewTransform, const gfx::Rect& aRect,
+                       const gfx::IntRect& aClipRect,
+                       DrawTarget* aDest, const DrawTarget* aBuffer)
+{
+  if (!mozilla::supports_ssse3())
+      return false;
+  if (aNewTransform.IsTranslation()) // unscaled painting should take the regular path
+      return false;
+  if (aNewTransform.HasNonAxisAlignedTransform() || aNewTransform.HasNegativeScaling())
+      return false;
+  if (aSourceMask || aOpacity != 1.0f)
+      return false;
+  if (aBlendMode != CompositionOp::OP_OVER && aBlendMode != CompositionOp::OP_SOURCE)
+      return false;
+
+  IntRect dstRect;
+  // the compiler should know a lot about aNewTransform at this point
+  // maybe it can do some sophisticated optimization of the following
+  if (!aNewTransform.TransformBounds(aRect).ToIntRect(&dstRect))
+      return false;
+
+  if (!(aTexturedEffect->mTextureCoords == Rect(0.0f, 0.0f, 1.0f, 1.0f)))
+      return false;
+  if (aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16)
+      return false;
+
+  uint8_t* dstData;
+  IntSize dstSize;
+  int32_t dstStride;
+  SurfaceFormat dstFormat;
+  if (aDest->LockBits(&dstData, &dstSize, &dstStride, &dstFormat)) {
+    // If we're not painting to aBuffer the clip will
+    // be applied later
+    IntRect fillRect = dstRect;
+    if (aDest == aBuffer) {
+      // we need to clip fillRect because LockBits ignores the clip on the aDest
+      fillRect = fillRect.Intersect(aClipRect);
+    }
+
+    fillRect = fillRect.Intersect(IntRect(IntPoint(0, 0), aDest->GetSize()));
+    IntPoint offset = fillRect.TopLeft() - dstRect.TopLeft();
+
+    RefPtr<DataSourceSurface> srcSource = aSource->GetSurface(aDest)->GetDataSurface();
+    DataSourceSurface::ScopedMap mapSrc(srcSource, DataSourceSurface::READ);
+
+    ssse3_scale_data((uint32_t*)mapSrc.GetData(), srcSource->GetSize().width, srcSource->GetSize().height,
+                     mapSrc.GetStride()/4,
+                     ((uint32_t*)dstData) + fillRect.x + (dstStride / 4) * fillRect.y, dstRect.width, dstRect.height,
+                     dstStride / 4,
+                     offset.x, offset.y,
+                     fillRect.width, fillRect.height);
+
+    aDest->ReleaseBits(dstData);
+    return true;
+  } else {
+    return false;
+  }
+}
+
 void
 BasicCompositor::DrawQuad(const gfx::Rect& aRect,
                           const gfx::IntRect& aClipRect,
                           const EffectChain &aEffectChain,
                           gfx::Float aOpacity,
                           const gfx::Matrix4x4& aTransform,
                           const gfx::Rect& aVisibleRect)
 {
@@ -358,22 +426,31 @@ BasicCompositor::DrawQuad(const gfx::Rec
       break;
     }
     case EffectTypes::RGB: {
       TexturedEffect* texturedEffect =
           static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic();
 
       if (source && texturedEffect->mPremultiplied) {
+        // we have a fast path for video here
+        if (source->mFromYCBCR &&
+            AttemptVideoScale(source, sourceMask, aOpacity, blendMode,
+                              texturedEffect,
+                              newTransform, aRect, aClipRect - offset,
+                              dest, buffer)) {
+          // we succeeded in scaling
+        } else {
           DrawSurfaceWithTextureCoords(dest, aRect,
                                        source->GetSurface(dest),
                                        texturedEffect->mTextureCoords,
                                        texturedEffect->mFilter,
                                        DrawOptions(aOpacity, blendMode),
                                        sourceMask, &maskTransform);
+        }
       } else if (source) {
         SourceSurface* srcSurf = source->GetSurface(dest);
         if (srcSurf) {
           RefPtr<DataSourceSurface> srcData = srcSurf->GetDataSurface();
 
           // Yes, we re-create the premultiplied data every time.
           // This might be better with a cache, eventually.
           RefPtr<DataSourceSurface> premultData = gfxUtils::CreatePremultipliedDataSurface(srcData);
--- a/gfx/layers/basic/TextureHostBasic.h
+++ b/gfx/layers/basic/TextureHostBasic.h
@@ -16,16 +16,18 @@ namespace mozilla {
 namespace layers {
 
 /**
  * A texture source interface that can be used by the software Compositor.
  */
 class TextureSourceBasic
 {
 public:
+  TextureSourceBasic() : mFromYCBCR(false) {}
   virtual ~TextureSourceBasic() {}
   virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) = 0;
+  bool mFromYCBCR; // we to track sources from YCBCR so we can use a less accurate fast path for video
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZILLA_GFX_TEXTUREHOSTBASIC_H_
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -1038,23 +1038,27 @@ TextureClient::RemoveFromCompositable(Co
 void
 TextureClient::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {
   mRemoveFromCompositableWaiter = aWaiter;
 }
 
 already_AddRefed<gfx::DataSourceSurface>
 TextureClient::GetAsSurface()
 {
-  Lock(OpenMode::OPEN_READ);
+  if (!Lock(OpenMode::OPEN_READ)) {
+    return nullptr;
+  }
   RefPtr<gfx::DataSourceSurface> data;
-  RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
-  if (dt) {
-    RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
-    if (surf) {
-      data = surf->GetDataSurface();
+  {  // scope so that the DrawTarget is destroyed before Unlock()
+    RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
+    if (dt) {
+      RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
+      if (surf) {
+        data = surf->GetDataSurface();
+      }
     }
   }
   Unlock();
   return data.forget();
 }
 
 void
 TextureClient::PrintInfo(std::stringstream& aStream, const char* aPrefix)
--- a/gfx/layers/composite/FrameUniformityData.h
+++ b/gfx/layers/composite/FrameUniformityData.h
@@ -57,17 +57,17 @@ struct ParamTraits<mozilla::layers::Fram
 {
   typedef mozilla::layers::FrameUniformityData paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mUniformities);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ParamTraitsStd<std::map<uintptr_t,float>>::Read(aMsg, aIter, &aResult->mUniformities);
   }
 };
 
 } // namespace IPC
 
 #endif // mozilla_layers_FrameUniformityData_h_
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -671,17 +671,17 @@ BufferTextureHost::Upload(nsIntRegion *a
 
     if (!mCompositor->SupportsEffect(EffectTypes::YCBCR)) {
       RefPtr<gfx::DataSourceSurface> surf =
         ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(buf, mDescriptor.get_YCbCrDescriptor());
       if (NS_WARN_IF(!surf)) {
         return false;
       }
       if (!mFirstSource) {
-        mFirstSource = mCompositor->CreateDataTextureSource(mFlags);
+        mFirstSource = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::RGB_FROM_YCBCR);
         mFirstSource->SetOwner(this);
       }
       mFirstSource->Update(surf, aRegion);
       return true;
     }
 
     RefPtr<DataTextureSource> srcY;
     RefPtr<DataTextureSource> srcU;
--- a/gfx/layers/d3d11/CompositorD3D11.hlsl
+++ b/gfx/layers/d3d11/CompositorD3D11.hlsl
@@ -316,17 +316,17 @@ float4 ComputeBlendSourceColor(const VS_
     if (iBlendConfig.x == PS_LAYER_RGB) {
       return RGBShader(tmp);
     } else if (iBlendConfig.x == PS_LAYER_RGBA) {
       return RGBAShader(tmp);
     } else if (iBlendConfig.x == PS_LAYER_YCBCR) {
       return YCbCrShader(tmp);
     }
     return SolidColorShader(tmp);
-  } else if (iBlendConfig.y == PS_MASK_2D) {
+  } else if (iBlendConfig.y == PS_MASK) {
     VS_MASK_OUTPUT tmp;
     tmp.vPosition = aVertex.vPosition;
     tmp.vTexCoords = aVertex.vTexCoords;
     tmp.vMaskCoords = aVertex.vMaskCoords;
 
     if (iBlendConfig.x == PS_LAYER_RGB) {
       return RGBShaderMask(tmp);
     } else if (iBlendConfig.x == PS_LAYER_RGBA) {
--- a/gfx/layers/ipc/FenceUtils.cpp
+++ b/gfx/layers/ipc/FenceUtils.cpp
@@ -28,17 +28,17 @@ ParamTraits<FenceHandle>::Write(Message*
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   RefPtr<FenceHandle::FdObj> fence = handle.GetAndResetFdObj();
   aMsg->WriteFileDescriptor(base::FileDescriptor(fence->GetAndResetFd(), true));
 #endif
 }
 
 bool
 ParamTraits<FenceHandle>::Read(const Message* aMsg,
-                               void** aIter, paramType* aResult)
+                               PickleIterator* aIter, paramType* aResult)
 {
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   base::FileDescriptor fd;
   if (aMsg->ReadFileDescriptor(aIter, &fd)) {
     aResult->Merge(FenceHandle(new FenceHandle::FdObj(fd.fd)));
   }
 #endif
   return true;
--- a/gfx/layers/ipc/FenceUtils.h
+++ b/gfx/layers/ipc/FenceUtils.h
@@ -71,14 +71,14 @@ private:
 
 namespace IPC {
 
 template <>
 struct ParamTraits<mozilla::layers::FenceHandle> {
   typedef mozilla::layers::FenceHandle paramType;
 
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
 };
 
 } // namespace IPC
 
 #endif // IPC_FencerUtils_h
--- a/gfx/layers/ipc/GonkNativeHandleUtils.cpp
+++ b/gfx/layers/ipc/GonkNativeHandleUtils.cpp
@@ -27,17 +27,17 @@ ParamTraits<GonkNativeHandle>::Write(Mes
 
   for (size_t i = 0; i < static_cast<size_t>(nativeHandle->numFds); ++i) {
     aMsg->WriteFileDescriptor(base::FileDescriptor(nativeHandle->data[i], true));
   }
 }
 
 bool
 ParamTraits<GonkNativeHandle>::Read(const Message* aMsg,
-                               void** aIter, paramType* aResult)
+                               PickleIterator* aIter, paramType* aResult)
 {
   size_t nbytes;
   const char* data;
   if (!aMsg->ReadSize(aIter, &nbytes) ||
       !aMsg->ReadBytes(aIter, &data, nbytes)) {
     return false;
   }
 
--- a/gfx/layers/ipc/GonkNativeHandleUtils.h
+++ b/gfx/layers/ipc/GonkNativeHandleUtils.h
@@ -15,22 +15,22 @@
 namespace IPC {
 
 #ifdef MOZ_WIDGET_GONK
 template <>
 struct ParamTraits<mozilla::layers::GonkNativeHandle> {
   typedef mozilla::layers::GonkNativeHandle paramType;
 
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
 };
 #else
 template <>
 struct ParamTraits<mozilla::layers::GonkNativeHandle> {
   typedef mozilla::layers::GonkNativeHandle paramType;
   static void Write(Message*, const paramType&) {}
-  static bool Read(const Message*, void**, paramType*) { return false; }
+  static bool Read(const Message*, PickleIterator*, paramType*) { return false; }
 };
 #endif
 
 } // namespace IPC
 
 #endif // IPC_GonkNativeHandleUtils_h
--- a/gfx/layers/ipc/ShadowLayerUtils.h
+++ b/gfx/layers/ipc/ShadowLayerUtils.h
@@ -45,33 +45,33 @@ struct GrallocBufferRef {
 
 namespace IPC {
 
 #if !defined(MOZ_HAVE_SURFACEDESCRIPTORX11)
 template <>
 struct ParamTraits<mozilla::layers::SurfaceDescriptorX11> {
   typedef mozilla::layers::SurfaceDescriptorX11 paramType;
   static void Write(Message*, const paramType&) {}
-  static bool Read(const Message*, void**, paramType*) { return false; }
+  static bool Read(const Message*, PickleIterator*, paramType*) { return false; }
 };
 #endif  // !defined(MOZ_HAVE_XSURFACEDESCRIPTORX11)
 
 #if !defined(MOZ_HAVE_SURFACEDESCRIPTORGRALLOC)
 template <>
 struct ParamTraits<mozilla::layers::MagicGrallocBufferHandle> {
   typedef mozilla::layers::MagicGrallocBufferHandle paramType;
   static void Write(Message*, const paramType&) {}
-  static bool Read(const Message*, void**, paramType*) { return false; }
+  static bool Read(const Message*, PickleIterator*, paramType*) { return false; }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::GrallocBufferRef> {
   typedef mozilla::layers::GrallocBufferRef paramType;
   static void Write(Message*, const paramType&) {}
-  static bool Read(const Message*, void**, paramType*) { return false; }
+  static bool Read(const Message*, PickleIterator*, paramType*) { return false; }
 };
 #endif  // !defined(MOZ_HAVE_XSURFACEDESCRIPTORGRALLOC)
 
 template <>
 struct ParamTraits<mozilla::ScreenRotation>
   : public ContiguousEnumSerializer<
              mozilla::ScreenRotation,
              mozilla::ROTATION_0,
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -44,17 +44,17 @@ void
 ParamTraits<GrallocBufferRef>::Write(Message* aMsg,
                                      const paramType& aParam)
 {
   aMsg->WriteInt(aParam.mOwner);
   aMsg->WriteInt64(aParam.mKey);
 }
 
 bool
-ParamTraits<GrallocBufferRef>::Read(const Message* aMsg, void** aIter,
+ParamTraits<GrallocBufferRef>::Read(const Message* aMsg, PickleIterator* aIter,
                                     paramType* aParam)
 {
   int owner;
   int64_t index;
   if (!aMsg->ReadInt(aIter, &owner) ||
       !aMsg->ReadInt64(aIter, &index)) {
     printf_stderr("ParamTraits<GrallocBufferRef>::Read() failed to read a message\n");
     return false;
@@ -104,17 +104,17 @@ ParamTraits<MagicGrallocBufferHandle>::W
     // synchonously and the parent-side buffer can only be dropped if
     // there's a crash.
     aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
   }
 }
 
 bool
 ParamTraits<MagicGrallocBufferHandle>::Read(const Message* aMsg,
-                                            void** aIter, paramType* aResult)
+                                            PickleIterator* aIter, paramType* aResult)
 {
   MOZ_ASSERT(!aResult->mGraphicBuffer.get());
   MOZ_ASSERT(aResult->mRef.mOwner == 0);
   MOZ_ASSERT(aResult->mRef.mKey == -1);
 
   size_t nbytes;
   const char* data;
   int owner;
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -74,22 +74,22 @@ android::sp<android::GraphicBuffer> GetG
 
 namespace IPC {
 
 template <>
 struct ParamTraits<mozilla::layers::MagicGrallocBufferHandle> {
   typedef mozilla::layers::MagicGrallocBufferHandle paramType;
 
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
 };
 
 template<>
 struct ParamTraits<mozilla::layers::GrallocBufferRef> {
   typedef mozilla::layers::GrallocBufferRef paramType;
   static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
 };
 
 
 } // namespace IPC
 
 #endif  // mozilla_layers_ShadowLayerUtilsGralloc_h
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.h
@@ -66,17 +66,17 @@ struct ParamTraits<mozilla::layers::Surf
 
   static void Write(Message* aMsg, const paramType& aParam) {
     WriteParam(aMsg, aParam.mId);
     WriteParam(aMsg, aParam.mSize);
     WriteParam(aMsg, aParam.mFormat);
     WriteParam(aMsg, aParam.mGLXPixmap);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
     return (ReadParam(aMsg, aIter, &aResult->mId) &&
             ReadParam(aMsg, aIter, &aResult->mSize) &&
             ReadParam(aMsg, aIter, &aResult->mFormat) &&
             ReadParam(aMsg, aIter, &aResult->mGLXPixmap)
             );
   }
 };
 
--- a/gfx/thebes/gfxColor.h
+++ b/gfx/thebes/gfxColor.h
@@ -2,17 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_COLOR_H
 #define GFX_COLOR_H
 
 #include "mozilla/Attributes.h" // for MOZ_ALWAYS_INLINE
-#include "mozilla/Endian.h" // for mozilla::NativeEndian::swapToBigEndian
+#include "mozilla/EndianUtils.h" // for mozilla::NativeEndian::swapToBigEndian
 
 /**
  * GFX_BLOCK_RGB_TO_FRGB(from,to)
  *   sizeof(*from) == sizeof(char)
  *   sizeof(*to)   == sizeof(uint32_t)
  *
  * Copy 4 pixels at a time, reading blocks of 12 bytes (RGB x4)
  *   and writing blocks of 16 bytes (FRGB x4)
--- a/gfx/thebes/gfxFontUtils.h
+++ b/gfx/thebes/gfxFontUtils.h
@@ -5,17 +5,17 @@
 
 #ifndef GFX_FONT_UTILS_H
 #define GFX_FONT_UTILS_H
 
 #include "gfxPlatform.h"
 #include "nsComponentManagerUtils.h"
 #include "nsTArray.h"
 #include "mozilla/Likely.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
 
 #include "zlib.h"
 #include <algorithm>
 
 /* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
 #ifdef __MINGW32__
@@ -1004,10 +1004,9 @@ protected:
                    ((mEncoding == rhs.mEncoding) && (mLanguage < rhs.mLanguage));
         }
     };
     static const MacFontNameCharsetMapping gMacFontNameCharsets[];
     static const char* gISOFontNameCharsets[];
     static const char* gMSFontNameCharsets[];
 };
 
-
 #endif /* GFX_FONT_UTILS_H */
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -32,17 +32,17 @@ struct ParamTraits<mozilla::gfx::VRDevic
   typedef mozilla::gfx::VRDeviceUpdate paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mDeviceInfo);
     WriteParam(aMsg, aParam.mSensorState);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mDeviceInfo)) ||
         !ReadParam(aMsg, aIter, &(aResult->mSensorState))) {
       return false;
     }
     return true;
   }
 };
@@ -53,17 +53,17 @@ struct ParamTraits<mozilla::gfx::VRSenso
   typedef mozilla::gfx::VRSensorUpdate paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mDeviceID);
     WriteParam(aMsg, aParam.mSensorState);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mDeviceID)) ||
         !ReadParam(aMsg, aIter, &(aResult->mSensorState))) {
       return false;
     }
     return true;
   }
 };
@@ -87,17 +87,17 @@ struct ParamTraits<mozilla::gfx::VRDevic
       WriteParam(aMsg, aParam.mMaximumEyeFOV[i]);
       WriteParam(aMsg, aParam.mRecommendedEyeFOV[i]);
       WriteParam(aMsg, aParam.mEyeFOV[i]);
       WriteParam(aMsg, aParam.mEyeTranslation[i]);
       WriteParam(aMsg, aParam.mEyeProjectionMatrix[i]);
     }
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDeviceID)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDeviceName)) ||
         !ReadParam(aMsg, aIter, &(aResult->mSupportedSensorBits)) ||
         !ReadParam(aMsg, aIter, &(aResult->mEyeResolution)) ||
         !ReadParam(aMsg, aIter, &(aResult->mScreenRect)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIsFakeScreen)) ||
@@ -145,17 +145,17 @@ struct ParamTraits<mozilla::gfx::VRHMDSe
     WriteParam(aMsg, aParam.linearVelocity[0]);
     WriteParam(aMsg, aParam.linearVelocity[1]);
     WriteParam(aMsg, aParam.linearVelocity[2]);
     WriteParam(aMsg, aParam.linearAcceleration[0]);
     WriteParam(aMsg, aParam.linearAcceleration[1]);
     WriteParam(aMsg, aParam.linearAcceleration[2]);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->timestamp)) ||
         !ReadParam(aMsg, aIter, &(aResult->inputFrameID)) ||
         !ReadParam(aMsg, aIter, &(aResult->flags)) ||
         !ReadParam(aMsg, aIter, &(aResult->orientation[0])) ||
         !ReadParam(aMsg, aIter, &(aResult->orientation[1])) ||
         !ReadParam(aMsg, aIter, &(aResult->orientation[2])) ||
         !ReadParam(aMsg, aIter, &(aResult->orientation[3])) ||
@@ -188,17 +188,17 @@ struct ParamTraits<mozilla::gfx::VRField
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.upDegrees);
     WriteParam(aMsg, aParam.rightDegrees);
     WriteParam(aMsg, aParam.downDegrees);
     WriteParam(aMsg, aParam.leftDegrees);
   }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->upDegrees)) ||
         !ReadParam(aMsg, aIter, &(aResult->rightDegrees)) ||
         !ReadParam(aMsg, aIter, &(aResult->downDegrees)) ||
         !ReadParam(aMsg, aIter, &(aResult->leftDegrees))) {
       return false;
     }
 
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -199,16 +199,17 @@ DecoderFactory::CreateMetadataDecoder(De
   }
 
   return decoder.forget();
 }
 
 /* static */ already_AddRefed<Decoder>
 DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
                                        SourceBuffer* aSourceBuffer,
+                                       const Maybe<IntSize>& aTargetSize,
                                        SurfaceFlags aSurfaceFlags)
 {
   if (aType == DecoderType::UNKNOWN) {
     return nullptr;
   }
 
   RefPtr<Decoder> decoder =
     GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
@@ -227,16 +228,22 @@ DecoderFactory::CreateAnonymousDecoder(D
   // Decoder::GetCurrentFrame(). That means that anonymous decoders should
   // always be first-frame-only decoders, because nobody ever wants the *last*
   // frame.
   decoderFlags |= DecoderFlags::FIRST_FRAME_ONLY;
 
   decoder->SetDecoderFlags(decoderFlags);
   decoder->SetSurfaceFlags(aSurfaceFlags);
 
+  // Set a target size for downscale-during-decode if applicable.
+  if (aTargetSize) {
+    DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
+    MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
+  }
+
   decoder->Init();
   if (NS_FAILED(decoder->GetDecoderError())) {
     return nullptr;
   }
 
   return decoder.forget();
 }
 
--- a/image/DecoderFactory.h
+++ b/image/DecoderFactory.h
@@ -115,22 +115,27 @@ public:
 
   /**
    * Creates and initializes an anonymous decoder (one which isn't associated
    * with an Image object). Only the first frame of the image will be decoded.
    *
    * @param aType Which type of decoder to create - JPEG, PNG, etc.
    * @param aSourceBuffer The SourceBuffer which the decoder will read its data
    *                      from.
+   * @param aTargetSize If not Nothing(), the target size which the image should
+   *                    be scaled to during decoding. It's an error to specify
+   *                    a target size for a decoder type which doesn't support
+   *                    downscale-during-decode.
    * @param aSurfaceFlags Flags specifying the type of output this decoder
    *                      should produce.
    */
   static already_AddRefed<Decoder>
   CreateAnonymousDecoder(DecoderType aType,
                          SourceBuffer* aSourceBuffer,
+                         const Maybe<gfx::IntSize>& aTargetSize,
                          SurfaceFlags aSurfaceFlags);
 
   /**
    * Creates and initializes an anonymous metadata decoder (one which isn't
    * associated with an Image object). This decoder will only decode the image's
    * header, extracting metadata like the size of the image. No actual image
    * data will be decoded and no surfaces will be allocated.
    *
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -115,16 +115,17 @@ ImageOps::DecodeToSurface(nsIInputStream
   sourceBuffer->Complete(NS_OK);
 
   // Create a decoder.
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get());
   RefPtr<Decoder> decoder =
     DecoderFactory::CreateAnonymousDecoder(decoderType,
                                            sourceBuffer,
+                                           Nothing(),
                                            ToSurfaceFlags(aFlags));
   if (!decoder) {
     return nullptr;
   }
 
   // Run the decoder synchronously.
   decoder->Decode();
   if (!decoder->GetDecodeDone() || decoder->HasError()) {
--- a/image/decoders/EXIF.cpp
+++ b/image/decoders/EXIF.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 "EXIF.h"
 
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 namespace mozilla {
 namespace image {
 
 // Section references in this file refer to the EXIF v2.3 standard, also known
 // as CIPA DC-008-Translation-2010.
 
 // See Section 4.6.4, Table 4.
--- a/image/decoders/icon/gtk/nsIconChannel.cpp
+++ b/image/decoders/icon/gtk/nsIconChannel.cpp
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "mozilla/DebugOnly.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include <algorithm>
 
 #ifdef MOZ_ENABLE_GIO
 #include <gio/gio.h>
 #endif
 
 #include <gtk/gtk.h>
 
--- a/image/decoders/icon/mac/nsIconChannelCocoa.mm
+++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * 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 "nsContentUtils.h"
 #include "nsIconChannel.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "nsIIconURI.h"
 #include "nsIServiceManager.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsXPIDLString.h"
 #include "nsMimeTypes.h"
 #include "nsMemory.h"
 #include "nsIStringStream.h"
--- a/image/decoders/icon/qt/nsIconChannel.cpp
+++ b/image/decoders/icon/qt/nsIconChannel.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 <QIcon>
 
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 #include "nsMimeTypes.h"
 #include "nsIMIMEService.h"
 
 #include "nsIStringBundle.h"
 
 #include "nsNetUtil.h"
 #include "nsNullPrincipal.h"
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -81,17 +81,17 @@
 //   support.
 // - We treat OS2-BMPv2 files as if they are WinBMPv3 (i.e. ignore the extra 24
 //   bytes in the info header), which in practice is good enough.
 
 #include <stdlib.h>
 
 #include "ImageLogging.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/Likely.h"
 #include "nsBMPDecoder.h"
 
 #include "nsIInputStream.h"
 #include "RasterImage.h"
 #include <algorithm>
 
 using namespace mozilla::gfx;
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.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/. */
 
 /* This is a Cross-Platform ICO Decoder, which should work everywhere, including
  * Big-Endian machines like the PowerPC. */
 
 #include <stdlib.h>
 
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/Move.h"
 #include "nsICODecoder.h"
 
 #include "RasterImage.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -14,17 +14,17 @@
 
 #include "nspr.h"
 #include "nsCRT.h"
 #include "gfxColor.h"
 
 #include "jerror.h"
 
 #include "gfxPlatform.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/Telemetry.h"
 
 extern "C" {
 #include "iccjpeg.h"
 }
 
 #if MOZ_BIG_ENDIAN
 #define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_XRGB
--- a/image/encoders/bmp/nsBMPEncoder.cpp
+++ b/image/encoders/bmp/nsBMPEncoder.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCRT.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "nsBMPEncoder.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "nsTArray.h"
 
 using namespace mozilla;
--- a/image/encoders/ico/nsICOEncoder.cpp
+++ b/image/encoders/ico/nsICOEncoder.cpp
@@ -1,14 +1,14 @@
 /* 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 "nsCRT.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 #include "nsBMPEncoder.h"
 #include "nsPNGEncoder.h"
 #include "nsICOEncoder.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "nsTArray.h"
 
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -156,17 +156,17 @@ RectIsSolidColor(SourceSurface* aSurface
 
 already_AddRefed<Decoder>
 CreateTrivialDecoder()
 {
   gfxPrefs::GetSingleton();
   DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif");
   RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   return decoder.forget();
 }
 
 void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
                                      const gfx::IntRect& aInputSpaceRect,
                                      const gfx::IntRect& aOutputSpaceRect)
 {
@@ -505,10 +505,60 @@ ImageTestCase NoFrameDelayGIFTestCase()
 {
   // This is an invalid (or at least, questionably valid) GIF that's animated
   // even though it specifies a frame delay of zero. It's animated, but it's not
   // marked TEST_CASE_IS_ANIMATED because the metadata decoder can't detect that
   // it's animated.
   return ImageTestCase("no-frame-delay.gif", "image/gif", IntSize(100, 100));
 }
 
+ImageTestCase DownscaledPNGTestCase()
+{
+  // This testcase (and all the other "downscaled") testcases) consists of 25
+  // lines of green, followed by 25 lines of red, followed by 25 lines of green,
+  // followed by 25 more lines of red. It's intended that tests downscale it
+  // from 100x100 to 20x20, so we specify a 20x20 output size.
+  return ImageTestCase("downscaled.png", "image/png", IntSize(100, 100),
+                       IntSize(20, 20));
+}
+
+ImageTestCase DownscaledGIFTestCase()
+{
+  return ImageTestCase("downscaled.gif", "image/gif", IntSize(100, 100),
+                       IntSize(20, 20));
+}
+
+ImageTestCase DownscaledJPGTestCase()
+{
+  return ImageTestCase("downscaled.jpg", "image/jpeg", IntSize(100, 100),
+                       IntSize(20, 20));
+}
+
+ImageTestCase DownscaledBMPTestCase()
+{
+  return ImageTestCase("downscaled.bmp", "image/bmp", IntSize(100, 100),
+                       IntSize(20, 20));
+}
+
+ImageTestCase DownscaledICOTestCase()
+{
+  return ImageTestCase("downscaled.ico", "image/x-icon", IntSize(100, 100),
+                       IntSize(20, 20), TEST_CASE_IS_TRANSPARENT);
+}
+
+ImageTestCase DownscaledIconTestCase()
+{
+  return ImageTestCase("downscaled.icon", "image/icon", IntSize(100, 100),
+                       IntSize(20, 20), TEST_CASE_IS_TRANSPARENT);
+}
+
+ImageTestCase DownscaledTransparentICOWithANDMaskTestCase()
+{
+  // This test case is an ICO with AND mask transparency. We want to ensure that
+  // we can downscale it without crashing or triggering ASAN failures, but its
+  // content isn't simple to verify, so for now we don't check the output.
+  return ImageTestCase("transparent-ico-with-and-mask.ico", "image/x-icon",
+                       IntSize(32, 32), IntSize(20, 20),
+                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IGNORE_OUTPUT);
+}
+
 } // namespace image
 } // namespace mozilla
--- a/image/test/gtest/Common.h
+++ b/image/test/gtest/Common.h
@@ -28,33 +28,48 @@ namespace image {
 
 enum TestCaseFlags
 {
   TEST_CASE_DEFAULT_FLAGS   = 0,
   TEST_CASE_IS_FUZZY        = 1 << 0,
   TEST_CASE_HAS_ERROR       = 1 << 1,
   TEST_CASE_IS_TRANSPARENT  = 1 << 2,
   TEST_CASE_IS_ANIMATED     = 1 << 3,
+  TEST_CASE_IGNORE_OUTPUT   = 1 << 4,
 };
 
 struct ImageTestCase
 {
   ImageTestCase(const char* aPath,
                 const char* aMimeType,
                 gfx::IntSize aSize,
                 uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS)
     : mPath(aPath)
     , mMimeType(aMimeType)
     , mSize(aSize)
+    , mOutputSize(aSize)
+    , mFlags(aFlags)
+  { }
+
+  ImageTestCase(const char* aPath,
+                const char* aMimeType,
+                gfx::IntSize aSize,
+                gfx::IntSize aOutputSize,
+                uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS)
+    : mPath(aPath)
+    , mMimeType(aMimeType)
+    , mSize(aSize)
+    , mOutputSize(aOutputSize)
     , mFlags(aFlags)
   { }
 
   const char* mPath;
   const char* mMimeType;
   gfx::IntSize mSize;
+  gfx::IntSize mOutputSize;
   uint32_t mFlags;
 };
 
 struct BGRAColor
 {
   BGRAColor(uint8_t aBlue, uint8_t aGreen, uint8_t aRed, uint8_t aAlpha)
     : mBlue(aBlue)
     , mGreen(aGreen)
@@ -307,12 +322,20 @@ ImageTestCase TransparentPNGTestCase();
 ImageTestCase TransparentGIFTestCase();
 ImageTestCase FirstFramePaddingGIFTestCase();
 ImageTestCase NoFrameDelayGIFTestCase();
 
 ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase();
 ImageTestCase RLE4BMPTestCase();
 ImageTestCase RLE8BMPTestCase();
 
+ImageTestCase DownscaledPNGTestCase();
+ImageTestCase DownscaledGIFTestCase();
+ImageTestCase DownscaledJPGTestCase();
+ImageTestCase DownscaledBMPTestCase();
+ImageTestCase DownscaledICOTestCase();
+ImageTestCase DownscaledIconTestCase();
+ImageTestCase DownscaledTransparentICOWithANDMaskTestCase();
+
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_test_gtest_Common_h
--- a/image/test/gtest/TestDecoders.cpp
+++ b/image/test/gtest/TestDecoders.cpp
@@ -33,31 +33,31 @@ TEST(ImageDecoders, ImageModuleAvailable
   // We can run into problems if XPCOM modules get initialized in the wrong
   // order. It's important that this test run first, both as a sanity check and
   // to ensure we get the module initialization order we want.
   nsCOMPtr<imgITools> imgTools =
     do_CreateInstance("@mozilla.org/image/tools;1");
   EXPECT_TRUE(imgTools != nullptr);
 }
 
-static void
-CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder)
+static already_AddRefed<SourceSurface>
+CheckDecoderState(const ImageTestCase& aTestCase, Decoder* aDecoder)
 {
   EXPECT_TRUE(aDecoder->GetDecodeDone());
   EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
             aDecoder->HasError());
   EXPECT_TRUE(!aDecoder->WasAborted());
 
   // Verify that the decoder made the expected progress.
   Progress progress = aDecoder->TakeProgress();
   EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
             bool(progress & FLAG_HAS_ERROR));
 
   if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
-    return;  // That's all we can check for bad images.
+    return nullptr;  // That's all we can check for bad images.
   }
 
   EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
   EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
   EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
   EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
             bool(progress & FLAG_HAS_TRANSPARENCY));
   EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
@@ -72,23 +72,42 @@ CheckDecoderResults(const ImageTestCase&
   // because CreateAnonymousDecoder() forces a first-frame-only decode.
   RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
   RefPtr<SourceSurface> surface = currentFrame->GetSurface();
 
   // Verify that the resulting surfaces matches our expectations.
   EXPECT_EQ(SurfaceType::DATA, surface->GetType());
   EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
               surface->GetFormat() == SurfaceFormat::B8G8R8A8);
-  EXPECT_EQ(aTestCase.mSize, surface->GetSize());
+  EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());
+
+  return surface.forget();
+}
+
+static void
+CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder)
+{
+  RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder);
+  if (!surface) {
+    return;
+  }
+
+  if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
+    return;
+  }
+
+  // Check the output.
   EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(),
                            aTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0));
 }
 
-static void
-CheckDecoderSingleChunk(const ImageTestCase& aTestCase)
+template <typename Func>
+void WithSingleChunkDecode(const ImageTestCase& aTestCase,
+                           const Maybe<IntSize>& aOutputSize,
+                           Func aResultChecker)
 {
   nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
   ASSERT_TRUE(inputStream != nullptr);
 
   // Figure out how much data we have.
   uint64_t length;
   nsresult rv = inputStream->Available(&length);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
@@ -99,24 +118,33 @@ CheckDecoderSingleChunk(const ImageTestC
   rv = sourceBuffer->AppendFromInputStream(inputStream, length);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
   sourceBuffer->Complete(NS_OK);
 
   // Create a decoder.
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(aTestCase.mMimeType);
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, aOutputSize,
                                            DefaultSurfaceFlags());
   ASSERT_TRUE(decoder != nullptr);
 
   // Run the full decoder synchronously.
   decoder->Decode();
-  
-  CheckDecoderResults(aTestCase, decoder);
+
+  // Call the lambda to verify the expected results.
+  aResultChecker(decoder);
+}
+
+static void
+CheckDecoderSingleChunk(const ImageTestCase& aTestCase)
+{
+  WithSingleChunkDecode(aTestCase, Nothing(), [&](Decoder* aDecoder) {
+    CheckDecoderResults(aTestCase, aDecoder);
+  });
 }
 
 class NoResume : public IResumable
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(NoResume, override)
   virtual void Resume() override { }
 
@@ -136,17 +164,17 @@ CheckDecoderMultiChunk(const ImageTestCa
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   // Create a SourceBuffer and a decoder.
   RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
   sourceBuffer->ExpectLength(length);
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(aTestCase.mMimeType);
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   ASSERT_TRUE(decoder != nullptr);
 
   // Decode synchronously, using a |NoResume| IResumable so the Decoder doesn't
   // attempt to schedule itself on a nonexistent DecodePool when we write more
   // data into the SourceBuffer.
   RefPtr<NoResume> noResume = new NoResume();
   for (uint64_t read = 0; read < length ; ++read) {
@@ -162,76 +190,141 @@ CheckDecoderMultiChunk(const ImageTestCa
   }
 
   sourceBuffer->Complete(NS_OK);
   decoder->Decode(noResume);
   
   CheckDecoderResults(aTestCase, decoder);
 }
 
+static void
+CheckDownscaleDuringDecode(const ImageTestCase& aTestCase)
+{
+  // This function expects that |aTestCase| consists of 25 lines of green,
+  // followed by 25 lines of red, followed by 25 lines of green, followed by 25
+  // more lines of red. We'll downscale it from 100x100 to 20x20.
+  IntSize outputSize(20, 20);
+
+  WithSingleChunkDecode(aTestCase, Some(outputSize), [&](Decoder* aDecoder) {
+    RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder);
+
+    // There are no downscale-during-decode tests that have TEST_CASE_HAS_ERROR
+    // set, so we expect to always get a surface here.
+    EXPECT_TRUE(surface != nullptr);
+
+    if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
+      return;
+    }
+
+    // Check that the downscaled image is correct. Note that we skip rows near
+    // the transitions between colors, since the downscaler does not produce a
+    // sharp boundary at these points. Even some of the rows we test need a
+    // small amount of fuzz; this is just the nature of Lanczos downscaling.
+    EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 4));
+    EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 4));
+    EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 4));
+    EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3));
+  });
+}
+
 TEST(ImageDecoders, PNGSingleChunk)
 {
   CheckDecoderSingleChunk(GreenPNGTestCase());
 }
 
 TEST(ImageDecoders, PNGMultiChunk)
 {
   CheckDecoderMultiChunk(GreenPNGTestCase());
 }
 
+TEST(ImageDecoders, PNGDownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledPNGTestCase());
+}
+
 TEST(ImageDecoders, GIFSingleChunk)
 {
   CheckDecoderSingleChunk(GreenGIFTestCase());
 }
 
 TEST(ImageDecoders, GIFMultiChunk)
 {
   CheckDecoderMultiChunk(GreenGIFTestCase());
 }
 
+TEST(ImageDecoders, GIFDownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledGIFTestCase());
+}
+
 TEST(ImageDecoders, JPGSingleChunk)
 {
   CheckDecoderSingleChunk(GreenJPGTestCase());
 }
 
 TEST(ImageDecoders, JPGMultiChunk)
 {
   CheckDecoderMultiChunk(GreenJPGTestCase());
 }
 
+TEST(ImageDecoders, JPGDownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledJPGTestCase());
+}
+
 TEST(ImageDecoders, BMPSingleChunk)
 {
   CheckDecoderSingleChunk(GreenBMPTestCase());
 }
 
 TEST(ImageDecoders, BMPMultiChunk)
 {
   CheckDecoderMultiChunk(GreenBMPTestCase());
 }
 
+TEST(ImageDecoders, BMPDownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledBMPTestCase());
+}
+
 TEST(ImageDecoders, ICOSingleChunk)
 {
   CheckDecoderSingleChunk(GreenICOTestCase());
 }
 
 TEST(ImageDecoders, ICOMultiChunk)
 {
   CheckDecoderMultiChunk(GreenICOTestCase());
 }
 
+TEST(ImageDecoders, ICODownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledICOTestCase());
+}
+
+TEST(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase());
+}
+
 TEST(ImageDecoders, IconSingleChunk)
 {
   CheckDecoderSingleChunk(GreenIconTestCase());
 }
 
 TEST(ImageDecoders, IconMultiChunk)
 {
   CheckDecoderMultiChunk(GreenIconTestCase());
 }
 
+TEST(ImageDecoders, IconDownscaleDuringDecode)
+{
+  CheckDownscaleDuringDecode(DownscaledIconTestCase());
+}
+
 TEST(ImageDecoders, AnimatedGIFSingleChunk)
 {
   CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
 }
 
 TEST(ImageDecoders, AnimatedGIFMultiChunk)
 {
   CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase());
--- a/image/test/gtest/TestMetadata.cpp
+++ b/image/test/gtest/TestMetadata.cpp
@@ -105,17 +105,17 @@ CheckMetadata(const ImageTestCase& aTest
                           : bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT);
   EXPECT_EQ(expectTransparency, bool(metadataProgress & FLAG_HAS_TRANSPARENCY));
 
   EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
             bool(metadataProgress & FLAG_IS_ANIMATED));
 
   // Create a full decoder, so we can compare the result.
   decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   ASSERT_TRUE(decoder != nullptr);
 
   if (aBMPWithinICO == BMPWithinICO::YES) {
     static_cast<nsBMPDecoder*>(decoder.get())->SetIsWithinICO();
   }
 
   // Run the full decoder synchronously.
new file mode 100644
index 0000000000000000000000000000000000000000..9e6a29e62ba6cae31498a7cc039d4ef1deaeb44b
GIT binary patch
literal 30138
zc%1Fdp$<V|7zW^D%!YVolT0uZ&8dPZk|GO&of|MsP!vVhT!x8m!bQk3X9r_$;GFQh
zd*1N<|Mq|XXmVZ!X?981Nf+-Hf<}7YOYXzktKU36(qS~7E;pBZcYbQtTiaV<7)9YG
zjyuCRE*}qv%Ak5JwrBhP?+c~iKMw!^000000RCmY9{>OV0000WkFx&(00000002P#
PWW65%0000003e5+*4hEW
new file mode 100644
index 0000000000000000000000000000000000000000..ff9a20bcdb44edf3ea04eea3654fcffe3a51f3ba
GIT binary patch
literal 223
zc$@*>03iQINk%w1VPpVg0Pz3-{{R30{{SXM$tFd~A^8LV00000EC2ui0Av7U00088
zjE||y?GK}zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDkp%Z
z^9hYgr_`$Tip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VMSZH{N
zn5ekO*y#8O8L72IS!sERnW?$S+3EQS8Y((UT55WVnyR|W+UojxA}KpdTWfoZo2$Fa
Z+w1!a94tIcTx@)doUFXe-0W5W06UaCazg+B
new file mode 100644
index 0000000000000000000000000000000000000000..ee112af0a9a77a74f5931f8e5bda019e6cac9d39
GIT binary patch
literal 41662
zc%1Fpp$&jA6h+a;5@;l2Figinp%{g&N(mN4NC@P-n^W;;XwtPxNqdK^OVTG9n|8{U
z^L}iabFo?h0000000000;PWI&k|arzBuSDaNs=T<`a^I3#{&QW00000004j|NRlK;
Vk|arzBuSDaNs{!3%*@PgYzG+X+W-In
new file mode 100644
index 0000000000000000000000000000000000000000..19785f5dcb84a0a3f1fd541f0de8ef9f3e8b4076
GIT binary patch
literal 40003
zc%1FpK?wjr2mnFfm(%_gyb^*a!!j*4GfI*qNs=T<k|arzBuSE_14RJ<000000002M
jev%|fk|arzBuSDaNs=U8X!^$k0000000000fClda<TTed
new file mode 100644
index 0000000000000000000000000000000000000000..5a4b3cd03608e26d06ca58a46c0fb4ca82903e54
GIT binary patch
literal 6035
zc%1E4dr(tX8vpV#JajMuYP*l5LF=QEKmZjgUIiqAs1UVitz|;qizI0hN_5eyuvE*~
zL3gpJoi0_D)!putX>Fy|P9uocb?c&HtF$}i;Zm`+-2_rM#N?j+E>h{(y5p{YHs76l
z&+mNadz|lg?m2VFRnh|!bF*`@fy3dzQhb2)hD(eNhc!(uH``@ut)*Be(^yL7PPJ8@
zC`*vT0?KJsYf5wuNwLmgGN()bb;2c;n6&BA!j$C+%dMF@qiN}8n{L(S6{|IyOEjrk
zDYa0tz?tSOwU+7}YKgOSquHM3OqY%XPeaVA<x<IriK8T4x^{WKB-3KkNm67fvIHr5
z+qC*LRaW+>FZR-<qmwKzFPD`k$t*U5JTWyjRi2=bD-`i)5pUmQcBq~4W_#Rs5wdi4
zjm>0rm@H-q+gBG`${guZsT{}UqbXQ;cdiR1Aqh!HLK2dYgyg3uW49fh8Lv3yc$Xnx
z!<>Ah#bL1<EmldAECJ?c<Sge;2UaFt{>84YT6l|pV_W#Xo4$;#q>pRN$;>RuSFOy>
z$y<UKEdcJ?jha$BKLMcB?69en8IrZ@o|XuEKme0q9Pr>twZ?8;oS&Zu_mx|p0EcZm
z<JnmExBF3v)Z$GDfD?vzk;ZCsAjZ2NtSEO_S-cN%jK-+eBK`~FIX0Xi;;XE__zu3w
zV#5gLvN2<9t5unZV-QOW-^0b<!y2Ql6mc@*X{8&>G^6ujD;cjduUW<F@%=g2K?O?4
z014#463B$PkO-;xoeS}x02%h+KK_ak{}o_CUk!e(unBBn0s|Pq0dr7WhS7D{>QS%5
zXCqpmuxoHHw|0G!;!cL~xd4J|gbd9F5WWHs+(F3gLxcny0eHyE$+|IrOC7-cZ&1H`
zOgHUSfT${fV;_v^ikkphb^}cP+^V*zM^rp~xq3ao;9-CX>j0uJ07R_6!`tXMG+qH%
z{cC`{^8ot~06dQNQO}UikSESV3LE5MV{phx5QTvjv^<UoxFQZu#3Ah<MivEk48Hph
zIb0rJFisd29ubKK?@R<PhsWdcc>)2SkE2^~9QY!^q{k8$kBcr)3#HG+D7No87#5fD
zW^1hKqI+6Wv8^&ZV)B%!k32g4@fkB`%}!34J8yn!T4vUgY~|9N+*PaBJXMH<YqUDO
z!D#xG-BI>@xpULzs^3(<uw&<oHNX8`-QJh$_w7G$sPPX?e>{BTPk(;v=-clcYkBv*
z<87zfPoMel>|f7a>b(5%Cs(d^ecIc1?VtT$TpzgcrDt%+`|YiN`-c5&T^!)uE&WI9
zLJ~M!KA*=IvUPE|<*b2-FL*3*+@!??LiKaeQpNVLn2bFK-)s$!OH#RGi)|MpCQnQ5
zo$g^v8>#HU3ak9TD!W_QSY4mOcpe8Ak0$~O{B5rO3Ia9O*SOmvU?x07Lp3z`o*^)m
z9(X;FOQ7wm)8fF}&0ac~-P7QY^Q|W!3LGY|KPtH2)mLA1bRM&}%NtAJjMB{`(B!7u
zuKP|ASW?ti$V_>5CV~DY@t5=X1TKo(x_!0%RN$=Gv#h!66#}_8{SgGN#rZe{F8Qcl
zdq7R#P_yR=0+G!z^x&o1Z+})v57hQr0?NS#MjPd8x^nY8CV75~fcESO0D&77V)uJY
z0!A<N?IlosrG^?dDg7_CQeLIIg^3$pNkAbCsJ^<T#~ddXR=Rv=8KAu%ME$VH#(PWT
zF|*2UC($=HG%PL(XlbDQMZ$oL-bH!WFw^PYvc6j8=>n$Fx-uvV#1q)btRnEyb^<ZS
zksI$D9j`Sr3Tm4;D6e9sP-n#c*#suJ+{Zmi0`W*p!Mih<oy=qc?er`HUo67)+pzVc
zZhxWSLLq@i#3!Se`c|Z(;aXHMmVU9wx53#+;N?2{$UmY9WYLjyA5}+SNJ5{Mx%8Ic
z6GsP-xm~qALITTrkc<w`4yMM{-W-s<UqIk*xzuHII1)@%yFB7^^zd%#r?-B;EGbga
zWdewSe9oc=YPNn(pOP?t@Aj^w2EX=n5J>(wfb@$Fw|Dqw(L)n<(?drHoQq;)YlFwc
z-UIaTH$_<;%pT-qeAVqI>5B`H`j!u=Kxe@{UQ}Oy?PthX4$k%W{oXueW1`r7mO9!J
zjP3}WsIU__pCa}=T7e^n>Io!t;lid>g%X7l-8Yf&(%xYc6I=bi{NULHPE}N3?t_-z
zW+ps<Q#=0>jr*<r1RiY@=HrYaZ4Hb~?9ZW3ze)g)jN1Cn*9lBE;Ng~sjuSk1(p0-%
zaQSAihuhp_`W{zdU|l!v#DU>0X)cf6iF8~(BX)O-aRaaSl@O?;W9T7`GO(-#51I>|
jHMF}0kHqVeP`*&Uhs|ebPr2Pips@A9w!?pGXwvl`>V<X;
new file mode 100644
index 0000000000000000000000000000000000000000..b71b4652d5288450d91a28c1d8da4a51f16cfb85
GIT binary patch
literal 1015
zc%17D@N?(olHy`uVBq!ia0vp^DIm<j1SJ1AFflVQFiK~JM3hAM`dB6B=jtV<<R_)-
zRpb^hfPjsCML}Y6c4~=2Qfhi;o~_dR-TRdkGE;1o!cBb*d<&dYGcrA@ic*8C{6dne
zvXd=Sl<e)eY$~jP2IQueBq~(o=HwMyRoE(l&9wruLBje<3ScEA*|tg%z5xo(`9-M;
zrh2A&21<5Z3N}S4X;wilZcxoYo~=?wNlAf~zJ7Umxn8-kUVc%!zM-Y1rM`iYzLAkG
zP=#)BWnM{Qg>GK4GRO#s87`^C$wiq3C7Jno3Lt)BQhsTPt&);H$P#_1EkNh$!`%zy
zz<r#W2lQqU&_7aMt6u?wsV&plIiNVm-ATdI)!EF@(#%ZPNY9XgL1SX+#Qok*fg;E4
zGxuvKYqYnqwP$qnZ0cCFv}c2p${L5&uJi49x5&NM6zt_)%ggt7!P1Ut&u%TMSKw&M
z>RMnb#TBI#_dIKX%e>QjzZdWSKBxG-t+>p@o@raNek<;tW_*}&zq(NDCli}scj>Pd
zlHHlp3=Pf2m#nJ27rgkH_4-qxci+cn`>E*iW=XXkH$8lY)1SNDtf=jgZQ}N6eX1?z
zTdRF{F8Hwc(qq-S&^cP0oS&A==6>jzxP60q=)sR%*Dj@nRe0>so_#WV|Mx)sLe=YH
z&!_6`749}*{8KR_vCFefG9lzx;+`KbCX0qXsy+Hc;I+`|lNlR2Pikpidh$ZlRR88=
zqt}bnm!=+Z_W678{;jBA3)Yu3WsALv%lW;SU5f8v_3>@{`*MH(W|<Q-{k4;2-ChRe
z{6+7lZC$6Faks5|^(Ha<*3+>sDvXlS)@WERwJwppcYc8?*W2wEw#2Nu{oYQUf5QgW
zgVHzb8}dHp$NpseRg`YJZsjIDVCv*7@Q5sCVBi)8VMc~ob0mO*A3R+gLn`LHy?v1L
zfB_GSqxRqLbG9s~oq52AHErkoi*vqj_;RQ2!2AwTQecn$HQUo%M@WLlRA0|aWlbUp
e>P0e>YK>jb3zmaY3+7gU@~fw-pUXO@geCygWQ7<2
--- a/image/test/gtest/moz.build
+++ b/image/test/gtest/moz.build
@@ -26,28 +26,35 @@ if CONFIG['MOZ_ENABLE_SKIA']:
 
 SOURCES += [
     # Can't be unified because it manipulates the preprocessor environment.
     'TestDownscalingFilterNoSkia.cpp',
 ]
 
 TEST_HARNESS_FILES.gtest += [
     'corrupt.jpg',
+    'downscaled.bmp',
+    'downscaled.gif',
+    'downscaled.ico',
+    'downscaled.icon',
+    'downscaled.jpg',
+    'downscaled.png',
     'first-frame-green.gif',
     'first-frame-green.png',
     'first-frame-padding.gif',
     'green.bmp',
     'green.gif',
     'green.ico',
     'green.icon',
     'green.jpg',
     'green.png',
     'no-frame-delay.gif',
     'rle4.bmp',
     'rle8.bmp',
+    'transparent-ico-with-and-mask.ico',
     'transparent-if-within-ico.bmp',
     'transparent.gif',
     'transparent.png',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
new file mode 100644
index 0000000000000000000000000000000000000000..ab0dc4bce1ebb02377bca48dae36775579e2414d
GIT binary patch
literal 3262
zc$~GCUuYx89mjt&qtvs$wi;a^-c<_GI4NlMQm}M=@m@;Lx)f?Tfmlu-PQE}ZT?;*_
zg-90)mRo3~+(S;HrPienx4uGSxq(<F5G#4HoKP%>Laoa~tu&C+T_3axrD&CeXpUH`
ztDrA=IS4HM4Znf;J$&agzxmA{05ooa0E~MTUi&)0LjVvQ`#1z=;eYY_8oBGipP#`0
zc@TFV#veUO{_!~a`)T~w?~&an$(v7kUjGsK^96kUBK|{~y!-<G?XU65OZfQ``S~mO
z$2ai#P5jI@`Qh96`|se{_wdY368tBA<PKIp#^3CdiO(=1%J2a?n4~=)?WpwjBeZpj
zHp8?rtJKfZohYp?(v7%c{)DcjXfZ?cD|F>Wnkmxs8cklO@mFbVTX|}SM(T>OPeX?j
z;)wEFRP9jKqZ6M_c!<vd@8@JZVisfVDRwmNI}~hx##^8Dy*0<S7krzGUh_OFCw#>e
z%V*fiiZAmbyY#XzvBu7?`xYzSXq82F*zB$^w9iD7@gt^w#JnA*{F@Q%AA(;Z%_gd)
zXl<Xr<<}0mwlB23kXAdRZlBXOquP2*D?jHiCAECYpL^b)$!V#AmMCfQvbK0bTc~J}
zEx%FILVKz>(D<QWYiaDZO8=!2JnaCNi1$&T>*4LmK+DIQDsN2ly5KuuzCFt;=lJ@3
zU~P$);=GUy<WfAF4Wx2BSqQ|7JXYrOCZF5nXR170<D$;_K|s4XeX_;rhnyh&7zv4m
zjf91QZ4zvq5Y3aKp^067swRTfkf<2KoYTwEU@;~Nagj^t*;Fu<70H~4=k-`o%$M~!
zQy3e1xGF?VACryO&zgeX3=#+rAtX`AMxic*Zr#7mzLHf!dUb}^!c)5;)(B0!H$$-D
zfFY4#gVBZAwo84}&^L|g>Y1rG4OTalcMT7Yj39CsA~u|}AmWz491&(Dun|#Tk9cbl
z<*f*T=n$e37J4w>fv8*lQdE?q0dqlpb-}x}pu92ffu$kDB#PM(>*CmLm->Z8QH=5O
zqH4xiWl{M{%!4i*qvZj_dpK@E+--hxagkr<#kjf__nL9#PjP}S4pCB~qz%a~B;4jF
zn-IAqFI?2FCdUV!zLF#)eT>orNcA9XLCUTErIg5|c`l{q)9h-B{ys&}<zvVW@Z~;a
zEtGYupUCQ|48NS!avAngmR`wVwE6|C4j^Yku8UUP>M!T?M2@F(S~ka4SLtt72);6e
z!T<_36f7vXt)Hd5zFe426x2%v@8!JmtAdA=94HN-*oTq@CAa(wMG-3o&X?3g(VH$R
zzqpF=H3zOqShJyQ!J6CpjFeB!m-$k8d~vg6nf|nl(TyRP12AncEim2k&t4aECXcRb
zi|Z_IPFyev+8m;a#FbA_#e#}k{ZK_WHh83>%~x2gqCC4n$o3Gb5>;*3vY_gAfAuX9
zu5x2rJG;&1x9HPVf@(vkNmT1Y%|bP|{Jb`PVEF0U__6dwYV-#+g7%JKPeQ#1bqnfl
z^|gAC?*&9%o2fISPM_E%=wJv35;bhtx1ixRKfZ=O)!@9L1sg2fP)_d?^1cI2iJCoV
zcA@E(fAUbAY;vus2AW>cRKC;n;17n-lF+i@$U-f*_5Z+;psfIF`KQL;ke2e;5k_~0
z&>q0;9<(iJyX8l1-E%82+17k*=5Nz)-SR+p2$qCS53DY9-137JL>BjS)Jco^I?96<
zA$<qz0q*yq*8#f?b_?50)H?us59}ReZ$ZC;Y!lhnkX=M}0qj-iXTiP%b^`1;*fG?L
zB0B=M0d^SKI_ga$+fRDzL{Irfk09xQlpuQ`yD(^j`~b<DARBPE4zdQa3bFzN6J#05
z639G~IgnY9DY%;ixeRg%22qgb(7-_QG#cnga*!&LJ~E)50U@J%*f~a{Pq6bbcJ7eT
zhuC=^kN$?8ckt+K<h+5M*N}6AIDf>W-x22uc2?2o1>*b?J3qst=dklE9zBhnC$aMc
j8Ge^Ik7MWC#CaGyCy6sjhF`m1A}8+Md-wn4U!Lc`Uedvd
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/downscaling/downscale-moz-icon-1-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html class="reftest-wait">
+<head>
+  <meta charset="utf-8" />
+  <title>Reference for downscaling moz-icon images (bug 1261964)</title>
+  <script>
+    function beginTest() {
+      var canvas = document.getElementById("canvas");
+      var ctx = canvas.getContext("2d");
+      var image = new Image();
+
+      image.onload = function() {
+        // When image loads: draw it to canvas, scale down the canvas, and
+        // then let the reftest snapshot happen.
+        ctx.drawImage(image, 0, 0);
+        canvas.setAttribute("class", "downscale");
+        document.documentElement.removeAttribute("class");
+      }
+
+      // Kick off the image load:
+      image.src = "moz-icon://bogus-unrecognized-icon?size=100";
+    }
+  </script>
+  <style>
+    body { margin: 0; }
+    .downscale {
+      transform-origin: 0 0;
+      transform: scale(0.9);
+    }
+  </style>
+</head>
+<body onload="beginTest()">
+  <canvas id="canvas" height="100px" width="100px"></canvas>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/downscaling/downscale-moz-icon-1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <meta charset="utf-8" />
+  <title>Testcase for downscaling moz-icon images (bug 1261964)</title>
+  <style>
+    body { margin: 0; }
+    .downscale {
+      transform-origin: 0 0;
+      transform: scale(0.9);
+    }
+  </style>
+</head>
+<body>
+  <img class="downscale" src="moz-icon://bogus-unrecognized-icon?size=100">
+</body>
+</html>
--- a/image/test/reftest/downscaling/reftest.list
+++ b/image/test/reftest/downscaling/reftest.list
@@ -82,16 +82,18 @@ fuzzy(20,999) != downscale-2d.html?203,5
 fuzzy(20,999) != downscale-2e.html?203,52,bottom about:blank
 
 fuzzy(20,999) != downscale-2a.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2b.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2c.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2d.html?205,53,bottom about:blank
 fuzzy(20,999) fails-if(OSX>=1008&&!skiaContent) != downscale-2e.html?205,53,bottom about:blank
 
+fuzzy(52,3386) == downscale-moz-icon-1.html downscale-moz-icon-1-ref.html
+
 == downscale-png.html?16,16,interlaced downscale-png.html?16,16,normal
 == downscale-png.html?24,24,interlaced downscale-png.html?24,24,normal
 
 # Non-transparent and transparent ICO images
 == downscale-16px.html?ff-0RGB.ico downscale-16px.html?ff-0RGB.png
 fuzzy(1,1) == downscale-16px.html?ff-ARGB.ico downscale-16px.html?ff-ARGB.png
 
 # Upside-down (negative height) BMP
@@ -163,16 +165,18 @@ fuzzy(20,999) != downscale-2f.html?203,5
 
 fuzzy(20,999) != downscale-2a.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2b.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2c.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2d.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2e.html?205,53,bottom about:blank
 fuzzy(20,999) != downscale-2f.html?205,53,bottom about:blank
 
+fuzzy(71,4439) == downscale-moz-icon-1.html downscale-moz-icon-1-ref.html
+
 == downscale-png.html?16,16,interlaced downscale-png.html?16,16,normal
 == downscale-png.html?24,24,interlaced downscale-png.html?24,24,normal
 
 # Non-transparent and transparent ICO images
 fuzzy(1,3) == downscale-16px.html?ff-0RGB.ico downscale-16px.html?ff-0RGB.png
 fuzzy(3,32) == downscale-16px.html?ff-ARGB.ico downscale-16px.html?ff-ARGB.png
 
 # Upside-down (negative height) BMP
--- a/intl/uconv/ucvlatin/nsUTF16ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsUTF16ToUnicode.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUTF16ToUnicode.h"
 #include "nsCharTraits.h"
 #include "mozilla/CheckedInt.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 enum {
   STATE_NORMAL = 0,
   STATE_HALF_CODE_POINT = 1,
   STATE_FIRST_CALL = 2,
   STATE_SECOND_BYTE = STATE_FIRST_CALL | STATE_HALF_CODE_POINT,
   STATE_ODD_SURROGATE_PAIR = 4
 };
--- a/intl/uconv/ucvlatin/nsUnicodeToUTF16.h
+++ b/intl/uconv/ucvlatin/nsUnicodeToUTF16.h
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsUnicodeToUTF16_h_
 #define nsUnicodeToUTF16_h_
 
 #include "nsUCSupport.h"
-#include "mozilla/Endian.h"
+#include "mozilla/EndianUtils.h"
 
 class nsUnicodeToUTF16BE: public nsBasicEncoder
 {
 public:
   nsUnicodeToUTF16BE() { mBOM = 0;}
 
   //--------------------------------------------------------------------
   // Interface nsIUnicodeEncoder [declaration]
--- a/ipc/chromium/moz.build
+++ b/ipc/chromium/moz.build
@@ -4,17 +4,16 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 libevent_path_prefix = 'src/third_party'
 include(libevent_path_prefix + '/libeventcommon.mozbuild')
 
 UNIFIED_SOURCES += [
     'src/base/at_exit.cc',
-    'src/base/buffer.cc',
     'src/base/command_line.cc',
     'src/base/file_path.cc',
     'src/base/file_util.cc',
     'src/base/histogram.cc',
     'src/base/lock.cc',
     'src/base/logging.cc',
     'src/base/message_loop.cc',
     'src/base/message_pump_default.cc',
deleted file mode 100644
--- a/ipc/chromium/src/base/buffer.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "buffer.h"
-#include "nsDebug.h"
-
-Buffer::Buffer()
- : mBuffer(nullptr),
-   mSize(0),
-   mReserved(0)
-{
-}
-
-Buffer::~Buffer()
-{
-  if (mBuffer) {
-    free(mBuffer);
-  }
-}
-
-bool
-Buffer::empty() const
-{
-  return mSize == 0;
-}
-
-size_t
-Buffer::size() const
-{
-  return mSize;
-}
-
-const char*
-Buffer::data() const
-{
-  return mBuffer;
-}
-
-void
-Buffer::clear()
-{
-  free(mBuffer);
-  mBuffer = nullptr;
-  mSize = 0;
-  mReserved = 0;
-}
-
-void
-Buffer::try_realloc(size_t newlength)
-{
-  char* buffer = (char*)realloc(mBuffer, newlength);
-  if (buffer || !newlength) {
-    mBuffer = buffer;
-    mReserved = newlength;
-    return;
-  }
-
-  // If we're growing the buffer, crash. If we're shrinking, then we continue to
-  // use the old (larger) buffer.
-  if (newlength > mReserved) {
-    NS_ABORT_OOM(newlength);
-  }
-}
-
-void
-Buffer::append(const char* bytes, size_t length)
-{
-  if (mSize + length > mReserved) {
-    try_realloc(mSize + length);
-  }
-
-  memcpy(mBuffer + mSize, bytes, length);
-  mSize += length;
-}
-
-void
-Buffer::assign(const char* bytes, size_t length)
-{
-  if (bytes >= mBuffer && bytes < mBuffer + mReserved) {
-    MOZ_RELEASE_ASSERT(bytes + length <= mBuffer + mSize);
-    memmove(mBuffer, bytes, length);
-    mSize = length;
-    try_realloc(length);
-  } else {
-    try_realloc(length);
-    mSize = length;
-    memcpy(mBuffer, bytes, length);
-  }
-}
-
-void
-Buffer::erase(size_t start, size_t count)
-{
-  mSize -= count;
-  memmove(mBuffer + start, mBuffer + start + count, mSize - start);
-  try_realloc(mSize);
-}
-
-void
-Buffer::reserve(size_t size)
-{
-  if (mReserved < size) {
-    try_realloc(size);
-  }
-}
-
-char*
-Buffer::trade_bytes(size_t count)
-{
-  MOZ_RELEASE_ASSERT(count);
-
-  char* result = mBuffer;
-  mSize = mReserved = mSize - count;
-  mBuffer = mReserved ? (char*)malloc(mReserved) : nullptr;
-  MOZ_RELEASE_ASSERT(!mReserved || mBuffer);
-  if (mSize) {
-    memcpy(mBuffer, result + count, mSize);
-  }
-
-  // Try to resize the buffer down, but ignore failure. This can cause extra
-  // copies, but so be it.
-  char* resized = (char*)realloc(result, count);
-  if (resized) {
-    return resized;
-  }
-  return result;
-}
deleted file mode 100644
--- a/ipc/chromium/src/base/buffer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef CHROME_BASE_BUFFER_H_
-#define CHROME_BASE_BUFFER_H_
-
-// Buffer is a simple std::string-like class for buffering up IPC messages. Its
-// main distinguishing characteristic is the trade_bytes function.
-class Buffer {
-public:
-  Buffer();
-  ~Buffer();
-
-  bool empty() const;
-  const char* data() const;
-  size_t size() const;
-
-  void clear();
-  void append(const char* bytes, size_t length);
-  void assign(const char* bytes, size_t length);
-  void erase(size_t start, size_t count);
-
-  void reserve(size_t size);
-
-  // This function should be used by a caller who wants to extract the first
-  // |count| bytes from the buffer. Rather than copying the bytes out, this
-  // function returns the entire buffer. The bytes in range [count, size()) are
-  // copied out to a new buffer which becomes the current buffer. The
-  // presumption is that |count| is very large and approximately equal to size()
-  // so not much needs to be copied.
-  char* trade_bytes(size_t count);
-
-private:
-  void try_realloc(size_t newlength);
-
-  char* mBuffer;
-  size_t mSize;
-  size_t mReserved;
-};
-
-#endif // CHROME_BASE_BUFFER_H_
--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -235,109 +235,16 @@ void Histogram::WriteAscii(bool graph_it
       WriteAsciiBucketGraph(current_size, max_size, output);
     WriteAsciiBucketContext(past, current, remaining, i, output);
     output->append(newline);
     past += current;
   }
   DCHECK_EQ(sample_count, past);
 }
 
-// static
-std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
-                                              const SampleSet& snapshot) {
-  DCHECK_NE(NOT_VALID_IN_RENDERER, histogram.histogram_type());
-
-  Pickle pickle;
-  pickle.WriteString(histogram.histogram_name());
-  pickle.WriteInt(histogram.declared_min());
-  pickle.WriteInt(histogram.declared_max());
-  pickle.WriteSize(histogram.bucket_count());
-  pickle.WriteUInt32(histogram.range_checksum());
-  pickle.WriteInt(histogram.histogram_type());
-  pickle.WriteInt(histogram.flags());
-
-  snapshot.Serialize(&pickle);
-  return std::string(static_cast<const char*>(pickle.data()), pickle.size());
-}
-
-// static
-bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) {
-  if (histogram_info.empty()) {
-      return false;
-  }
-
-  Pickle pickle(histogram_info.data(),
-                static_cast<int>(histogram_info.size()));
-  std::string histogram_name;
-  int declared_min;
-  int declared_max;
-  size_t bucket_count;
-  uint32_t range_checksum;
-  int histogram_type;
-  int pickle_flags;
-  SampleSet sample;
-
-  void* iter = NULL;
-  if (!pickle.ReadString(&iter, &histogram_name) ||
-      !pickle.ReadInt(&iter, &declared_min) ||
-      !pickle.ReadInt(&iter, &declared_max) ||
-      !pickle.ReadSize(&iter, &bucket_count) ||
-      !pickle.ReadUInt32(&iter, &range_checksum) ||
-      !pickle.ReadInt(&iter, &histogram_type) ||
-      !pickle.ReadInt(&iter, &pickle_flags) ||
-      !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) {
-    CHROMIUM_LOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name;
-    return false;
-  }
-  DCHECK(pickle_flags & kIPCSerializationSourceFlag);
-  // Since these fields may have come from an untrusted renderer, do additional
-  // checks above and beyond those in Histogram::Initialize()
-  if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min ||
-      INT_MAX / sizeof(Count) <= bucket_count || bucket_count < 2) {
-    CHROMIUM_LOG(ERROR) << "Values error decoding Histogram: " << histogram_name;
-    return false;
-  }
-
-  Flags flags = static_cast<Flags>(pickle_flags & ~kIPCSerializationSourceFlag);
-
-  DCHECK_NE(NOT_VALID_IN_RENDERER, histogram_type);
-
-  Histogram* render_histogram(NULL);
-
-  if (histogram_type == HISTOGRAM) {
-    render_histogram = Histogram::FactoryGet(
-        histogram_name, declared_min, declared_max, bucket_count, flags);
-  } else if (histogram_type == LINEAR_HISTOGRAM) {
-    render_histogram = LinearHistogram::FactoryGet(
-        histogram_name, declared_min, declared_max, bucket_count, flags);
-  } else if (histogram_type == BOOLEAN_HISTOGRAM) {
-    render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags);
-  } else {
-    CHROMIUM_LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: "
-                        << histogram_type;
-    return false;
-  }
-
-  DCHECK_EQ(render_histogram->declared_min(), declared_min);
-  DCHECK_EQ(render_histogram->declared_max(), declared_max);
-  DCHECK_EQ(render_histogram->bucket_count(), bucket_count);
-  DCHECK_EQ(render_histogram->range_checksum(), range_checksum);
-  DCHECK_EQ(render_histogram->histogram_type(), histogram_type);
-
-  if (render_histogram->flags() & kIPCSerializationSourceFlag) {
-    DVLOG(1) << "Single process mode, histogram observed and not copied: "
-             << histogram_name;
-  } else {
-    DCHECK_EQ(flags & render_histogram->flags(), flags);
-    render_histogram->AddSampleSet(sample);
-  }
-
-  return true;
-}
-
 //------------------------------------------------------------------------------
 // Methods for the validating a sample and a related histogram.
 //------------------------------------------------------------------------------
 
 Histogram::Inconsistencies Histogram::FindCorruption(
     const SampleSet& snapshot,
     const OffTheBooksMutexAutoLock& snapshotLockEvidence) const {
   int inconsistencies = NO_INCONSISTENCIES;
@@ -768,58 +675,16 @@ void Histogram::SampleSet::Add(const Sam
   OffTheBooksMutexAutoLock locker(mutex_);
   DCHECK_EQ(counts_.size(), other.counts_.size());
   sum_ += other.sum_;
   redundant_count_ += other.redundant_count_;
   for (size_t index = 0; index < counts_.size(); ++index)
     counts_[index] += other.counts_[index];
 }
 
-bool Histogram::SampleSet::Serialize(Pickle* pickle) const {
-  OffTheBooksMutexAutoLock locker(mutex_);
-  pickle->WriteInt64(sum_);
-  pickle->WriteInt64(redundant_count_);
-  pickle->WriteSize(counts_.size());
-
-  for (size_t index = 0; index < counts_.size(); ++index) {
-    pickle->WriteInt(counts_[index]);
-  }
-
-  return true;
-}
-
-bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) {
-  OffTheBooksMutexAutoLock locker(mutex_);
-  DCHECK_EQ(counts_.size(), 0u);
-  DCHECK_EQ(sum_, 0);
-  DCHECK_EQ(redundant_count_, 0);
-
-  size_t counts_size;
-
-  if (!pickle.ReadInt64(iter, &sum_) ||
-      !pickle.ReadInt64(iter, &redundant_count_) ||
-      !pickle.ReadSize(iter, &counts_size)) {
-    return false;
-  }
-
-  if (counts_size == 0)
-    return false;
-
-  int count = 0;
-  for (size_t index = 0; index < counts_size; ++index) {
-    int i;
-    if (!pickle.ReadInt(iter, &i))
-      return false;
-    counts_.push_back(i);
-    count += i;
-  }
-
-  return true;
-}
-
 //------------------------------------------------------------------------------
 // LinearHistogram: This histogram uses a traditional set of evenly spaced
 // buckets.
 //------------------------------------------------------------------------------
 
 LinearHistogram::~LinearHistogram() {
 }
 
--- a/ipc/chromium/src/base/histogram.h
+++ b/ipc/chromium/src/base/histogram.h
@@ -49,18 +49,16 @@
 
 #include <map>
 #include <string>
 #include <vector>
 
 #include "base/time.h"
 #include "base/lock.h"
 
-class Pickle;
-
 namespace base {
 
 using mozilla::OffTheBooksMutex;
 using mozilla::OffTheBooksMutexAutoLock;
 
 //------------------------------------------------------------------------------
 // Provide easy general purpose histogram in a macro, just like stats counters.
 // The first four macros use 50 buckets.
@@ -296,23 +294,16 @@ class Histogram {
     LINEAR,
     CUSTOM
   };
 
   enum Flags {
     kNoFlags = 0,
     kUmaTargetedHistogramFlag = 0x1,  // Histogram should be UMA uploaded.
 
-    // Indicate that the histogram was pickled to be sent across an IPC Channel.
-    // If we observe this flag on a histogram being aggregated into after IPC,
-    // then we are running in a single process mode, and the aggregation should
-    // not take place (as we would be aggregating back into the source
-    // histogram!).
-    kIPCSerializationSourceFlag = 0x10,
-
     kHexRangePrintingFlag = 0x8000  // Fancy bucket-naming supported.
   };
 
   enum Inconsistencies {
     NO_INCONSISTENCIES = 0x0,
     RANGE_CHECKSUM_ERROR = 0x1,
     BUCKET_ORDER_ERROR = 0x2,
     COUNT_HIGH_ERROR = 0x4,
@@ -355,19 +346,16 @@ class Histogram {
     void Resize(const Histogram& histogram);
 
     // Accessor for histogram to make routine additions.
     void Accumulate(Sample value, Count count, size_t index);
 
     // Arithmetic manipulation of corresponding elements of the set.
     void Add(const SampleSet& other);
 
-    bool Serialize(Pickle* pickle) const;
-    bool Deserialize(void** iter, const Pickle& pickle);
-
     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
     //---------------- THREAD UNSAFE METHODS ----------------//
     //
     // The caller must hold |this.mutex_|, and must supply evidence by passing
     // a const reference to the relevant OffTheBooksMutexAutoLock used.
 
     Count counts(const OffTheBooksMutexAutoLock& ev, size_t i) const {
@@ -468,31 +456,16 @@ class Histogram {
 
   // Support generic flagging of Histograms.
   // 0x1 Currently used to mark this histogram to be recorded by UMA..
   // 0x8000 means print ranges in hex.
   void SetFlags(Flags flags) { flags_ = static_cast<Flags> (flags_ | flags); }
   void ClearFlags(Flags flags) { flags_ = static_cast<Flags>(flags_ & ~flags); }
   int flags() const { return flags_; }
 
-  // Convenience methods for serializing/deserializing the histograms.
-  // Histograms from Renderer process are serialized and sent to the browser.
-  // Browser process reconstructs the histogram from the pickled version
-  // accumulates the browser-side shadow copy of histograms (that mirror
-  // histograms created in the renderer).
-
-  // Serialize the given snapshot of a Histogram into a String. Uses
-  // Pickle class to flatten the object.
-  static std::string SerializeHistogramInfo(const Histogram& histogram,
-                                            const SampleSet& snapshot);
-  // The following method accepts a list of pickled histograms and
-  // builds a histogram and updates shadow copy of histogram data in the
-  // browser process.
-  static bool DeserializeHistogramInfo(const std::string& histogram_info);
-
   // Check to see if bucket ranges, counts and tallies in the snapshot are
   // consistent with the bucket ranges and checksums in our histogram.  This can
   // produce a false-alarm if a race occurred in the reading of the data during
   // a SnapShot process, but should otherwise be false at all times (unless we
   // have memory over-writes, or DRAM failures).
   virtual Inconsistencies FindCorruption(const SampleSet& snapshot,
                                          const OffTheBooksMutexAutoLock&
                                                snapshotLockEvidence) const;
--- a/ipc/chromium/src/base/pickle.cc
+++ b/ipc/chromium/src/base/pickle.cc
@@ -2,39 +2,40 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/pickle.h"
 
 #include "mozilla/Alignment.h"
-#include "mozilla/Endian.h"
+#include "mozilla/CheckedInt.h"
+#include "mozilla/EndianUtils.h"
 #include "mozilla/TypeTraits.h"
 
 #include <stdlib.h>
 
 #include <limits>
 #include <string>
 #include <algorithm>
 
 #include "nsDebug.h"
 
+#if !defined(RELEASE_BUILD) || defined(DEBUG)
+#define SENTINEL_CHECKING
+#endif
+
 //------------------------------------------------------------------------------
 
 static_assert(MOZ_ALIGNOF(Pickle::memberAlignmentType) >= MOZ_ALIGNOF(uint32_t),
               "Insufficient alignment");
 
-// static
-const int Pickle::kPayloadUnit = 64;
+static const uint32_t kHeaderSegmentCapacity = 64;
 
-const uint32_t kFastGrowthCap = 128 * 1024;
-
-// We mark a read only pickle with a special capacity_.
-static const uint32_t kCapacityReadOnly = (uint32_t) -1;
+static const uint32_t kDefaultSegmentCapacity = 4096;
 
 static const char kBytePaddingMarker = char(0xbf);
 
 namespace {
 
 // We want to copy data to our payload as efficiently as possible.
 // memcpy fits the bill for copying, but not all compilers or
 // architectures support inlining memcpy from void*, which has unknown
@@ -43,525 +44,479 @@ namespace {
 // therefore use that knowledge to construct a copier that will copy
 // efficiently (via standard C++ assignment mechanisms) if the datatype
 // needs that alignment or less, and memcpy otherwise.  (The compiler
 // may still inline memcpy, of course.)
 
 template<typename T, size_t size, bool hasSufficientAlignment>
 struct Copier
 {
-  static void Copy(T* dest, void** iter) {
-    memcpy(dest, *iter, sizeof(T));
+  static void Copy(T* dest, const char* iter) {
+    memcpy(dest, iter, sizeof(T));
   }
 };
 
 // Copying 64-bit quantities happens often enough and can easily be made
 // worthwhile on 32-bit platforms, so handle it specially.  Only do it
 // if 64-bit types aren't sufficiently aligned; the alignment
 // requirements for them vary between 32-bit platforms.
 #ifndef HAVE_64BIT_BUILD
 template<typename T>
 struct Copier<T, sizeof(uint64_t), false>
 {
-  static void Copy(T* dest, void** iter) {
+  static void Copy(T* dest, const char* iter) {
 #if MOZ_LITTLE_ENDIAN
     static const int loIndex = 0, hiIndex = 1;
 #else
     static const int loIndex = 1, hiIndex = 0;
 #endif
     static_assert(MOZ_ALIGNOF(uint32_t*) == MOZ_ALIGNOF(void*),
                   "Pointers have different alignments");
-    uint32_t* src = *reinterpret_cast<uint32_t**>(iter);
+    const uint32_t* src = reinterpret_cast<const uint32_t*>(iter);
     uint32_t* uint32dest = reinterpret_cast<uint32_t*>(dest);
     uint32dest[loIndex] = src[loIndex];
     uint32dest[hiIndex] = src[hiIndex];
   }
 };
 #endif
 
 template<typename T, size_t size>
 struct Copier<T, size, true>
 {
-  static void Copy(T* dest, void** iter) {
-    // The reinterpret_cast is only safe if two conditions hold:
-    // (1) If the alignment of T* is the same as void*;
-    // (2) The alignment of the data in *iter is at least as
-    //     big as MOZ_ALIGNOF(T).
-    // Check the first condition, as the second condition is already
-    // known to be true, or we wouldn't be here.
-    static_assert(MOZ_ALIGNOF(T*) == MOZ_ALIGNOF(void*),
-                  "Pointers have different alignments");
-    *dest = *(*reinterpret_cast<T**>(iter));
+  static void Copy(T* dest, const char* iter) {
+    *dest = *reinterpret_cast<const T*>(iter);
   }
 };
 
-template<typename T>
-void CopyFromIter(T* dest, void** iter) {
-  static_assert(mozilla::IsPod<T>::value, "Copied type must be a POD type");
-  Copier<T, sizeof(T), (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter);
-}
-
 } // anonymous namespace
 
-// Payload is sizeof(Pickle::memberAlignmentType) aligned.
+PickleIterator::PickleIterator(const Pickle& pickle)
+   : iter_(pickle.buffers_.Iter()) {
+  iter_.Advance(pickle.buffers_, pickle.header_size_);
+}
 
-Pickle::Pickle()
-    : header_(NULL),
-      header_size_(sizeof(Header)),
-      capacity_(0),
-      variable_buffer_offset_(0) {
-  Resize(kPayloadUnit);
-  header_->payload_size = 0;
+template<typename T>
+void
+PickleIterator::CopyInto(T* dest) {
+  static_assert(mozilla::IsPod<T>::value, "Copied type must be a POD type");
+  Copier<T, sizeof(T), (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter_.Data());
 }
 
-Pickle::Pickle(int header_size)
-    : header_(NULL),
-      header_size_(AlignInt(header_size)),
-      capacity_(0),
-      variable_buffer_offset_(0) {
+bool Pickle::IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const {
+  // Make sure we don't get into trouble where AlignInt(len) == 0.
+  MOZ_RELEASE_ASSERT(len < 64);
+
+  return iter.iter_.HasRoomFor(AlignInt(len));
+}
+
+void Pickle::UpdateIter(PickleIterator* iter, uint32_t bytes) const {
+  // Make sure we don't get into trouble where AlignInt(bytes) == 0.
+  MOZ_RELEASE_ASSERT(bytes < 64);
+
+  iter->iter_.Advance(buffers_, AlignInt(bytes));
+}
+
+// Payload is sizeof(Pickle::memberAlignmentType) aligned.
+
+Pickle::Pickle(uint32_t header_size)
+    : buffers_(AlignInt(header_size), kHeaderSegmentCapacity, kDefaultSegmentCapacity),
+      header_(nullptr),
+      header_size_(AlignInt(header_size)) {
   DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
-  DCHECK(header_size <= kPayloadUnit);
-  Resize(kPayloadUnit);
-  if (!header_) {
-    NS_ABORT_OOM(kPayloadUnit);
-  }
+  DCHECK(header_size_ <= kHeaderSegmentCapacity);
+  header_ = reinterpret_cast<Header*>(buffers_.Start());
   header_->payload_size = 0;
 }
 
-Pickle::Pickle(const char* data, int data_len, Ownership ownership)
-    : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
-      header_size_(0),
-      capacity_(ownership == BORROWS ? kCapacityReadOnly : data_len),
-      variable_buffer_offset_(0) {
-  if (data_len >= static_cast<int>(sizeof(Header)))
-    header_size_ = data_len - header_->payload_size;
-
-  if (header_size_ > static_cast<unsigned int>(data_len))
-    header_size_ = 0;
-
-  if (header_size_ != AlignInt(header_size_))
-    header_size_ = 0;
+Pickle::Pickle(uint32_t header_size, const char* data, uint32_t length)
+    : buffers_(length, AlignCapacity(length), kDefaultSegmentCapacity),
+      header_(nullptr),
+      header_size_(AlignInt(header_size)) {
+  DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
+  DCHECK(header_size <= kHeaderSegmentCapacity);
+  MOZ_RELEASE_ASSERT(header_size <= length);
 
-  // If there is anything wrong with the data, we're not going to use it.
-  if (!header_size_)
-    header_ = nullptr;
-}
-
-Pickle::Pickle(const Pickle& other)
-    : header_(NULL),
-      header_size_(other.header_size_),
-      capacity_(0),
-      variable_buffer_offset_(other.variable_buffer_offset_) {
-  uint32_t payload_size = header_size_ + other.header_->payload_size;
-  Resize(payload_size);
-  memcpy(header_, other.header_, payload_size);
+  header_ = reinterpret_cast<Header*>(buffers_.Start());
+  memcpy(header_, data, length);
 }
 
 Pickle::Pickle(Pickle&& other)
-  : header_(other.header_),
-    header_size_(other.header_size_),
-    capacity_(other.capacity_),
-    variable_buffer_offset_(other.variable_buffer_offset_) {
-  other.header_ = NULL;
-  other.capacity_ = 0;
-  other.variable_buffer_offset_ = 0;
+   : buffers_(mozilla::Move(other.buffers_)),
+     header_(other.header_),
+     header_size_(other.header_size_) {
+  other.header_ = nullptr;
 }
 
 Pickle::~Pickle() {
-  if (capacity_ != kCapacityReadOnly)
-    free(header_);
 }
 
-Pickle& Pickle::operator=(const Pickle& other) {
-  if (header_size_ != other.header_size_ && capacity_ != kCapacityReadOnly) {
-    free(header_);
-    header_ = NULL;
-    header_size_ = other.header_size_;
-  }
-  Resize(other.header_size_ + other.header_->payload_size);
-  memcpy(header_, other.header_, header_size_ + other.header_->payload_size);
-  variable_buffer_offset_ = other.variable_buffer_offset_;
+Pickle& Pickle::operator=(Pickle&& other) {
+  BufferList tmp = mozilla::Move(other.buffers_);
+  other.buffers_ = mozilla::Move(buffers_);
+  buffers_ = mozilla::Move(tmp);
+
+  //std::swap(buffers_, other.buffers_);
+  std::swap(header_, other.header_);
+  std::swap(header_size_, other.header_size_);
   return *this;
 }
 
-Pickle& Pickle::operator=(Pickle&& other) {
-  std::swap(header_, other.header_);
-  std::swap(header_size_, other.header_size_);
-  std::swap(capacity_, other.capacity_);
-  std::swap(variable_buffer_offset_, other.variable_buffer_offset_);
-  return *this;
-}
-
-bool Pickle::ReadBool(void** iter, bool* result) const {
+bool Pickle::ReadBool(PickleIterator* iter, bool* result) const {
   DCHECK(iter);
 
   int tmp;
   if (!ReadInt(iter, &tmp))
     return false;
   DCHECK(0 == tmp || 1 == tmp);
   *result = tmp ? true : false;
   return true;
 }
 
-bool Pickle::ReadInt16(void** iter, int16_t* result) const {
+bool Pickle::ReadInt16(PickleIterator* iter, int16_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadUInt16(void** iter, uint16_t* result) const {
+bool Pickle::ReadUInt16(PickleIterator* iter, uint16_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadInt(void** iter, int* result) const {
+bool Pickle::ReadInt(PickleIterator* iter, int* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 // Always written as a 64-bit value since the size for this type can
 // differ between architectures.
-bool Pickle::ReadLong(void** iter, long* result) const {
+bool Pickle::ReadLong(PickleIterator* iter, long* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
-  int64_t bigResult = 0;
-  if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
-    return false;
+  int64_t big_result = 0;
+  if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
+    iter->CopyInto(&big_result);
+    UpdateIter(iter, sizeof(big_result));
+  } else {
+    if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
+      return false;
+    }
+  }
+  DCHECK(big_result <= LONG_MAX && big_result >= LONG_MIN);
+  *result = static_cast<long>(big_result);
 
-  CopyFromIter(&bigResult, iter);
-  DCHECK(bigResult <= LONG_MAX && bigResult >= LONG_MIN);
-  *result = static_cast<long>(bigResult);
-
-  UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
 // Always written as a 64-bit value since the size for this type can
 // differ between architectures.
-bool Pickle::ReadULong(void** iter, unsigned long* result) const {
+bool Pickle::ReadULong(PickleIterator* iter, unsigned long* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
-  uint64_t bigResult = 0;
-  if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
-    return false;
+  uint64_t big_result = 0;
+  if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
+    iter->CopyInto(&big_result);
+    UpdateIter(iter, sizeof(big_result));
+  } else {
+    if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
+      return false;
+    }
+  }
+  DCHECK(big_result <= ULONG_MAX);
+  *result = static_cast<unsigned long>(big_result);
 
-  CopyFromIter(&bigResult, iter);
-  DCHECK(bigResult <= ULONG_MAX);
-  *result = static_cast<unsigned long>(bigResult);
-
-  UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
-bool Pickle::ReadLength(void** iter, int* result) const {
+bool Pickle::ReadLength(PickleIterator* iter, int* result) const {
   if (!ReadInt(iter, result))
     return false;
   return ((*result) >= 0);
 }
 
 // Always written as a 64-bit value since the size for this type can
 // differ between architectures.
-bool Pickle::ReadSize(void** iter, size_t* result) const {
+bool Pickle::ReadSize(PickleIterator* iter, size_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
-  uint64_t bigResult = 0;
-  if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
-    return false;
+  uint64_t big_result = 0;
+  if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
+    iter->CopyInto(&big_result);
+    UpdateIter(iter, sizeof(big_result));
+  } else {
+    if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
+      return false;
+    }
+  }
+  DCHECK(big_result <= std::numeric_limits<size_t>::max());
+  *result = static_cast<size_t>(big_result);
 
-  CopyFromIter(&bigResult, iter);
-  DCHECK(bigResult <= std::numeric_limits<size_t>::max());
-  *result = static_cast<size_t>(bigResult);
-
-  UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
-bool Pickle::ReadInt32(void** iter, int32_t* result) const {
+bool Pickle::ReadInt32(PickleIterator* iter, int32_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadUInt32(void** iter, uint32_t* result) const {
+bool Pickle::ReadUInt32(PickleIterator* iter, uint32_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadInt64(void** iter, int64_t* result) const {
+bool Pickle::ReadInt64(PickleIterator* iter, int64_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadUInt64(void** iter, uint64_t* result) const {
+bool Pickle::ReadUInt64(PickleIterator* iter, uint64_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadDouble(void** iter, double* result) const {
+bool Pickle::ReadDouble(PickleIterator* iter, double* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 // Always written as a 64-bit value since the size for this type can
 // differ between architectures.
-bool Pickle::ReadIntPtr(void** iter, intptr_t* result) const {
+bool Pickle::ReadIntPtr(PickleIterator* iter, intptr_t* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
-  int64_t bigResult = 0;
-  if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
-    return false;
+  int64_t big_result = 0;
+  if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
+    iter->CopyInto(&big_result);
+    UpdateIter(iter, sizeof(big_result));
+  } else {
+    if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
+      return false;
+    }
+  }
 
-  CopyFromIter(&bigResult, iter);
-  DCHECK(bigResult <= std::numeric_limits<intptr_t>::max() && bigResult >= std::numeric_limits<intptr_t>::min());
-  *result = static_cast<intptr_t>(bigResult);
+  DCHECK(big_result <= std::numeric_limits<intptr_t>::max() && big_result >= std::numeric_limits<intptr_t>::min());
+  *result = static_cast<intptr_t>(big_result);
 
-  UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
-bool Pickle::ReadUnsignedChar(void** iter, unsigned char* result) const {
+bool Pickle::ReadUnsignedChar(PickleIterator* iter, unsigned char* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
-    return false;
+    return ReadBytesInto(iter, result, sizeof(*result));
 
-  CopyFromIter(result, iter);
+  iter->CopyInto(result);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
-bool Pickle::ReadString(void** iter, std::string* result) const {
+bool Pickle::ReadString(PickleIterator* iter, std::string* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   int len;
   if (!ReadLength(iter, &len))
     return false;
-  if (!IteratorHasRoomFor(*iter, len))
-    return false;
 
-  char* chars = reinterpret_cast<char*>(*iter);
-  result->assign(chars, len);
+  auto chars = mozilla::MakeUnique<char[]>(len);
+  if (!ReadBytesInto(iter, chars.get(), len)) {
+    return false;
+  }
+  result->assign(chars.get(), len);
 
-  UpdateIter(iter, len);
   return true;
 }
 
-bool Pickle::ReadWString(void** iter, std::wstring* result) const {
+bool Pickle::ReadWString(PickleIterator* iter, std::wstring* result) const {
   DCHECK(iter);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
 
   int len;
   if (!ReadLength(iter, &len))
     return false;
   // Avoid integer multiplication overflow.
   if (len > INT_MAX / static_cast<int>(sizeof(wchar_t)))
     return false;
-  if (!IteratorHasRoomFor(*iter, len * sizeof(wchar_t)))
-    return false;
 
-  wchar_t* chars = reinterpret_cast<wchar_t*>(*iter);
-  result->assign(chars, len);
+  auto chars = mozilla::MakeUnique<wchar_t[]>(len);
+  if (!ReadBytesInto(iter, chars.get(), len * sizeof(wchar_t))) {
+    return false;
+  }
+  result->assign(chars.get(), len);
 
-  UpdateIter(iter, len * sizeof(wchar_t));
   return true;
 }
 
-bool Pickle::ReadBytes(void** iter, const char** data, int length,
-                       uint32_t alignment) const {
+bool Pickle::FlattenBytes(PickleIterator* iter, const char** data, uint32_t length,
+                          uint32_t alignment) {
   DCHECK(iter);
   DCHECK(data);
   DCHECK(alignment == 4 || alignment == 8);
   DCHECK(intptr_t(header_) % alignment == 0);
 
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
+  if (AlignInt(length) < length) {
+    return false;
+  }
+
+  uint32_t padding_len = intptr_t(iter->iter_.Data()) % alignment;
+  if (!iter->iter_.AdvanceAcrossSegments(buffers_, padding_len)) {
+    return false;
+  }
+
+  if (!buffers_.FlattenBytes(iter->iter_, data, length)) {
+    return false;
+  }
 
-  uint32_t paddingLen = intptr_t(*iter) % alignment;
-  if (paddingLen) {
-#ifdef DEBUG
-    {
-      const char* padding = static_cast<const char*>(*iter);
-      for (uint32_t i = 0; i < paddingLen; i++) {
-        DCHECK(*(padding + i) == kBytePaddingMarker);
-      }
-    }
-#endif
-    length += paddingLen;
+  header_ = reinterpret_cast<Header*>(buffers_.Start());
+
+  return iter->iter_.AdvanceAcrossSegments(buffers_, AlignInt(length) - length);
+}
+
+bool Pickle::ReadBytesInto(PickleIterator* iter, void* data, uint32_t length) const {
+  if (AlignInt(length) < length) {
+    return false;
+  }
+
+  if (!buffers_.ReadBytes(iter->iter_, reinterpret_cast<char*>(data), length)) {
+    return false;
   }
 
-  if (!IteratorHasRoomFor(*iter, length))
-    return false;
-
-  *data = static_cast<const char*>(*iter) + paddingLen;
-  DCHECK(intptr_t(*data) % alignment == 0);
-
-  UpdateIter(iter, length);
-  return true;
+  return iter->iter_.AdvanceAcrossSegments(buffers_, AlignInt(length) - length);
 }
 
-bool Pickle::ReadData(void** iter, const char** data, int* length) const {
-  DCHECK(iter);
-  DCHECK(data);
-  DCHECK(length);
-  if (!*iter)
-    *iter = const_cast<char*>(payload());
-
-  if (!ReadLength(iter, length))
+bool Pickle::ReadSentinel(PickleIterator* iter, uint32_t sentinel) const {
+#ifdef SENTINEL_CHECKING
+  uint32_t found;
+  if (!ReadUInt32(iter, &found)) {
     return false;
-
-  return ReadBytes(iter, data, *length);
+  }
+  return found == sentinel;
+#else
+  return true;
+#endif
 }
 
-char* Pickle::BeginWrite(uint32_t length, uint32_t alignment) {
+bool Pickle::WriteSentinel(uint32_t sentinel) {
+#ifdef SENTINEL_CHECKING
+  return WriteUInt32(sentinel);
+#else
+  return true;
+#endif
+}
+
+void Pickle::EndRead(PickleIterator& iter) const {
+  DCHECK(iter.iter_.Done());
+}
+
+void Pickle::BeginWrite(uint32_t length, uint32_t alignment) {
   DCHECK(alignment % 4 == 0) << "Must be at least 32-bit aligned!";
 
   // write at an alignment-aligned offset from the beginning of the header
   uint32_t offset = AlignInt(header_->payload_size);
-  uint32_t padding = (header_size_ + offset) %  alignment;
+  uint32_t padding = (header_size_ + offset) % alignment;
   uint32_t new_size = offset + padding + AlignInt(length);
-  uint32_t needed_size = header_size_ + new_size;
-
-  if (needed_size > capacity_) {
-    double growth_rate = capacity_ < kFastGrowthCap ? 2.0 : 1.4;
-    Resize(std::max(static_cast<uint32_t>(capacity_ * growth_rate), needed_size));
-  }
+  MOZ_RELEASE_ASSERT(new_size >= header_->payload_size);
 
   DCHECK(intptr_t(header_) % alignment == 0);
 
 #ifdef ARCH_CPU_64_BITS
   DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
 #endif
 
-  char* buffer = payload() + offset;
-
   if (padding) {
-    memset(buffer, kBytePaddingMarker, padding);
-    buffer += padding;
+    MOZ_RELEASE_ASSERT(padding <= 8);
+    static const char padding_data[8] = {
+      kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
+      kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
+    };
+    buffers_.WriteBytes(padding_data, padding);
   }
 
-  DCHECK(intptr_t(buffer) % alignment == 0);
+  DCHECK((header_size_ + header_->payload_size + padding) % alignment == 0);
 
   header_->payload_size = new_size;
-
-#ifdef MOZ_VALGRIND
-  // pad the trailing end as well, so that valgrind
-  // doesn't complain when we write the buffer
-  padding = AlignInt(length) - length;
-  if (padding) {
-    memset(buffer + length, kBytePaddingMarker, padding);
-  }
-#endif
-
-  return buffer;
 }
 
-void Pickle::EndWrite(char* dest, int length) {
+void Pickle::EndWrite(uint32_t length) {
   // Zero-pad to keep tools like purify from complaining about uninitialized
   // memory.
-  if (length % sizeof(memberAlignmentType))
-    memset(dest + length, 0,
-           sizeof(memberAlignmentType) - (length % sizeof(memberAlignmentType)));
+  uint32_t padding = AlignInt(length) - length;
+  if (padding) {
+    MOZ_RELEASE_ASSERT(padding <= 4);
+    static const char padding_data[4] = {
+      kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
+    };
+    buffers_.WriteBytes(padding_data, padding);
+  }
 }
 
-bool Pickle::WriteBytes(const void* data, int data_len, uint32_t alignment) {
-  DCHECK(capacity_ != kCapacityReadOnly) << "oops: pickle is readonly";
+bool Pickle::WriteBytes(const void* data, uint32_t data_len, uint32_t alignment) {
   DCHECK(alignment == 4 || alignment == 8);
   DCHECK(intptr_t(header_) % alignment == 0);
 
-  char* dest = BeginWrite(data_len, alignment);
-  if (!dest)
-    return false;
+  BeginWrite(data_len, alignment);
 
-  memcpy(dest, data, data_len);
+  buffers_.WriteBytes(reinterpret_cast<const char*>(data), data_len);
 
-  EndWrite(dest, data_len);
+  EndWrite(data_len);
   return true;
 }
 
 bool Pickle::WriteString(const std::string& value) {
   if (!WriteInt(static_cast<int>(value.size())))
     return false;
 
   return WriteBytes(value.data(), static_cast<int>(value.size()));
@@ -570,97 +525,48 @@ bool Pickle::WriteString(const std::stri
 bool Pickle::WriteWString(const std::wstring& value) {
   if (!WriteInt(static_cast<int>(value.size())))
     return false;
 
   return WriteBytes(value.data(),
                     static_cast<int>(value.size() * sizeof(wchar_t)));
 }
 
-bool Pickle::WriteData(const char* data, int length) {
+bool Pickle::WriteData(const char* data, uint32_t length) {
   return WriteInt(length) && WriteBytes(data, length);
 }
 
-char* Pickle::BeginWriteData(int length) {
-  DCHECK_EQ(variable_buffer_offset_, 0U) <<
-    "There can only be one variable buffer in a Pickle";
-
-  if (!WriteInt(length))
-    return NULL;
-
-  char *data_ptr = BeginWrite(length, sizeof(memberAlignmentType));
-  if (!data_ptr)
-    return NULL;
-
-  variable_buffer_offset_ =
-      data_ptr - reinterpret_cast<char*>(header_) - sizeof(int);
-
-  // EndWrite doesn't necessarily have to be called after the write operation,
-  // so we call it here to pad out what the caller will eventually write.
-  EndWrite(data_ptr, length);
-  return data_ptr;
+void Pickle::InputBytes(const char* data, uint32_t length) {
+  buffers_.WriteBytes(data, length);
 }
 
-void Pickle::TrimWriteData(int new_length) {
-  DCHECK(variable_buffer_offset_ != 0);
-
-  // Fetch the the variable buffer size
-  int* cur_length = reinterpret_cast<int*>(
-      reinterpret_cast<char*>(header_) + variable_buffer_offset_);
-
-  if (new_length < 0 || new_length > *cur_length) {
-    NOTREACHED() << "Invalid length in TrimWriteData.";
-    return;
-  }
-
-  // Update the payload size and variable buffer size
-  header_->payload_size -= (*cur_length - new_length);
-  *cur_length = new_length;
-}
-
-void Pickle::Resize(uint32_t new_capacity) {
-  new_capacity = ConstantAligner<kPayloadUnit>::align(new_capacity);
-
-  void* p = moz_xrealloc(header_, new_capacity);
-
-  header_ = reinterpret_cast<Header*>(p);
-  capacity_ = new_capacity;
+int32_t* Pickle::GetInt32PtrForTest(uint32_t offset) {
+  size_t pos = buffers_.Size() - offset;
+  BufferList::IterImpl iter(buffers_);
+  MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(buffers_, pos));
+  return reinterpret_cast<int32_t*>(iter.Data());
 }
 
 // static
-const char* Pickle::FindNext(uint32_t header_size,
+uint32_t Pickle::MessageSize(uint32_t header_size,
                              const char* start,
                              const char* end) {
   DCHECK(header_size == AlignInt(header_size));
-  DCHECK(header_size <= static_cast<memberAlignmentType>(kPayloadUnit));
-
-  if (end < start)
-    return nullptr;
-  size_t length = static_cast<size_t>(end - start);
-  if (length < sizeof(Header))
-    return nullptr;
-
-  const Header* hdr = reinterpret_cast<const Header*>(start);
-  if (length < header_size || length - header_size < hdr->payload_size)
-    return nullptr;
-
-  return start + header_size + hdr->payload_size;
-}
-
-// static
-uint32_t Pickle::GetLength(uint32_t header_size,
-                           const char* start,
-                           const char* end) {
-  DCHECK(header_size == AlignInt(header_size));
-  DCHECK(header_size <= static_cast<memberAlignmentType>(kPayloadUnit));
+  DCHECK(header_size <= static_cast<memberAlignmentType>(kHeaderSegmentCapacity));
 
   if (end < start)
     return 0;
   size_t length = static_cast<size_t>(end - start);
   if (length < sizeof(Header))
     return 0;
 
   const Header* hdr = reinterpret_cast<const Header*>(start);
   if (length < header_size)
     return 0;
 
-  return header_size + hdr->payload_size;
+  mozilla::CheckedInt<uint32_t> sum(header_size);
+  sum += hdr->payload_size;
+
+  if (!sum.isValid())
+    return 0;
+
+  return sum.value();
 }
--- a/ipc/chromium/src/base/pickle.h
+++ b/ipc/chromium/src/base/pickle.h
@@ -9,16 +9,33 @@
 
 #include <string>
 
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/string16.h"
 
 #include "mozilla/Attributes.h"
+#include "mozilla/BufferList.h"
+#include "mozilla/mozalloc.h"
+
+class Pickle;
+
+class PickleIterator {
+public:
+  explicit PickleIterator(const Pickle& pickle);
+
+private:
+  friend class Pickle;
+
+  mozilla::BufferList<InfallibleAllocPolicy>::IterImpl iter_;
+
+  template<typename T>
+  void CopyInto(T* dest);
+};
 
 // This class provides facilities for basic binary value packing and unpacking.
 //
 // The Pickle class supports appending primitive values (ints, strings, etc.)
 // to a pickle instance.  The Pickle instance grows its internal memory buffer
 // dynamically to hold the sequence of primitive values.   The internal memory
 // buffer is exposed as the "data" of the Pickle.  This "data" can be passed
 // to a Pickle object to initialize it for reading.
@@ -29,89 +46,77 @@
 //
 // The Pickle's data has a header which contains the size of the Pickle's
 // payload.  It can optionally support additional space in the header.  That
 // space is controlled by the header_size parameter passed to the Pickle
 // constructor.
 //
 class Pickle {
  public:
-  enum Ownership {
-    BORROWS,
-    OWNS,
-  };
-
   ~Pickle();
 
-  // Initialize a Pickle object using the default header size.
-  Pickle();
+  Pickle() = delete;
 
   // Initialize a Pickle object with the specified header size in bytes, which
   // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
   // will be rounded up to ensure that the header size is 32bit-aligned.
-  explicit Pickle(int header_size);
+  explicit Pickle(uint32_t header_size);
 
-  // Initializes a Pickle from a const block of data. If ownership == BORROWS,
-  // the data is not copied; instead the data is merely referenced by this
-  // Pickle. Only const methods should be used on the Pickle when initialized
-  // this way. The header padding size is deduced from the data length.  If
-  // ownership == OWNS, then again no copying takes place. However, the buffer
-  // is writable and will be freed when this Pickle is destroyed.
-  Pickle(const char* data, int data_len, Ownership ownership = BORROWS);
+  Pickle(uint32_t header_size, const char* data, uint32_t length);
 
-  // Initializes a Pickle as a deep copy of another Pickle.
-  Pickle(const Pickle& other);
+  Pickle(const Pickle& other) = delete;
 
   Pickle(Pickle&& other);
 
   // Performs a deep copy.
-  Pickle& operator=(const Pickle& other);
+  Pickle& operator=(const Pickle& other) = delete;
 
   Pickle& operator=(Pickle&& other);
 
   // Returns the size of the Pickle's data.
-  int size() const { return static_cast<int>(header_size_ +
-                                             header_->payload_size); }
+  uint32_t size() const { return header_size_ + header_->payload_size; }
+
+  typedef mozilla::BufferList<InfallibleAllocPolicy> BufferList;
 
-  // Return the full size of the memory allocated for this Pickle's data.
-  uint32_t capacity() const {
-    return capacity_;
-  }
+  const BufferList& Buffers() const { return buffers_; }
 
-  // Returns the data for this Pickle.
-  const void* data() const { return header_; }
+  uint32_t CurrentSize() const { return buffers_.Size(); }
 
   // Methods for reading the payload of the Pickle.  To read from the start of
   // the Pickle, initialize *iter to NULL.  If successful, these methods return
   // true.  Otherwise, false is returned to indicate that the result could not
   // be extracted.
-  MOZ_MUST_USE bool ReadBool(void** iter, bool* result) const;
-  MOZ_MUST_USE bool ReadInt16(void** iter, int16_t* result) const;
-  MOZ_MUST_USE bool ReadUInt16(void** iter, uint16_t* result) const;
-  MOZ_MUST_USE bool ReadShort(void** iter, short* result) const;
-  MOZ_MUST_USE bool ReadInt(void** iter, int* result) const;
-  MOZ_MUST_USE bool ReadLong(void** iter, long* result) const;
-  MOZ_MUST_USE bool ReadULong(void** iter, unsigned long* result) const;
-  MOZ_MUST_USE bool ReadSize(void** iter, size_t* result) const;
-  MOZ_MUST_USE bool ReadInt32(void** iter, int32_t* result) const;
-  MOZ_MUST_USE bool ReadUInt32(void** iter, uint32_t* result) const;
-  MOZ_MUST_USE bool ReadInt64(void** iter, int64_t* result) const;
-  MOZ_MUST_USE bool ReadUInt64(void** iter, uint64_t* result) const;
-  MOZ_MUST_USE bool ReadDouble(void** iter, double* result) const;
-  MOZ_MUST_USE bool ReadIntPtr(void** iter, intptr_t* result) const;
-  MOZ_MUST_USE bool ReadUnsignedChar(void** iter, unsigned char* result) const;
-  MOZ_MUST_USE bool ReadString(void** iter, std::string* result) const;
-  MOZ_MUST_USE bool ReadWString(void** iter, std::wstring* result) const;
-  MOZ_MUST_USE bool ReadData(void** iter, const char** data, int* length) const;
-  MOZ_MUST_USE bool ReadBytes(void** iter, const char** data, int length,
-                              uint32_t alignment = sizeof(memberAlignmentType)) const;
+  MOZ_MUST_USE bool ReadBool(PickleIterator* iter, bool* result) const;
+  MOZ_MUST_USE bool ReadInt16(PickleIterator* iter, int16_t* result) const;
+  MOZ_MUST_USE bool ReadUInt16(PickleIterator* iter, uint16_t* result) const;
+  MOZ_MUST_USE bool ReadShort(PickleIterator* iter, short* result) const;
+  MOZ_MUST_USE bool ReadInt(PickleIterator* iter, int* result) const;
+  MOZ_MUST_USE bool ReadLong(PickleIterator* iter, long* result) const;
+  MOZ_MUST_USE bool ReadULong(PickleIterator* iter, unsigned long* result) const;
+  MOZ_MUST_USE bool ReadSize(PickleIterator* iter, size_t* result) const;
+  MOZ_MUST_USE bool ReadInt32(PickleIterator* iter, int32_t* result) const;
+  MOZ_MUST_USE bool ReadUInt32(PickleIterator* iter, uint32_t* result) const;
+  MOZ_MUST_USE bool ReadInt64(PickleIterator* iter, int64_t* result) const;
+  MOZ_MUST_USE bool ReadUInt64(PickleIterator* iter, uint64_t* result) const;
+  MOZ_MUST_USE bool ReadDouble(PickleIterator* iter, double* result) const;
+  MOZ_MUST_USE bool ReadIntPtr(PickleIterator* iter, intptr_t* result) const;
+  MOZ_MUST_USE bool ReadUnsignedChar(PickleIterator* iter, unsigned char* result) const;
+  MOZ_MUST_USE bool ReadString(PickleIterator* iter, std::string* result) const;
+  MOZ_MUST_USE bool ReadWString(PickleIterator* iter, std::wstring* result) const;
+  MOZ_MUST_USE bool ReadBytesInto(PickleIterator* iter, void* data, uint32_t length) const;
+  MOZ_MUST_USE bool FlattenBytes(PickleIterator* iter, const char** data, uint32_t length,
+                                 uint32_t alignment = sizeof(memberAlignmentType));
 
   // Safer version of ReadInt() checks for the result not being negative.
   // Use it for reading the object sizes.
-  MOZ_MUST_USE bool ReadLength(void** iter, int* result) const;
+  MOZ_MUST_USE bool ReadLength(PickleIterator* iter, int* result) const;
+
+  MOZ_MUST_USE bool ReadSentinel(PickleIterator* iter, uint32_t sentinel) const;
+
+  void EndRead(PickleIterator& iter) const;
 
   // Methods for adding to the payload of the Pickle.  These values are
   // appended to the end of the Pickle's payload.  When reading values from a
   // Pickle, it is important to read them in the order in which they were added
   // to the Pickle.
   bool WriteBool(bool value) {
     return WriteInt(value ? 1 : 0);
   }
@@ -159,44 +164,25 @@ class Pickle {
     // differ between architectures.
     return WriteInt64(int64_t(value));
   }
   bool WriteUnsignedChar(unsigned char value) {
     return WriteBytes(&value, sizeof(value));
   }
   bool WriteString(const std::string& value);
   bool WriteWString(const std::wstring& value);
-  bool WriteData(const char* data, int length);
-  bool WriteBytes(const void* data, int data_len,
+  bool WriteData(const char* data, uint32_t length);
+  bool WriteBytes(const void* data, uint32_t data_len,
                   uint32_t alignment = sizeof(memberAlignmentType));
 
-  // Same as WriteData, but allows the caller to write directly into the
-  // Pickle. This saves a copy in cases where the data is not already
-  // available in a buffer. The caller should take care to not write more
-  // than the length it declares it will. Use ReadData to get the data.
-  // Returns NULL on failure.
-  //
-  // The returned pointer will only be valid until the next write operation
-  // on this Pickle.
-  char* BeginWriteData(int length);
+  bool WriteSentinel(uint32_t sentinel);
 
-  // For Pickles which contain variable length buffers (e.g. those created
-  // with BeginWriteData), the Pickle can
-  // be 'trimmed' if the amount of data required is less than originally
-  // requested.  For example, you may have created a buffer with 10K of data,
-  // but decided to only fill 10 bytes of that data.  Use this function
-  // to trim the buffer so that we don't send 9990 bytes of unused data.
-  // You cannot increase the size of the variable buffer; only shrink it.
-  // This function assumes that the length of the variable buffer has
-  // not been changed.
-  void TrimWriteData(int length);
+  int32_t* GetInt32PtrForTest(uint32_t offset);
 
-  void EndRead(void* iter) const {
-    DCHECK(iter == end_of_payload());
-  }
+  void InputBytes(const char* data, uint32_t length);
 
   // Payload follows after allocation of Header (header size is customizable).
   struct Header {
     uint32_t payload_size;  // Specifies the size of the payload.
   };
 
   // Returns the header, cast to a user-specified type T.  The type T must be a
   // subclass of Header and its size must correspond to the header_size passed
@@ -207,103 +193,72 @@ class Pickle {
     return static_cast<T*>(header_);
   }
   template <class T>
   const T* headerT() const {
     DCHECK(sizeof(T) == header_size_);
     return static_cast<const T*>(header_);
   }
 
-  // Returns true if the given iterator could point to data with the given
-  // length. If there is no room for the given data before the end of the
-  // payload, returns false.
-  bool IteratorHasRoomFor(const void* iter, int len) const {
-    if ((len < 0) || (iter < header_) || iter > end_of_payload())
-      return false;
-    const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
-    // Watch out for overflow in pointer calculation, which wraps.
-    return (iter <= end_of_region) && (end_of_region <= end_of_payload());
-  }
-
   typedef uint32_t memberAlignmentType;
 
  protected:
   uint32_t payload_size() const { return header_->payload_size; }
 
-  char* payload() {
-    return reinterpret_cast<char*>(header_) + header_size_;
-  }
-  const char* payload() const {
-    return reinterpret_cast<const char*>(header_) + header_size_;
-  }
-
-  // Returns the address of the byte immediately following the currently valid
-  // header + payload.
-  char* end_of_payload() {
-    // We must have a valid header_.
-    return payload() + payload_size();
-  }
-  const char* end_of_payload() const {
-    // This object may be invalid.
-    return header_ ? payload() + payload_size() : nullptr;
-  }
-
   // Resizes the buffer for use when writing the specified amount of data. The
   // location that the data should be written at is returned, or NULL if there
   // was an error. Call EndWrite with the returned offset and the given length
   // to pad out for the next write.
-  char* BeginWrite(uint32_t length, uint32_t alignment);
+  void BeginWrite(uint32_t length, uint32_t alignment);
 
   // Completes the write operation by padding the data with NULL bytes until it
   // is padded. Should be paired with BeginWrite, but it does not necessarily
   // have to be called after the data is written.
-  void EndWrite(char* dest, int length);
-
-  // Resize the capacity, note that the input value should include the size of
-  // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
-  // A realloc() failure will cause a Resize failure... and caller should check
-  // the return result for true (i.e., successful resizing).
-  void Resize(uint32_t new_capacity);
+  void EndWrite(uint32_t length);
 
   // Round 'bytes' up to the next multiple of 'alignment'.  'alignment' must be
   // a power of 2.
   template<uint32_t alignment> struct ConstantAligner {
     static uint32_t align(int bytes) {
       static_assert((alignment & (alignment - 1)) == 0,
                     "alignment must be a power of two");
       return (bytes + (alignment - 1)) & ~static_cast<uint32_t>(alignment - 1);
     }
   };
 
   static uint32_t AlignInt(int bytes) {
     return ConstantAligner<sizeof(memberAlignmentType)>::align(bytes);
   }
 
+  static uint32_t AlignCapacity(int bytes) {
+    return ConstantAligner<kSegmentAlignment>::align(bytes);
+  }
+
+  // Returns true if the given iterator could point to data with the given
+  // length. If there is no room for the given data before the end of the
+  // payload, returns false.
+  bool IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const;
+
   // Moves the iterator by the given number of bytes, making sure it is aligned.
   // Pointer (iterator) is NOT aligned, but the change in the pointer
   // is guaranteed to be a multiple of sizeof(memberAlignmentType).
-  static void UpdateIter(void** iter, int bytes) {
-    *iter = static_cast<char*>(*iter) + AlignInt(bytes);
-  }
+  void UpdateIter(PickleIterator* iter, uint32_t bytes) const;
 
-  // Find the end of the pickled data that starts at range_start.  Returns NULL
-  // if the entire Pickle is not found in the given data range.
-  static const char* FindNext(uint32_t header_size,
+  // Figure out how big the message starting at range_start is. Returns 0 if
+  // there's no enough data to determine (i.e., if [range_start, range_end) does
+  // not contain enough of the message header to know the size).
+  static uint32_t MessageSize(uint32_t header_size,
                               const char* range_start,
                               const char* range_end);
 
-  // If the given range contains at least header_size bytes, return the length
-  // of the pickled data including the header.
-  static uint32_t GetLength(uint32_t header_size,
-                            const char* range_start,
-                            const char* range_end);
-
-  // The allocation granularity of the payload.
-  static const int kPayloadUnit;
+  // Segments capacities are aligned to 8 bytes to ensure that all reads/writes
+  // at 8-byte aligned offsets will be on 8-byte aligned pointers.
+  static const uint32_t kSegmentAlignment = 8;
 
  private:
+  friend class PickleIterator;
+
+  BufferList buffers_;
   Header* header_;
   uint32_t header_size_;
-  uint32_t capacity_;
-  uint32_t variable_buffer_offset_;
 };
 
 #endif  // BASE_PICKLE_H__
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
@@ -30,16 +30,19 @@
 #include "base/string_util.h"
 #include "base/singleton.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/file_descriptor_set_posix.h"
 #include "chrome/common/ipc_message_utils.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/UniquePtr.h"
 
+// Work around possible OS limitations.
+static const size_t kMaxIOVecSize = 256;
+
 #ifdef MOZ_TASK_TRACER
 #include "GeckoTaskTracerImpl.h"
 using namespace mozilla::tasktracer;
 #endif
 
 namespace IPC {
 
 // IPC channels on Windows use named pipes (CreateNamedPipe()) with
@@ -180,17 +183,18 @@ Channel::ChannelImpl::ChannelImpl(int fd
   EnqueueHelloMessage();
 }
 
 void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
   DCHECK(kControlBufferSlopBytes >= CMSG_SPACE(0));
 
   mode_ = mode;
   is_blocked_on_write_ = false;
-  message_send_bytes_written_ = 0;
+  partial_write_iter_.reset();
+  input_buf_offset_ = 0;
   server_listen_pipe_ = -1;
   pipe_ = -1;
   client_pipe_ = -1;
   listener_ = listener;
   waiting_connect_ = true;
   processing_incoming_ = false;
   closed_ = false;
 #if defined(OS_MACOSX)
@@ -258,21 +262,16 @@ bool Channel::ChannelImpl::EnqueueHelloM
     Close();
     return false;
   }
 
   OutputQueuePush(msg.release());
   return true;
 }
 
-void Channel::ChannelImpl::ClearAndShrinkInputOverflowBuf()
-{
-  input_overflow_buf_.clear();
-}
-
 bool Channel::ChannelImpl::Connect() {
   if (pipe_ == -1) {
     return false;
   }
 
   MessageLoopForIO::current()->WatchFileDescriptor(
       pipe_,
       true,
@@ -282,49 +281,50 @@ bool Channel::ChannelImpl::Connect() {
   waiting_connect_ = false;
 
   if (!waiting_connect_)
     return ProcessOutgoingMessages();
   return true;
 }
 
 bool Channel::ChannelImpl::ProcessIncomingMessages() {
-  ssize_t bytes_read = 0;
-
   struct msghdr msg = {0};
-  struct iovec iov = {input_buf_, Channel::kReadBufferSize};
+  struct iovec iov;
 
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
   msg.msg_control = input_cmsg_buf_;
 
   for (;;) {
     msg.msg_controllen = sizeof(input_cmsg_buf_);
 
-    if (bytes_read == 0) {
-      if (pipe_ == -1)
-        return false;
+    if (pipe_ == -1)
+      return false;
 
-      // Read from pipe.
-      // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
-      // is waiting on the pipe.
-      bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
+    // In some cases the beginning of a message will be stored in input_buf_. We
+    // don't want to overwrite that, so we store the new data after it.
+    iov.iov_base = input_buf_ + input_buf_offset_;
+    iov.iov_len = Channel::kReadBufferSize - input_buf_offset_;
 
-      if (bytes_read < 0) {
-        if (errno == EAGAIN) {
-          return true;
-        } else {
-          CHROMIUM_LOG(ERROR) << "pipe error (" << pipe_ << "): " << strerror(errno);
-          return false;
-        }
-      } else if (bytes_read == 0) {
-        // The pipe has closed...
-        Close();
+    // Read from pipe.
+    // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
+    // is waiting on the pipe.
+    ssize_t bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
+
+    if (bytes_read < 0) {
+      if (errno == EAGAIN) {
+        return true;
+      } else {
+        CHROMIUM_LOG(ERROR) << "pipe error (" << pipe_ << "): " << strerror(errno);
         return false;
       }
+    } else if (bytes_read == 0) {
+      // The pipe has closed...
+      Close();
+      return false;
     }
     DCHECK(bytes_read);
 
     if (client_pipe_ != -1) {
       Singleton<PipeMap>()->Remove(pipe_name_);
       HANDLE_EINTR(close(client_pipe_));
       client_pipe_ = -1;
     }
@@ -368,54 +368,18 @@ bool Channel::ChannelImpl::ProcessIncomi
             return false;
           }
           break;
         }
       }
     }
 
     // Process messages from input buffer.
-    const char *p;
-    const char *overflowp;
-    const char *end;
-    if (input_overflow_buf_.empty()) {
-      overflowp = NULL;
-      p = input_buf_;
-      end = p + bytes_read;
-    } else {
-      if (input_overflow_buf_.size() >
-         static_cast<size_t>(kMaximumMessageSize - bytes_read)) {
-        ClearAndShrinkInputOverflowBuf();
-        CHROMIUM_LOG(ERROR) << "IPC message is too big";
-        return false;
-      }
-
-      input_overflow_buf_.append(input_buf_, bytes_read);
-      overflowp = p = input_overflow_buf_.data();
-      end = p + input_overflow_buf_.size();
-
-      // If we've received the entire header, then we know the message
-      // length. In that case, reserve enough space to hold the entire
-      // message. This is more efficient than repeatedly enlarging the buffer as
-      // more data comes in.
-      uint32_t length = Message::GetLength(p, end);
-      if (length) {
-        if (length > kMaximumMessageSize) {
-          ClearAndShrinkInputOverflowBuf();
-          CHROMIUM_LOG(ERROR) << "IPC message is too big";
-          return false;
-        }
-
-        input_overflow_buf_.reserve(length + kReadBufferSize);
-
-        // Recompute these pointers in case the buffer moved.
-        overflowp = p = input_overflow_buf_.data();
-        end = p + input_overflow_buf_.size();
-      }
-    }
+    const char *p = input_buf_;
+    const char *end = input_buf_ + input_buf_offset_ + bytes_read;
 
     // A pointer to an array of |num_fds| file descriptors which includes any
     // fds that have spilled over from a previous read.
     const int* fds;
     unsigned num_fds;
     unsigned fds_i = 0;  // the index of the first unused descriptor
 
     if (input_overflow_fds_.empty()) {
@@ -425,141 +389,164 @@ bool Channel::ChannelImpl::ProcessIncomi
       const size_t prev_size = input_overflow_fds_.size();
       input_overflow_fds_.resize(prev_size + num_wire_fds);
       memcpy(&input_overflow_fds_[prev_size], wire_fds,
              num_wire_fds * sizeof(int));
       fds = &input_overflow_fds_[0];
       num_fds = input_overflow_fds_.size();
     }
 
+    // The data for the message we're currently reading consists of any data
+    // stored in incoming_message_ followed by data in input_buf_ (followed by
+    // other messages).
+
     while (p < end) {
-      const char* message_tail = Message::FindNext(p, end);
-      if (message_tail) {
-        int len = static_cast<int>(message_tail - p);
-        char* buf;
+      // Try to figure out how big the message is. Size is 0 if we haven't read
+      // enough of the header to know the size.
+      uint32_t message_length = 0;
+      if (incoming_message_.isSome()) {
+        message_length = incoming_message_.ref().size();
+      } else {
+        message_length = Message::MessageSize(p, end);
+      }
+
+      if (!message_length) {
+        // We haven't seen the full message header.
+        MOZ_ASSERT(incoming_message_.isNothing());
+
+        // Move everything we have to the start of the buffer. We'll finish
+        // reading this message when we get more data. For now we leave it in
+        // input_buf_.
+        memmove(input_buf_, p, end - p);
+        input_buf_offset_ = end - p;
+
+        break;
+      }
+
+      input_buf_offset_ = 0;
+
+      bool partial;
+      if (incoming_message_.isSome()) {
+        // We already have some data for this message stored in
+        // incoming_message_. We want to append the new data there.
+        Message& m = incoming_message_.ref();
 
-        // The Message |m| allocated below needs to own its data. We can either
-        // copy the data out of the buffer or else steal the buffer and move the
-        // remaining data elsewhere. If len is large enough, we steal. Otherwise
-        // we copy.
-        if (len > kMaxCopySize) {
-          // Since len > kMaxCopySize > kReadBufferSize, we know that we must be
-          // using the overflow buffer. And since we always shift everything to
-          // the left at the end of a read, we must be at the start of the
-          // overflow buffer.
-          MOZ_RELEASE_ASSERT(p == overflowp);
-          buf = input_overflow_buf_.trade_bytes(len);
+        // How much data from this message remains to be added to
+        // incoming_message_?
+        MOZ_ASSERT(message_length > m.CurrentSize());
+        uint32_t remaining = message_length - m.CurrentSize();
+
+        // How much data from this message is stored in input_buf_?
+        uint32_t in_buf = std::min(remaining, uint32_t(end - p));
+
+        m.InputBytes(p, in_buf);
+        p += in_buf;
+
+        // Are we done reading this message?
+        partial = in_buf != remaining;
+      } else {
+        // How much data from this message is stored in input_buf_?
+        uint32_t in_buf = std::min(message_length, uint32_t(end - p));
 
-          // At this point the remaining data is at the front of
-          // input_overflow_buf_. p will get fixed up at the end of the
-          // loop. Set it to null here to make sure no one uses it.
-          p = nullptr;
-          overflowp = message_tail = input_overflow_buf_.data();
-          end = overflowp + input_overflow_buf_.size();
-        } else {
-          buf = (char*)moz_xmalloc(len);
-          memcpy(buf, p, len);
+        incoming_message_.emplace(p, in_buf);
+        p += in_buf;
+
+        // Are we done reading this message?
+        partial = in_buf != message_length;
+      }
+
+      if (partial) {
+        break;
+      }
+
+      Message& m = incoming_message_.ref();
+
+      if (m.header()->num_fds) {
+        // the message has file descriptors
+        const char* error = NULL;
+        if (m.header()->num_fds > num_fds - fds_i) {
+          // the message has been completely received, but we didn't get
+          // enough file descriptors.
+          error = "Message needs unreceived descriptors";
         }
-        Message m(buf, len, Message::OWNS);
-        if (m.header()->num_fds) {
-          // the message has file descriptors
-          const char* error = NULL;
-          if (m.header()->num_fds > num_fds - fds_i) {
-            // the message has been completely received, but we didn't get
-            // enough file descriptors.
-            error = "Message needs unreceived descriptors";
-          }
+
+        if (m.header()->num_fds >
+            FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) {
+          // There are too many descriptors in this message
+          error = "Message requires an excessive number of descriptors";
+        }
 
-          if (m.header()->num_fds >
-              FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) {
-            // There are too many descriptors in this message
-            error = "Message requires an excessive number of descriptors";
-          }