Merge inbound to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Mon, 25 Aug 2014 17:19:50 -0700
changeset 201520 dc352a7bf234df7682ceedbf70b1f676e82e8171
parent 201519 0736ab6957b2de9c87c05e41be8c356dcb1bf3b1 (current diff)
parent 201489 156f1bee413918f0296c648075c5b4de6aa95478 (diff)
child 201521 0843c26857a9d0534a461ec3fdacfd8b6112167e
child 201635 145df5e2de3d7de995e59ebea3e09f45fc2c39de
child 201687 be6073a0d24a2c504c0b137a1363e686b054c8ac
child 204782 0b020d3a84b90f3ace790e5de01ef9a0e45a4da5
push id48191
push userkwierso@gmail.com
push dateTue, 26 Aug 2014 00:25:28 +0000
treeherdermozilla-inbound@0843c26857a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.0a1
first release with
nightly linux32
dc352a7bf234 / 34.0a1 / 20140826030203 / files
nightly linux64
dc352a7bf234 / 34.0a1 / 20140826030203 / files
nightly mac
dc352a7bf234 / 34.0a1 / 20140826030203 / files
nightly win32
dc352a7bf234 / 34.0a1 / 20140826030203 / files
nightly win64
dc352a7bf234 / 34.0a1 / 20140826030203 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c a=merge
browser/base/content/nsContextMenu.js
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -243,17 +243,17 @@ this.AccessFu = { // jshint ignore:line
       try {
         Output[presenter.type](presenter.details, aBrowser);
       } catch (x) {
         Logger.logException(x);
       }
     }
 
     if (this._notifyOutputPref.value) {
-      Services.obs.notifyObservers(null, 'accessfu-output',
+      Services.obs.notifyObservers(null, 'accessibility-output',
                                    JSON.stringify(aPresentationData));
     }
   },
 
   _loadFrameScript: function _loadFrameScript(aMessageManager) {
     if (this._processedMessageManagers.indexOf(aMessageManager) < 0) {
       aMessageManager.loadFrameScript(
         'chrome://global/content/accessibility/content-script.js', true);
@@ -509,17 +509,17 @@ var Output = {
   stop: function stop() {
     if (this.highlightBox) {
       Utils.win.document.documentElement.removeChild(this.highlightBox.get());
       delete this.highlightBox;
     }
   },
 
   B2G: function B2G(aDetails) {
-    Utils.dispatchChromeEvent('accessfu-output', aDetails);
+    Utils.dispatchChromeEvent('accessibility-output', aDetails);
   },
 
   Visual: function Visual(aDetail, aBrowser) {
     switch (aDetail.eventType) {
       case 'viewport-change':
       case 'vc-change':
       {
         let highlightBox = null;
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -76,31 +76,31 @@ var AccessFuTest = {
       var data = JSON.parse(aData)[1];
       // Ignore non-relevant outputs.
       if (!data) {
         return;
       }
       isDeeply(data.details, aWaitForData, "Data is correct");
       aListener.apply(listener);
     };
-    Services.obs.addObserver(listener, 'accessfu-output', false);
+    Services.obs.addObserver(listener, 'accessibility-output', false);
     return listener;
   },
 
   on: function AccessFuTest_on(aWaitForData, aListener) {
     return this._addObserver(aWaitForData, aListener);
   },
 
   off: function AccessFuTest_off(aListener) {
-    Services.obs.removeObserver(aListener, 'accessfu-output');
+    Services.obs.removeObserver(aListener, 'accessibility-output');
   },
 
   once: function AccessFuTest_once(aWaitForData, aListener) {
     return this._addObserver(aWaitForData, function observerAndRemove() {
-      Services.obs.removeObserver(this, 'accessfu-output');
+      Services.obs.removeObserver(this, 'accessibility-output');
       aListener();
     });
   },
 
   _waitForExplicitFinish: false,
 
   waitForExplicitFinish: function AccessFuTest_waitForExplicitFinish() {
     this._waitForExplicitFinish = true;
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -49,17 +49,17 @@ pref("browser.cache.disk.smart_size.firs
 pref("browser.cache.memory.enable", true);
 pref("browser.cache.memory.capacity", 1024); // kilobytes
 
 pref("browser.cache.memory_limit", 2048); // 2 MB
 
 /* image cache prefs */
 pref("image.cache.size", 1048576); // bytes
 pref("image.high_quality_downscaling.enabled", false);
-pref("canvas.image.cache.limit", 10485760); // 10 MB
+pref("canvas.image.cache.limit", 20971520); // 20 MB
 
 /* offline cache prefs */
 pref("browser.offline-apps.notify", false);
 pref("browser.cache.offline.enable", true);
 pref("offline-apps.allow_by_default", true);
 
 /* protocol warning prefs */
 pref("network.protocol-handler.warn-external.tel", false);
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -1217,23 +1217,25 @@ var gPluginHandler = {
 
     // If we're showing the link to manually trigger report submission, we'll
     // want to be able to update all the instances of the UI for this crash to
     // show an updated message when a report is submitted.
     if (doPrompt) {
       let observer = {
         QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                                Ci.nsISupportsWeakReference]),
-        observe : function(subject, topic, data) {
+        observe : (subject, topic, data) => {
           let propertyBag = subject;
           if (!(propertyBag instanceof Ci.nsIPropertyBag2))
             return;
           // Ignore notifications for other crashes.
           if (propertyBag.get("minidumpID") != pluginDumpID)
             return;
+
+          let statusDiv = this.getPluginUI(plugin, "submitStatus");
           statusDiv.setAttribute("status", data);
         },
 
         handleEvent : function(event) {
             // Not expected to be called, just here for the closure.
         }
       }
 
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1163,23 +1163,23 @@ nsContextMenu.prototype = {
 
             const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                               getService(Ci.nsIPromptService);
             promptSvc.alert(doc.defaultView, title, msg);
           } catch (ex) {}
           return;
         }
 
-        var extHelperAppSvc = 
+        let extHelperAppSvc = 
           Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
           getService(Ci.nsIExternalHelperAppService);
-        var channel = aRequest.QueryInterface(Ci.nsIChannel);
-        this.extListener = 
+        let channel = aRequest.QueryInterface(Ci.nsIChannel);
+        this.extListener =
           extHelperAppSvc.doContent(channel.contentType, aRequest, 
-                                    doc.defaultView, true);
+                                    doc.defaultView, true, window);
         this.extListener.onStartRequest(aRequest, aContext);
       }, 
 
       onStopRequest: function saveLinkAs_onStopRequest(aRequest, aContext, 
                                                        aStatusCode) {
         if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
           // do it the old fashioned way, which will pick the best filename
           // it can without waiting.
--- a/browser/base/content/test/plugins/browser_CTP_crashreporting.js
+++ b/browser/base/content/test/plugins/browser_CTP_crashreporting.js
@@ -109,16 +109,25 @@ function onSubmitStatus(subj, topic, dat
 
     let val = getPropertyBagValue(extra, "PluginUserComment");
     is(val, "a test comment",
        "Comment in extra data should match comment in textbox");
 
     val = getPropertyBagValue(extra, "PluginContentURL");
     ok(val === undefined,
        "URL should be absent from extra data when opt-in not checked");
+
+    // Execute this later in case the event to change submitStatus has not
+    // have been dispatched yet.
+    executeSoon(function () {
+      let plugin = gBrowser.contentDocument.getElementById("test");
+      let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
+      is(elt("submitStatus").getAttribute("status"), data,
+         "submitStatus data should match");
+    });
   }
   catch (err) {
     failWithException(err);
   }
   finish();
 }
 
 function getPropertyBagValue(bag, key) {
--- a/build/gyp.mozbuild
+++ b/build/gyp.mozbuild
@@ -104,17 +104,17 @@ if CONFIG['ARM_ARCH']:
         gyp_vars['arm_neon_optional'] = 0
     elif os == 'Android':
         gyp_vars['armv7'] = 1
     else:
         # CPU detection for ARM works on Android only.  armv7 always uses CPU
         # detection, so we have to set armv7=0 for non-Android target
         gyp_vars['armv7'] = 0
     # For libyuv
-    gyp_vars['arm_version'] = CONFIG['ARM_ARCH']
+    gyp_vars['arm_version'] = int(CONFIG['ARM_ARCH'])
 
 # Don't try to compile ssse3/sse4.1 code if toolchain doesn't support
 if CONFIG['INTEL_ARCHITECTURE']:
     if not CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3'] or not CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSE4_1']:
         gyp_vars['yuv_disable_asm'] = 1
 
 if CONFIG['MACOS_SDK_DIR']:
     gyp_vars['mac_sdk_path'] = CONFIG['MACOS_SDK_DIR']
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -7496,21 +7496,27 @@ nsIDocument::AdoptNode(nsINode& aAdopted
                "Should still be in the document we just got adopted into");
 
   return adoptedNode;
 }
 
 nsViewportInfo
 nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
 {
+  // Compute the CSS-to-LayoutDevice pixel scale as the product of the
+  // widget scale and the full zoom.
   nsPresContext* context = mPresShell->GetPresContext();
   float fullZoom = context ? context->GetFullZoom() : 1.0;
   fullZoom = (fullZoom == 0.0) ? 1.0 : fullZoom;
-  CSSToScreenScale defaultScale = CSSToLayoutDeviceScale(fullZoom) *
-                                  LayoutDeviceToScreenScale(1.0);
+  nsIWidget *widget = nsContentUtils::WidgetForDocument(this);
+  float widgetScale = widget ? widget->GetDefaultScale().scale : 1.0f;
+  CSSToLayoutDeviceScale layoutDeviceScale(widgetScale * fullZoom);
+
+  CSSToScreenScale defaultScale = layoutDeviceScale
+                                * LayoutDeviceToScreenScale(1.0);
 
   // In cases where the width of the CSS viewport is less than or equal to the width
   // of the display (i.e. width <= device-width) then we disable double-tap-to-zoom
   // behaviour. See bug 941995 for details.
 
   switch (mViewportType) {
   case DisplayWidthHeight:
     return nsViewportInfo(aDisplaySize,
@@ -7684,29 +7690,23 @@ nsDocument::GetViewportInfo(const Screen
     if (!mValidHeight) {
       if (!aDisplaySize.IsEmpty()) {
         size.height = size.width * aDisplaySize.height / aDisplaySize.width;
       } else {
         size.height = size.width;
       }
     }
 
-    // Now convert the scale into device pixels per CSS pixel base on this formula
-    //   CSSPixel x widget scale x full zoom = LayoutDevicePixel
-    nsIWidget *widget = nsContentUtils::WidgetForDocument(this);
-    CSSToLayoutDeviceScale pixelRatio = CSSToLayoutDeviceScale(
-          (widget ? widget->GetDefaultScale().scale : 1.0f) * fullZoom);
-
-    CSSToScreenScale scaleFloat = mScaleFloat * pixelRatio;
-    CSSToScreenScale scaleMinFloat = mScaleMinFloat * pixelRatio;
-    CSSToScreenScale scaleMaxFloat = mScaleMaxFloat * pixelRatio;
+    CSSToScreenScale scaleFloat = mScaleFloat * layoutDeviceScale;
+    CSSToScreenScale scaleMinFloat = mScaleMinFloat * layoutDeviceScale;
+    CSSToScreenScale scaleMaxFloat = mScaleMaxFloat * layoutDeviceScale;
 
     if (mAutoSize) {
       // aDisplaySize is in screen pixels; convert them to CSS pixels for the viewport size.
-      CSSToScreenScale defaultPixelScale = pixelRatio * LayoutDeviceToScreenScale(1.0f);
+      CSSToScreenScale defaultPixelScale = layoutDeviceScale * LayoutDeviceToScreenScale(1.0f);
       size = ScreenSize(aDisplaySize) / defaultPixelScale;
     }
 
     size.width = clamped(size.width, float(kViewportMinSize.width), float(kViewportMaxSize.width));
 
     // Also recalculate the default zoom, if it wasn't specified in the metadata,
     // and the width is specified.
     if (mScaleStrEmpty && !mWidthStrEmpty) {
--- a/content/html/content/src/HTMLSelectElement.cpp
+++ b/content/html/content/src/HTMLSelectElement.cpp
@@ -968,18 +968,18 @@ HTMLSelectElement::SetOptionsSelectedByI
   bool optionsDeselected = false;
 
   nsISelectControlFrame* selectFrame = nullptr;
   bool didGetFrame = false;
   nsWeakFrame weakSelectFrame;
 
   if (aOptionsMask & IS_SELECTED) {
     // Setting selectedIndex to an out-of-bounds index means -1. (HTML5)
-    if (aStartIndex < 0 || SafeCast<uint32_t>(aStartIndex) >= numItems ||
-        aEndIndex < 0 || SafeCast<uint32_t>(aEndIndex) >= numItems) {
+    if (aStartIndex < 0 || AssertedCast<uint32_t>(aStartIndex) >= numItems ||
+        aEndIndex < 0 || AssertedCast<uint32_t>(aEndIndex) >= numItems) {
       aStartIndex = -1;
       aEndIndex = -1;
     }
 
     // Only select the first value if it's not multiple
     if (!isMultiple) {
       aEndIndex = aStartIndex;
     }
@@ -999,18 +999,18 @@ HTMLSelectElement::SetOptionsSelectedByI
     // Select the requested indices
     //
     // If index is -1, everything will be deselected (bug 28143)
     if (aStartIndex != -1) {
       MOZ_ASSERT(aStartIndex >= 0);
       MOZ_ASSERT(aEndIndex >= 0);
       // Loop through the options and select them (if they are not disabled and
       // if they are not already selected).
-      for (uint32_t optIndex = SafeCast<uint32_t>(aStartIndex);
-           optIndex <= SafeCast<uint32_t>(aEndIndex);
+      for (uint32_t optIndex = AssertedCast<uint32_t>(aStartIndex);
+           optIndex <= AssertedCast<uint32_t>(aEndIndex);
            optIndex++) {
         nsRefPtr<HTMLOptionElement> option = Item(optIndex);
 
         // Ignore disabled options.
         if (!(aOptionsMask & SET_DISABLED)) {
           if (option && IsOptionDisabled(option)) {
             continue;
           }
@@ -1035,17 +1035,17 @@ HTMLSelectElement::SetOptionsSelectedByI
     }
 
     // Next remove all other options if single select or all is clear
     // If index is -1, everything will be deselected (bug 28143)
     if (((!isMultiple && optionsSelected)
        || ((aOptionsMask & CLEAR_ALL) && !allDisabled)
        || aStartIndex == -1)
        && previousSelectedIndex != -1) {
-      for (uint32_t optIndex = SafeCast<uint32_t>(previousSelectedIndex);
+      for (uint32_t optIndex = AssertedCast<uint32_t>(previousSelectedIndex);
            optIndex < numItems;
            optIndex++) {
         if (static_cast<int32_t>(optIndex) < aStartIndex ||
             static_cast<int32_t>(optIndex) > aEndIndex) {
           HTMLOptionElement* option = Item(optIndex);
           // If the index is already selected, ignore it.
           if (option && option->Selected()) {
             if (!didGetFrame || (selectFrame && !weakSelectFrame.IsAlive())) {
--- a/content/media/gmp/GMPChild.cpp
+++ b/content/media/gmp/GMPChild.cpp
@@ -121,30 +121,84 @@ GetPluginPaths(const std::string& aPlugi
     libFile->GetNativeTarget(aPluginFilePath);
   } else {
     libFile->GetNativePath(aPluginFilePath);
   }
 
   return true;
 }
 
+static bool
+GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath)
+{
+  nsAutoCString appPath;
+  nsAutoCString appBinaryPath(
+    (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
+
+  nsAutoCString::const_iterator start, end;
+  appBinaryPath.BeginReading(start);
+  appBinaryPath.EndReading(end);
+  if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
+    end = start;
+    ++end; ++end; ++end; ++end;
+    appBinaryPath.BeginReading(start);
+    appPath.Assign(Substring(start, end));
+  } else {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> app, appBinary;
+  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
+                                true, getter_AddRefs(app));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
+                       true, getter_AddRefs(appBinary));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  bool isLink;
+  app->IsSymlink(&isLink);
+  if (isLink) {
+    app->GetNativeTarget(aAppPath);
+  } else {
+    app->GetNativePath(aAppPath);
+  }
+  appBinary->IsSymlink(&isLink);
+  if (isLink) {
+    appBinary->GetNativeTarget(aAppBinaryPath);
+  } else {
+    appBinary->GetNativePath(aAppBinaryPath);
+  }
+
+  return true;
+}
+
 void
 GMPChild::OnChannelConnected(int32_t aPid)
 {
   nsAutoCString pluginDirectoryPath, pluginFilePath;
   if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
     MOZ_CRASH("Error scanning plugin path");
   }
+  nsAutoCString appPath, appBinaryPath;
+  if (!GetAppPaths(appPath, appBinaryPath)) {
+    MOZ_CRASH("Error resolving child process path");
+  }
 
   MacSandboxInfo info;
   info.type = MacSandboxType_Plugin;
   info.pluginInfo.type = MacSandboxPluginType_GMPlugin_Default;
   info.pluginInfo.pluginPath.Assign(pluginDirectoryPath);
   mPluginBinaryPath.Assign(pluginFilePath);
   info.pluginInfo.pluginBinaryPath.Assign(pluginFilePath);
+  info.appPath.Assign(appPath);
+  info.appBinaryPath.Assign(appBinaryPath);
 
   nsAutoCString err;
   if (!mozilla::StartMacSandbox(info, err)) {
     NS_WARNING(err.get());
     MOZ_CRASH("sandbox_init() failed");
   }
 
   if (!LoadPluginLibrary(mPluginPath)) {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -872,17 +872,17 @@ nsDocShell::nsDocShell():
 #ifdef DEBUG
   // We're counting the number of |nsDocShells| to help find leaks
   ++gNumberOfDocShells;
   if (!PR_GetEnv("MOZ_QUIET")) {
       printf_stderr("++DOCSHELL %p == %ld [pid = %d] [id = %llu]\n",
                     (void*) this,
                     gNumberOfDocShells,
                     getpid(),
-                    SafeCast<unsigned long long>(mHistoryID));
+                    AssertedCast<unsigned long long>(mHistoryID));
   }
 #endif
 }
 
 nsDocShell::~nsDocShell()
 {
     Destroy();
 
@@ -904,17 +904,17 @@ nsDocShell::~nsDocShell()
 #ifdef DEBUG
     // We're counting the number of |nsDocShells| to help find leaks
     --gNumberOfDocShells;
     if (!PR_GetEnv("MOZ_QUIET")) {
         printf_stderr("--DOCSHELL %p == %ld [pid = %d] [id = %llu]\n",
                       (void*) this,
                       gNumberOfDocShells,
                       getpid(),
-                      SafeCast<unsigned long long>(mHistoryID));
+                      AssertedCast<unsigned long long>(mHistoryID));
     }
 #endif
 }
 
 nsresult
 nsDocShell::Init()
 {
     nsresult rv = nsDocLoader::Init();
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1030,16 +1030,22 @@ class CGHeaders(CGWrapper):
             elif unrolled.isDate():
                 if dictionary or jsImplementedDescriptors:
                     declareIncludes.add("mozilla/dom/Date.h")
                 else:
                     bindingHeaders.add("mozilla/dom/Date.h")
             elif unrolled.isInterface():
                 if unrolled.isSpiderMonkeyInterface():
                     bindingHeaders.add("jsfriendapi.h")
+                    if jsImplementedDescriptors:
+                        # Since we can't forward-declare typed array types
+                        # (because they're typedefs), we have to go ahead and
+                        # just include their header if we need to have functions
+                        # taking references to them declared in that header.
+                        headerSet = declareIncludes
                     headerSet.add("mozilla/dom/TypedArray.h")
                 else:
                     providers = getRelevantProviders(descriptor, config)
                     for p in providers:
                         try:
                             typeDesc = p.getDescriptor(unrolled.inner.identifier.name)
                         except NoSuchDescriptorError:
                             continue
@@ -5480,17 +5486,18 @@ def getWrapTemplateForType(type, descrip
             type.inner, descriptorProvider,
             {
                 'result': "%s[%s]" % (result, index),
                 'successCode': "break;\n",
                 'jsvalRef': "tmp",
                 'jsvalHandle': "&tmp",
                 'returnsNewObject': returnsNewObject,
                 'exceptionCode': exceptionCode,
-                'obj': "returnArray"
+                'obj': "returnArray",
+                'typedArraysAreStructs': typedArraysAreStructs
             })
         sequenceWrapLevel -= 1
         code = fill(
             """
 
             uint32_t length = ${result}.Length();
             JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
             if (!returnArray) {
@@ -5533,17 +5540,18 @@ def getWrapTemplateForType(type, descrip
             type.inner, descriptorProvider,
             {
                 'result': valueName,
                 'successCode': "break;\n",
                 'jsvalRef': "tmp",
                 'jsvalHandle': "&tmp",
                 'returnsNewObject': returnsNewObject,
                 'exceptionCode': exceptionCode,
-                'obj': "returnObj"
+                'obj': "returnObj",
+                'typedArraysAreStructs': typedArraysAreStructs
             })
         mozMapWrapLevel -= 1
         code = fill(
             """
 
             nsTArray<nsString> keys;
             ${result}.GetKeys(keys);
             JS::Rooted<JSObject*> returnObj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
@@ -11804,16 +11812,18 @@ class CGForwardDeclarations(CGWrapper):
                         pass
                 # Find and add the worker implementation, if any.
                 if workerness != 'mainthreadonly':
                     try:
                         desc = config.getDescriptor(name, True)
                         builder.add(desc.nativeType)
                     except NoSuchDescriptorError:
                         pass
+            # Note: Spidermonkey interfaces are typedefs, so can't be
+            # forward-declared
             elif t.isCallback():
                 builder.addInMozillaDom(str(t))
             elif t.isDictionary():
                 builder.addInMozillaDom(t.inner.identifier.name, isStruct=True)
             elif t.isCallbackInterface():
                 builder.addInMozillaDom(t.inner.identifier.name)
             elif t.isUnion():
                 # Forward declare both the owning and non-owning version,
@@ -12010,17 +12020,17 @@ class CGBindingRoot(CGThing):
 
         # Do codegen for JS implemented classes
         def getParentDescriptor(desc):
             if not desc.interface.parent:
                 return set()
             return {desc.getDescriptor(desc.interface.parent.identifier.name)}
         for x in dependencySortObjects(jsImplemented, getParentDescriptor,
                                        lambda d: d.interface.identifier.name):
-            cgthings.append(CGCallbackInterface(x))
+            cgthings.append(CGCallbackInterface(x, typedArraysAreStructs=True))
             cgthings.append(CGJSImplClass(x))
 
         # And make sure we have the right number of newlines at the end
         curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'],
                                  CGWrapper(curr, pre="\n"))
@@ -12068,31 +12078,32 @@ class CGBindingRoot(CGThing):
 
     def deps(self):
         return self.root.deps()
 
 
 class CGNativeMember(ClassMethod):
     def __init__(self, descriptorProvider, member, name, signature, extendedAttrs,
                  breakAfter=True, passJSBitsAsNeeded=True, visibility="public",
-                 jsObjectsArePtr=False, variadicIsSequence=False):
+                 typedArraysAreStructs=True, variadicIsSequence=False):
         """
-        If jsObjectsArePtr is true, typed arrays and "object" will be
-        passed as JSObject*.
+        If typedArraysAreStructs is false, typed arrays will be passed as
+        JS::Handle<JSObject*>.  If it's true they will be passed as one of the
+        dom::TypedArray subclasses.
 
         If passJSBitsAsNeeded is false, we don't automatically pass in a
         JSContext* or a JSObject* based on the return and argument types.  We
         can still pass it based on 'implicitJSContext' annotations.
         """
         self.descriptorProvider = descriptorProvider
         self.member = member
         self.extendedAttrs = extendedAttrs
         self.resultAlreadyAddRefed = isResultAlreadyAddRefed(self.extendedAttrs)
         self.passJSBitsAsNeeded = passJSBitsAsNeeded
-        self.jsObjectsArePtr = jsObjectsArePtr
+        self.typedArraysAreStructs = typedArraysAreStructs
         self.variadicIsSequence = variadicIsSequence
         breakAfterSelf = "\n" if breakAfter else ""
         ClassMethod.__init__(self, name,
                              self.getReturnType(signature[0], False),
                              self.getArgs(signature[0], signature[1]),
                              static=member.isStatic(),
                              # Mark our getters, which are attrs that
                              # have a non-void return type, as const.
@@ -12190,19 +12201,19 @@ class CGNativeMember(ClassMethod):
                 # No need for a third element in the isMember case
                 return "JSObject*", None, None
             return "void", "", "aRetVal.set(${declName});\n"
         if type.isSpiderMonkeyInterface():
             if isMember:
                 # No need for a third element in the isMember case
                 return "JSObject*", None, None
             if type.nullable():
-                returnCode = "${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();\n"
-            else:
-                returnCode = "${declName}.Obj();\n"
+                returnCode = "${declName}.IsNull() ? nullptr : ${declName}.Value().Obj()"
+            else:
+                returnCode = "${declName}.Obj()"
             return "void", "", "aRetVal.set(%s);\n" % returnCode
         if type.isSequence():
             # If we want to handle sequence-of-sequences return values, we're
             # going to need to fix example codegen to not produce nsTArray<void>
             # for the relevant argument...
             assert not isMember
             # Outparam.
             if type.nullable():
@@ -12368,18 +12379,18 @@ class CGNativeMember(ClassMethod):
                         typeDecl = "NonNull<%s>"
                 else:
                     typeDecl = "%s&"
             return ((typeDecl %
                      self.descriptorProvider.getDescriptor(iface.identifier.name).prettyNativeType),
                     False, False)
 
         if type.isSpiderMonkeyInterface():
-            if self.jsObjectsArePtr:
-                return "JSObject*", False, False
+            if not self.typedArraysAreStructs:
+                return "JS::Handle<JSObject*>", False, False
 
             return type.name, True, True
 
         if type.isDOMString() or type.isScalarValueString():
             if isMember:
                 declType = "nsString"
             else:
                 declType = "nsAString"
@@ -12857,23 +12868,21 @@ def jsImplName(name):
 
 class CGJSImplMember(CGNativeMember):
     """
     Base class for generating code for the members of the implementation class
     for a JS-implemented WebIDL interface.
     """
     def __init__(self, descriptorProvider, member, name, signature,
                  extendedAttrs, breakAfter=True, passJSBitsAsNeeded=True,
-                 visibility="public", jsObjectsArePtr=False,
-                 variadicIsSequence=False):
+                 visibility="public", variadicIsSequence=False):
         CGNativeMember.__init__(self, descriptorProvider, member, name,
                                 signature, extendedAttrs, breakAfter=breakAfter,
                                 passJSBitsAsNeeded=passJSBitsAsNeeded,
                                 visibility=visibility,
-                                jsObjectsArePtr=jsObjectsArePtr,
                                 variadicIsSequence=variadicIsSequence)
         self.body = self.getImpl()
 
     def getArgs(self, returnType, argList):
         args = CGNativeMember.getArgs(self, returnType, argList)
         args.append(Argument("JSCompartment*", "aCompartment", "nullptr"))
         return args
 
@@ -13365,26 +13374,27 @@ class CGCallbackFunction(CGCallback):
                 [Argument("CallbackFunction*", "aOther")],
                 bodyInHeader=True,
                 visibility="public",
                 explicit=True,
                 baseConstructors=["CallbackFunction(aOther)"])]
 
 
 class CGCallbackInterface(CGCallback):
-    def __init__(self, descriptor):
+    def __init__(self, descriptor, typedArraysAreStructs=False):
         iface = descriptor.interface
         attrs = [m for m in iface.members if m.isAttr() and not m.isStatic()]
-        getters = [CallbackGetter(a, descriptor) for a in attrs]
-        setters = [CallbackSetter(a, descriptor) for a in attrs
-                   if not a.readonly]
+        getters = [CallbackGetter(a, descriptor, typedArraysAreStructs)
+                   for a in attrs]
+        setters = [CallbackSetter(a, descriptor, typedArraysAreStructs)
+                   for a in attrs if not a.readonly]
         methods = [m for m in iface.members
                    if m.isMethod() and not m.isStatic() and not m.isIdentifierLess()]
-        methods = [CallbackOperation(m, sig, descriptor) for m in methods
-                   for sig in m.signatures()]
+        methods = [CallbackOperation(m, sig, descriptor, typedArraysAreStructs)
+                   for m in methods for sig in m.signatures()]
         if iface.isJSImplemented() and iface.ctor():
             sigs = descriptor.interface.ctor().signatures()
             if len(sigs) != 1:
                 raise TypeError("We only handle one constructor.  See bug 869268.")
             methods.append(CGJSImplInitOperation(sigs[0], descriptor))
         if any(m.isAttr() or m.isMethod() for m in iface.members) or (iface.isJSImplemented() and iface.ctor()):
             methods.append(initIdsClassMethod([descriptor.binaryNameFor(m.identifier.name)
                                                for m in iface.members
@@ -13415,17 +13425,18 @@ class FakeMember():
         # resultNotAddRefed" comments CGNativeMember codegen would
         # otherwise stick in.
         if name == "NewObject":
             return True
         return None
 
 
 class CallbackMember(CGNativeMember):
-    def __init__(self, sig, name, descriptorProvider, needThisHandling, rethrowContentException=False):
+    def __init__(self, sig, name, descriptorProvider, needThisHandling,
+                 rethrowContentException=False, typedArraysAreStructs=False):
         """
         needThisHandling is True if we need to be able to accept a specified
         thisObj, False otherwise.
         """
         assert not rethrowContentException or not needThisHandling
 
         self.retvalType = sig[0]
         self.originalSig = sig
@@ -13447,17 +13458,17 @@ class CallbackMember(CGNativeMember):
         # We don't care, for callback codegen, whether our original member was
         # a method or attribute or whatnot.  Just always pass FakeMember()
         # here.
         CGNativeMember.__init__(self, descriptorProvider, FakeMember(),
                                 name, (self.retvalType, args),
                                 extendedAttrs={},
                                 passJSBitsAsNeeded=False,
                                 visibility=visibility,
-                                jsObjectsArePtr=True)
+                                typedArraysAreStructs=typedArraysAreStructs)
         # We have to do all the generation of our body now, because
         # the caller relies on us throwing if we can't manage it.
         self.exceptionCode = ("aRv.Throw(NS_ERROR_UNEXPECTED);\n"
                               "return%s;\n" % self.getDefaultRetval())
         self.body = self.getImpl()
 
     def getImpl(self):
         setupCall = self.getCallSetup()
@@ -13563,17 +13574,18 @@ class CallbackMember(CGNativeMember):
                     'successCode': "continue;\n" if arg.variadic else "break;\n",
                     'jsvalRef': "argv[%s]" % jsvalIndex,
                     'jsvalHandle': "argv[%s]" % jsvalIndex,
                     # XXXbz we don't have anything better to use for 'obj',
                     # really...  It's OK to use CallbackPreserveColor because
                     # CallSetup already handled the unmark-gray bits for us.
                     'obj': 'CallbackPreserveColor()',
                     'returnsNewObject': False,
-                    'exceptionCode': self.exceptionCode
+                    'exceptionCode': self.exceptionCode,
+                    'typedArraysAreStructs': self.typedArraysAreStructs
                 })
         except MethodNotNewObjectError as err:
             raise TypeError("%s being passed as an argument to %s but is not "
                             "wrapper cached, so can't be reliably converted to "
                             "a JS object." %
                             (err.typename, self.getPrettyName()))
         if arg.variadic:
             conversion = fill(
@@ -13666,19 +13678,20 @@ class CallbackMember(CGNativeMember):
                               "double-quote character.  We can't handle "
                               "that.  %s" %
                               (type, idlObject.identifier.name,
                                idlObject.location))
 
 
 class CallbackMethod(CallbackMember):
     def __init__(self, sig, name, descriptorProvider, needThisHandling,
-                 rethrowContentException=False):
+                 rethrowContentException=False, typedArraysAreStructs=False):
         CallbackMember.__init__(self, sig, name, descriptorProvider,
-                                needThisHandling, rethrowContentException)
+                                needThisHandling, rethrowContentException,
+                                typedArraysAreStructs=typedArraysAreStructs)
 
     def getRvalDecl(self):
         return "JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());\n"
 
     def getCall(self):
         if self.argCount > 0:
             args = "JS::HandleValueArray::subarray(argv, 0, argc)"
         else:
@@ -13725,20 +13738,24 @@ class CallCallback(CallbackMethod):
             return "JS_ObjectIsCallable(cx, mCallback) && "
         return ""
 
 
 class CallbackOperationBase(CallbackMethod):
     """
     Common class for implementing various callback operations.
     """
-    def __init__(self, signature, jsName, nativeName, descriptor, singleOperation, rethrowContentException=False):
+    def __init__(self, signature, jsName, nativeName, descriptor,
+                 singleOperation, rethrowContentException=False,
+                 typedArraysAreStructs=False):
         self.singleOperation = singleOperation
         self.methodName = descriptor.binaryNameFor(jsName)
-        CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation, rethrowContentException)
+        CallbackMethod.__init__(self, signature, nativeName, descriptor,
+                                singleOperation, rethrowContentException,
+                                typedArraysAreStructs=typedArraysAreStructs)
 
     def getThisDecl(self):
         if not self.singleOperation:
             return "JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));\n"
         # This relies on getCallableDecl declaring a boolean
         # isCallable in the case when we're a single-operation
         # interface.
         return dedent("""
@@ -13779,53 +13796,56 @@ class CallbackOperationBase(CallbackMeth
     def getCallGuard(self):
         return ""
 
 
 class CallbackOperation(CallbackOperationBase):
     """
     Codegen actual WebIDL operations on callback interfaces.
     """
-    def __init__(self, method, signature, descriptor):
+    def __init__(self, method, signature, descriptor, typedArraysAreStructs):
         self.ensureASCIIName(method)
         self.method = method
         jsName = method.identifier.name
         CallbackOperationBase.__init__(self, signature,
                                        jsName,
                                        MakeNativeName(descriptor.binaryNameFor(jsName)),
                                        descriptor, descriptor.interface.isSingleOperationInterface(),
-                                       rethrowContentException=descriptor.interface.isJSImplemented())
+                                       rethrowContentException=descriptor.interface.isJSImplemented(),
+                                       typedArraysAreStructs=typedArraysAreStructs)
 
     def getPrettyName(self):
         return "%s.%s" % (self.descriptorProvider.interface.identifier.name,
                           self.method.identifier.name)
 
 
 class CallbackAccessor(CallbackMember):
     """
     Shared superclass for CallbackGetter and CallbackSetter.
     """
-    def __init__(self, attr, sig, name, descriptor):
+    def __init__(self, attr, sig, name, descriptor, typedArraysAreStructs):
         self.ensureASCIIName(attr)
         self.attrName = attr.identifier.name
         CallbackMember.__init__(self, sig, name, descriptor,
                                 needThisHandling=False,
-                                rethrowContentException=descriptor.interface.isJSImplemented())
+                                rethrowContentException=descriptor.interface.isJSImplemented(),
+                                typedArraysAreStructs=typedArraysAreStructs)
 
     def getPrettyName(self):
         return "%s.%s" % (self.descriptorProvider.interface.identifier.name,
                           self.attrName)
 
 
 class CallbackGetter(CallbackAccessor):
-    def __init__(self, attr, descriptor):
+    def __init__(self, attr, descriptor, typedArraysAreStructs):
         CallbackAccessor.__init__(self, attr,
                                   (attr.type, []),
                                   callbackGetterName(attr, descriptor),
-                                  descriptor)
+                                  descriptor,
+                                  typedArraysAreStructs)
 
     def getRvalDecl(self):
         return "JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());\n"
 
     def getCall(self):
         return fill(
             """
             JS::Rooted<JSObject *> callback(cx, mCallback);
@@ -13837,22 +13857,22 @@ class CallbackGetter(CallbackAccessor):
             }
             """,
             atomCacheName=self.descriptorProvider.interface.identifier.name + "Atoms",
             attrAtomName=CGDictionary.makeIdName(self.descriptorProvider.binaryNameFor(self.attrName)),
             errorReturn=self.getDefaultRetval())
 
 
 class CallbackSetter(CallbackAccessor):
-    def __init__(self, attr, descriptor):
+    def __init__(self, attr, descriptor, typedArraysAreStructs):
         CallbackAccessor.__init__(self, attr,
                                   (BuiltinTypes[IDLBuiltinType.Types.void],
                                    [FakeArgument(attr.type, attr)]),
                                   callbackSetterName(attr, descriptor),
-                                  descriptor)
+                                  descriptor, typedArraysAreStructs)
 
     def getRvalDecl(self):
         # We don't need an rval
         return ""
 
     def getCall(self):
         return fill(
             """
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -1002,17 +1002,24 @@ class IDLInterface(IDLObjectWithScope):
                               [attr.location])
 
                     iface = forwardIface
                     attr = fowardAttr
                     putForwards = attr.getExtendedAttribute("PutForwards")
 
         if (self.getExtendedAttribute("Pref") and
             self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
-            raise WebIDLError("[Pref] used on an member that is not %s-only" %
+            raise WebIDLError("[Pref] used on an interface that is not %s-only" %
+                              self.parentScope.primaryGlobalName,
+                              [self.location])
+
+        if (self.getExtendedAttribute("CheckPermissions") and
+            self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
+            raise WebIDLError("[CheckPermissions] used on an interface that is "
+                              "not %s-only" %
                               self.parentScope.primaryGlobalName,
                               [self.location])
 
 
     def isInterface(self):
         return True
 
     def isExternal(self):
@@ -3017,16 +3024,23 @@ class IDLInterfaceMember(IDLObjectWithId
 
     def validate(self):
         if (self.getExtendedAttribute("Pref") and
             self.exposureSet != set([self._scope.primaryGlobalName])):
             raise WebIDLError("[Pref] used on an interface member that is not "
                               "%s-only" % self._scope.primaryGlobalName,
                               [self.location])
 
+        if (self.getExtendedAttribute("CheckPermissions") and
+            self.exposureSet != set([self._scope.primaryGlobalName])):
+            raise WebIDLError("[CheckPermissions] used on an interface member "
+                              "that is not %s-only" %
+                              self._scope.primaryGlobalName,
+                              [self.location])
+
 class IDLConst(IDLInterfaceMember):
     def __init__(self, location, identifier, type, value):
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Const)
 
         assert isinstance(type, IDLType)
         if type.isDictionary():
             raise WebIDLError("A constant cannot be of a dictionary type",
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -456,16 +456,18 @@ public:
   void PassFloat64Array(const Float64Array&);
   void PassSequenceOfArrayBuffers(const Sequence<ArrayBuffer>&);
   void PassSequenceOfNullableArrayBuffers(const Sequence<Nullable<ArrayBuffer> >&);
   void PassMozMapOfArrayBuffers(const MozMap<ArrayBuffer>&);
   void PassMozMapOfNullableArrayBuffers(const MozMap<Nullable<ArrayBuffer> >&);
   void PassVariadicTypedArray(const Sequence<Float32Array>&);
   void PassVariadicNullableTypedArray(const Sequence<Nullable<Float32Array> >&);
   void ReceiveUint8Array(JSContext*, JS::MutableHandle<JSObject*>);
+  void SetUint8ArrayAttr(const Uint8Array&);
+  void GetUint8ArrayAttr(JSContext*, JS::MutableHandle<JSObject*>);
 
   // DOMString types
   void PassString(const nsAString&);
   void PassNullableString(const nsAString&);
   void PassOptionalString(const Optional<nsAString>&);
   void PassOptionalStringWithDefaultValue(const nsAString&);
   void PassOptionalNullableString(const Optional<nsAString>&);
   void PassOptionalNullableStringWithDefaultValue(const nsAString&);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -28,16 +28,37 @@ callback interface TestCallbackInterface
   sequence<TestInterface?> getSequenceOfNullableInterfaces();
   sequence<TestInterface?>? getNullableSequenceOfNullableInterfaces();
   sequence<TestCallbackInterface> getSequenceOfCallbackInterfaces();
   sequence<TestCallbackInterface>? getNullableSequenceOfCallbackInterfaces();
   sequence<TestCallbackInterface?> getSequenceOfNullableCallbackInterfaces();
   sequence<TestCallbackInterface?>? getNullableSequenceOfNullableCallbackInterfaces();
   MozMap<long> getMozMapOfLong();
   Dict? getDictionary();
+  void passArrayBuffer(ArrayBuffer arg);
+  void passNullableArrayBuffer(ArrayBuffer? arg);
+  void passOptionalArrayBuffer(optional ArrayBuffer arg);
+  void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg);
+  void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null);
+  void passArrayBufferView(ArrayBufferView arg);
+  void passInt8Array(Int8Array arg);
+  void passInt16Array(Int16Array arg);
+  void passInt32Array(Int32Array arg);
+  void passUint8Array(Uint8Array arg);
+  void passUint16Array(Uint16Array arg);
+  void passUint32Array(Uint32Array arg);
+  void passUint8ClampedArray(Uint8ClampedArray arg);
+  void passFloat32Array(Float32Array arg);
+  void passFloat64Array(Float64Array arg);
+  void passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg);
+  void passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg);
+  void passVariadicTypedArray(Float32Array... arg);
+  void passVariadicNullableTypedArray(Float32Array?... arg);
+  Uint8Array receiveUint8Array();
+  attribute Uint8Array uint8ArrayAttr;
 };
 
 callback interface TestSingleOperationCallbackInterface {
   TestInterface doSomething(short arg, sequence<double> anotherArg);
 };
 
 enum TestEnum {
   "1",
@@ -415,16 +436,17 @@ interface TestInterface {
   void passFloat64Array(Float64Array arg);
   void passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg);
   void passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg);
   void passMozMapOfArrayBuffers(MozMap<ArrayBuffer> arg);
   void passMozMapOfNullableArrayBuffers(MozMap<ArrayBuffer?> arg);
   void passVariadicTypedArray(Float32Array... arg);
   void passVariadicNullableTypedArray(Float32Array?... arg);
   Uint8Array receiveUint8Array();
+  attribute Uint8Array uint8ArrayAttr;
 
   // DOMString types
   void passString(DOMString arg);
   void passNullableString(DOMString? arg);
   void passOptionalString(optional DOMString arg);
   void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
   void passOptionalNullableString(optional DOMString? arg);
   void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -302,16 +302,17 @@ interface TestExampleInterface {
   void passFloat64Array(Float64Array arg);
   void passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg);
   void passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg);
   void passMozMapOfArrayBuffers(MozMap<ArrayBuffer> arg);
   void passMozMapOfNullableArrayBuffers(MozMap<ArrayBuffer?> arg);
   void passVariadicTypedArray(Float32Array... arg);
   void passVariadicNullableTypedArray(Float32Array?... arg);
   Uint8Array receiveUint8Array();
+  attribute Uint8Array uint8ArrayAttr;
 
   // DOMString types
   void passString(DOMString arg);
   void passNullableString(DOMString? arg);
   void passOptionalString(optional DOMString arg);
   void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
   void passOptionalNullableString(optional DOMString? arg);
   void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -298,43 +298,40 @@ interface TestJSImplInterface {
   MozMap<long> receiveMozMap();
   MozMap<long>? receiveNullableMozMap();
   MozMap<long?> receiveMozMapOfNullableInts();
   MozMap<long?>? receiveNullableMozMapOfNullableInts();
   //XXXbz No support for MozMap of MozMaps return values yet.
   //MozMap<MozMap<long>> receiveMozMapOfMozMaps();
   MozMap<any> receiveAnyMozMap();
 
-  // ArrayBuffer is handled differently in callback interfaces and the example generator.
-  // Need to figure out what should be done there.  Seems like other typed array stuff is
-  // similarly not working in the JS implemented generator.  Probably some other issues
-  // here as well.
   // Typed array types
-  //void passArrayBuffer(ArrayBuffer arg);
-  //void passNullableArrayBuffer(ArrayBuffer? arg);
-  //void passOptionalArrayBuffer(optional ArrayBuffer arg);
-  //void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg);
-  //void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null);
-  //void passArrayBufferView(ArrayBufferView arg);
-  //void passInt8Array(Int8Array arg);
-  //void passInt16Array(Int16Array arg);
-  //void passInt32Array(Int32Array arg);
-  //void passUint8Array(Uint8Array arg);
-  //void passUint16Array(Uint16Array arg);
-  //void passUint32Array(Uint32Array arg);
-  //void passUint8ClampedArray(Uint8ClampedArray arg);
-  //void passFloat32Array(Float32Array arg);
-  //void passFloat64Array(Float64Array arg);
-  //void passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg);
-  //void passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg);
-  //void passMozMapOfArrayBuffers(MozMap<ArrayBuffer> arg);
-  //void passMozMapOfNullableArrayBuffers(MozMap<ArrayBuffer?> arg);
-  //void passVariadicTypedArray(Float32Array... arg);
-  //void passVariadicNullableTypedArray(Float32Array?... arg);
-  //Uint8Array receiveUint8Array();
+  void passArrayBuffer(ArrayBuffer arg);
+  void passNullableArrayBuffer(ArrayBuffer? arg);
+  void passOptionalArrayBuffer(optional ArrayBuffer arg);
+  void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg);
+  void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null);
+  void passArrayBufferView(ArrayBufferView arg);
+  void passInt8Array(Int8Array arg);
+  void passInt16Array(Int16Array arg);
+  void passInt32Array(Int32Array arg);
+  void passUint8Array(Uint8Array arg);
+  void passUint16Array(Uint16Array arg);
+  void passUint32Array(Uint32Array arg);
+  void passUint8ClampedArray(Uint8ClampedArray arg);
+  void passFloat32Array(Float32Array arg);
+  void passFloat64Array(Float64Array arg);
+  void passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg);
+  void passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg);
+  void passMozMapOfArrayBuffers(MozMap<ArrayBuffer> arg);
+  void passMozMapOfNullableArrayBuffers(MozMap<ArrayBuffer?> arg);
+  void passVariadicTypedArray(Float32Array... arg);
+  void passVariadicNullableTypedArray(Float32Array?... arg);
+  Uint8Array receiveUint8Array();
+  attribute Uint8Array uint8ArrayAttr;
 
   // DOMString types
   void passString(DOMString arg);
   void passNullableString(DOMString? arg);
   void passOptionalString(optional DOMString arg);
   void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
   void passOptionalNullableString(optional DOMString? arg);
   void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -76,27 +76,31 @@ let SEC_ERROR_UNTRUSTED_ISSUER = (SEC_ER
 let SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = (SEC_ERROR_BASE + 30);
 let SEC_ERROR_UNTRUSTED_CERT = (SEC_ERROR_BASE + 21);
 let SEC_ERROR_EXPIRED_CERTIFICATE = (SEC_ERROR_BASE + 11);
 let SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = (SEC_ERROR_BASE + 176);
 
 let SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE;
 let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
 
+let MOZILLA_PKIX_ERROR_BASE = Ci.nsINSSErrorsService.MOZILLA_PKIX_ERROR_BASE;
+let MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = (MOZILLA_PKIX_ERROR_BASE + 1);
+
 function getErrorClass(errorCode) {
   let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
 
   switch (NSPRCode) {
     case SEC_ERROR_UNKNOWN_ISSUER:
     case SEC_ERROR_UNTRUSTED_ISSUER:
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
     case SEC_ERROR_UNTRUSTED_CERT:
     case SSL_ERROR_BAD_CERT_DOMAIN:
     case SEC_ERROR_EXPIRED_CERTIFICATE:
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
+    case MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
       return Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT;
     default:
       return Ci.nsINSSErrorsService.ERROR_CLASS_SSL_PROTOCOL;
   }
 
   return null;
 }
 
--- a/dom/canvas/CanvasImageCache.cpp
+++ b/dom/canvas/CanvasImageCache.cpp
@@ -80,55 +80,130 @@ public:
   enum { ALLOW_MEMMOVE = true };
 
   nsAutoPtr<ImageCacheEntryData> mData;
 };
 
 static bool sPrefsInitialized = false;
 static int32_t sCanvasImageCacheLimit = 0;
 
+class ImageCacheObserver;
+
 class ImageCache MOZ_FINAL : public nsExpirationTracker<ImageCacheEntryData,4> {
 public:
   // We use 3 generations of 1 second each to get a 2-3 seconds timeout.
   enum { GENERATION_MS = 1000 };
-  ImageCache()
-    : nsExpirationTracker<ImageCacheEntryData,4>(GENERATION_MS)
-    , mTotal(0)
-  {
-    if (!sPrefsInitialized) {
-      sPrefsInitialized = true;
-      Preferences::AddIntVarCache(&sCanvasImageCacheLimit, "canvas.image.cache.limit", 0);
-    }
-  }
-  ~ImageCache() {
-    AgeAllGenerations();
-  }
+  ImageCache();
+  ~ImageCache();
 
   virtual void NotifyExpired(ImageCacheEntryData* aObject)
   {
     mTotal -= aObject->SizeInBytes();
     RemoveObject(aObject);
     // Deleting the entry will delete aObject since the entry owns aObject
     mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas));
   }
 
   nsTHashtable<ImageCacheEntry> mCache;
   size_t mTotal;
+  nsRefPtr<ImageCacheObserver> mImageCacheObserver;
 };
 
 static ImageCache* gImageCache = nullptr;
 
+// Listen memory-pressure event for image cache purge
+class ImageCacheObserver MOZ_FINAL : public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  ImageCacheObserver(ImageCache* aImageCache)
+    : mImageCache(aImageCache)
+  {
+    RegisterMemoryPressureEvent();
+  }
+
+  void Destroy()
+  {
+    UnregisterMemoryPressureEvent();
+    mImageCache = nullptr;
+  }
+
+  NS_IMETHODIMP Observe(nsISupports* aSubject,
+                        const char* aTopic,
+                        const char16_t* aSomeData)
+  {
+    if (!mImageCache || strcmp(aTopic, "memory-pressure")) {
+      return NS_OK;
+    }
+
+    mImageCache->AgeAllGenerations();
+    return NS_OK;
+  }
+
+private:
+  virtual ~ImageCacheObserver()
+  {
+  }
+
+  void RegisterMemoryPressureEvent()
+  {
+    nsCOMPtr<nsIObserverService> observerService =
+      mozilla::services::GetObserverService();
+
+    MOZ_ASSERT(observerService);
+
+    if (observerService) {
+      observerService->AddObserver(this, "memory-pressure", false);
+    }
+  }
+
+  void UnregisterMemoryPressureEvent()
+  {
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+
+    // Do not assert on observerService here. This might be triggered by
+    // the cycle collector at a late enough time, that XPCOM services are
+    // no longer available. See bug 1029504.
+    if (observerService) {
+        observerService->RemoveObserver(this, "memory-pressure");
+    }
+  }
+
+  ImageCache* mImageCache;
+};
+
+NS_IMPL_ISUPPORTS(ImageCacheObserver, nsIObserver)
+
 class CanvasImageCacheShutdownObserver MOZ_FINAL : public nsIObserver
 {
   ~CanvasImageCacheShutdownObserver() {}
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 };
 
+ImageCache::ImageCache()
+  : nsExpirationTracker<ImageCacheEntryData,4>(GENERATION_MS)
+  , mTotal(0)
+{
+  if (!sPrefsInitialized) {
+    sPrefsInitialized = true;
+    Preferences::AddIntVarCache(&sCanvasImageCacheLimit, "canvas.image.cache.limit", 0);
+  }
+  mImageCacheObserver = new ImageCacheObserver(this);
+  MOZ_RELEASE_ASSERT(mImageCacheObserver, "Can't alloc ImageCacheObserver");
+}
+
+ImageCache::~ImageCache() {
+  AgeAllGenerations();
+  mImageCacheObserver->Destroy();
+}
+
 void
 CanvasImageCache::NotifyDrawImage(Element* aImage,
                                   HTMLCanvasElement* aCanvas,
                                   imgIRequest* aRequest,
                                   SourceSurface* aSource,
                                   const gfxIntSize& aSize)
 {
   if (!gImageCache) {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -86,16 +86,17 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/unused.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
+#include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/dom/TextMetrics.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/SVGMatrix.h"
 #include "nsGlobalWindow.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "SVGContentUtils.h"
 #include "SVGImageContext.h"
@@ -4589,16 +4590,35 @@ CanvasPath::BezierTo(const gfx::Point& a
                      const gfx::Point& aCP2,
                      const gfx::Point& aCP3)
 {
   EnsurePathBuilder();
 
   mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
 }
 
+void
+CanvasPath::AddPath(CanvasPath& aCanvasPath, const Optional<NonNull<SVGMatrix>>& aMatrix)
+{
+  RefPtr<gfx::Path> tempPath = aCanvasPath.GetPath(CanvasWindingRule::Nonzero,
+                                                   gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
+
+  if (aMatrix.WasPassed()) {
+    const SVGMatrix& m = aMatrix.Value();
+    Matrix transform(m.A(), m.B(), m.C(), m.D(), m.E(), m.F());
+
+    if (!transform.IsIdentity()) {
+      RefPtr<PathBuilder> tempBuilder = tempPath->TransformedCopyToBuilder(transform, FillRule::FILL_WINDING);
+      tempPath = tempBuilder->Finish();
+    }
+  }
+
+  tempPath->StreamToSink(mPathBuilder);
+}
+
 TemporaryRef<gfx::Path>
 CanvasPath::GetPath(const CanvasWindingRule& winding, const DrawTarget* aTarget) const
 {
   FillRule fillRule = FillRule::FILL_WINDING;
   if (winding == CanvasWindingRule::Evenodd) {
     fillRule = FillRule::FILL_EVEN_ODD;
   }
 
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -36,16 +36,17 @@ class SurfaceStream;
 }
 
 namespace dom {
 class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
 class ImageData;
 class StringOrCanvasGradientOrCanvasPattern;
 class OwningStringOrCanvasGradientOrCanvasPattern;
 class TextMetrics;
+class SVGMatrix;
 
 extern const mozilla::gfx::Float SIGMA_MAX;
 
 template<typename T> class Optional;
 
 class CanvasPath MOZ_FINAL :
   public nsWrapperCache
 {
@@ -89,16 +90,19 @@ public:
                                   const gfx::DrawTarget* aTarget) const;
 
   explicit CanvasPath(nsISupports* aParent);
   // TemporaryRef arg because the return value from Path::CopyToBuilder() is
   // passed directly and we can't drop the only ref to have a raw pointer.
   CanvasPath(nsISupports* aParent,
              TemporaryRef<gfx::PathBuilder> aPathBuilder);
 
+  void AddPath(CanvasPath& aCanvasPath,
+               const Optional<NonNull<SVGMatrix>>& aMatrix);
+
 private:
   virtual ~CanvasPath() {}
 
   nsCOMPtr<nsISupports> mParent;
   static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
 
   mutable RefPtr<gfx::Path> mPath;
   mutable RefPtr<gfx::PathBuilder> mPathBuilder;
--- a/dom/canvas/test/test_canvas_path.html
+++ b/dom/canvas/test/test_canvas_path.html
@@ -332,60 +332,110 @@ function test_pathconstructor_canvas() {
 
   // copy constructor. This should not crash.
   var p1 = new Path2D();
   var _p2 = new Path2D(p1);
   p1.arcTo(0, 0, 1, 1, 2);
 }
 </script>
 
+<p>Canvas test: test_addpath_canvas</p>
+<canvas id="c8" class="output" width="200" height="200">+
+</canvas>
+<script type="text/javascript">
+
+function test_addpath_canvas() {
+  var c = document.getElementById("c8");
+  var ctx = c.getContext("2d");
+  ctx.beginPath();
+  var p1 = new Path2D();
+  p1.rect(0,0,100,100);
+  var p2 = new Path2D();
+  p2.rect(0,100,100,100);
+  var m = ctx.currentTransform;
+  p1.addPath(p2, m);
+  ctx.fillStyle = 'yellow';
+  ctx.fill(p1);
+  isPixel(ctx, 0, 100, [255, 255, 0, 255], 0);
+
+  ctx.clearRect(0,0,200,200);
+
+  ctx.beginPath();
+  var p3 = new Path2D();
+  p3.rect(0,0,100,100);
+  var p4 = new Path2D();
+  p4.rect(0,100,100,100);
+  var m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix();
+  m.a = 1; m.b = 0;
+  m.c = 0; m.d = 1;
+  m.e = 100; m.f = -100;
+  p3.addPath(p4, m);
+  ctx.fillStyle = 'yellow';
+  ctx.fill(p3);
+  isPixel(ctx, 50, 50, [255, 255, 0, 255], 0);
+  isPixel(ctx, 150, 150, [0, 0, 0, 0], 0);
+
+  var p5 = new Path2D();
+  p5.rect(0,0,100,100);
+  shouldThrow(ctx, "p5.addPath(null, m)");
+  shouldThrow(ctx, "p5.addPath([], m)");
+  shouldThrow(ctx, "p5.addPath({}, m)");
+}
+</script>
+
 <script>
 
 function runTests() {
  try {
   test_drawClipPath_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_drawClipPath_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_drawClipPath_canvas");
  }
  try {
   test_drawFillPath_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_drawFillPath_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_drawFillPath_canvas");
  }
  try {
   test_drawStrokePath_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_drawStrokePath_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_drawStrokePath_canvas");
  }
  try {
   test_large_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_large_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_large_canvas");
  }
  try {
   test_isPointInPath_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_isPointInPath_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_isPointInPath_canvas");
  }
  try {
   test_isPointInStroke_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_isPointInStroke_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_isPointInStroke_canvas");
  }
  try {
   test_pathconstructor_canvas();
  } catch(e) {
+  ok(false, "unexpected exception thrown in: test_pathconstructor_canvas");
   throw e;
-  ok(false, "unexpected exception thrown in: test_pathconstructor_canvas");
+ }
+ try {
+  test_addpath_canvas();
+ } catch(e) {
+  ok(false, "unexpected exception thrown in: test_addpath_canvas");
+  throw e;
  }
  SpecialPowers.setBoolPref("canvas.path.enabled", false);
  SimpleTest.finish();
 }
 
 addLoadEvent(runTests);
 
 // Don't leak the world via the Path2D reference to its window.
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1591,18 +1591,18 @@ EventStateManager::GenerateDragGesture(n
       if (!pixelThresholdY)
         pixelThresholdY = 5;
     }
 
     // fire drag gesture if mouse has moved enough
     LayoutDeviceIntPoint pt = aEvent->refPoint +
       LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
     LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
-    if (Abs(distance.x.value) > SafeCast<uint32_t>(pixelThresholdX) ||
-        Abs(distance.y.value) > SafeCast<uint32_t>(pixelThresholdY)) {
+    if (Abs(distance.x.value) > AssertedCast<uint32_t>(pixelThresholdX) ||
+        Abs(distance.y.value) > AssertedCast<uint32_t>(pixelThresholdY)) {
       if (Prefs::ClickHoldContextMenu()) {
         // stop the click-hold before we fire off the drag gesture, in case
         // it takes a long time
         KillClickHoldTimer();
       }
 
       nsCOMPtr<nsISupports> container = aPresContext->GetContainerWeak();
       nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(container);
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -318,10 +318,12 @@ interface TextMetrics {
 
 };
 
 [Pref="canvas.path.enabled",
  Constructor,
  Constructor(Path2D other),
  Constructor(DOMString pathString)]
 interface Path2D
-{};
+{
+  void addPath(Path2D path, optional SVGMatrix transformation);
+};
 Path2D implements CanvasPathMethods;
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -1684,24 +1684,25 @@ nsEditor::InsertContainerAbove(nsIConten
 ///////////////////////////////////////////////////////////////////////////
 // MoveNode:  move aNode to {aParent,aOffset}
 nsresult
 nsEditor::MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset)
 {
   MOZ_ASSERT(aNode);
   MOZ_ASSERT(aParent);
   MOZ_ASSERT(aOffset == -1 ||
-             (0 <= aOffset && SafeCast<uint32_t>(aOffset) <= aParent->Length()));
+             (0 <= aOffset &&
+              AssertedCast<uint32_t>(aOffset) <= aParent->Length()));
 
   nsCOMPtr<nsINode> oldParent = aNode->GetParentNode();
   int32_t oldOffset = oldParent ? oldParent->IndexOf(aNode) : -1;
 
   if (aOffset == -1) {
     // Magic value meaning "move to end of aParent"
-    aOffset = SafeCast<int32_t>(aParent->Length());
+    aOffset = AssertedCast<int32_t>(aParent->Length());
   }
 
   // Don't do anything if it's already in right place
   if (aParent == oldParent && aOffset == oldOffset) {
     return NS_OK;
   }
 
   // Notify our internal selection state listener
@@ -2865,17 +2866,17 @@ nsEditor::JoinNodesImpl(nsINode* aNodeTo
   }
 
   // delete the extra node
   ErrorResult err;
   aParent->RemoveChild(*aNodeToJoin, err);
 
   if (GetShouldTxnSetSelection()) {
     // editor wants us to set selection at join point
-    selection->Collapse(aNodeToKeep, SafeCast<int32_t>(firstNodeLength));
+    selection->Collapse(aNodeToKeep, AssertedCast<int32_t>(firstNodeLength));
   } else if (selStartNode) {
     // and adjust the selection if needed
     // HACK: this is overly simplified - multi-range selections need more work than this
     bool bNeedToAdjust = false;
 
     // check to see if we joined nodes where selection starts
     if (selStartNode == aNodeToJoin) {
       bNeedToAdjust = true;
--- a/editor/libeditor/nsWSRunObject.cpp
+++ b/editor/libeditor/nsWSRunObject.cpp
@@ -1353,23 +1353,25 @@ nsWSRunObject::DeleteChars(nsINode* aSta
     nsRefPtr<Text> node = mNodeArray[idx];
     if (!node) {
       // We ran out of ws nodes; must have been deleting to end
       return NS_OK;
     }
     if (node == aStartNode) {
       uint32_t len = node->Length();
       if (uint32_t(aStartOffset) < len) {
-        res = mHTMLEditor->DeleteText(*node, SafeCast<uint32_t>(aStartOffset),
+        res = mHTMLEditor->DeleteText(*node,
+                                      AssertedCast<uint32_t>(aStartOffset),
                                       len - aStartOffset);
         NS_ENSURE_SUCCESS(res, res);
       }
     } else if (node == aEndNode) {
       if (aEndOffset) {
-        res = mHTMLEditor->DeleteText(*node, 0, SafeCast<uint32_t>(aEndOffset));
+        res = mHTMLEditor->DeleteText(*node, 0,
+                                      AssertedCast<uint32_t>(aEndOffset));
         NS_ENSURE_SUCCESS(res, res);
       }
       break;
     } else {
       if (!range) {
         range = new nsRange(aStartNode);
         res = range->Set(aStartNode, aStartOffset, aEndNode, aEndOffset);
         NS_ENSURE_SUCCESS(res, res);
--- a/extensions/spellcheck/hunspell/src/mozHunspellAllocator.h
+++ b/extensions/spellcheck/hunspell/src/mozHunspellAllocator.h
@@ -2,15 +2,15 @@
 /* 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 mozHunspellAllocator_h__
 #define mozHunspellAllocator_h__
 
-#include "nsIMemoryReporter.h"
+#include "mozilla/CountingAllocatorBase.h"
 
 class HunspellAllocator : public mozilla::CountingAllocatorBase<HunspellAllocator>
 {
 };
 
 #endif
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -14,51 +14,16 @@
 #include "skia/GrTypes.h"
 #endif
 #include "mozilla/Assertions.h"
 #include <vector>
 
 namespace mozilla {
 namespace gfx {
 
-static inline SkBitmap::Config
-GfxFormatToSkiaConfig(SurfaceFormat format)
-{
-  switch (format)
-  {
-    case SurfaceFormat::B8G8R8A8:
-      return SkBitmap::kARGB_8888_Config;
-    case SurfaceFormat::B8G8R8X8:
-      // We probably need to do something here.
-      return SkBitmap::kARGB_8888_Config;
-    case SurfaceFormat::R5G6B5:
-      return SkBitmap::kRGB_565_Config;
-    case SurfaceFormat::A8:
-      return SkBitmap::kA8_Config;
-    default:
-      return SkBitmap::kARGB_8888_Config;
-  }
-}
-
-static inline SurfaceFormat
-SkiaConfigToGfxFormat(SkBitmap::Config config)
-{
-  switch (config)
-  {
-    case SkBitmap::kARGB_8888_Config:
-      return SurfaceFormat::B8G8R8A8;
-    case SkBitmap::kRGB_565_Config:
-      return SurfaceFormat::R5G6B5;
-    case SkBitmap::kA8_Config:
-      return SurfaceFormat::A8;
-    default:
-      return SurfaceFormat::B8G8R8A8;
-  }
-}
-
 static inline SkColorType
 GfxFormatToSkiaColorType(SurfaceFormat format)
 {
   switch (format)
   {
     case SurfaceFormat::B8G8R8A8:
       return kBGRA_8888_SkColorType;
     case SurfaceFormat::B8G8R8X8:
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point, IntPoint
 #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor, etc
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticFlags::CONTAINER
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
 #include "mozilla/layers/AsyncPanZoomController.h"  // for AsyncPanZoomController
+#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
@@ -81,26 +82,16 @@ GetOpaqueRect(Layer* aLayer)
   const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
   if (clipRect) {
     result.IntersectRect(result, *clipRect);
   }
 
   return result;
 }
 
-static gfx::Point GetScrollData(Layer* aLayer) {
-  gfx::Matrix matrix;
-  if (aLayer->GetLocalTransform().Is2D(&matrix)) {
-    return matrix.GetTranslation();
-  }
-
-  gfx::Point origin;
-  return origin;
-}
-
 static void DrawLayerInfo(const RenderTargetIntRect& aClipRect,
                           LayerManagerComposite* aManager,
                           Layer* aLayer)
 {
 
   if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
     // XXX - should figure out a way to render this, but for now this
     // is hard to do, since it will often get superimposed over the first
@@ -114,38 +105,41 @@ static void DrawLayerInfo(const RenderTa
   nsIntRegion visibleRegion = aLayer->GetVisibleRegion();
 
   uint32_t maxWidth = std::min<uint32_t>(visibleRegion.GetBounds().width, 500);
 
   nsIntPoint topLeft = visibleRegion.GetBounds().TopLeft();
   aManager->GetTextRenderer()->RenderText(ss.str().c_str(), gfx::IntPoint(topLeft.x, topLeft.y),
                                           aLayer->GetEffectiveTransform(), 16,
                                           maxWidth);
-
 }
 
 static void PrintUniformityInfo(Layer* aLayer)
 {
   // Don't want to print a log for smaller layers
   if (aLayer->GetEffectiveVisibleRegion().GetBounds().width < 300 ||
       aLayer->GetEffectiveVisibleRegion().GetBounds().height < 300) {
     return;
   }
 
   FrameMetrics frameMetrics = aLayer->GetFrameMetrics();
   if (!frameMetrics.IsScrollable()) {
     return;
   }
 
-  const LayerPoint scrollOffset = frameMetrics.GetScrollOffsetInLayerPixels();
-  const gfx::Point layerTransform = GetScrollData(aLayer);
-  const gfx::Point layerScroll = scrollOffset.ToUnknownPoint() - layerTransform;
-
-  printf_stderr("UniformityInfo Layer_Move %llu %p %f, %f\n",
-    TimeStamp::Now(), aLayer, layerScroll.x, layerScroll.y);
+  AsyncPanZoomController* apzc = aLayer->GetAsyncPanZoomController();
+  if (apzc) {
+    ViewTransform asyncTransform, overscrollTransform;
+    ScreenPoint scrollOffset;
+    apzc->SampleContentTransformForFrame(&asyncTransform,
+                                         scrollOffset,
+                                         &overscrollTransform);
+    printf_stderr("UniformityInfo Layer_Move %llu %p %f, %f\n",
+          TimeStamp::Now(), aLayer, scrollOffset.x.value, scrollOffset.y.value);
+  }
 }
 
 /* all of the per-layer prepared data we need to maintain */
 struct PreparedLayer
 {
   PreparedLayer(LayerComposite *aLayer, RenderTargetIntRect aClipRect, bool aRestoreVisibleRegion, nsIntRegion &aVisibleRegion) :
     mLayer(aLayer), mClipRect(aClipRect), mRestoreVisibleRegion(aRestoreVisibleRegion), mSavedVisibleRegion(aVisibleRegion) {}
   LayerComposite* mLayer;
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -406,61 +406,97 @@ LayerManagerComposite::RenderDebugOverla
 
   if (drawFrameColorBars || drawFrameCounter) {
     // We intentionally overflow at 2^16.
     sFrameCount++;
   }
 }
 
 RefPtr<CompositingRenderTarget>
-LayerManagerComposite::PushGroup()
+LayerManagerComposite::PushGroupForLayerEffects()
 {
+  // This is currently true, so just making sure that any new use of this
+  // method is flagged for investigation
+  MOZ_ASSERT(gfxPrefs::LayersEffectInvert() ||
+             gfxPrefs::LayersEffectGrayscale() ||
+             gfxPrefs::LayersEffectContrast() != 0.0);
+
   RefPtr<CompositingRenderTarget> previousTarget = mCompositor->GetCurrentRenderTarget();
   // make our render target the same size as the destination target
   // so that we don't have to change size if the drawing area changes.
   IntRect rect(previousTarget->GetOrigin(), previousTarget->GetSize());
   // XXX: I'm not sure if this is true or not...
   MOZ_ASSERT(rect.x == 0 && rect.y == 0);
   if (!mTwoPassTmpTarget ||
       mTwoPassTmpTarget->GetSize() != previousTarget->GetSize() ||
       mTwoPassTmpTarget->GetOrigin() != previousTarget->GetOrigin()) {
     mTwoPassTmpTarget = mCompositor->CreateRenderTarget(rect, INIT_MODE_NONE);
   }
   mCompositor->SetRenderTarget(mTwoPassTmpTarget);
   return previousTarget;
 }
-void LayerManagerComposite::PopGroup(RefPtr<CompositingRenderTarget> aPreviousTarget, nsIntRect aClipRect)
+void
+LayerManagerComposite::PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> aPreviousTarget,
+                                               nsIntRect aClipRect,
+                                               bool aGrayscaleEffect,
+                                               bool aInvertEffect,
+                                               float aContrastEffect)
 {
+  MOZ_ASSERT(mTwoPassTmpTarget);
+
+  // This is currently true, so just making sure that any new use of this
+  // method is flagged for investigation
+  MOZ_ASSERT(aInvertEffect || aGrayscaleEffect || aContrastEffect != 0.0);
+
   mCompositor->SetRenderTarget(aPreviousTarget);
 
   EffectChain effectChain(RootLayer());
-  Matrix5x4 matrix;
-  if (gfxPrefs::Grayscale()) {
-    matrix._11 = matrix._12 = matrix._13 = 0.2126f;
-    matrix._21 = matrix._22 = matrix._23 = 0.7152f;
-    matrix._31 = matrix._32 = matrix._33 = 0.0722f;
+  Matrix5x4 effectMatrix;
+  if (aGrayscaleEffect) {
+    // R' = G' = B' = luminance
+    // R' = 0.2126*R + 0.7152*G + 0.0722*B
+    // G' = 0.2126*R + 0.7152*G + 0.0722*B
+    // B' = 0.2126*R + 0.7152*G + 0.0722*B
+    Matrix5x4 grayscaleMatrix(0.2126f, 0.2126f, 0.2126f, 0,
+                              0.7152f, 0.7152f, 0.7152f, 0,
+                              0.0722f, 0.0722f, 0.0722f, 0,
+                              0,       0,       0,       1,
+                              0,       0,       0,       0);
+    effectMatrix = grayscaleMatrix;
   }
 
-  if (gfxPrefs::Invert()) {
-    matrix._11 = -matrix._11;
-    matrix._12 = -matrix._12;
-    matrix._13 = -matrix._13;
-    matrix._21 = -matrix._21;
-    matrix._22 = -matrix._22;
-    matrix._23 = -matrix._23;
-    matrix._31 = -matrix._31;
-    matrix._32 = -matrix._32;
-    matrix._33 = -matrix._33;
-    matrix._51 = 1;
-    matrix._52 = 1;
-    matrix._53 = 1;
+  if (aInvertEffect) {
+    // R' = 1 - R
+    // G' = 1 - G
+    // B' = 1 - B
+    Matrix5x4 colorInvertMatrix(-1,  0,  0, 0,
+                                 0, -1,  0, 0,
+                                 0,  0, -1, 0,
+                                 0,  0,  0, 1,
+                                 1,  1,  1, 0);
+    effectMatrix = effectMatrix * colorInvertMatrix;
+  }
+
+  if (aContrastEffect != 0.0) {
+    // Multiplying with:
+    // R' = (1 + c) * (R - 0.5) + 0.5
+    // G' = (1 + c) * (G - 0.5) + 0.5
+    // B' = (1 + c) * (B - 0.5) + 0.5
+    float cP1 = aContrastEffect + 1;
+    float hc = 0.5*aContrastEffect;
+    Matrix5x4 contrastMatrix( cP1,   0,   0, 0,
+                                0, cP1,   0, 0,
+                                0,   0, cP1, 0,
+                                0,   0,   0, 1,
+                              -hc, -hc, -hc, 0);
+    effectMatrix = effectMatrix * contrastMatrix;
   }
 
   effectChain.mPrimaryEffect = new EffectRenderTarget(mTwoPassTmpTarget);
-  effectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX] = new EffectColorMatrix(matrix);
+  effectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX] = new EffectColorMatrix(effectMatrix);
 
   gfx::Rect clipRectF(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
   mCompositor->DrawQuad(Rect(Point(0, 0), Size(mTwoPassTmpTarget->GetSize())), clipRectF, effectChain, 1.,
                         Matrix4x4());
 }
 
 void
 LayerManagerComposite::Render()
@@ -468,18 +504,25 @@ LayerManagerComposite::Render()
   PROFILER_LABEL("LayerManagerComposite", "Render",
     js::ProfileEntry::Category::GRAPHICS);
 
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
-  /** Our more efficient but less powerful alter ego, if one is available. */
-  nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
+  // At this time, it doesn't really matter if these preferences change
+  // during the execution of the function; we should be safe in all
+  // permutations. However, may as well just get the values onces and
+  // then use them, just in case the consistency becomes important in
+  // the future.
+  bool invertVal = gfxPrefs::LayersEffectInvert();
+  bool grayscaleVal = gfxPrefs::LayersEffectGrayscale();
+  float contrastVal = gfxPrefs::LayersEffectContrast();
+  bool haveLayerEffects = (invertVal || grayscaleVal || contrastVal != 0.0);
 
   // Set LayerScope begin/end frame
   LayerScopeAutoFrame frame(PR_Now());
 
   // Dump to console
   if (gfxPrefs::LayersDump()) {
     this->Dump();
   }
@@ -489,18 +532,23 @@ LayerManagerComposite::Render()
     // Create a LayersPacket, dump Layers into it and transfer the
     // packet('s ownership) to LayerScope.
     auto packet = MakeUnique<layerscope::Packet>();
     layerscope::LayersPacket* layersPacket = packet->mutable_layers();
     this->Dump(layersPacket);
     LayerScope::SendLayerDump(Move(packet));
   }
 
-  if (gfxPrefs::Invert() || gfxPrefs::Grayscale()) {
-    composer2D = nullptr;
+  /** Our more efficient but less powerful alter ego, if one is available. */
+  nsRefPtr<Composer2D> composer2D;
+
+  // We can't use composert2D if we have layer effects, so only get it
+  // when we don't have any effects.
+  if (!haveLayerEffects) {
+    composer2D = mCompositor->GetWidget()->GetComposer2D();
   }
 
   if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
     if (mFPS) {
       double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
       if (gfxPrefs::LayersDrawFPS()) {
         printf_stderr("HWComposer: FPS is %g\n", fps);
       }
@@ -553,18 +601,18 @@ LayerManagerComposite::Render()
 
   // Allow widget to render a custom background.
   mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x,
                                                                actualBounds.y,
                                                                actualBounds.width,
                                                                actualBounds.height));
 
   RefPtr<CompositingRenderTarget> previousTarget;
-  if (gfxPrefs::Invert() || gfxPrefs::Grayscale()) {
-    previousTarget = PushGroup();
+  if (haveLayerEffects) {
+    previousTarget = PushGroupForLayerEffects();
   } else {
     mTwoPassTmpTarget = nullptr;
   }
 
   // Render our layers.
   RootLayer()->Prepare(RenderTargetPixel::FromUntyped(clipRect));
   RootLayer()->RenderLayer(clipRect);
 
@@ -572,17 +620,19 @@ LayerManagerComposite::Render()
     nsIntRegionRectIterator iter(mRegionToClear);
     const nsIntRect *r;
     while ((r = iter.Next())) {
       mCompositor->ClearRect(Rect(r->x, r->y, r->width, r->height));
     }
   }
 
   if (mTwoPassTmpTarget) {
-    PopGroup(previousTarget, clipRect);
+    MOZ_ASSERT(haveLayerEffects);
+    PopGroupForLayerEffects(previousTarget, clipRect,
+                            grayscaleVal, invertVal, contrastVal);
   }
 
   // Allow widget to render a custom foreground.
   mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
                                                               actualBounds.y,
                                                               actualBounds.width,
                                                               actualBounds.height));
 
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -264,18 +264,22 @@ private:
 
   /**
    * Render debug overlays such as the FPS/FrameCounter above the frame.
    */
   void RenderDebugOverlay(const gfx::Rect& aBounds);
 
   void WorldTransformRect(nsIntRect& aRect);
 
-  RefPtr<CompositingRenderTarget> PushGroup();
-  void PopGroup(RefPtr<CompositingRenderTarget> aPreviousTarget, nsIntRect aClipRect);
+  RefPtr<CompositingRenderTarget> PushGroupForLayerEffects();
+  void PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> aPreviousTarget,
+                               nsIntRect aClipRect,
+                               bool aGrayscaleEffect,
+                               bool aInvertEffect,
+                               float aContrastEffect);
 
   RefPtr<Compositor> mCompositor;
   nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
 
   /**
    * Context target, nullptr when drawing directly to our swap chain.
    */
   RefPtr<gfx::DrawTarget> mTarget;
--- a/gfx/skia/trunk/include/config/SkUserConfig.h
+++ b/gfx/skia/trunk/include/config/SkUserConfig.h
@@ -201,12 +201,11 @@
 #else
 #  define SK_BARRIERS_PLATFORM_H "skia/SkBarriers_x86.h"
 #endif
 
 #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
 
 #define SK_SUPPORT_LEGACY_GETDEVICE
 #define SK_SUPPORT_LEGACY_GETTOPDEVICE
-#define SK_SUPPORT_LEGACY_BITMAP_CONFIG
 #define SK_IGNORE_ETC1_SUPPORT
 
 #endif
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.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 "base/basictypes.h"
 
 #include "gfxAndroidPlatform.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/CountingAllocatorBase.h"
 #include "mozilla/Preferences.h"
 
 #include "gfx2DGlue.h"
 #include "gfxFT2FontList.h"
 #include "gfxImageSurface.h"
 #include "mozilla/dom/ContentChild.h"
 #include "nsXULAppAPI.h"
 #include "nsIScreen.h"
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -217,16 +217,23 @@ private:
   DECL_GFX_PREF(Once, "layers.componentalpha.enabled",         ComponentAlphaEnabled, bool, true);
 #endif
   DECL_GFX_PREF(Live, "layers.draw-bigimage-borders",          DrawBigImageBorders, bool, false);
   DECL_GFX_PREF(Live, "layers.draw-borders",                   DrawLayerBorders, bool, false);
   DECL_GFX_PREF(Live, "layers.draw-tile-borders",              DrawTileBorders, bool, false);
   DECL_GFX_PREF(Live, "layers.flash-borders",                  FlashLayerBorders, bool, false);
   DECL_GFX_PREF(Live, "layers.draw-layer-info",                DrawLayerInfo, bool, false);
   DECL_GFX_PREF(Live, "layers.dump",                           LayersDump, bool, false);
+
+  // 0 is "no change" for contrast, positive values increase it, negative values
+  // decrease it until we hit mid gray at -1 contrast, after that it gets weird.
+  DECL_GFX_PREF(Live, "layers.effect.contrast",                LayersEffectContrast, float, 0.0f);
+  DECL_GFX_PREF(Live, "layers.effect.grayscale",               LayersEffectGrayscale, bool, false);
+  DECL_GFX_PREF(Live, "layers.effect.invert",                  LayersEffectInvert, bool, false);
+
   DECL_GFX_PREF(Once, "layers.enable-tiles",                   LayersTilesEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.simple-tiles",                   LayersUseSimpleTiles, bool, false);
   DECL_GFX_PREF(Once, "layers.force-per-tile-drawing",         PerTileDrawing, bool, false);
   DECL_GFX_PREF(Once, "layers.tiled-drawtarget.enabled",       TiledDrawTargetEnabled, bool, false);
   // We allow for configurable and rectangular tile size to avoid wasting memory on devices whose
   // screen size does not align nicely to the default tile size. Although layers can be any size,
   // they are often the same size as the screen, especially for width.
   DECL_GFX_PREF(Once, "layers.tile-width",                     LayersTileWidth, int32_t, 256);
@@ -244,18 +251,16 @@ private:
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-enabled", LayersOffMainThreadCompositionForceEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.testing.enabled", LayersOffMainThreadCompositionTestingEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces",   UseImageOffscreenSurfaces, bool, false);
   DECL_GFX_PREF(Live, "layers.orientation.sync.timeout",       OrientationSyncMillis, uint32_t, (uint32_t)0);
   DECL_GFX_PREF(Once, "layers.prefer-d3d9",                    LayersPreferD3D9, bool, false);
   DECL_GFX_PREF(Once, "layers.prefer-opengl",                  LayersPreferOpenGL, bool, false);
   DECL_GFX_PREF(Once, "layers.progressive-paint",              UseProgressiveTilePainting, bool, false);
   DECL_GFX_PREF(Once, "layers.uniformity-info",                UniformityInfo, bool, false);
-  DECL_GFX_PREF(Live, "layers.invert",                         Invert, bool, false);
-  DECL_GFX_PREF(Live, "layers.grayscale",                      Grayscale, bool, false);
 
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled",    ScrollBehaviorEnabled, bool, false);
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.spring-constant", ScrollBehaviorSpringConstant, float, 250.0f);
   DECL_GFX_PREF(Once, "layout.css.touch_action.enabled",       TouchActionEnabled, bool, false);
   DECL_GFX_PREF(Once, "layout.frame_rate",                     LayoutFrameRate, int32_t, -1);
   DECL_GFX_PREF(Live, "layout.display-list.dump",              LayoutDumpDisplayList, bool, false);
   DECL_GFX_PREF(Once, "layout.paint_rects_separately",         LayoutPaintRectsSeparately, bool, true);
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -5960,19 +5960,21 @@ GenerateEntry(ModuleCompiler &m, unsigne
 
     // In constrast to the system ABI, the Ion convention is that all registers
     // are clobbered by calls. Thus, we must save the caller's non-volatile
     // registers.
     masm.PushRegsInMask(NonVolatileRegs);
     JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
 
     // ARM and MIPS have a globally-pinned GlobalReg (x64 uses RIP-relative
-    // addressing, x86 uses immediates in effective addresses).
+    // addressing, x86 uses immediates in effective addresses). For the
+    // AsmJSGlobalRegBias addition, see Assembler-(mips,arm).h.
 #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
     masm.movePtr(IntArgReg1, GlobalReg);
+    masm.addPtr(Imm32(AsmJSGlobalRegBias), GlobalReg);
 #endif
 
     // ARM, MIPS and x64 have a globally-pinned HeapReg (x86 uses immediates in
     // effective addresses).
 #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
     masm.loadPtr(Address(IntArgReg1, AsmJSModule::heapGlobalDataOffset()), HeapReg);
 #endif
 
@@ -6249,17 +6251,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
 
     // 2.1. Get ExitDatum
     unsigned globalDataOffset = m.module().exitIndexToGlobalDataOffset(exitIndex);
 #if defined(JS_CODEGEN_X64)
     m.masm().append(AsmJSGlobalAccess(masm.leaRipRelative(callee), globalDataOffset));
 #elif defined(JS_CODEGEN_X86)
     m.masm().append(AsmJSGlobalAccess(masm.movlWithPatch(Imm32(0), callee), globalDataOffset));
 #else
-    masm.computeEffectiveAddress(Address(GlobalReg, globalDataOffset), callee);
+    masm.computeEffectiveAddress(Address(GlobalReg, globalDataOffset - AsmJSGlobalRegBias), callee);
 #endif
 
     // 2.2. Get callee
     masm.loadPtr(Address(callee, offsetof(AsmJSModule::ExitDatum, fun)), callee);
 
     // 2.3. Save callee
     masm.storePtr(callee, Address(StackPointer, argOffset));
     argOffset += sizeof(size_t);
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -22,19 +22,19 @@
 #include "vm/StringBuffer.h"
 #include "vm/TypedArrayObject.h"
 
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 
 #include "vm/Shape-inl.h"
 
+using mozilla::AssertedCast;
 using mozilla::CheckedInt32;
 using mozilla::DebugOnly;
-using mozilla::SafeCast;
 
 using namespace js;
 
 const Class js::TypedObjectModuleObject::class_ = {
     "TypedObject",
     JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject),
     JS_PropertyStub,         /* addProperty */
@@ -1157,26 +1157,26 @@ StructTypeDescr::fieldName(size_t index)
 }
 
 size_t
 StructTypeDescr::fieldOffset(size_t index) const
 {
     JSObject &fieldOffsets =
         getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject();
     JS_ASSERT(index < fieldOffsets.getDenseInitializedLength());
-    return SafeCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
+    return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
 }
 
 size_t
 StructTypeDescr::maybeForwardedFieldOffset(size_t index) const
 {
     JSObject &fieldOffsets =
         *MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject());
     JS_ASSERT(index < fieldOffsets.getDenseInitializedLength());
-    return SafeCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
+    return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
 }
 
 SizedTypeDescr&
 StructTypeDescr::fieldDescr(size_t index) const
 {
     JSObject &fieldDescrs =
         getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject();
     JS_ASSERT(index < fieldDescrs.getDenseInitializedLength());
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -140,16 +140,19 @@ IonContext::~IonContext()
 }
 
 bool
 jit::InitializeIon()
 {
     if (!TlsIonContext.initialized() && !TlsIonContext.init())
         return false;
     CheckLogging();
+#if defined(JS_CODEGEN_ARM)
+    InitARMFlags();
+#endif
     CheckPerf();
     return true;
 }
 
 JitRuntime::JitRuntime()
   : execAlloc_(nullptr),
     ionAlloc_(nullptr),
     exceptionTail_(nullptr),
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -28,19 +28,19 @@
 #include "jsscriptinlines.h"
 
 #include "jit/CompileInfo-inl.h"
 #include "jit/ExecutionMode-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
+using mozilla::AssertedCast;
 using mozilla::DebugOnly;
 using mozilla::Maybe;
-using mozilla::SafeCast;
 
 class jit::BaselineFrameInspector
 {
   public:
     types::Type thisType;
     JSObject *singletonScopeChain;
 
     Vector<types::Type, 4, IonAllocPolicy> argTypes;
@@ -7547,17 +7547,17 @@ IonBuilder::addTypedArrayLengthAndData(M
             // The 'data' pointer can change in rare circumstances
             // (ArrayBufferObject::changeContents).
             types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr);
             if (!tarrType->unknownProperties()) {
                 tarrType->watchStateChangeForTypedArrayData(constraints());
 
                 obj->setImplicitlyUsedUnchecked();
 
-                int32_t len = SafeCast<int32_t>(tarr->length());
+                int32_t len = AssertedCast<int32_t>(tarr->length());
                 *length = MConstant::New(alloc(), Int32Value(len));
                 current->add(*length);
 
                 if (index) {
                     if (checking == DoBoundsCheck)
                         *index = addBoundsCheck(*index, *length);
 
                     *elements = MConstantElements::New(alloc(), data);
--- a/js/src/jit/arm/Architecture-arm.cpp
+++ b/js/src/jit/arm/Architecture-arm.cpp
@@ -11,18 +11,18 @@
 #endif
 
 #include <fcntl.h>
 #include <unistd.h>
 
 #include "jit/arm/Assembler-arm.h"
 #include "jit/RegisterSets.h"
 
-#if defined(ANDROID) || defined(MOZ_B2G) || defined(JS_ARM_SIMULATOR)
-// The Android NDK does not include the hwcap.h kernel header, and it is not
+#if defined(ANDROID) || defined(JS_ARM_SIMULATOR)
+// The Android NDK and B2G do not include the hwcap.h kernel header, and it is not
 // defined when building the simulator, so inline the header defines we need.
 # define HWCAP_VFP        (1 << 6)
 # define HWCAP_NEON       (1 << 12)
 # define HWCAP_VFPv3      (1 << 13)
 # define HWCAP_VFPv3D16   (1 << 14) /* also set for VFPv4-D16 */
 # define HWCAP_VFPv4      (1 << 16)
 # define HWCAP_IDIVA      (1 << 17)
 # define HWCAP_IDIVT      (1 << 18)
@@ -33,30 +33,37 @@
 # if !defined(HWCAP_IDIVA)
 #  define HWCAP_IDIVA     (1 << 17)
 # endif
 # if !defined(HWCAP_VFPD32)
 #  define HWCAP_VFPD32    (1 << 19) /* set if VFP has 32 regs (not 16) */
 # endif
 #endif
 
-// Not part of the HWCAP flag, but we need to know this, and this bit is not
-// used so we are using it.
+// Not part of the HWCAP flag, but we need to know these and these bits are not used.
+
+// A bit to flag the use of the ARMv7 arch, otherwise ARMv6.
 #define HWCAP_ARMv7 (1 << 28)
 
-// Also take a bit to flag the use of the hardfp ABI.
+// A bit to flag the use of the hardfp ABI.
 #define HWCAP_USE_HARDFP_ABI (1 << 27)
 
+// A bit to flag when alignment faults are enabled and signal.
+#define HWCAP_ALIGNMENT_FAULT (1 << 26)
+
+// A bit to flag when the flags are uninitialized, so they can be atomically set.
+#define HWCAP_UNINITIALIZED (1 << 25)
+
 namespace js {
 namespace jit {
 
 
 // Parse the Linux kernel cpuinfo features. This is also used to parse the
-// override features which has some extensions: 'armv7' and 'hardfp'.
-uint32_t
+// override features which has some extensions: 'armv7', 'align' and 'hardfp'.
+static uint32_t
 ParseARMCpuFeatures(const char *features, bool override = false)
 {
     uint32_t flags = 0;
 
     for (;;) {
         char  ch = *features;
         if (!ch) {
             // End of string.
@@ -88,107 +95,138 @@ ParseARMCpuFeatures(const char *features
         else if (count == 5 && strncmp(features, "idiva", 5) == 0)
             flags |= HWCAP_IDIVA;
         else if (count == 5 && strncmp(features, "idivt", 5) == 0)
             flags |= HWCAP_IDIVT;
         else if (count == 6 && strncmp(features, "vfpd32", 6) == 0)
             flags |= HWCAP_VFPD32;
         else if (count == 5 && strncmp(features, "armv7", 5) == 0)
             flags |= HWCAP_ARMv7;
+        else if (count == 5 && strncmp(features, "align", 5) == 0)
+            flags |= HWCAP_ALIGNMENT_FAULT;
 #if defined(JS_ARM_SIMULATOR)
         else if (count == 6 && strncmp(features, "hardfp", 6) == 0)
             flags |= HWCAP_USE_HARDFP_ABI;
 #endif
         else if (override)
             fprintf(stderr, "Warning: unexpected ARM feature at: %s\n", features);
         features = end;
     }
-    IonSpew(IonSpew_Codegen, "ARM features: '%s'\n   flags: 0x%x\n", features, flags);
+    return flags;
+}
+
+static uint32_t
+CanonicalizeARMHwCapFlags(uint32_t flags)
+{
+    // Canonicalize the flags. These rules are also applied to the features
+    // supplied for simulation.
+
+    // The VFPv3 feature is expected when the VFPv3D16 is reported, but add it
+    // just in case of a kernel difference in feature reporting.
+    if (flags & HWCAP_VFPv3D16)
+        flags |= HWCAP_VFPv3;
+
+    // If VFPv3 or Neon is supported then this must be an ARMv7.
+    if (flags & (HWCAP_VFPv3 | HWCAP_NEON))
+        flags |= HWCAP_ARMv7;
+
+    // Some old kernels report VFP and not VFPv3, but if ARMv7 then it must be
+    // VFPv3.
+    if (flags & HWCAP_VFP && flags & HWCAP_ARMv7)
+        flags |= HWCAP_VFPv3;
+
+    // Older kernels do not implement the HWCAP_VFPD32 flag.
+    if ((flags & HWCAP_VFPv3) && !(flags & HWCAP_VFPv3D16))
+        flags |= HWCAP_VFPD32;
+
     return flags;
 }
 
 // The override flags parsed from the ARMHWCAP environment variable or from the
 // --arm-hwcap js shell argument.
-volatile static uint32_t armHwCapFlags = 0;
+volatile static uint32_t armHwCapFlags = HWCAP_UNINITIALIZED;
 
 bool
 ParseARMHwCapFlags(const char *armHwCap)
 {
     uint32_t flags = 0;
 
-    if (!armHwCap || !armHwCap[0])
+    if (!armHwCap)
         return false;
 
-#ifdef JS_CODEGEN_ARM_HARDFP
-    flags |= HWCAP_USE_HARDFP_ABI;
-#endif
-
     if (strstr(armHwCap, "help")) {
         fflush(NULL);
         printf(
                "\n"
                "usage: ARMHWCAP=option,option,option,... where options can be:\n"
                "\n"
-               "  armv7    \n"
                "  vfp      \n"
                "  neon     \n"
                "  vfpv3    \n"
                "  vfpv3d16 \n"
                "  vfpv4    \n"
                "  idiva    \n"
                "  idivt    \n"
                "  vfpd32   \n"
+               "  armv7    \n"
+               "  align    \n"
 #if defined(JS_ARM_SIMULATOR)
                "  hardfp   \n"
 #endif
                "\n"
                );
         exit(0);
         /*NOTREACHED*/
     }
 
-    armHwCapFlags = ParseARMCpuFeatures(armHwCap, /* override = */ true);
+    flags = ParseARMCpuFeatures(armHwCap, /* override = */ true);
+
+#ifdef JS_CODEGEN_ARM_HARDFP
+    flags |= HWCAP_USE_HARDFP_ABI;
+#endif
+
+    armHwCapFlags = CanonicalizeARMHwCapFlags(flags);
+    IonSpew(IonSpew_Codegen, "ARM HWCAP: 0x%x\n", armHwCapFlags);
     return true;
 }
 
-uint32_t GetARMFlags()
+void
+InitARMFlags()
 {
-    volatile static bool isSet = false;
-    volatile static uint32_t flags = 0;
-    if (isSet)
-        return flags;
+    uint32_t flags = 0;
+
+    if (armHwCapFlags != HWCAP_UNINITIALIZED)
+        return;
 
     const char *env = getenv("ARMHWCAP");
-    if (ParseARMHwCapFlags(env) || armHwCapFlags) {
-        flags = armHwCapFlags;
-        isSet = true;
-        return flags;
-    }
+    if (ParseARMHwCapFlags(env))
+        return;
 
 #ifdef JS_ARM_SIMULATOR
     flags = HWCAP_ARMv7 | HWCAP_VFP | HWCAP_VFPv3 | HWCAP_VFPv4 | HWCAP_NEON;
 #else
 
-#if defined(__linux__) || defined(ANDROID) || defined(MOZ_B2G)
+#if defined(__linux__)
+    // This includes Android and B2G.
     bool readAuxv = false;
     int fd = open("/proc/self/auxv", O_RDONLY);
     if (fd > 0) {
         struct { uint32_t a_type; uint32_t a_val; } aux;
         while (read(fd, &aux, sizeof(aux))) {
             if (aux.a_type == AT_HWCAP) {
                 flags = aux.a_val;
                 readAuxv = true;
                 break;
             }
         }
         close(fd);
     }
 
     if (!readAuxv) {
-        // Read the Features if the auxv is not available.
+        // Read the cpuinfo Features if the auxv is not available.
         FILE *fp = fopen("/proc/cpuinfo", "r");
         if (fp) {
             char buf[1024];
             memset(buf, 0, sizeof(buf));
             size_t len = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
             fclose(fp);
             buf[len] = '\0';
             char *featureList = strstr(buf, "Features");
@@ -218,70 +256,73 @@ uint32_t GetARMFlags()
 
 #if defined(__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
     // Compiled to use ARMv7 instructions so assume the ARMv7 arch.
     flags |= HWCAP_ARMv7;
 #endif
 
 #endif // JS_ARM_SIMULATOR
 
-    // Canonicalize the flags. These rules are also applied to the features
-    // supplied for simulation.
+    armHwCapFlags = CanonicalizeARMHwCapFlags(flags);
 
-    // The VFPv3 feature is expected when the VFPv3D16 is reported, but add it
-    // just in case of a kernel difference in feature reporting.
-    if (flags & HWCAP_VFPv3D16)
-        flags |= HWCAP_VFPv3;
-
-    // If VFPv3 or Neon is supported then this must be an ARMv7.
-    if (flags & (HWCAP_VFPv3 | HWCAP_NEON))
-        flags |= HWCAP_ARMv7;
+    IonSpew(IonSpew_Codegen, "ARM HWCAP: 0x%x\n", armHwCapFlags);
+    return;
+}
 
-    // Some old kernels report VFP and not VFPv3, but if ARMv7 then it must be
-    // VFPv3.
-    if (flags & HWCAP_VFP && flags & HWCAP_ARMv7)
-        flags |= HWCAP_VFPv3;
-
-    // Older kernels do not implement the HWCAP_VFPD32 flag.
-    if ((flags & HWCAP_VFPv3) && !(flags & HWCAP_VFPv3D16))
-        flags |= HWCAP_VFPD32;
-
-    IonSpew(IonSpew_Codegen, "ARM HWCAP: 0x%x\n", flags);
-    isSet = true;
-    return flags;
+uint32_t
+GetARMFlags()
+{
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags;
 }
 
 bool HasMOVWT()
 {
-    return GetARMFlags() & HWCAP_ARMv7;
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_ARMv7;
 }
+
 bool HasVFPv3()
 {
-    return GetARMFlags() & HWCAP_VFPv3;
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_VFPv3;
 }
+
 bool HasVFP()
 {
-    return GetARMFlags() & HWCAP_VFP;
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_VFP;
 }
 
 bool Has32DP()
 {
-    return GetARMFlags() & HWCAP_VFPD32;
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_VFPD32;
 }
 
 bool HasIDIV()
 {
-    return GetARMFlags() & HWCAP_IDIVA;
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_IDIVA;
+}
+
+// Returns true when cpu alignment faults are enabled and signaled, and thus we
+// should ensure loads and stores are aligned.
+bool HasAlignmentFault()
+{
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_ALIGNMENT_FAULT;
 }
 
 // This is defined in the header and inlined when not using the simulator.
 #if defined(JS_ARM_SIMULATOR)
 bool UseHardFpABI()
 {
-    return GetARMFlags() & HWCAP_USE_HARDFP_ABI;
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_USE_HARDFP_ABI;
 }
 #endif
 
 Registers::Code
 Registers::FromName(const char *name)
 {
     // Check for some register aliases first.
     if (strcmp(name, "ip") == 0)
--- a/js/src/jit/arm/Architecture-arm.h
+++ b/js/src/jit/arm/Architecture-arm.h
@@ -9,18 +9,18 @@
 
 #include "mozilla/MathAlgorithms.h"
 
 #include <limits.h>
 #include <stdint.h>
 
 #include "js/Utility.h"
 
-// Gcc appears to use __ARM_PCS_VFP to denote that the target is a hard-float
-// target.
+// GCC versions 4.6 and above define __ARM_PCS_VFP to denote a hard-float
+// ABI target.
 #if defined(__ARM_PCS_VFP)
 #define JS_CODEGEN_ARM_HARDFP
 #endif
 
 namespace js {
 namespace jit {
 
 // In bytes: slots needed for potential memory->memory move spills.
@@ -514,16 +514,17 @@ class VFPRegister
 typedef VFPRegister FloatRegister;
 
 uint32_t GetARMFlags();
 bool HasMOVWT();
 bool HasVFPv3();
 bool HasVFP();
 bool Has32DP();
 bool HasIDIV();
+bool HasAlignmentFault();
 
 // Arm/D32 has double registers that can NOT be treated as float32 and this
 // requires some dances in lowering.
 inline bool
 hasUnaliasedDouble()
 {
     return Has32DP();
 }
@@ -532,16 +533,18 @@ hasUnaliasedDouble()
 // a double as a temporary, you need a temporary double register.
 inline bool
 hasMultiAlias()
 {
     return true;
 }
 
 bool ParseARMHwCapFlags(const char *armHwCap);
+void InitARMFlags();
+uint32_t GetARMFlags();
 
 // If the simulator is used then the ABI choice is dynamic. Otherwise the ABI is
 // static and useHardFpABI is inlined so that unused branches can be optimized
 // away.
 #if defined(JS_ARM_SIMULATOR)
 bool UseHardFpABI();
 #else
 static inline bool UseHardFpABI()
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -97,16 +97,21 @@ static MOZ_CONSTEXPR_VAR FloatRegister R
 static MOZ_CONSTEXPR_VAR FloatRegister ReturnDoubleReg = { FloatRegisters::d0, VFPRegister::Double};
 static MOZ_CONSTEXPR_VAR FloatRegister ReturnSimdReg = InvalidFloatReg;
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchFloat32Reg = { FloatRegisters::d30, VFPRegister::Single };
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchDoubleReg = { FloatRegisters::d15, VFPRegister::Double };
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchSimdReg = InvalidFloatReg;
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchUIntReg = { FloatRegisters::d15, VFPRegister::UInt };
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchIntReg = { FloatRegisters::d15, VFPRegister::Int };
 
+// A bias applied to the GlobalReg to allow the use of instructions with small
+// negative immediate offsets which doubles the range of global data that can be
+// accessed with a single instruction.
+static const int32_t AsmJSGlobalRegBias = 1024;
+
 // Registers used in the GenerateFFIIonExit Enable Activation block.
 static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegCallee = r4;
 static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE0 = r0;
 static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE1 = r1;
 static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE2 = r2;
 static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE3 = r3;
 
 // Registers used in the GenerateFFIIonExit Disable Activation block.
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1758,27 +1758,16 @@ CodeGeneratorARM::generateInvalidateEpil
 
 void
 DispatchIonCache::initializeAddCacheState(LInstruction *ins, AddCacheState *addState)
 {
     // Can always use the scratch register on ARM.
     addState->dispatchScratch = ScratchRegister;
 }
 
-template <class U>
-Register
-getBase(U *mir)
-{
-    switch (mir->base()) {
-      case U::Heap: return HeapReg;
-      case U::Global: return GlobalReg;
-    }
-    return InvalidReg;
-}
-
 bool
 CodeGeneratorARM::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins)
 {
     MOZ_ASSUME_UNREACHABLE("NYI");
 }
 
 bool
 CodeGeneratorARM::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins)
@@ -1840,20 +1829,22 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAs
         return true;
     }
 
     BufferOffset bo = masm.ma_BoundsCheck(ptrReg);
     if (isFloat) {
         FloatRegister dst = ToFloatRegister(ins->output());
         VFPRegister vd(dst);
         if (size == 32) {
-            masm.ma_vldr(Operand(GlobalReg, AsmJSNaN32GlobalDataOffset), vd.singleOverlay(), Assembler::AboveOrEqual);
+            masm.ma_vldr(Operand(GlobalReg, AsmJSNaN32GlobalDataOffset - AsmJSGlobalRegBias),
+                         vd.singleOverlay(), Assembler::AboveOrEqual);
             masm.ma_vldr(vd.singleOverlay(), HeapReg, ptrReg, 0, Assembler::Below);
         } else {
-            masm.ma_vldr(Operand(GlobalReg, AsmJSNaN64GlobalDataOffset), vd, Assembler::AboveOrEqual);
+            masm.ma_vldr(Operand(GlobalReg, AsmJSNaN64GlobalDataOffset - AsmJSGlobalRegBias),
+                         vd, Assembler::AboveOrEqual);
             masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Below);
         }
     } else {
         Register d = ToRegister(ins->output());
         masm.ma_mov(Imm32(0), d, NoSetCond, Assembler::AboveOrEqual);
         masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, ptrReg, d, Offset, Assembler::Below);
     }
     masm.append(AsmJSHeapAccess(bo.getOffset()));
@@ -2063,17 +2054,17 @@ CodeGeneratorARM::visitEffectiveAddress(
     masm.ma_add(Imm32(mir->displacement()), output);
     return true;
 }
 
 bool
 CodeGeneratorARM::visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins)
 {
     const MAsmJSLoadGlobalVar *mir = ins->mir();
-    unsigned addr = mir->globalDataOffset();
+    unsigned addr = mir->globalDataOffset() - AsmJSGlobalRegBias;
     if (mir->type() == MIRType_Int32) {
         masm.ma_dtr(IsLoad, GlobalReg, Imm32(addr), ToRegister(ins->output()));
     } else if (mir->type() == MIRType_Float32) {
         VFPRegister vd(ToFloatRegister(ins->output()));
         masm.ma_vldr(Operand(GlobalReg, addr), vd.singleOverlay());
     } else {
         masm.ma_vldr(Operand(GlobalReg, addr), ToFloatRegister(ins->output()));
     }
@@ -2082,17 +2073,17 @@ CodeGeneratorARM::visitAsmJSLoadGlobalVa
 
 bool
 CodeGeneratorARM::visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins)
 {
     const MAsmJSStoreGlobalVar *mir = ins->mir();
 
     MIRType type = mir->value()->type();
     JS_ASSERT(IsNumberType(type));
-    unsigned addr = mir->globalDataOffset();
+    unsigned addr = mir->globalDataOffset() - AsmJSGlobalRegBias;
     if (mir->value()->type() == MIRType_Int32) {
         masm.ma_dtr(IsStore, GlobalReg, Imm32(addr), ToRegister(ins->value()));
     } else if (mir->value()->type() == MIRType_Float32) {
         VFPRegister vd(ToFloatRegister(ins->value()));
         masm.ma_vstr(vd.singleOverlay(), Operand(GlobalReg, addr));
     } else {
         masm.ma_vstr(ToFloatRegister(ins->value()), Operand(GlobalReg, addr));
     }
@@ -2103,29 +2094,30 @@ bool
 CodeGeneratorARM::visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins)
 {
     const MAsmJSLoadFuncPtr *mir = ins->mir();
 
     Register index = ToRegister(ins->index());
     Register tmp = ToRegister(ins->temp());
     Register out = ToRegister(ins->output());
     unsigned addr = mir->globalDataOffset();
-    masm.ma_mov(Imm32(addr), tmp);
+    masm.ma_mov(Imm32(addr - AsmJSGlobalRegBias), tmp);
     masm.as_add(tmp, tmp, lsl(index, 2));
     masm.ma_ldr(DTRAddr(GlobalReg, DtrRegImmShift(tmp, LSL, 0)), out);
 
     return true;
 }
 
 bool
 CodeGeneratorARM::visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins)
 {
     const MAsmJSLoadFFIFunc *mir = ins->mir();
 
-    masm.ma_ldr(Operand(GlobalReg, mir->globalDataOffset()), ToRegister(ins->output()));
+    masm.ma_ldr(Operand(GlobalReg, mir->globalDataOffset() - AsmJSGlobalRegBias),
+                ToRegister(ins->output()));
 
     return true;
 }
 
 bool
 CodeGeneratorARM::visitNegI(LNegI *ins)
 {
     Register input = ToRegister(ins->input());
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1622,17 +1622,17 @@ class MacroAssemblerARMCompat : public M
     }
 
 #ifdef JSGC_GENERATIONAL
     void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label);
     void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label);
 #endif
 
     void loadAsmJSActivation(Register dest) {
-        loadPtr(Address(GlobalReg, AsmJSActivationGlobalDataOffset), dest);
+        loadPtr(Address(GlobalReg, AsmJSActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
     }
 };
 
 typedef MacroAssemblerARMCompat MacroAssemblerSpecific;
 
 } // namespace jit
 } // namespace js
 
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1652,17 +1652,17 @@ const size_t TypedArrayLengthSlot = 1;
  */
 
 #define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
 inline void \
 Get ## Type ## ArrayLengthAndData(JSObject *obj, uint32_t *length, type **data) \
 { \
     JS_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
     const JS::Value &slot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
-    *length = mozilla::SafeCast<uint32_t>(slot.toInt32()); \
+    *length = mozilla::AssertedCast<uint32_t>(slot.toInt32()); \
     *data = static_cast<type*>(GetObjectPrivate(obj)); \
 }
 
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -53,25 +53,25 @@
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::unicode;
 
 using JS::Symbol;
 using JS::SymbolCode;
 
+using mozilla::AssertedCast;
 using mozilla::CheckedInt;
 using mozilla::IsNaN;
 using mozilla::IsNegativeZero;
 using mozilla::IsSame;
 using mozilla::Move;
 using mozilla::PodCopy;
 using mozilla::PodEqual;
 using mozilla::RangedPtr;
-using mozilla::SafeCast;
 using mozilla::UniquePtr;
 
 using JS::AutoCheckCannotGC;
 
 static JSLinearString *
 ArgToRootedString(JSContext *cx, CallArgs &args, unsigned argno)
 {
     if (argno >= args.length())
@@ -235,17 +235,17 @@ template <typename CharT>
 static bool
 Unescape(StringBuffer &sb, const mozilla::Range<const CharT> chars)
 {
     /*
      * NB: use signed integers for length/index to allow simple length
      * comparisons without unsigned-underflow hazards.
      */
     static_assert(JSString::MAX_LENGTH <= INT_MAX, "String length must fit in a signed integer");
-    int length = SafeCast<int>(chars.length());
+    int length = AssertedCast<int>(chars.length());
 
     /*
      * Note that the spec algorithm has been optimized to avoid building
      * a string in the case where no escapes are present.
      */
 
     /* Step 4. */
     int k = 0;
@@ -1009,17 +1009,17 @@ str_normalize(JSContext *cx, unsigned ar
     // Step 8.
     AutoStableStringChars stableChars(cx);
     if (!str->ensureFlat(cx) || !stableChars.initTwoByte(cx, str))
         return false;
 
     static const size_t INLINE_CAPACITY = 32;
 
     const UChar *srcChars = JSCharToUChar(stableChars.twoByteRange().start().get());
-    int32_t srcLen = SafeCast<int32_t>(str->length());
+    int32_t srcLen = AssertedCast<int32_t>(str->length());
     Vector<jschar, INLINE_CAPACITY> chars(cx);
     if (!chars.resize(INLINE_CAPACITY))
         return false;
 
     UErrorCode status = U_ZERO_ERROR;
     int32_t size = unorm_normalize(srcChars, srcLen, form, 0,
                                    JSCharToUChar(chars.begin()), INLINE_CAPACITY,
                                    &status);
--- a/js/src/vm/NumericConversions.h
+++ b/js/src/vm/NumericConversions.h
@@ -47,17 +47,17 @@ ToUintWidth(double d)
         int_fast16_t((bits & mozilla::FloatingPoint<double>::kExponentBits) >> DoubleExponentShift) -
         int_fast16_t(mozilla::FloatingPoint<double>::kExponentBias);
 
     // If the exponent's less than zero, abs(d) < 1, so the result is 0.  (This
     // also handles subnormals.)
     if (exp < 0)
         return 0;
 
-    uint_fast16_t exponent = mozilla::SafeCast<uint_fast16_t>(exp);
+    uint_fast16_t exponent = mozilla::AssertedCast<uint_fast16_t>(exp);
 
     // If the exponent is greater than or equal to the bits of precision of a
     // double plus ResultType's width, the number is either infinite, NaN, or
     // too large to have lower-order bits in the congruent value.  (Example:
     // 2**84 is exactly representable as a double.  The next exact double is
     // 2**84 + 2**32.  Thus if ResultType is int32_t, an exponent >= 84 implies
     // floor(abs(d)) == 0 mod 2**32.)  Return 0 in all these cases.
     const size_t ResultWidth = CHAR_BIT * sizeof(ResultType);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2764,17 +2764,19 @@ JSReporter::CollectReports(WindowPaths *
                               anonymize);
     OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject);
     if (!JS::CollectRuntimeStats(xpcrt->Runtime(), &rtStats, &orphanReporter,
                                  anonymize))
     {
         return NS_ERROR_FAILURE;
     }
 
-    size_t xpconnect = xpcrt->SizeOfIncludingThis(JSMallocSizeOf);
+    size_t xpcJSRuntimeSize = xpcrt->SizeOfIncludingThis(JSMallocSizeOf);
+
+    size_t wrappedJSSize = xpcrt->GetWrappedJSMap()->SizeOfWrappedJS(JSMallocSizeOf);
 
     XPCWrappedNativeScope::ScopeSizeInfo sizeInfo(JSMallocSizeOf);
     XPCWrappedNativeScope::AddSizeOfAllScopesIncludingThis(&sizeInfo);
 
     mozJSComponentLoader* loader = mozJSComponentLoader::Get();
     size_t jsComponentLoaderSize = loader ? loader->SizeOfIncludingThis(JSMallocSizeOf) : 0;
 
     // This is the second step (see above).  First we report stuff in the
@@ -2844,19 +2846,23 @@ JSReporter::CollectReports(WindowPaths *
 
     REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things"),
         KIND_OTHER, rtStats.gcHeapGCThings,
         "GC things: objects, strings, scripts, etc.");
 
     // Report xpconnect.
 
     REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/runtime"),
-        KIND_HEAP, xpconnect,
+        KIND_HEAP, xpcJSRuntimeSize,
         "The XPConnect runtime.");
 
+    REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/wrappedjs"),
+        KIND_HEAP, wrappedJSSize,
+        "Wrappers used to implement XPIDL interfaces with JS.");
+
     REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/scopes"),
         KIND_HEAP, sizeInfo.mScopeAndMapSize,
         "XPConnect scopes.");
 
     REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/proto-iface-cache"),
         KIND_HEAP, sizeInfo.mProtoAndIfaceCacheSize,
         "Prototype and interface binding caches.");
 
--- a/js/xpconnect/src/XPCMaps.cpp
+++ b/js/xpconnect/src/XPCMaps.cpp
@@ -106,16 +106,33 @@ JSObject2WrappedJSMap::ShutdownMarker()
     for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) {
         nsXPCWrappedJS* wrapper = r.front().value();
         MOZ_ASSERT(wrapper, "found a null JS wrapper!");
         MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!");
         wrapper->SystemIsBeingShutDown();
     }
 }
 
+size_t
+JSObject2WrappedJSMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
+{
+    size_t n = mallocSizeOf(this);
+    n += mTable.sizeOfExcludingThis(mallocSizeOf);
+    return n;
+}
+
+size_t
+JSObject2WrappedJSMap::SizeOfWrappedJS(mozilla::MallocSizeOf mallocSizeOf) const
+{
+    size_t n = 0;
+    for (Map::Range r = mTable.all(); !r.empty(); r.popFront())
+        n += r.front().value()->SizeOfIncludingThis(mallocSizeOf);
+    return n;
+}
+
 /***************************************************************************/
 // implement Native2WrappedNativeMap...
 
 // static
 Native2WrappedNativeMap*
 Native2WrappedNativeMap::newMap(int length)
 {
     Native2WrappedNativeMap* map = new Native2WrappedNativeMap(length);
--- a/js/xpconnect/src/XPCMaps.h
+++ b/js/xpconnect/src/XPCMaps.h
@@ -67,21 +67,21 @@ public:
         for (Map::Range r = mTable.all(); !r.empty(); r.popFront())
             r.front().value()->DebugDump(depth);
     }
 
     void FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying);
 
     void ShutdownMarker();
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
-        size_t n = mallocSizeOf(this);
-        n += mTable.sizeOfExcludingThis(mallocSizeOf);
-        return n;
-    }
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
+    // Report the sum of SizeOfIncludingThis() for all wrapped JS in the map.
+    // Each wrapped JS is only in one map.
+    size_t SizeOfWrappedJS(mozilla::MallocSizeOf mallocSizeOf) const;
 
 private:
     JSObject2WrappedJSMap() {}
 
     /*
      * This function is called during minor GCs for each key in the HashMap that
      * has been moved.
      */
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -547,16 +547,35 @@ nsXPCWrappedJS::SystemIsBeingShutDown()
     // at this point.
     *mJSObj.unsafeGet() = nullptr;
 
     // Notify other wrappers in the chain.
     if (mNext)
         mNext->SystemIsBeingShutDown();
 }
 
+size_t
+nsXPCWrappedJS::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
+{
+    // mJSObject is a JS pointer, so don't measure the object.
+    // mClass is not uniquely owned by this WrappedJS. Measure it in IID2WrappedJSClassMap.
+    // mRoot is not measured because it is either |this| or we have already measured it.
+    // mOuter is rare and probably not uniquely owned by this.
+    size_t n = mallocSizeOf(this);
+    n += nsAutoXPTCStub::SizeOfExcludingThis(mallocSizeOf);
+
+    // Wrappers form a linked list via the mNext field, so include them all
+    // in the measurement. Only root wrappers are stored in the map, so
+    // everything will be measured exactly once.
+    if (mNext)
+        n += mNext->SizeOfIncludingThis(mallocSizeOf);
+
+    return n;
+}
+
 /***************************************************************************/
 
 /* readonly attribute nsISimpleEnumerator enumerator; */
 NS_IMETHODIMP
 nsXPCWrappedJS::GetEnumerator(nsISimpleEnumerator * *aEnumerate)
 {
     AutoJSContext cx;
     XPCCallContext ccx(NATIVE_CALLER, cx);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2484,16 +2484,18 @@ public:
             return;
         }
         mRoot->mOuter = aNative;
     }
 
     void TraceJS(JSTracer* trc);
     static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
 
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
     virtual ~nsXPCWrappedJS();
 protected:
     nsXPCWrappedJS();   // not implemented
     nsXPCWrappedJS(JSContext* cx,
                    JSObject* aJSObj,
                    nsXPCWrappedJSClass* aClass,
                    nsXPCWrappedJS* root);
 
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -290,17 +290,27 @@ struct RenderTargetPixel {
  * generally be represented in ScreenPixel units.
  */
 struct ScreenPixel {
   static ScreenIntPoint FromUntyped(const nsIntPoint& aPoint) {
     return ScreenIntPoint(aPoint.x, aPoint.y);
   }
 };
 
-// Operators to apply ScaleFactors directly to Points, Rects, Sizes and Margins
+// Operators to apply ScaleFactors directly to Coords, Points, Rects, Sizes and Margins
+
+template<class src, class dst>
+gfx::CoordTyped<dst> operator*(gfx::CoordTyped<src>& aCoord, const gfx::ScaleFactor<src, dst>& aScale) {
+  return gfx::CoordTyped<dst>(aCoord.value * aScale.scale);
+}
+
+template<class src, class dst>
+gfx::CoordTyped<dst> operator/(gfx::CoordTyped<src>& aCoord, const gfx::ScaleFactor<src, dst>& aScale) {
+  return gfx::CoordTyped<dst>(aCoord.value / aScale.scale);
+}
 
 template<class src, class dst>
 gfx::PointTyped<dst> operator*(const gfx::PointTyped<src>& aPoint, const gfx::ScaleFactor<src, dst>& aScale) {
   return gfx::PointTyped<dst>(aPoint.x * aScale.scale,
                               aPoint.y * aScale.scale);
 }
 
 template<class src, class dst>
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -1073,17 +1073,17 @@ dom::HTMLOptionElement*
 nsListControlFrame::GetCurrentOption()
 {
   // The mEndSelectionIndex is what is currently being selected. Use
   // the selected index if this is kNothingSelected.
   int32_t focusedIndex = (mEndSelectionIndex == kNothingSelected) ?
     GetSelectedIndex() : mEndSelectionIndex;
 
   if (focusedIndex != kNothingSelected) {
-    return GetOption(SafeCast<uint32_t>(focusedIndex));
+    return GetOption(AssertedCast<uint32_t>(focusedIndex));
   }
 
   // There is no selected item. Return the first non-disabled item.
   nsRefPtr<dom::HTMLSelectElement> selectElement =
     dom::HTMLSelectElement::FromContent(mContent);
 
   for (uint32_t i = 0, length = selectElement->Length(); i < length; ++i) {
     dom::HTMLOptionElement* node = selectElement->Item(i);
@@ -1901,17 +1901,17 @@ void
 nsListControlFrame::ScrollToIndex(int32_t aIndex)
 {
   if (aIndex < 0) {
     // XXX shouldn't we just do nothing if we're asked to scroll to
     // kNothingSelected?
     ScrollTo(nsPoint(0, 0), nsIScrollableFrame::INSTANT);
   } else {
     nsRefPtr<dom::HTMLOptionElement> option =
-      GetOption(SafeCast<uint32_t>(aIndex));
+      GetOption(AssertedCast<uint32_t>(aIndex));
     if (option) {
       ScrollToFrame(*option);
     }
   }
 }
 
 void
 nsListControlFrame::ScrollToFrame(dom::HTMLOptionElement& aOptElement)
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-darken-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Darken an HTML Element Using the Brightness Function</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(0, 64, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a dark green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-darken.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Darken an HTML Element Using the Brightness Function</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
+  <link rel="match" href="brightness-darken-ref.html">
+  <meta name="assert"
+        content="Given a factor less than one, the CSS brightness filter
+                 function should darken the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: brightness(0.25);
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a dark green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-extreme-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element Using a Large Factor</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-extreme.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element Using a Large Factor</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
+  <link rel="match" href="brightness-extreme-ref.html">
+  <meta name="assert"
+        content="Given a large factor, the CSS brightness filter function should
+                 completely change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: brightness(1000);
+      background-color: rgb(0, 1, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-one-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-one.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
+  <link rel="match" href="brightness-one-ref.html">
+  <meta name="assert"
+        content="Given a factor of one, the CSS brightness filter function
+                 should not change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: brightness(1);
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-percent-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element Using a Percentage</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-percent.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element Using a Percentage</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
+  <link rel="match" href="brightness-percent-ref.html">
+  <meta name="assert"
+        content="Given a percentage, the CSS brightness filter function should
+                 change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: brightness(400%);
+      background-color: rgb(0, 32, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-zero-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Darken an HTML Element Using the Brightness Function and a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: black;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a black square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness-zero.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Darken an HTML Element Using the Brightness Function and a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
+  <link rel="match" href="brightness-zero-ref.html">
+  <meta name="assert"
+        content="Given a factor of zero, the CSS brightness filter function
+                 should change the color of an HTML element to black.">
+  <style type="text/css">
+    #target {
+      filter: brightness(0);
+      background-color: #f00;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a black square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/brightness.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Brighten an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
+  <link rel="match" href="brightness-ref.html">
+  <meta name="assert"
+        content="The CSS brightness filter function should change the color of
+                 an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: brightness(4);
+      background-color: rgb(0, 32, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-extreme-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Increase the Contrast of an HTML Element Using a Large Factor</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-extreme.html
@@ -0,0 +1,29 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Increase the Contrast of an HTML Element Using a Large Factor</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
+  <link rel="match" href="contrast-extreme-ref.html">
+  <meta name="assert"
+        content="Given a large factor, the CSS contrast filter function should
+                 should change color channel values to be much farther from
+                 their middle value.">
+  <style type="text/css">
+    #target {
+      filter: contrast(1000);
+      background-color: rgb(127, 129, 127); /* 127 should change to 0, and 129 should change to 255. */
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-one-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Set the Contrast of HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-one.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Set the Contrast of HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
+  <link rel="match" href="contrast-one-ref.html">
+  <meta name="assert"
+        content="Given a factor of one, the CSS contrast filter function
+                 should not change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: contrast(1);
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-percent-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Increase the Contrast of an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-percent.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Increase the Contrast of an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
+  <link rel="match" href="contrast-percent-ref.html">
+  <meta name="assert"
+        content="Given a percentage, the CSS contrast filter function should
+                 change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: contrast(200%);
+      background-color: rgb(0, 196, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-reduce-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Reduce the Contrast of an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(64, 191, 64);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-reduce.html
@@ -0,0 +1,29 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Reduce the Contrast of an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
+  <link rel="match" href="contrast-reduce-ref.html">
+  <meta name="assert"
+        content="Given a factor of less than one, the CSS contrast filter
+                 function should change color channel values to be closer to
+                 their middle value.">
+  <style type="text/css">
+    #target {
+      filter: contrast(0.5);
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Increase the Contrast of an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-zero-ref.html
@@ -0,0 +1,23 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Reduce the Contrast of an HTML Element Using a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      filter: contrast(0);
+      background-color: rgb(128, 128, 128);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a gray square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast-zero.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Reduce the Contrast of an HTML Element Using a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
+  <link rel="match" href="contrast-zero-ref.html">
+  <meta name="assert"
+        content="Given a factor of zero, the CSS contrast filter function
+                 should change the color of an HTML element to gray.">
+  <style type="text/css">
+    #target {
+      filter: contrast(0);
+      background-color: rgb(0, 128, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a gray square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/contrast.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Increase the Contrast of an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
+  <link rel="match" href="contrast-ref.html">
+  <meta name="assert"
+        content="The CSS contrast filter function should change the color of
+                 an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: contrast(2);
+      background-color: rgb(0, 196, 0);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a bright green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-half-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor of One Half</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(127, 127, 127);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a gray square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-half.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor of One Half</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-invert">
+  <link rel="match" href="invert-half-ref.html">
+  <meta name="assert"
+        content="Given a factor of one half, the CSS invert filter function
+                 should change the color of an HTML element to gray.">
+  <style type="text/css">
+    #target {
+      filter: invert(0.5);
+      background-color: #f00;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a gray square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-one-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-one.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-invert">
+  <link rel="match" href="invert-one-ref.html">
+  <meta name="assert"
+        content="Given a factor of one, the CSS invert filter function should
+                 completely change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: invert(1);
+      background-color: #f0f;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-over-one-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor Over One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-over-one.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor Over One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-invert">
+  <link rel="match" href="invert-over-one-ref.html">
+  <meta name="assert"
+        content="Given a factor over one, the CSS invert filter function
+                 should completely change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: invert(1000);
+      background-color: #f0f;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-percent-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Percentage</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(63, 191, 63);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-percent.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Percentage</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-invert">
+  <link rel="match" href="invert-percent-ref.html">
+  <meta name="assert"
+        content="Given a percentage, the CSS invert filter function should
+                 change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: invert(75%);
+      background-color: #f0f;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(63, 191, 63);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-zero-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert-zero.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element Using a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-invert">
+  <link rel="match" href="invert-zero-ref.html">
+  <meta name="assert"
+        content="Given a factor of zero, the CSS invert filter function should
+                 not change the color of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: invert(0);
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/invert.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Invert an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-invert">
+  <link rel="match" href="invert-ref.html">
+  <meta name="assert"
+        content="The CSS invert filter function should change the color of an
+                 HTML element.">
+  <style type="text/css">
+    #target {
+      filter: invert(0.75);
+      background-color: #f0f;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-one-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-one.html
@@ -0,0 +1,36 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Factor of One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-opacity">
+  <link rel="match" href="opacity-one-ref.html">
+  <meta name="assert"
+        content="Given a factor of one, the CSS opacity filter function should
+                 not change the opaqueness of an HTML element.">
+  <style type="text/css">
+    #below-target {
+      background-color: #f00;
+      width: 100px;
+      height: 100px;
+    }
+    #target {
+      filter: opacity(1000);
+      background-color: #0f0;
+      position: relative;
+      top: -100px;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="below-target"></div>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-over-one-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Factor Over One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-over-one-translucent-source-ref.html
@@ -0,0 +1,21 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to a Translucent HTML Element Using a Factor Over One</title>
+  <style type="text/css">
+    #target {
+      background-color: rgba(0, 255, 0, 0.25);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a faded green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-over-one-translucent-source.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to a Translucent HTML Element Using a Factor Over One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-opacity">
+  <link rel="match" href="opacity-over-one-translucent-source-ref.html">
+  <meta name="assert"
+        content="Given a factor over one, the CSS opacity filter function should
+                 not change the translucency of an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: opacity(1000);
+      background-color: rgba(0, 255, 0, 0.25);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a faded green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-over-one.html
@@ -0,0 +1,36 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Factor Over One</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-opacity">
+  <link rel="match" href="opacity-over-one-ref.html">
+  <meta name="assert"
+        content="Given a factor over one, the CSS opacity filter function should
+                 not change the opaqueness of an HTML element.">
+  <style type="text/css">
+    #below-target {
+      background-color: #f00;
+      width: 100px;
+      height: 100px;
+    }
+    #target {
+      filter: opacity(1000);
+      background-color: #0f0;
+      position: relative;
+      top: -100px;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="below-target"></div>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-percent-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Percentage</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(192, 255, 192);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a faded green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-percent.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Percentage</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-opacity">
+  <link rel="match" href="opacity-percent-ref.html">
+  <meta name="assert"
+        content="Given a percentage, the CSS opacity filter function should make
+                 an HTML element translucent.">
+  <style type="text/css">
+    #target {
+      filter: opacity(25%);
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a faded green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      background-color: rgb(192, 255, 192);
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a faded green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-zero-ref.html
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #below-target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="below-target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity-zero.html
@@ -0,0 +1,36 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element Using a Factor of Zero</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-opacity">
+  <link rel="match" href="opacity-zero-ref.html">
+  <meta name="assert"
+        content="Given a factor of zero, the CSS opacity filter function should
+                 make an HTML element completely transparent.">
+  <style type="text/css">
+    #below-target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+    #target {
+      filter: opacity(0);
+      background-color: #f00;
+      position: relative;
+      top: -100px;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="below-target"></div>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/opacity.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Apply Opacity to an HTML Element</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-opacity">
+  <link rel="match" href="opacity-ref.html">
+  <meta name="assert"
+        content="The CSS opacity filter function should make an HTML element
+                 translucent.">
+  <style type="text/css">
+    #target {
+      filter: opacity(0.25);
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a faded green square.</p>
+  <div id="target"></div>
+</body>
+</html>
--- a/layout/reftests/svg/filters/css-filters/reftest.list
+++ b/layout/reftests/svg/filters/css-filters/reftest.list
@@ -2,32 +2,56 @@
 # e.g. filter: blur(3px)
 
 default-preferences pref(layout.css.filters.enabled,true)
 
 == blur.html blur-ref.html
 == blur.svg blur-ref.svg
 == blur-zero-radius.html blur-zero-radius-ref.html
 == blur-zoomed-page.html blur-zoomed-page-ref.html
+== brightness.html brightness-ref.html
+== brightness-darken.html brightness-darken-ref.html
+== brightness-extreme.html brightness-extreme-ref.html
+== brightness-one.html brightness-one-ref.html
+== brightness-percent.html brightness-percent-ref.html
+== brightness-zero.html brightness-zero-ref.html
+== contrast.html contrast-ref.html
+== contrast-extreme.html contrast-extreme-ref.html
+== contrast-one.html contrast-one-ref.html
+== contrast-percent.html contrast-percent-ref.html
+== contrast-reduce.html contrast-reduce-ref.html
+== contrast-zero.html contrast-zero-ref.html
 == drop-shadow.html drop-shadow-ref.html
 == drop-shadow-default-color.html drop-shadow-default-color-ref.html
 == drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
 fuzzy-if(d2d,1,10000) == grayscale.html grayscale-ref.html
 fuzzy-if(d2d,1,10000) == grayscale-one.html grayscale-one-ref.html
 fuzzy-if(d2d,1,10000) == grayscale-over-one.html grayscale-over-one-ref.html
 fuzzy-if(d2d,1,10000) == grayscale-percent.html grayscale-percent-ref.html
 == grayscale-zero.html grayscale-zero-ref.html
 == hue-rotate.html hue-rotate-ref.html
 == hue-rotate-360.html hue-rotate-360-ref.html
 == hue-rotate-grad.html hue-rotate-grad-ref.html
 == hue-rotate-negative.html hue-rotate-negative-ref.html
 == hue-rotate-over-360.html hue-rotate-over-360-ref.html
 == hue-rotate-rad.html hue-rotate-rad-ref.html
 == hue-rotate-turn.html hue-rotate-turn-ref.html
 == hue-rotate-zero.html hue-rotate-zero-ref.html
+fuzzy-if(d2d,1,10000) == invert.html invert-ref.html
+== invert-half.html invert-half-ref.html
+== invert-one.html invert-one-ref.html
+== invert-over-one.html invert-over-one-ref.html
+fuzzy-if(d2d,1,10000) == invert-percent.html invert-percent-ref.html
+== invert-zero.html invert-zero-ref.html
+fuzzy-if(d2d,1,10000) == opacity.html opacity-ref.html
+== opacity-one.html opacity-one-ref.html
+== opacity-over-one.html opacity-over-one-ref.html
+== opacity-over-one-translucent-source.html opacity-over-one-translucent-source-ref.html
+fuzzy-if(d2d,1,10000) == opacity-percent.html opacity-percent-ref.html
+== opacity-zero.html opacity-zero-ref.html
 == saturate.html saturate-ref.html
 fuzzy-if(d2d,1,10000) == saturate-desaturate.html saturate-desaturate-ref.html
 == saturate-extreme.html saturate-extreme-ref.html
 == saturate-one.html saturate-one-ref.html
 == saturate-percent.html saturate-percent-ref.html
 fuzzy-if(d2d,1,10000) == saturate-zero.html saturate-zero-ref.html
 fuzzy-if(d2d,1,10000) == sepia.html sepia-ref.html
 fuzzy-if(d2d,1,10000) == sepia-one.html sepia-one-ref.html
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -89,17 +89,17 @@ CSSRuleListImpl::GetParentObject()
 
 uint32_t
 CSSRuleListImpl::Length()
 {
   if (!mStyleSheet) {
     return 0;
   }
 
-  return SafeCast<uint32_t>(mStyleSheet->StyleRuleCount());
+  return AssertedCast<uint32_t>(mStyleSheet->StyleRuleCount());
 }
 
 nsIDOMCSSRule*    
 CSSRuleListImpl::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   aFound = false;
 
   if (mStyleSheet) {
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -13776,16 +13776,17 @@ CSSParserImpl::ParseSingleFilter(nsCSSVa
 
   if (!GetToken(true)) {
     REPORT_UNEXPECTED_EOF(PEFilterEOF);
     return false;
   }
 
   if (mToken.mType != eCSSToken_Function) {
     REPORT_UNEXPECTED_TOKEN(PEExpectedNoneOrURLOrFilterFunction);
+    UngetToken();
     return false;
   }
 
   nsCSSKeyword functionName = nsCSSKeywords::LookupKeyword(mToken.mIdent);
   // Parse drop-shadow independently of the other filter functions
   // because of its more complex characteristics.
   if (functionName == eCSSKeyword_drop_shadow) {
     if (ParseDropShadow(aValue)) {
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -179,17 +179,17 @@ GroupRuleRuleList::GetParentObject()
 
 uint32_t
 GroupRuleRuleList::Length()
 {
   if (!mGroupRule) {
     return 0;
   }
 
-  return SafeCast<uint32_t>(mGroupRule->StyleRuleCount());
+  return AssertedCast<uint32_t>(mGroupRule->StyleRuleCount());
 }
 
 nsIDOMCSSRule*
 GroupRuleRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   aFound = false;
 
   if (mGroupRule) {
--- a/layout/svg/nsCSSFilterInstance.cpp
+++ b/layout/svg/nsCSSFilterInstance.cpp
@@ -46,35 +46,43 @@ nsCSSFilterInstance::BuildPrimitives(nsT
   nsresult result;
 
   switch(mFilter.GetType()) {
     case NS_STYLE_FILTER_BLUR:
       descr = CreatePrimitiveDescription(PrimitiveType::GaussianBlur, aPrimitiveDescrs);
       result = SetAttributesForBlur(descr);
       break;
     case NS_STYLE_FILTER_BRIGHTNESS:
-      return NS_ERROR_NOT_IMPLEMENTED;
+      descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+      result = SetAttributesForBrightness(descr);
+      break;
     case NS_STYLE_FILTER_CONTRAST:
-      return NS_ERROR_NOT_IMPLEMENTED;
+      descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+      result = SetAttributesForContrast(descr);
+      break;
     case NS_STYLE_FILTER_DROP_SHADOW:
       descr = CreatePrimitiveDescription(PrimitiveType::DropShadow, aPrimitiveDescrs);
       result = SetAttributesForDropShadow(descr);
       break;
     case NS_STYLE_FILTER_GRAYSCALE:
       descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
       result = SetAttributesForGrayscale(descr);
       break;
     case NS_STYLE_FILTER_HUE_ROTATE:
       descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
       result = SetAttributesForHueRotate(descr);
       break;
     case NS_STYLE_FILTER_INVERT:
-      return NS_ERROR_NOT_IMPLEMENTED;
+      descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+      result = SetAttributesForInvert(descr);
+      break;
     case NS_STYLE_FILTER_OPACITY:
-      return NS_ERROR_NOT_IMPLEMENTED;
+      descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+      result = SetAttributesForOpacity(descr);
+      break;
     case NS_STYLE_FILTER_SATURATE:
       descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
       result = SetAttributesForSaturate(descr);
       break;
     case NS_STYLE_FILTER_SEPIA:
       descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
       result = SetAttributesForSepia(descr);
       break;
@@ -118,16 +126,67 @@ nsCSSFilterInstance::SetAttributesForBlu
   }
 
   Size radiusInFilterSpace = BlurRadiusToFilterSpace(radiusInFrameSpace.GetCoordValue());
   aDescr.Attributes().Set(eGaussianBlurStdDeviation, radiusInFilterSpace);
   return NS_OK;
 }
 
 nsresult
+nsCSSFilterInstance::SetAttributesForBrightness(FilterPrimitiveDescription& aDescr)
+{
+  const nsStyleCoord& styleValue = mFilter.GetFilterParameter();
+  float value = styleValue.GetFactorOrPercentValue();
+
+  // Set transfer functions for RGB.
+  AttributeMap brightnessAttrs;
+  brightnessAttrs.Set(eComponentTransferFunctionType,
+                      (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_LINEAR);
+  brightnessAttrs.Set(eComponentTransferFunctionSlope, value);
+  brightnessAttrs.Set(eComponentTransferFunctionIntercept, 0.0f);
+  aDescr.Attributes().Set(eComponentTransferFunctionR, brightnessAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionG, brightnessAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionB, brightnessAttrs);
+
+  // Set identity transfer function for A.
+  AttributeMap identityAttrs;
+  identityAttrs.Set(eComponentTransferFunctionType,
+                    (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+  aDescr.Attributes().Set(eComponentTransferFunctionA, identityAttrs);
+
+  return NS_OK;
+}
+
+nsresult
+nsCSSFilterInstance::SetAttributesForContrast(FilterPrimitiveDescription& aDescr)
+{
+  const nsStyleCoord& styleValue = mFilter.GetFilterParameter();
+  float value = styleValue.GetFactorOrPercentValue();
+  float intercept = -(0.5 * value) + 0.5;
+
+  // Set transfer functions for RGB.
+  AttributeMap contrastAttrs;
+  contrastAttrs.Set(eComponentTransferFunctionType,
+                    (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_LINEAR);
+  contrastAttrs.Set(eComponentTransferFunctionSlope, value);
+  contrastAttrs.Set(eComponentTransferFunctionIntercept, intercept);
+  aDescr.Attributes().Set(eComponentTransferFunctionR, contrastAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionG, contrastAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionB, contrastAttrs);
+
+  // Set identity transfer function for A.
+  AttributeMap identityAttrs;
+  identityAttrs.Set(eComponentTransferFunctionType,
+                    (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+  aDescr.Attributes().Set(eComponentTransferFunctionA, identityAttrs);
+
+  return NS_OK;
+}
+
+nsresult
 nsCSSFilterInstance::SetAttributesForDropShadow(FilterPrimitiveDescription& aDescr)
 {
   nsCSSShadowArray* shadows = mFilter.GetDropShadow();
   if (!shadows || shadows->Length() != 1) {
     NS_NOTREACHED("Exactly one drop shadow should have been parsed.");
     return NS_ERROR_FAILURE;
   }
 
@@ -173,16 +232,70 @@ nsCSSFilterInstance::SetAttributesForHue
   const nsStyleCoord& styleValue = mFilter.GetFilterParameter();
   float value = styleValue.GetAngleValueInDegrees();
   aDescr.Attributes().Set(eColorMatrixValues, &value, 1);
 
   return NS_OK;
 }
 
 nsresult
+nsCSSFilterInstance::SetAttributesForInvert(FilterPrimitiveDescription& aDescr)
+{
+  const nsStyleCoord& styleValue = mFilter.GetFilterParameter();
+  float value = ClampFactor(styleValue.GetFactorOrPercentValue());
+
+  // Set transfer functions for RGB.
+  AttributeMap invertAttrs;
+  float invertTableValues[2];
+  invertTableValues[0] = value;
+  invertTableValues[1] = 1 - value;
+  invertAttrs.Set(eComponentTransferFunctionType,
+                  (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_TABLE);
+  invertAttrs.Set(eComponentTransferFunctionTableValues, invertTableValues, 2);
+  aDescr.Attributes().Set(eComponentTransferFunctionR, invertAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionG, invertAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionB, invertAttrs);
+
+  // Set identity transfer function for A.
+  AttributeMap identityAttrs;
+  identityAttrs.Set(eComponentTransferFunctionType,
+                    (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+  aDescr.Attributes().Set(eComponentTransferFunctionA, identityAttrs);
+
+  return NS_OK;
+}
+
+nsresult
+nsCSSFilterInstance::SetAttributesForOpacity(FilterPrimitiveDescription& aDescr)
+{
+  const nsStyleCoord& styleValue = mFilter.GetFilterParameter();
+  float value = ClampFactor(styleValue.GetFactorOrPercentValue());
+
+  // Set identity transfer functions for RGB.
+  AttributeMap identityAttrs;
+  identityAttrs.Set(eComponentTransferFunctionType,
+                    (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+  aDescr.Attributes().Set(eComponentTransferFunctionR, identityAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionG, identityAttrs);
+  aDescr.Attributes().Set(eComponentTransferFunctionB, identityAttrs);
+
+  // Set transfer function for A.
+  AttributeMap opacityAttrs;
+  float opacityTableValues[2];
+  opacityTableValues[0] = 0;
+  opacityTableValues[1] = value;
+  opacityAttrs.Set(eComponentTransferFunctionType,
+                  (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_TABLE);
+  opacityAttrs.Set(eComponentTransferFunctionTableValues, opacityTableValues, 2);
+  aDescr.Attributes().Set(eComponentTransferFunctionA, opacityAttrs);
+
+  return NS_OK;
+}
+
+nsresult
 nsCSSFilterInstance::SetAttributesForSaturate(FilterPrimitiveDescription& aDescr)
 {
   // Set color matrix type.
   aDescr.Attributes().Set(eColorMatrixType, (uint32_t)SVG_FECOLORMATRIX_TYPE_SATURATE);
 
   // Set color matrix values.
   const nsStyleCoord& styleValue = mFilter.GetFilterParameter();
   float value = styleValue.GetFactorOrPercentValue();
--- a/layout/svg/nsCSSFilterInstance.h
+++ b/layout/svg/nsCSSFilterInstance.h
@@ -58,19 +58,23 @@ private:
    */
   FilterPrimitiveDescription CreatePrimitiveDescription(PrimitiveType aType,
                                                         const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs);
 
   /**
    * Sets aDescr's attributes using the style info in mFilter.
    */
   nsresult SetAttributesForBlur(FilterPrimitiveDescription& aDescr);
+  nsresult SetAttributesForBrightness(FilterPrimitiveDescription& aDescr);
+  nsresult SetAttributesForContrast(FilterPrimitiveDescription& aDescr);
   nsresult SetAttributesForDropShadow(FilterPrimitiveDescription& aDescr);
   nsresult SetAttributesForGrayscale(FilterPrimitiveDescription& aDescr);
   nsresult SetAttributesForHueRotate(FilterPrimitiveDescription& aDescr);
+  nsresult SetAttributesForInvert(FilterPrimitiveDescription& aDescr);
+  nsresult SetAttributesForOpacity(FilterPrimitiveDescription& aDescr);
   nsresult SetAttributesForSaturate(FilterPrimitiveDescription& aDescr);
   nsresult SetAttributesForSepia(FilterPrimitiveDescription& aDescr);
 
   /**
    * Returns the index of the last result in the aPrimitiveDescrs, which we'll
    * use as the input to this CSS filter.
    */
   int32_t GetLastResultIndex(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs);
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -513,49 +513,54 @@ int NrSocket::sendto(const void *msg, si
   if(fd_==nullptr)
     ABORT(R_EOD);
 
   if (nr_is_stun_request_message((UCHAR*)msg, len)) {
     // Global rate limiting for stun requests, to mitigate the ice hammer DoS
     // (see http://tools.ietf.org/html/draft-thomson-mmusic-ice-webrtc)
 
     // Tolerate rate of 8k/sec, for one second.
-    static SimpleTokenBucket burst(8192*1, 8192);
+    static SimpleTokenBucket burst(16384*1, 16384);
     // Tolerate rate of 3.6k/sec over twenty seconds.
     static SimpleTokenBucket sustained(3686*20, 3686);
 
     // Check number of tokens in each bucket.
     if (burst.getTokens(UINT32_MAX) < len) {
       r_log(LOG_GENERIC, LOG_ERR,
                  "Short term global rate limit for STUN requests exceeded.");
+#ifdef MOZILLA_INTERNAL_API
+      nr_socket_short_term_violation_time = TimeStamp::Now();
+#endif
+
+// Bug 1013007
+#if !EARLY_BETA_OR_EARLIER
+      ABORT(R_WOULDBLOCK);
+#else
       MOZ_ASSERT(false,
                  "Short term global rate limit for STUN requests exceeded. Go "
                  "bug bcampen@mozilla.com if you weren't intentionally "
                  "spamming ICE candidates, or don't know what that means.");
-#ifdef MOZILLA_INTERNAL_API
-      nr_socket_short_term_violation_time = TimeStamp::Now();
 #endif
-      // TODO(bcampen@mozilla.com): Bug 1013007 Once we have better data on
-      // normal usage, re-enable this.
-      // ABORT(R_WOULDBLOCK);
     }
 
     if (sustained.getTokens(UINT32_MAX) < len) {
       r_log(LOG_GENERIC, LOG_ERR,
                  "Long term global rate limit for STUN requests exceeded.");
+#ifdef MOZILLA_INTERNAL_API
+      nr_socket_long_term_violation_time = TimeStamp::Now();
+#endif
+// Bug 1013007
+#if !EARLY_BETA_OR_EARLIER
+      ABORT(R_WOULDBLOCK);
+#else
       MOZ_ASSERT(false,
                  "Long term global rate limit for STUN requests exceeded. Go "
                  "bug bcampen@mozilla.com if you weren't intentionally "
                  "spamming ICE candidates, or don't know what that means.");
-#ifdef MOZILLA_INTERNAL_API
-      nr_socket_long_term_violation_time = TimeStamp::Now();
 #endif
-      // TODO(bcampen@mozilla.com): Bug 1013007 Once we have better data on
-      // normal usage, re-enable this.
-      // ABORT(R_WOULDBLOCK);
     }
 
     // Take len tokens from both buckets.
     // (not threadsafe, but no problem since this is only called from STS)
     burst.getTokens(len);
     sustained.getTokens(len);
   }
 
--- a/media/webrtc/trunk/webrtc/modules/audio_processing/audio_processing.gypi
+++ b/media/webrtc/trunk/webrtc/modules/audio_processing/audio_processing.gypi
@@ -194,19 +194,20 @@
           '<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
         ],
         'sources': [
           'aecm/aecm_core_neon.c',
           'ns/nsx_core_neon.c',
         ],
         'conditions': [
           ['OS=="android" or OS=="ios"', {
-            'dependencies': [
-              '<(gen_core_neon_offsets_gyp):*',
-            ],
+	    # This also provokes it to try to invoke gypi's in libvpx
+            #'dependencies': [
+            #  '<(gen_core_neon_offsets_gyp):*',
+            #],
 	    #
 	    # We disable the ASM source, because our gyp->Makefile translator
 	    # does not support the build steps to get the asm offsets.
             'sources!': [
               'aecm/aecm_core_neon.S',
               'ns/nsx_core_neon.S',
             ],
             'include_dirs': [
--- a/mfbt/Casting.h
+++ b/mfbt/Casting.h
@@ -205,17 +205,17 @@ IsInBounds(const From aFrom)
 
 /**
  * Cast a value of integral type |From| to a value of integral type |To|,
  * asserting that the cast will be a safe cast per C++ (that is, that |to| is in
  * the range of values permitted for the type |From|).
  */
 template<typename To, typename From>
 inline To
-SafeCast(const From aFrom)
+AssertedCast(const From aFrom)
 {
   MOZ_ASSERT((detail::IsInBounds<From, To>(aFrom)));
   return static_cast<To>(aFrom);
 }
 
 } // namespace mozilla
 
 #endif /* mozilla_Casting_h */
--- a/mfbt/decimal/moz-decimal-utils.h
+++ b/mfbt/decimal/moz-decimal-utils.h
@@ -49,17 +49,17 @@ namespace std {
 
 typedef std::string String;
 
 double mozToDouble(const String &aStr, bool *valid) {
   double_conversion::StringToDoubleConverter converter(
     double_conversion::StringToDoubleConverter::NO_FLAGS,
     mozilla::UnspecifiedNaN<double>(), mozilla::UnspecifiedNaN<double>(), nullptr, nullptr);
   const char* str = aStr.c_str();
-  int length = mozilla::SafeCast<int>(strlen(str));
+  int length = mozilla::AssertedCast<int>(strlen(str));
   int processed_char_count; // unused - NO_FLAGS requires the whole string to parse
   double result = converter.StringToDouble(str, length, &processed_char_count);
   *valid = mozilla::IsFinite(result);
   return result;
 }
 
 String mozToString(double aNum) {
   char buffer[64];
--- a/other-licenses/skia-npapi/SkANP.cpp
+++ b/other-licenses/skia-npapi/SkANP.cpp
@@ -52,52 +52,52 @@ ANPRectF* SkANP::SetRect(ANPRectF* dst, 
     dst->top = SkScalarToFloat(src.fTop);
     dst->right = SkScalarToFloat(src.fRight);
     dst->bottom = SkScalarToFloat(src.fBottom);
     return dst;
 }
 
 SkBitmap* SkANP::SetBitmap(SkBitmap* dst, const ANPBitmap& src) {
     SkColorType colorType = kUnknown_SkColorType;
-    
+
     switch (src.format) {
         case kRGBA_8888_ANPBitmapFormat:
             colorType = kRGBA_8888_SkColorType;
             break;
         case kRGB_565_ANPBitmapFormat:
             colorType = kRGB_565_SkColorType;
             break;
         default:
             break;
     }
-    
+
     SkImageInfo info = SkImageInfo::Make(src.width, src.height, colorType, kPremul_SkAlphaType);
     dst->setInfo(info, src.rowBytes);
     dst->setPixels(src.baseAddr);
     return dst;
 }
 
 bool SkANP::SetBitmap(ANPBitmap* dst, const SkBitmap& src) {
     if (!(dst->baseAddr = src.getPixels())) {
         SkDebugf("SkANP::SetBitmap - getPixels() returned null\n");
         return false;
     }
 
-    switch (src.config()) {
-        case SkBitmap::kARGB_8888_Config:
+    switch (src.colorType()) {
+        case SkColorType::kRGBA_8888_SkColorType:
             dst->format = kRGBA_8888_ANPBitmapFormat;
             break;
-        case SkBitmap::kRGB_565_Config:
+        case SkColorType::kRGB_565_SkColorType:
             dst->format = kRGB_565_ANPBitmapFormat;
             break;
         default:
-            SkDebugf("SkANP::SetBitmap - unsupported src.config %d\n", src.config());
+            SkDebugf("SkANP::SetBitmap - unsupported src.colorType %d\n", src.colorType());
             return false;
     }
-    
+
     dst->width    = src.width();
     dst->height   = src.height();
     dst->rowBytes = src.rowBytes();
     return true;
 }
 
 void SkANP::InitEvent(ANPEvent* event, ANPEventType et) {
     event->inSize = sizeof(ANPEvent);
--- a/rdf/base/nsInMemoryDataSource.cpp
+++ b/rdf/base/nsInMemoryDataSource.cpp
@@ -154,34 +154,34 @@ struct Entry {
 
 
 Assertion::Assertion(nsIRDFResource* aSource)
     : mSource(aSource),
       mNext(nullptr),
       mRefCnt(0),
       mHashEntry(true)
 {
-    MOZ_COUNT_CTOR(RDF_Assertion);
+    MOZ_COUNT_CTOR(Assertion);
 
     NS_ADDREF(mSource);
 
     u.hash.mPropertyHash =
         PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, sizeof(Entry));
 }
 
 Assertion::Assertion(nsIRDFResource* aSource,
                      nsIRDFResource* aProperty,
                      nsIRDFNode* aTarget,
                      bool aTruthValue)
     : mSource(aSource),
       mNext(nullptr),
       mRefCnt(0),
       mHashEntry(false)
 {
-    MOZ_COUNT_CTOR(RDF_Assertion);
+    MOZ_COUNT_CTOR(Assertion);
 
     u.as.mProperty = aProperty;
     u.as.mTarget = aTarget;
 
     NS_ADDREF(mSource);
     NS_ADDREF(u.as.mProperty);
     NS_ADDREF(u.as.mTarget);
 
@@ -194,17 +194,17 @@ Assertion::~Assertion()
 {
     if (mHashEntry && u.hash.mPropertyHash) {
         PL_DHashTableEnumerate(u.hash.mPropertyHash, DeletePropertyHashEntry,
                                nullptr);
         PL_DHashTableDestroy(u.hash.mPropertyHash);
         u.hash.mPropertyHash = nullptr;
     }
 
-    MOZ_COUNT_DTOR(RDF_Assertion);
+    MOZ_COUNT_DTOR(Assertion);
 #ifdef DEBUG_REFS
     --gInstanceCount;
     fprintf(stdout, "%d - RDF: Assertion\n", gInstanceCount);
 #endif
 
     NS_RELEASE(mSource);
     if (!mHashEntry)
     {
--- a/security/manager/ssl/src/NSSErrorsService.cpp
+++ b/security/manager/ssl/src/NSSErrorsService.cpp
@@ -136,16 +136,17 @@ NSSErrorsService::GetErrorClass(nsresult
     // Overridable errors.
     case SEC_ERROR_UNKNOWN_ISSUER:
     case SEC_ERROR_UNTRUSTED_ISSUER:
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
     case SEC_ERROR_UNTRUSTED_CERT:
     case SSL_ERROR_BAD_CERT_DOMAIN:
     case SEC_ERROR_EXPIRED_CERTIFICATE:
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
+    case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
       *aErrorClass = ERROR_CLASS_BAD_CERT;
       break;
     // Non-overridable errors.
     default:
       *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
       break;
   }
   return NS_OK;
--- a/security/manager/ssl/src/PSMContentListener.cpp
+++ b/security/manager/ssl/src/PSMContentListener.cpp
@@ -89,17 +89,17 @@ PSMContentDownloader::OnStartRequest(nsI
   rv = channel->GetContentLength(&contentLength);
   if (NS_FAILED(rv) || contentLength <= 0)
     contentLength = kDefaultCertAllocLength;
   if (contentLength > INT32_MAX)
     return NS_ERROR_OUT_OF_MEMORY;
   
   mBufferOffset = 0;
   mBufferSize = 0;
-  mByteData = (char*) nsMemory::Alloc(SafeCast<size_t>(contentLength));
+  mByteData = (char*)nsMemory::Alloc(AssertedCast<size_t>(contentLength));
   if (!mByteData)
     return NS_ERROR_OUT_OF_MEMORY;
   
   mBufferSize = int32_t(contentLength);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -92,16 +92,17 @@
 // we need the event to interrupt the PR_Poll that may waiting for I/O on the
 // socket for which we are validating the cert.
 
 #include "SSLServerCertVerification.h"
 
 #include <cstring>
 
 #include "pkix/pkixtypes.h"
+#include "pkix/pkixnss.h"
 #include "CertVerifier.h"
 #include "CryptoTask.h"
 #include "ExtendedValidation.h"
 #include "NSSCertDBTrustDomain.h"
 #include "nsIBadCertListener2.h"
 #include "nsICertOverrideService.h"
 #include "nsISiteSecurityService.h"
 #include "nsNSSComponent.h"
@@ -295,19 +296,20 @@ MapCertErrorToProbeValue(PRErrorCode err
     case SEC_ERROR_UNKNOWN_ISSUER:                     return  2;
     case SEC_ERROR_UNTRUSTED_ISSUER:                   return  4;
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:         return  5;
     case SEC_ERROR_UNTRUSTED_CERT:                     return  6;
     case SEC_ERROR_INADEQUATE_KEY_USAGE:               return  7;
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:  return  8;
     case SSL_ERROR_BAD_CERT_DOMAIN:                    return  9;
     case SEC_ERROR_EXPIRED_CERTIFICATE:                return 10;
+    case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: return 11;
   }
   NS_WARNING("Unknown certificate error code. Does MapCertErrorToProbeValue "
-             "handle everything in PRErrorCodeToOverrideType?");
+             "handle everything in DetermineCertOverrideErrors?");
   return 0;
 }
 
 SECStatus
 DetermineCertOverrideErrors(CERTCertificate* cert, const char* hostName,
                             PRTime now, PRErrorCode defaultErrorCodeToReport,
                             /*out*/ uint32_t& collectedErrors,
                             /*out*/ PRErrorCode& errorCodeTrust,
@@ -323,16 +325,17 @@ DetermineCertOverrideErrors(CERTCertific
 
   // Assumes the error prioritization described in mozilla::pkix's
   // BuildForward function. Also assumes that CERT_VerifyCertName was only
   // called if CertVerifier::VerifyCert succeeded.
   switch (defaultErrorCodeToReport) {
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
     case SEC_ERROR_UNKNOWN_ISSUER:
+    case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
     {
       collectedErrors = nsICertOverrideService::ERROR_UNTRUSTED;
       errorCodeTrust = defaultErrorCodeToReport;
 
       SECCertTimeValidity validity = CERT_CheckCertValidTimes(cert, now, false);
       if (validity == secCertTimeUndetermined) {
         PR_SetError(defaultErrorCodeToReport, 0);
         return SECFailure;
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -633,17 +633,17 @@ nsNSSSocketInfo::SetCertVerificationResu
   }
 
   if (errorCode) {
     SetCanceled(errorCode, errorMessageType);
   }
 
   if (mPlaintextBytesRead && !errorCode) {
     Telemetry::Accumulate(Telemetry::SSL_BYTES_BEFORE_CERT_CALLBACK,
-                          SafeCast<uint32_t>(mPlaintextBytesRead));
+                          AssertedCast<uint32_t>(mPlaintextBytesRead));
   }
 
   mCertVerificationState = after_cert_verification;
 }
 
 SharedSSLState&
 nsNSSSocketInfo::SharedState()
 {
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -55,16 +55,17 @@ const SEC_ERROR_POLICY_VALIDATION_FAILED
 const SEC_ERROR_OCSP_BAD_SIGNATURE                      = SEC_ERROR_BASE + 157;
 const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED       = SEC_ERROR_BASE + 176;
 const SEC_ERROR_APPLICATION_CALLBACK_ERROR              = SEC_ERROR_BASE + 178;
 
 const SSL_ERROR_BAD_CERT_DOMAIN                         = SSL_ERROR_BASE +  12;
 const SSL_ERROR_BAD_CERT_ALERT                          = SSL_ERROR_BASE +  17;
 
 const MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE            = MOZILLA_PKIX_ERROR_BASE +   0;
+const MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY     = MOZILLA_PKIX_ERROR_BASE +   1;
 const MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE            = MOZILLA_PKIX_ERROR_BASE +   2; // -16382
 
 // Supported Certificate Usages
 const certificateUsageSSLClient              = 0x0001;
 const certificateUsageSSLServer              = 0x0002;
 const certificateUsageSSLCA                  = 0x0008;
 const certificateUsageEmailSigner            = 0x0010;
 const certificateUsageEmailRecipient         = 0x0020;
--- a/security/manager/ssl/tests/unit/test_cert_overrides.js
+++ b/security/manager/ssl/tests/unit/test_cert_overrides.js
@@ -54,18 +54,19 @@ function check_telemetry() {
   do_check_eq(histogram.counts[ 0], 0);
   do_check_eq(histogram.counts[ 2], 7); // SEC_ERROR_UNKNOWN_ISSUER
   do_check_eq(histogram.counts[ 3], 0); // SEC_ERROR_CA_CERT_INVALID
   do_check_eq(histogram.counts[ 4], 0); // SEC_ERROR_UNTRUSTED_ISSUER
   do_check_eq(histogram.counts[ 5], 1); // SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
   do_check_eq(histogram.counts[ 6], 0); // SEC_ERROR_UNTRUSTED_CERT
   do_check_eq(histogram.counts[ 7], 0); // SEC_ERROR_INADEQUATE_KEY_USAGE
   do_check_eq(histogram.counts[ 8], 2); // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
-  do_check_eq(histogram.counts[ 9], 4); // SSL_ERROR_BAD_CERT_DOMAIN
+  do_check_eq(histogram.counts[ 9], 5); // SSL_ERROR_BAD_CERT_DOMAIN
   do_check_eq(histogram.counts[10], 5); // SEC_ERROR_EXPIRED_CERTIFICATE
+  do_check_eq(histogram.counts[11], 2); // MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY
   run_next_test();
 }
 
 function run_test() {
   add_tls_server_setup("BadCertServer");
 
   let fakeOCSPResponder = new HttpServer();
   fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
@@ -116,16 +117,20 @@ function add_simple_tests() {
                            SEC_ERROR_INADEQUATE_KEY_USAGE);
 
   // Bug 990603: Apache documentation has recommended generating a self-signed
   // test certificate with basic constraints: CA:true. For compatibility, this
   // is a scenario in which an override is allowed.
   add_cert_override_test("self-signed-end-entity-with-cA-true.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
+
+  add_cert_override_test("ca-used-as-end-entity.example.com",
+                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                         getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY));
 }
 
 function add_combo_tests() {
   add_cert_override_test("mismatch-expired.example.com",
                          Ci.nsICertOverrideService.ERROR_MISMATCH |
                          Ci.nsICertOverrideService.ERROR_TIME,
                          getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
   add_cert_override_test("mismatch-untrusted.example.com",
@@ -142,29 +147,38 @@ function add_combo_tests() {
                          Ci.nsICertOverrideService.ERROR_TIME,
                          getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
 
   add_cert_override_test("md5signature-expired.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED |
                          Ci.nsICertOverrideService.ERROR_TIME,
                          getXPCOMStatusFromNSS(
                             SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
+
+  add_cert_override_test("ca-used-as-end-entity-name-mismatch.example.com",
+                         Ci.nsICertOverrideService.ERROR_MISMATCH |
+                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                         getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY));
 }
 
 function add_distrust_tests() {
   // Before we specifically distrust this certificate, it should be trusted.
   add_connection_test("untrusted.example.com", Cr.NS_OK);
 
   add_distrust_override_test("tlsserver/default-ee.der",
                              "untrusted.example.com",
                              getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT));
 
   add_distrust_override_test("tlsserver/other-test-ca.der",
                              "untrustedissuer.example.com",
                              getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER));
+
+  add_distrust_override_test("tlsserver/test-ca.der",
+                             "ca-used-as-end-entity.example.com",
+                             getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER));
 }
 
 function add_distrust_override_test(certFileName, hostName, expectedResult) {
   let certToDistrust = constructCertFromFile(certFileName);
 
   add_test(function () {
     // Add an entry to the NSS certDB that says to distrust the cert
     setCertTrust(certToDistrust, "pu,,");
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_nsCertType.js
@@ -0,0 +1,27 @@
+// -*- indent-tabs-mode: nil; js-indent-level: 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/.
+//
+// While the Netscape certificate type extension is not a standard and has been
+// discouraged from use for quite some time, it is still encountered. Thus, we
+// handle it slightly differently from other unknown extensions.
+// If it is not marked critical, we ignore it.
+// If it is marked critical:
+//   If the basic constraints and extended key usage extensions are also
+//   present, we ignore it, because they are standardized and should convey the
+//   same information.
+//   Otherwise, we reject it with an error indicating an unknown critical
+//   extension.
+
+"use strict";
+
+function run_test() {
+  do_get_profile();
+  add_tls_server_setup("BadCertServer");
+  add_connection_test("nsCertTypeNotCritical.example.com", Cr.NS_OK);
+  add_connection_test("nsCertTypeCriticalWithExtKeyUsage.example.com", Cr.NS_OK);
+  add_connection_test("nsCertTypeCritical.example.com",
+                      getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION));
+  run_next_test();
+}
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js
@@ -138,28 +138,31 @@ function add_tests(certDB, otherTestCA) 
   // ocsp-stapling-expired-fresh-ca.example.com are handled in
   // test_ocsp_stapling_expired.js
 
   // Check that OCSP responder certificates with key sizes below 1024 bits are
   // rejected, even when the main certificate chain keys are at least 1024 bits.
   add_ocsp_test("keysize-ocsp-delegated.example.com",
                 getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE),
                 true);
+
+  add_ocsp_test("revoked-ca-cert-used-as-end-entity.example.com",
+                getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE), true);
 }
 
 function check_ocsp_stapling_telemetry() {
   let histogram = Cc["@mozilla.org/base/telemetry;1"]
                     .getService(Ci.nsITelemetry)
                     .getHistogramById("SSL_OCSP_STAPLING")
                     .snapshot();
   do_check_eq(histogram.counts[0], 0); // histogram bucket 0 is unused
   do_check_eq(histogram.counts[1], 5); // 5 connections with a good response
   do_check_eq(histogram.counts[2], 18); // 18 connections with no stapled resp.
   do_check_eq(histogram.counts[3], 0); // 0 connections with an expired response
-  do_check_eq(histogram.counts[4], 20); // 20 connections with bad responses
+  do_check_eq(histogram.counts[4], 21); // 21 connections with bad responses
   run_next_test();
 }
 
 function run_test() {
   do_get_profile();
 
   let certDB = Cc["@mozilla.org/security/x509certdb;1"]
                   .getService(Ci.nsIX509CertDB);
index 19bbfdcc82a59d8a8e02d70eeaf77f3f5a641ea0..fe22bc496350c880eacd0b1ebb0b44a3f3e3136c
GIT binary patch
literal 294912
zc%1B=1zZ$e+y8f2LO{BENoi*3ZV*I3N>U|u2`Po8Her>pyG2yIQ8BPv>_kv(L`4w0
zyHNi-yQ?6u#{E7%y#LR8eeZkcn%(PMXU?4X&2g9r3mKk9CgGE_b21aicq>dX28+eG
z<M9{_W-t3Ais?p({SoZ(9gF!jdogBrg(R3=7-8xl3{8%Cih7PZnL3R91poj500000
z00000000000000000000000000000000000000000000000000000000000000000
z000000000000000000000000000000000000002^UyZx4u#%D%HaabfNGeQ9Pe>zX
z<>rpaOUy`167dT4@d)?9`v-aZMBzC;d~gu{yB}|uKtL>wT!lC}L~wG*NJu1Qd`}_#
zLk=8Y?;Na*yak1o)U>dpIPtl8iDOAg<nJkje#n96?OO_hkq1s#N#)yqq~+%3k#fE#
z5&R(&uCsR@_5`DHE3Al;mKJup4LKn(gY@0|eMNwmPq>HYaG##h?1~u?>L2J48jTO|
ziN;3+`G-XKpj+??4)PuD?-h>s@C*(OH^nC)><@wcv1EU&&~?ra=r08HCwug(J^Iz2
z^A$~EZ;dW&(1k6!utOL2=)wVAB%q5#_QHXa6~bL|azrdSOYU~8IZGSP(w4Kd<1Fnt
zO9##}fwN5HER#3|;}(xwKF+!&cb${7B`0S~PR^E`oGm#yTXJ%?<m7C{iL&BES#hGQ
zI8j!dC|i!#mgBYMcx^deTdtRrr!6N>J5EY_?vhi3oISNfxa(-FC8xC32pdaIk$J0}
zy5^*|;-t3Xq_#%5sksTczgTgW)|{mcXNhjxnzL1F&Q`5C?P9};wc*6tAlzTj*d&sT
zm9>=(p?lS`d$mUb>+V&X?p53FRlDw0`|qo^-C?%fVYc02w%uX2-@<IWi(}he9NX^V
z*mf7kw!1jC-Nmu(E{<(?aoDR4-Kz=RtBKvKN!_c&?p0FvYV!A0PDkLbCUzGm5iJhU
zCIKNPa%$Wj;m}>bwhl%F0bwN{Ei8sBALBF9$fPj|dE{))_c7lG=@`QIRUBLP1clfO
zEb|j8fudXk0000000000000000000000000000000000000000000000000000000
z0000000000000000000000000000000000000000000000000000000000000095j
z7=(zim&vqk80H7&3+4l6JF|t^%sj<B#N5r?%v{S{!Cb_g#hk<}VHPpRGt-y}%xGo^
z)1T?VbYK#gMoev{3R8wD%6P$ez-VV;86OxejAq6u#v#UT#%9J^#tOzF#w^ApMhT;c
zF`kjeNMJ-WLKyxG4~7GSz%XKHGgKHd3{eJ_{(=62{(#<2Z=pBSPtgz2chfh~SJRi#
z=h3IqC(tSM@$^*s82U(hAl;kpM7N|H(eZR8x+GnQ)<t_odq``iU8S9+9jEPQ?+gF{
z00000000000000000000000000000000000000000000000000000000000000000
z0000000000000000000000000000000000000000000000Q?_f5Ka&)^R_iLmA8_T
z!dppB=B%`~T9MEdsf*3BMBa)_5^qI1k+X8DDI<Zmk{-`n89Rova!{Q-nzxcWino#z
z$5~lfml}(%U}i?Hjp41ViRP`Wj^eCLb!v{}t(+UlTR9uSS*duc7|vT!2;;5DhjLaX
zveH6$E2$%RD=ER8l@e*!Al`~gAaBKaxCjo1rA=!J;M&GvTzkeJwM9Pleq6hMDA(@u
zMQxr&v=7%td2?-~7iz~lxp;D|vj^8YxuZ5irrnKeZ@F@9n+s}FX=k0ew#kWW8y!(g
zth(dCwVn1{d)p4R@ior2T<c`RwT{-Pjk|iyifdaex%MgnwNZ`J5U!nS!L?J&Q5)es
z%8YB{Ou07J1hpX}9vO4(LnE$zV2Ikl`jR22^(*tx<63uJu65Jl`il*?mZ^_g?_Gzq
zQ0rcGO_OU|G`RMvI%-|Qoz=M3NtJ6IRZwg1e^i-kk0^2NVMWwhw@*^w+6sBDEtf+r
zvPxQ(Yo%nkR#F<ZW}fS$xVBc3Yu8Gk)^I}dV6G*Jb1hK}wR(3Zh;l7!5Z9K7pcY^H
zRG4d@2yyLWLDZ_NMdP?ON<bKg6IEA>6l0I4<brGrvx|9*$zldD2Qiu%iy6TTWqLcE
zMGv6U>0{_I^a%P0YAbaiHG(QjX{D^93@LhEw7V#)$gT)eSY9}yFrZMr;6_1B!3ySW
z=4oaca|GiV<1%9xql#h6(4c>%-=!02S7~Xq5!4UVTa*u!Ta?3;wG_#sH$_*9>Wd<Z
zoQpJzgbK3?BML1GRSG^8bQBydSXWR{kj<=NmNQM65;Ou$mb#BxNiCwrP;IG7i~>e@
z(fp!Z+6EenzKvc^*QC8DJYG1Jl1echXng_z000000000000000000000000000000
z00000000000000000000000000000000000000000000000000000000000000000
z00000000000090NWt=q@ktIkYlESzML7bdOI4PHm_wq>P=SUI6VX(>Qg2XQgk)I<8
z4NK(bP2lH<N5jVO^N!}{7=?z#p^I34Nn-dpqS3G@2V6cDu_6!<3$E9Y;|(KaB%9@?
zrDTzac%Lky87YgLMlQk^q>)qEk$7@W9x3u)M~*}{9Ko+x;rtw7XjmveZwNof2sA8M
z2j_=H)CsDHGS@4^@%m?xNjaG$Vp;;36!hyPfoN94`E4kGpJNyr=FiXT$Imeo4fA!v
zQLu;&!3rU8y~aH&*gq?QNE)BVE*jn^AOg<`?5=d5|3R!bx^XXlMf2q6@Ib@d`FY*=
zIb6{&7fqZy7EvZBBJy0XL@+s(l!GU8(>VX!?Sy9G`13RlKX==sS=jwNjqT6fHfR>s
z{C3ldpTqL!xgtMzTky-)jGx2Q7#D>_^awf#p6gKYDIAxU!|oM*`n>V)CpF@?xgn;w
zI4oj7&_i^%4z)h9cyczLNXj6QNqT>hSQo8t9dtoJ7v|`~1YH>ND~kc@)khaveKyo{
zc=Q?%ntzg51I=EYUkTLsIaJXw6@Ff2ehwuxO!3$1rSR({@@Q6a{5B-Z&mn_`N%Qkc
z@pDL`VG=*@+k=1Z7DuxX<F^4(evUzCn8?qw7XG<g2+cx}-v)5}90E8TMpTSFDM>D9
z$1z)(b<7f`FH?i@gt389z;I^>(<jqk&^zf@XnSZ>nj`fibu%@KYC`FttfRzH#ENzl
z5sNem+Y0|F%q}!7XlLGH>M*x4%NQ>UYZ<gcGQ)?mi9UuQ&I~B*q!lx^P`}dLXm9B=
z=*Co};4U?{kU%?7q(j|7xkpK$NEM|O?PY#oUSO_f7BO9!3XD69e;C;ed-@mpQTki@
z1NwFPS=ts_F3pnqlDd|fOx2}aqf}GEDFQ_si{gqD3a=ENEvzg|Dby=eALvOQ00000
z00000000000000000000000000000000000000000000000000000000000000000
z000000000000000000000000000000000000002+{{iT`fm3a8Sy;q^V1}4*UjeMw
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
KTe8jD_<sTHrt5G3
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
@@ -38,26 +38,31 @@ const BadCertHost sBadCertHosts[] =
   { "mismatch-expired.example.com", "mismatch-expired" },
   { "mismatch-untrusted.example.com", "mismatch-untrusted" },
   { "untrusted-expired.example.com", "untrusted-expired" },
   { "md5signature-expired.example.com", "md5signature-expired" },
   { "mismatch-untrusted-expired.example.com", "mismatch-untrusted-expired" },
   { "inadequatekeyusage.example.com", "inadequatekeyusage" },
   { "selfsigned-inadequateEKU.example.com", "selfsigned-inadequateEKU" },
   { "self-signed-end-entity-with-cA-true.example.com", "self-signed-EE-with-cA-true" },
+  { "ca-used-as-end-entity.example.com", "ca-used-as-end-entity" },
+  { "ca-used-as-end-entity-name-mismatch.example.com", "ca-used-as-end-entity" },
   // All of include-subdomains.pinning.example.com is pinned to End Entity
   // Test Cert with nick localhostAndExampleCom. Any other nick will only
   // pass pinning when security.cert_pinning.enforcement.level != strict and
   // otherCA is added as a user-specified trust anchor. See StaticHPKPins.h.
   { "include-subdomains.pinning.example.com", "localhostAndExampleCom" },
   { "good.include-subdomains.pinning.example.com", "localhostAndExampleCom" },
   { "bad.include-subdomains.pinning.example.com", "otherIssuerEE" },
   { "exclude-subdomains.pinning.example.com", "localhostAndExampleCom" },
   { "sub.exclude-subdomains.pinning.example.com", "otherIssuerEE" },
   { "test-mode.pinning.example.com", "otherIssuerEE" },
+  { "nsCertTypeNotCritical.example.com", "nsCertTypeNotCritical" },
+  { "nsCertTypeCriticalWithExtKeyUsage.example.com", "nsCertTypeCriticalWithExtKeyUsage" },
+  { "nsCertTypeCritical.example.com", "nsCertTypeCritical" },
   { nullptr, nullptr }
 };
 
 int32_t
 DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
                   uint32_t aSrvNameArrSize, void *aArg)
 {
   const BadCertHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -48,16 +48,17 @@ const OCSPHost sOCSPHosts[] =
   { "ocsp-stapling-delegated-missing.example.com", ORTDelegatedMissing, "delegatedSigner" },
   { "ocsp-stapling-delegated-missing-multiple.example.com", ORTDelegatedMissingMultiple, "delegatedSigner" },
   { "ocsp-stapling-delegated-no-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerNoExtKeyUsage" },
   { "ocsp-stapling-delegated-from-intermediate.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerFromIntermediate" },
   { "ocsp-stapling-delegated-keyUsage-crlSigning.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerKeyUsageCrlSigning" },
   { "ocsp-stapling-delegated-wrong-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerWrongExtKeyUsage" },
   { "ocsp-stapling-ancient-valid.example.com", ORTAncientAlmostExpired, nullptr},
   { "keysize-ocsp-delegated.example.com", ORTDelegatedIncluded, "badKeysizeDelegatedSigner" },
+  { "revoked-ca-cert-used-as-end-entity.example.com", ORTRevoked, "ca-used-as-end-entity" },
   { nullptr, ORTNull, nullptr }
 };
 
 int32_t
 DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
                   uint32_t aSrvNameArrSize, void *aArg)
 {
   const OCSPHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
--- a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
+++ b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
@@ -167,16 +167,47 @@ function make_EE {
                                                      -t ",," \
                                                      -m $SERIALNO \
                                                      --extAIA \
                                                      $COMMON_ARGS \
                                                      $EXTRA_ARGS
   SERIALNO=$(($SERIALNO + 1))
 }
 
+function make_EE_with_nsCertType {
+  NICKNAME="${1}"
+  SUBJECT="${2}"
+  CA="${3}"
+  SUBJECT_ALT_NAME="${4}"
+  NS_CERT_TYPE_CRITICAL="${5}"
+  EXTRA_ARGS="${6}"
+  # This adds the Netscape certificate type extension with the "sslServer"
+  # bit asserted. Its criticality depends on if "y" or "n" was passed as
+  # an argument to this function.
+  CERT_RESPONSES="n\n\ny\n1\n8\n$NS_CERT_TYPE_CRITICAL\n"
+
+  cert_already_exists $NICKNAME
+  if [ $ALREADY_EXISTS -eq 1 ]; then
+    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
+    return
+  fi
+
+  echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
+                                                     -n $NICKNAME \
+                                                     -s "$SUBJECT" \
+                                                     -8 $SUBJECT_ALT_NAME \
+                                                     -c $CA \
+                                                     -t ",," \
+                                                     -m $SERIALNO \
+                                                     -5 \
+                                                     $COMMON_ARGS \
+                                                     $EXTRA_ARGS
+  SERIALNO=$(($SERIALNO + 1))
+}
+
 function make_delegated {
   CERT_RESPONSES="n\n\ny\n"
   NICKNAME="${1}"
   SUBJECT="${2}"
   CA="${3}"
   EXTRA_ARGS="${4}"
 
   cert_already_exists $NICKNAME
@@ -243,12 +274,17 @@ make_EE selfsigned-inadequateEKU 'CN=Sel
 
 make_delegated delegatedSigner 'CN=Test Delegated Responder' testCA "--extKeyUsage ocspResponder"
 make_delegated invalidDelegatedSignerNoExtKeyUsage 'CN=Test Invalid Delegated Responder No extKeyUsage' testCA
 make_delegated invalidDelegatedSignerFromIntermediate 'CN=Test Invalid Delegated Responder From Intermediate' testINT "--extKeyUsage ocspResponder"
 make_delegated invalidDelegatedSignerKeyUsageCrlSigning 'CN=Test Invalid Delegated Responder keyUsage crlSigning' testCA "--keyUsage crlSigning"
 make_delegated invalidDelegatedSignerWrongExtKeyUsage 'CN=Test Invalid Delegated Responder Wrong extKeyUsage' testCA "--extKeyUsage codeSigning"
 
 make_INT self-signed-EE-with-cA-true 'CN=Test Self-signed End-entity with CA true' unused "-x -8 self-signed-end-entity-with-cA-true.example.com"
+make_INT ca-used-as-end-entity 'CN=Test Intermediate used as End-Entity' testCA "-8 ca-used-as-end-entity.example.com"
 
 make_delegated badKeysizeDelegatedSigner 'CN=Bad Keysize Delegated Responder' testCA "--extKeyUsage ocspResponder -g 1008"
 
+make_EE_with_nsCertType nsCertTypeCritical 'CN=nsCertType Critical' testCA "localhost,*.example.com" "y"
+make_EE_with_nsCertType nsCertTypeNotCritical 'CN=nsCertType Not Critical' testCA "localhost,*.example.com" "n"
+make_EE_with_nsCertType nsCertTypeCriticalWithExtKeyUsage 'CN=nsCertType Critical With extKeyUsage' testCA "localhost,*.example.com" "y" "--extKeyUsage serverAuth"
+
 cleanup
index e33f19881080a4208713fb8c4739e16c8d498eed..9d6453d125c50d86bf079d3ecd276263fa697309
GIT binary patch
literal 458752
zc%1CrcUV(f_b>W{-h1x^M6d=37?7?M3sM9`dP0-lds##QDIzuyD|SEy#e&$eHx#fV
ziXx(diijwP3O8Z%{-SKoOy1}Ian8MGe4b~ox%A6ed+d>IW=KL@>a;i{K2R+vDmH==
zucnX7!r}2a3pF(y4p&G2M+C>jL;r{Ck6+_)tkvOWzU3Cie&P61y>RIw*p0MXX|y!+
z)Sszdskhmv2LJ#700000000000000000000000000000000000000000000000000
z000000000000000000000000000000000000002^|CMlFURh;jJZ*YBg&H0h5g1RI
zPl>1eXXTscY;Eact>$8Bwb)wiKfkM{9TK4C=)Az*(s{YsBJ1U9u1gj;xmv3^EK!^1
zu*7EZf_W}#&eo2LE$3O!Pz#9<jL`jO(bJjD$0IvW8IKEz3<yk)iwURyt}i7aK5FdO
zzW=$tukL@&_^o(&WM$Ryo?~C&A4UlYh>VMKj15Vo#0T<@H@9HPd~0{Lv5?UM^9$6p
zDY`^G9SiQUYb+bPMmU8U7|#3>p1-a!7XIrR`Z_jTJhF=Fc;A28PN0Sc`o}ZBg!`{+
zjK`C7qN_8HlSfwmKmRo$ad8QOvCOaG`s*_Pr2o1KSyyMZA)Z%OT^+x6&e%=HjG1Q~
zf8A_<UV!xtXKCf&>@q`*LZtsgzuhQ$^ndgj=VQOY_#IuwZ;=_lBr|?V9{VNZOUNX~
z!GLivWE|!&4rIo`h;g7W4pjQVXzWtNe~x2UB<hVF|M~Zj#*PMKN5iq>oUtQ$>}WK0
zq>LS@V@Ln7#{OyVpZ><q_5L{@yRzQcmG#E1tT%RLy|F9nja^x9?8^FMRr+I9`eRl4
zV^#WNRfc1!;aF-omKu(whX15v*EAfv=A5ywB>!_9o8Z`gsUGp4b4IP+Shpl1o!(f>
z<ELY@9{Xzjv9H!2`)U&LpRfMs3;+2Y{jnoy>}W7{Wc<5HWB*pt*uRxDcDopi)f$Y|
z8W8{a9Y(Expn*O~-$0jns>eM2;|oa4Qv>FyA@g(&^OXEQr-sZjLuQ#Fv&@iLX84~n
zLuNaM%ytZ!?HDrKF=V!5$ZW@u*^VKz9r~#e^OV9or7}<bnWq8F(?I5F(Epr{{g3d^
zDV5m{mC;Us0fiVq9h*3rIEFc2Ln9r14jx%s_5anKAM;PCuP*bPlYSS?#Z5opv7d~)
zYvF$u000000000000000000000000000000000000000000000000000000000000
z00000000000000000000000000000000000007|sHbM#l^rL3xV;uGa`+{|29at;Y
zg5AO{VW+WLtP0zWZNb)K`4|mL!D6rwjDju4oUjF$C1!*Xv8k8}CXESUoSDO!Uozik
zzNB9W000000000000000000000000000000000000000000000000000000000000
z000000000000000000000000000000000000Kor2_&B-n;@{f>HOEfc+VnISC!!Bq
zL<wUjx9)|gkDW9q#i)&)>^Tyw$~eKTTXsNY>}1W{d&*-cdA*WKV<*`wgA~V3Xkv2}
zcsV)o=|y+s8EcC5Svkg<pzJ2gSYzfI%P`h(@pfs(x+1+%im?Wizm{aIeg}*s7^~OQ
zC*q9N{ceF6V|AVHA<9^t9N&vDR{IN?!i?1}*G!19&aZC}WULnDPXrjNsf!UmV<j)R
z#K%}k9l5-WmAFrshq2DIs^n&@+N=Dz7^`Mi7AIp>%lW{;!^z37r06C<pOz+OkHdap
zgIGWI344!qV(nNf_7H2rZe!Q52J9?Wht*<-u?lPtwgW4}HezeBd@LKouv9Doi^jsR
zAdG@}VaqUQ`h@@h00000000000000000000000000000000000000000000000000
z00000000000000000000000000000000000000000000004`1(UXyXqU>pdHgF54&
z#yF@l4l0a;GUK4cI4Cj>3XFq1;~>X4$TAKxjDs}eAjLRHG7b`qgE-?L#yE&F4kC<$
zFykP^I0!Nh0*nJc<G{x_@G=fOi~~30z{NOlG7cP^oH%{~dfS?r9XRX<_66(4I<Qu(
z1-pe^!cJqgSQWM#+k&mf@-Z5gg2iAV7zJC7IbjPhOUww<#dI)rOdb=*_%VFukIXNb
z-Si6q000000000000000000000000000000000000000000000000000000000000
z000000000000000000000000000000000000Qf%>FQ){4Kh8sQeAO6V3FE8!_^LL(
zs*bNJ<E!%csx-bTj;{*itNi#XH@?b_uQKDS^!O?@zDka-6634*_$oHOijJ=$<E!xa
zDm1<dj;{jaEC2Y)H@@<YuRP-`_xQ>+zH*MQ96X#7{EX|+N2HnAfx~`aU$Abh18c=v
zuv^$A>@-%3RbjiaE!cW2AERL@SPT||QLyEh6Se@e#EdXqOb1iP<S}uKAH!$<$o!Jo
zO}`KT000000000000000000000000000000000000000000000000000000000000
z00000000000000000000000000000000000fd4a%|9$tG<EzH_N*G_&$5*xSRdsw-
z8DEvhSEcb)aeP%6U**SFx$#wYe3cnrrN>vP@l|qsl^9>e$5*lORdjq68DE9RSE2D$
zaC{XQU-`#ZzVVfJeB~KmxyM(o@s)FY<>29z;AdQiJ|fNZ3|vN1`f$dK49SeD3?Gaa
z%f_5D3o;+2AHm*d3TL!sT+WQi7|7g<HDNn4wbE~9x?^gXQHFJ9FIJaciiKsK%QR2V
z$XJ)&@xS}#1^@s600000000000000000000000000000000000000000000000000
z0000000000000000000000000000000000000000;QzDaI7#@f%1h#V3so~zALLlL
zl3tB`|FPt^CL_2I@IfuDeFo`l!0Yhb_BZjt9cob;jKET3j@v17Y!A<(9jlz@g`GcA
z<2poO1bMntKm867_1-Jj30k|1vL4td>{Vw3U$X8xRhn$RyY|#M@j9aJ)$m<AKB_SS
zu{G}ssy<UI61FH9wJg9THHcfesWJkY+84VPxnA1($o`f{-HDCcla;MhRTzQP=X{m&
zOQO58bI)oX3^fwGk#TRgG9y_3YH#mGiyx}JH#NC-oN6t2Xjr^hi4kaab2YwcY`1!=
zXSc;`nTl4Y^v}hLjDX|C&Bj)Xx-&oeGR-bd4_kwGi>y*$1U)Mcg_C}BXstcAZ_2h8
zF7wuj(gfrgfl{=t+=cTFXErb28<?i$Gw)M%F^3!@2zhI5pJ1h7RDT<9Z}xn~9{inH
zJy}LT&Acw7R^i!pv`s%VeyEklJZrc>h7m;ne00$3n#%!84FiSms=GQia_lIOW(1U0
zh0_(WiwivDYsp!8_uiMhPF^R)2v*&3T&Q02TmM(jv70yL?;mUqSpQy<5p?EUl9n`e
z=AR*yEnN9pQJpFl{X&8f<Qq(@eA*;@|1w@}#Z!6eaQ>p+4Dqpl`K6fOjk;G;YnKHd
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
anFww|n5mydpX5?!NVnLX^)^vrwEq_xwb-Bl
--- a/security/pkix/include/pkix/bind.h
+++ b/security/pkix/include/pkix/bind.h
@@ -57,16 +57,17 @@ using std::placeholders::_1;
 using std::placeholders::_2;
 using std::placeholders::_3;
 
 #else
 
 extern class Placeholder1 { } _1;
 extern class Placeholder2 { } _2;
 extern class Placeholder3 { } _3;
+extern class Placeholder4 { } _4;
 
 template <typename V>       V&  ref(V& v)       { return v; }
 template <typename V> const V& cref(const V& v) { return v; }
 
 namespace internal {
 
 template <typename R, typename P1, typename B1>
 class Bind1
@@ -108,27 +109,28 @@ private:
   const F f;
   B1& b1;
   B2& b2;
   B3& b3;
   B4& b4;
   void operator=(const Bind4&) /*= delete*/;
 };
 
-template <typename R, typename C1, typename P1, typename P2, typename P3>
-class BindToMemberFunction3
+template <typename R, typename C1, typename P1, typename P2, typename P3,
+          typename P4>
+class BindToMemberFunction4
 {
 public:
-  typedef R (C1::*F)(P1&, P2&, P3&);
-  BindToMemberFunction3(F f, C1* that) : f(f), that(that) { }
-  R operator()(P1& p1, P2& p2, P3& p3) const { return (that->*f)(p1, p2, p3); }
+  typedef R (C1::*F)(P1&, P2&, P3, P4&);
+  BindToMemberFunction4(F f, C1* that) : f(f), that(that) { }
+  R operator()(P1& p1, P2& p2, P3 p3, P4& p4) const { return (that->*f)(p1, p2, p3, p4); }
 private:
   const F f;
   C1* const that;
-  void operator=(const BindToMemberFunction3&) /*= delete*/;
+  void operator=(const BindToMemberFunction4&) /*= delete*/;
 };
 
 } // namespace internal
 
 template <typename R, typename P1, typename B1>
 inline internal::Bind1<R, P1, B1>
 bind(R (*f)(P1&, B1&), Placeholder1&, B1& b1)
 {
@@ -146,21 +148,22 @@ template <typename R, typename P1, typen
           typename B4>
 inline internal::Bind4<R, P1, const B1, const B2, B3, B4>
 bind(R (*f)(P1&, B1, B2, B3&, B4&), Placeholder1&, const B1& b1, const B2& b2,
      B3& b3, B4& b4)
 {
   return internal::Bind4<R, P1, const B1, const B2, B3, B4>(f, b1, b2, b3, b4);
 }
 
-template <typename R, typename C1, typename P1, typename P2, typename P3>
-inline internal::BindToMemberFunction3<R, C1, P1, P2, P3>
-bind(R (C1::*f)(P1&, P2&, P3&), C1* that, Placeholder1&, Placeholder2&,
-     Placeholder3&)
+template <typename R, typename C1, typename P1, typename P2, typename P3,
+          typename P4>
+inline internal::BindToMemberFunction4<R, C1, P1, P2, P3, P4>
+bind(R (C1::*f)(P1&, P2&, P3, P4&), C1* that, Placeholder1&, Placeholder2&,
+     Placeholder3, Placeholder4&)
 {
-  return internal::BindToMemberFunction3<R, C1, P1, P2, P3>(f, that);
+  return internal::BindToMemberFunction4<R, C1, P1, P2, P3, P4>(f, that);
 }
 
 #endif
 
 } } // namespace mozilla::pkix
 
 #endif // mozilla_pkix__bind_h
--- a/security/pkix/lib/pkixbind.cpp
+++ b/security/pkix/lib/pkixbind.cpp
@@ -26,12 +26,13 @@
 
 #ifndef MOZILLA_PKIX_USE_REAL_FUNCTIONAL
 
 namespace mozilla { namespace pkix {
 
 Placeholder1 _1;
 Placeholder2 _2;
 Placeholder3 _3;
+Placeholder4 _4;
 
 } } // namespace mozilla::pkix
 
 #endif
--- a/security/pkix/lib/pkixcert.cpp
+++ b/security/pkix/lib/pkixcert.cpp
@@ -147,30 +147,57 @@ BackCert::Init()
 
   // Extensions were added in v3, so only accept extensions in v3 certificates.
   // v4 certificates are not defined but there are some certificates issued
   // with v4 that expect v3 decoding. For compatibility reasons we handle them
   // as v3 certificates.
   if (version == der::Version::v3 || version == der::Version::v4) {
     rv = der::OptionalExtensions(tbsCertificate, CSC | 3,
                                  bind(&BackCert::RememberExtension, this, _1,
-                                      _2, _3));
+                                      _2, _3, _4));
     if (rv != Success) {
       return rv;
     }
+    // The Netscape Certificate Type extension is an obsolete
+    // Netscape-proprietary mechanism that we ignore in favor of the standard
+    // extensions. However, some CAs have issued certificates with the Netscape
+    // Cert Type extension marked critical. Thus, for compatibility reasons, we
+    // "understand" this extension by ignoring it when it is not critical, and
+    // by ensuring that the equivalent standardized extensions are present when
+    // it is marked critical, based on the assumption that the information in
+    // the Netscape Cert Type extension is consistent with the information in
+    // the standard extensions.
+    //
+    // Here is a mapping between the Netscape Cert Type extension and the
+    // standard extensions:
+    //
+    // Netscape Cert Type  |  BasicConstraints.cA  |  Extended Key Usage
+    // --------------------+-----------------------+----------------------
+    // SSL Server          |  false                |  id_kp_serverAuth
+    // SSL Client          |  false                |  id_kp_clientAuth
+    // S/MIME Client       |  false                |  id_kp_emailProtection
+    // Object Signing      |  false                |  id_kp_codeSigning
+    // SSL Server CA       |  true                 |  id_pk_serverAuth
+    // SSL Client CA       |  true                 |  id_kp_clientAuth
+    // S/MIME CA           |  true                 |  id_kp_emailProtection
+    // Object Signing CA   |  true                 |  id_kp_codeSigning
+    if (criticalNetscapeCertificateType.GetLength() > 0 &&
+        (basicConstraints.GetLength() == 0 || extKeyUsage.GetLength() == 0)) {
+      return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
+    }
   }
 
   return der::End(tbsCertificate);
 }
 
 // XXX: The second value is of type |const Input&| instead of type |Input| due
 // to limitations in our std::bind polyfill.
 Result
 BackCert::RememberExtension(Reader& extnID, const Input& extnValue,
-                            /*out*/ bool& understood)
+                            bool critical, /*out*/ bool& understood)
 {
   understood = false;
 
   // python DottedOIDToCode.py id-ce-keyUsage 2.5.29.15
   static const uint8_t id_ce_keyUsage[] = {
     0x55, 0x1d, 0x0f
   };
   // python DottedOIDToCode.py id-ce-subjectAltName 2.5.29.17
@@ -200,16 +227,20 @@ BackCert::RememberExtension(Reader& extn
   // python DottedOIDToCode.py id-ce-inhibitAnyPolicy 2.5.29.54
   static const uint8_t id_ce_inhibitAnyPolicy[] = {
     0x55, 0x1d, 0x36
   };
   // python DottedOIDToCode.py id-pe-authorityInfoAccess 1.3.6.1.5.5.7.1.1
   static const uint8_t id_pe_authorityInfoAccess[] = {
     0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01
   };
+  // python DottedOIDToCode.py Netscape-certificate-type 2.16.840.1.113730.1.1
+  static const uint8_t Netscape_certificate_type[] = {
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01
+  };
 
   Input* out = nullptr;
 
   // We already enforce the maximum possible constraints for policies so we
   // can safely ignore even critical policy constraint extensions.
   //
   // XXX: Doing it this way won't allow us to detect duplicate
   // policyConstraints extensions, but that's OK because (and only because) we
@@ -233,16 +264,18 @@ BackCert::RememberExtension(Reader& extn
   } else if (extnID.MatchRest(id_ce_policyConstraints)) {
     out = &dummyPolicyConstraints;
   } else if (extnID.MatchRest(id_ce_extKeyUsage)) {
     out = &extKeyUsage;
   } else if (extnID.MatchRest(id_ce_inhibitAnyPolicy)) {
     out = &inhibitAnyPolicy;
   } else if (extnID.MatchRest(id_pe_authorityInfoAccess)) {
     out = &authorityInfoAccess;
+  } else if (extnID.MatchRest(Netscape_certificate_type) && critical) {
+    out = &criticalNetscapeCertificateType;
   }
 
   if (out) {
     // Don't allow an empty value for any extension we understand. This way, we
     // can test out->GetLength() != 0 or out->Init() to check for duplicates.
     if (extnValue.GetLength() == 0) {
       return Result::ERROR_EXTENSION_VALUE_INVALID;
     }
--- a/security/pkix/lib/pkixder.h
+++ b/security/pkix/lib/pkixder.h
@@ -565,17 +565,17 @@ OptionalExtensions(Reader& input, uint8_
       return rv;
     }
     rv = End(extension);
     if (rv != Success) {
       return rv;
     }
 
     bool understood = false;
-    rv = extensionHandler(extnID, extnValue, understood);
+    rv = extensionHandler(extnID, extnValue, critical, understood);
     if (rv != Success) {
       return rv;
     }
     if (critical && !understood) {
       return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
     }
   }
 
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -151,17 +151,17 @@ static inline Result ResponseBytes(Reade
 static inline Result BasicResponse(Reader&, Context&);
 static inline Result ResponseData(
                        Reader& tbsResponseData,
                        Context& context,
                        const SignedDataWithSignature& signedResponseData,
                        const DERArray& certs);
 static inline Result SingleResponse(Reader& input, Context& context);
 static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
-                                     /*out*/ bool& understood);
+                                     bool critical, /*out*/ bool& understood);
 static inline Result CertID(Reader& input,
                             const Context& context,
                             /*out*/ bool& match);
 static Result MatchKeyHash(TrustDomain& trustDomain,
                            Input issuerKeyHash,
                            Input issuerSubjectPublicKeyInfo,
                            /*out*/ bool& match);
 static Result KeyHash(TrustDomain& trustDomain,
@@ -819,17 +819,17 @@ KeyHash(TrustDomain& trustDomain, const 
     return rv;
   }
 
   return trustDomain.DigestBuf(subjectPublicKey, hashBuf, hashBufSize);
 }
 
 Result
 ExtensionNotUnderstood(Reader& /*extnID*/, Input /*extnValue*/,
-                       /*out*/ bool& understood)
+                       bool /*critical*/, /*out*/ bool& understood)
 {
   understood = false;
   return Success;
 }
 
 //   1. The certificate identified in a received response corresponds to
 //      the certificate that was identified in the corresponding request;
 //   2. The signature on the response is valid;
--- a/security/pkix/lib/pkixutil.h
+++ b/security/pkix/lib/pkixutil.h
@@ -129,19 +129,20 @@ private:
   Input authorityInfoAccess;
   Input basicConstraints;
   Input certificatePolicies;
   Input extKeyUsage;
   Input inhibitAnyPolicy;
   Input keyUsage;
   Input nameConstraints;
   Input subjectAltName;
+  Input criticalNetscapeCertificateType;
 
   Result RememberExtension(Reader& extnID, const Input& extnValue,
-                           /*out*/ bool& understood);
+                           bool critical, /*out*/ bool& understood);
 
   BackCert(const BackCert&) /* = delete */;
   void operator=(const BackCert&); /* = delete */;
 };
 
 class NonOwningDERArray : public DERArray
 {
 public:
--- a/security/sandbox/mac/Sandbox.h
+++ b/security/sandbox/mac/Sandbox.h
@@ -30,16 +30,18 @@ typedef struct _MacSandboxPluginInfo {
   nsCString pluginBinaryPath;
 } MacSandboxPluginInfo;
 
 typedef struct _MacSandboxInfo {
   _MacSandboxInfo()
     : type(MacSandboxType_Default) {}
   MacSandboxType type;
   MacSandboxPluginInfo pluginInfo;
+  nsCString appPath;
+  nsCString appBinaryPath;
 } MacSandboxInfo;
 
 namespace mozilla {
 
 bool StartMacSandbox(MacSandboxInfo aInfo, nsCString &aErrorMessage);
 
 } // namespace mozilla
 
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -28,36 +28,41 @@ static const char rules[] =
   "    (global-name \"com.apple.cfprefsd.daemon\")\n"
   "    (global-name \"com.apple.system.opendirectoryd.libinfo\")\n"
   "    (global-name \"com.apple.system.logger\")\n"
   "    (global-name \"com.apple.ls.boxd\"))\n"
   "(allow file-read*\n"
   "    (regex #\"^/etc$\")\n"
   "    (regex #\"^/dev/u?random$\")\n"
   "    (regex #\"^/(private/)?var($|/)\")\n"
-  "    (regex #\"\\.app/Contents/MacOS/plugin-container\\.app/Contents/\")\n"
   "    (literal \"/usr/share/icu/icudt51l.dat\")\n"
+  "    (literal \"%s\")\n"
+  "    (literal \"%s\")\n"
   "    (literal \"%s\"))\n";
 
 bool StartMacSandbox(MacSandboxInfo aInfo, nsCString &aErrorMessage)
 {
   if (aInfo.type != MacSandboxType_Plugin) {
     aErrorMessage.AppendPrintf("Unexpected sandbox type %u", aInfo.type);
     return false;
   }
 
   nsAutoCString profile;
   if (nsCocoaFeatures::OnLionOrLater()) {
     profile.AppendPrintf(rules, ";",
                          aInfo.pluginInfo.pluginPath.get(),
-                         aInfo.pluginInfo.pluginBinaryPath.get());
+                         aInfo.pluginInfo.pluginBinaryPath.get(),
+                         aInfo.appPath.get(),
+                         aInfo.appBinaryPath.get());
   } else {
     profile.AppendPrintf(rules, "",
                          aInfo.pluginInfo.pluginPath.get(),
-                         aInfo.pluginInfo.pluginBinaryPath.get());
+                         aInfo.pluginInfo.pluginBinaryPath.get(),
+                         aInfo.appPath.get(),
+                         aInfo.appBinaryPath.get());
   }
 
   char *errorbuf = NULL;
   if (sandbox_init(profile.get(), 0, &errorbuf)) {
     if (errorbuf) {
       aErrorMessage.AppendPrintf("sandbox_init() failed with error \"%s\"",
                                  errorbuf);
       printf("profile: %s\n", profile.get());
--- a/toolkit/modules/BrowserUtils.jsm
+++ b/toolkit/modules/BrowserUtils.jsm
@@ -10,20 +10,19 @@ const {interfaces: Ci, utils: Cu, classe
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 this.BrowserUtils = {
 
   /**
    * Prints arguments separated by a space and appends a new line.
    */
-  dumpLn: function () {
-    for (let i = 0; i < arguments.length; i++) {
-      dump(arguments[i] + " ");
-    }
+  dumpLn: function (...args) {
+    for (let a of args)
+      dump(a + " ");
     dump("\n");
   },
 
   /**
    * urlSecurityCheck: JavaScript wrapper for checkLoadURIWithPrincipal
    * and checkLoadURIStrWithPrincipal.
    * If |aPrincipal| is not allowed to link to |aURL|, this function throws with
    * an error message.
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -583,16 +583,17 @@ nsresult nsDocumentOpenInfo::DispatchCon
       mContentType = APPLICATION_GUESS_FROM_EXT;
       aChannel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_GUESS_FROM_EXT));
     }
 
     rv = helperAppService->DoContent(mContentType,
                                      request,
                                      m_originalContext,
                                      false,
+                                     nullptr,
                                      getter_AddRefs(m_targetStreamListener));
     if (NS_FAILED(rv)) {
       request->SetLoadFlags(loadFlags);
       m_targetStreamListener = nullptr;
     }
   }
       
   NS_ASSERTION(m_targetStreamListener || NS_FAILED(rv),
--- a/uriloader/exthandler/ExternalHelperAppParent.cpp
+++ b/uriloader/exthandler/ExternalHelperAppParent.cpp
@@ -82,17 +82,18 @@ ExternalHelperAppParent::Init(ContentPar
   nsCOMPtr<nsIInterfaceRequestor> window;
   if (aBrowser) {
     TabParent* tabParent = static_cast<TabParent*>(aBrowser);
     if (tabParent->GetOwnerElement())
       window = do_QueryInterface(tabParent->GetOwnerElement()->OwnerDoc()->GetWindow());
   }
 
   helperAppService->DoContent(aMimeContentType, this, window,
-                              aForceSave, getter_AddRefs(mListener));
+                              aForceSave, nullptr,
+                              getter_AddRefs(mListener));
 }
 
 void
 ExternalHelperAppParent::ActorDestroy(ActorDestroyReason why)
 {
   mIPCClosed = true;
 }
 
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -607,94 +607,117 @@ nsresult nsExternalHelperAppService::Ini
   NS_ENSURE_SUCCESS(rv, rv);
   return obs->AddObserver(this, "last-pb-context-exited", true);
 }
 
 nsExternalHelperAppService::~nsExternalHelperAppService()
 {
 }
 
+
+nsresult
+nsExternalHelperAppService::DoContentContentProcessHelper(const nsACString& aMimeContentType,
+                                                          nsIRequest *aRequest,
+                                                          nsIInterfaceRequestor *aContentContext,
+                                                          bool aForceSave,
+                                                          nsIInterfaceRequestor *aWindowContext,
+                                                          nsIStreamListener ** aStreamListener)
+{
+  nsCOMPtr<nsIDOMWindow> window = do_GetInterface(aContentContext);
+  NS_ENSURE_STATE(window);
+
+  // We need to get a hold of a ContentChild so that we can begin forwarding
+  // this data to the parent.  In the HTTP case, this is unfortunate, since
+  // we're actually passing data from parent->child->parent wastefully, but
+  // the Right Fix will eventually be to short-circuit those channels on the
+  // parent side based on some sort of subscription concept.
+  using mozilla::dom::ContentChild;
+  using mozilla::dom::ExternalHelperAppChild;
+  ContentChild *child = ContentChild::GetSingleton();
+  if (!child) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCString disp;
+  nsCOMPtr<nsIURI> uri;
+  int64_t contentLength = -1;
+  uint32_t contentDisposition = -1;
+  nsAutoString fileName;
+
+  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+  if (channel) {
+    channel->GetURI(getter_AddRefs(uri));
+    channel->GetContentLength(&contentLength);
+    channel->GetContentDisposition(&contentDisposition);
+    channel->GetContentDispositionFilename(fileName);
+    channel->GetContentDispositionHeader(disp);
+  }
+
+  nsCOMPtr<nsIURI> referrer;
+  NS_GetReferrerFromChannel(channel, getter_AddRefs(referrer));
+
+  OptionalURIParams uriParams, referrerParams;
+  SerializeURI(uri, uriParams);
+  SerializeURI(referrer, referrerParams);
+
+  // Now we build a protocol for forwarding our data to the parent.  The
+  // protocol will act as a listener on the child-side and create a "real"
+  // helperAppService listener on the parent-side, via another call to
+  // DoContent.
+  mozilla::dom::PExternalHelperAppChild *pc =
+    child->SendPExternalHelperAppConstructor(uriParams,
+                                              nsCString(aMimeContentType),
+                                              disp, contentDisposition,
+                                              fileName, aForceSave, 
+                                              contentLength, referrerParams,
+                                              mozilla::dom::TabChild::GetFrom(window));
+  ExternalHelperAppChild *childListener = static_cast<ExternalHelperAppChild *>(pc);
+
+  NS_ADDREF(*aStreamListener = childListener);
+
+  uint32_t reason = nsIHelperAppLauncherDialog::REASON_CANTHANDLE;
+
+  nsRefPtr<nsExternalAppHandler> handler =
+    new nsExternalAppHandler(nullptr, EmptyCString(), aContentContext, aWindowContext, this,
+                             fileName, reason, aForceSave);
+  if (!handler) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  childListener->SetHandler(handler);
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeContentType,
                                                     nsIRequest *aRequest,
+                                                    nsIInterfaceRequestor *aContentContext,
+                                                    bool aForceSave,
                                                     nsIInterfaceRequestor *aWindowContext,
-                                                    bool aForceSave,
                                                     nsIStreamListener ** aStreamListener)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    return DoContentContentProcessHelper(aMimeContentType, aRequest, aContentContext,
+                                         aForceSave, aWindowContext, aStreamListener);
+  }
+
   nsAutoString fileName;
   nsAutoCString fileExtension;
   uint32_t reason = nsIHelperAppLauncherDialog::REASON_CANTHANDLE;
   uint32_t contentDisposition = -1;
 
-  nsresult rv;
-
   // Get the file extension and name that we will need later
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   nsCOMPtr<nsIURI> uri;
   int64_t contentLength = -1;
   if (channel) {
     channel->GetURI(getter_AddRefs(uri));
     channel->GetContentLength(&contentLength);
     channel->GetContentDisposition(&contentDisposition);
     channel->GetContentDispositionFilename(fileName);
-  }
-  
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    nsCOMPtr<nsIDOMWindow> window = do_GetInterface(aWindowContext);
-    NS_ENSURE_STATE(window);
-
-    // We need to get a hold of a ContentChild so that we can begin forwarding
-    // this data to the parent.  In the HTTP case, this is unfortunate, since
-    // we're actually passing data from parent->child->parent wastefully, but
-    // the Right Fix will eventually be to short-circuit those channels on the
-    // parent side based on some sort of subscription concept.
-    using mozilla::dom::ContentChild;
-    using mozilla::dom::ExternalHelperAppChild;
-    ContentChild *child = ContentChild::GetSingleton();
-    if (!child)
-      return NS_ERROR_FAILURE;
-
-    nsCString disp;
-    if (channel) {
-      channel->GetContentDispositionHeader(disp);
-    }
-
-    nsCOMPtr<nsIURI> referrer;
-    rv = NS_GetReferrerFromChannel(channel, getter_AddRefs(referrer));
-
-    OptionalURIParams uriParams, referrerParams;
-    SerializeURI(uri, uriParams);
-    SerializeURI(referrer, referrerParams);
-
-    // Now we build a protocol for forwarding our data to the parent.  The
-    // protocol will act as a listener on the child-side and create a "real"
-    // helperAppService listener on the parent-side, via another call to
-    // DoContent.
-    mozilla::dom::PExternalHelperAppChild *pc =
-      child->SendPExternalHelperAppConstructor(uriParams,
-                                               nsCString(aMimeContentType),
-                                               disp, contentDisposition,
-                                               fileName, aForceSave, 
-                                               contentLength, referrerParams,
-                                               mozilla::dom::TabChild::GetFrom(window));
-    ExternalHelperAppChild *childListener = static_cast<ExternalHelperAppChild *>(pc);
-
-    NS_ADDREF(*aStreamListener = childListener);
-
-    nsRefPtr<nsExternalAppHandler> handler =
-      new nsExternalAppHandler(nullptr, EmptyCString(), aWindowContext, this,
-                               fileName,
-                               reason, aForceSave);
-    if (!handler)
-      return NS_ERROR_OUT_OF_MEMORY;
-
-    childListener->SetHandler(handler);
-    return NS_OK;
-  }
-
-  if (channel) {
+
     // Check if we have a POST request, in which case we don't want to use
     // the url's extension
     bool allowURLExt = true;
     nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(channel);
     if (httpChan) {
       nsAutoCString requestMethod;
       httpChan->GetRequestMethod(requestMethod);
       allowURLExt = !requestMethod.EqualsLiteral("POST");
@@ -706,49 +729,53 @@ NS_IMETHODIMP nsExternalHelperAppService
     // bother checking the query
     if (uri && allowURLExt) {
       nsCOMPtr<nsIURL> url = do_QueryInterface(uri);
 
       if (url) {
         nsAutoCString query;
 
         // We only care about the query for HTTP and HTTPS URLs
+        nsresult rv;
         bool isHTTP, isHTTPS;
         rv = uri->SchemeIs("http", &isHTTP);
-        if (NS_FAILED(rv))
+        if (NS_FAILED(rv)) {
           isHTTP = false;
+        }
         rv = uri->SchemeIs("https", &isHTTPS);
-        if (NS_FAILED(rv))
+        if (NS_FAILED(rv)) {
           isHTTPS = false;
-
-        if (isHTTP || isHTTPS)
+        }
+        if (isHTTP || isHTTPS) {
           url->GetQuery(query);
+        }
 
         // Only get the extension if the query is empty; if it isn't, then the
         // extension likely belongs to a cgi script and isn't helpful
         allowURLExt = query.IsEmpty();
       }
     }
     // Extract name & extension
     bool isAttachment = GetFilenameAndExtensionFromChannel(channel, fileName,
                                                              fileExtension,
                                                              allowURLExt);
     LOG(("Found extension '%s' (filename is '%s', handling attachment: %i)",
          fileExtension.get(), NS_ConvertUTF16toUTF8(fileName).get(),
          isAttachment));
-    if (isAttachment)
+    if (isAttachment) {
       reason = nsIHelperAppLauncherDialog::REASON_SERVERREQUEST;
+    }
   }
 
   LOG(("HelperAppService::DoContent: mime '%s', extension '%s'\n",
        PromiseFlatCString(aMimeContentType).get(), fileExtension.get()));
 
-  // we get the mime service here even though we're the default implementation of it,
-  // so it's possible to override only the mime service and not need to reimplement the
-  // whole external helper app service itself
+  // We get the mime service here even though we're the default implementation
+  // of it, so it's possible to override only the mime service and not need to
+  // reimplement the whole external helper app service itself.
   nsCOMPtr<nsIMIMEService> mimeSvc(do_GetService(NS_MIMESERVICE_CONTRACTID));
   NS_ENSURE_TRUE(mimeSvc, NS_ERROR_FAILURE);
 
   // Try to find a mime object by looking at the mime type/extension
   nsCOMPtr<nsIMIMEInfo> mimeInfo;
   if (aMimeContentType.Equals(APPLICATION_GUESS_FROM_EXT, nsCaseInsensitiveCStringComparator())) {
     nsAutoCString mimeType;
     if (!fileExtension.IsEmpty()) {
@@ -762,49 +789,55 @@ NS_IMETHODIMP nsExternalHelperAppService
     }
 
     if (fileExtension.IsEmpty() || mimeType.IsEmpty()) {
       // Extension lookup gave us no useful match
       mimeSvc->GetFromTypeAndExtension(NS_LITERAL_CSTRING(APPLICATION_OCTET_STREAM), fileExtension,
                                        getter_AddRefs(mimeInfo));
       mimeType.AssignLiteral(APPLICATION_OCTET_STREAM);
     }
-    if (channel)
+
+    if (channel) {
       channel->SetContentType(mimeType);
+    }
+
     // Don't overwrite SERVERREQUEST
-    if (reason == nsIHelperAppLauncherDialog::REASON_CANTHANDLE)
+    if (reason == nsIHelperAppLauncherDialog::REASON_CANTHANDLE) {
       reason = nsIHelperAppLauncherDialog::REASON_TYPESNIFFED;
-  } 
-  else {
+    }
+  } else {
     mimeSvc->GetFromTypeAndExtension(aMimeContentType, fileExtension,
                                      getter_AddRefs(mimeInfo));
   } 
   LOG(("Type/Ext lookup found 0x%p\n", mimeInfo.get()));
 
   // No mimeinfo -> we can't continue. probably OOM.
-  if (!mimeInfo)
+  if (!mimeInfo) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   *aStreamListener = nullptr;
   // We want the mimeInfo's primary extension to pass it to
   // nsExternalAppHandler
   nsAutoCString buf;
   mimeInfo->GetPrimaryExtension(buf);
 
   nsExternalAppHandler * handler = new nsExternalAppHandler(mimeInfo,
                                                             buf,
+                                                            aContentContext,
                                                             aWindowContext,
                                                             this,
                                                             fileName,
                                                             reason,
                                                             aForceSave);
-  if (!handler)
+  if (!handler) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   NS_ADDREF(*aStreamListener = handler);
-  
   return NS_OK;
 }
 
 NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension(const nsACString& aExtension,
                                                                     const nsACString& aEncodingType,
                                                                     bool *aApplyDecoding)
 {
   *aApplyDecoding = true;
@@ -1149,21 +1182,23 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHand
    NS_INTERFACE_MAP_ENTRY(nsIHelperAppLauncher)
    NS_INTERFACE_MAP_ENTRY(nsICancelable)
    NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
    NS_INTERFACE_MAP_ENTRY(nsIBackgroundFileSaverObserver)
 NS_INTERFACE_MAP_END_THREADSAFE
 
 nsExternalAppHandler::nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo,
                                            const nsCSubstring& aTempFileExtension,
+                                           nsIInterfaceRequestor* aContentContext,
                                            nsIInterfaceRequestor* aWindowContext,
                                            nsExternalHelperAppService *aExtProtSvc,
                                            const nsAString& aSuggestedFilename,
                                            uint32_t aReason, bool aForceSave)
 : mMimeInfo(aMIMEInfo)
+, mContentContext(aContentContext)
 , mWindowContext(aWindowContext)
 , mWindowToClose(nullptr)
 , mSuggestedFileName(aSuggestedFilename)
 , mForceSave(aForceSave)
 , mCanceled(false)
 , mShouldCloseWindow(false)
 , mStopRequestIssued(false)
 , mReason(aReason)
@@ -1281,27 +1316,29 @@ void nsExternalAppHandler::RetargetLoadN
   // ideally we should be able to just use mChannel (the channel we are extracting content from) or
   // the default load channel associated with the original load group. Unfortunately because
   // a redirect may have occurred, the doc loader is the only one with a ptr to the original channel 
   // which is what we really want....
 
   // Note that we need to do this before removing aChannel from the loadgroup,
   // since that would mess with the original channel on the loader.
   nsCOMPtr<nsIDocumentLoader> origContextLoader =
-    do_GetInterface(mWindowContext);
-  if (origContextLoader)
+    do_GetInterface(mContentContext);
+  if (origContextLoader) {
     origContextLoader->GetDocumentChannel(getter_AddRefs(mOriginalChannel));
+  }
 
   bool isPrivate = NS_UsePrivateBrowsing(aChannel);
 
   nsCOMPtr<nsILoadGroup> oldLoadGroup;
   aChannel->GetLoadGroup(getter_AddRefs(oldLoadGroup));
 
-  if(oldLoadGroup)
-     oldLoadGroup->RemoveRequest(request, nullptr, NS_BINDING_RETARGETED);
+  if(oldLoadGroup) {
+    oldLoadGroup->RemoveRequest(request, nullptr, NS_BINDING_RETARGETED);
+  }
       
   aChannel->SetLoadGroup(nullptr);
   aChannel->SetNotificationCallbacks(nullptr);
 
   nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(aChannel);
   if (pbChannel) {
     pbChannel->SetPrivate(isPrivate);
   }
@@ -1486,18 +1523,17 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
   if (props) {
     bool tmp = false;
     props->GetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
                              &tmp);
     mShouldCloseWindow = tmp;
   }
 
   // Now get the URI
-  if (aChannel)
-  {
+  if (aChannel) {
     aChannel->GetURI(getter_AddRefs(mSourceUrl));
   }
 
   // retarget all load notifications to our docloader instead of the original window's docloader...
   RetargetLoadNotifications(request);
 
   // Check to see if there is a refresh header on the original channel.
   if (mOriginalChannel) {
@@ -1518,55 +1554,50 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
 
   // In an IPC setting, we're allowing the child process, here, to make
   // decisions about decoding the channel (e.g. decompression).  It will
   // still forward the decoded (uncompressed) data back to the parent.
   // Con: Uncompressed data means more IPC overhead.
   // Pros: ExternalHelperAppParent doesn't need to implement nsIEncodedChannel.
   //       Parent process doesn't need to expect CPU time on decompression.
   nsCOMPtr<nsIEncodedChannel> encChannel = do_QueryInterface( aChannel );
-  if (encChannel) 
-  {
+  if (encChannel) {
     // Turn off content encoding conversions if needed
     bool applyConversion = true;
 
     nsCOMPtr<nsIURL> sourceURL(do_QueryInterface(mSourceUrl));
-    if (sourceURL)
-    {
+    if (sourceURL) {
       nsAutoCString extension;
       sourceURL->GetFileExtension(extension);
-      if (!extension.IsEmpty())
-      {
+      if (!extension.IsEmpty()) {
         nsCOMPtr<nsIUTF8StringEnumerator> encEnum;
         encChannel->GetContentEncodings(getter_AddRefs(encEnum));
-        if (encEnum)
-        {
+        if (encEnum) {
           bool hasMore;
           rv = encEnum->HasMore(&hasMore);
-          if (NS_SUCCEEDED(rv) && hasMore)
-          {
+          if (NS_SUCCEEDED(rv) && hasMore) {
             nsAutoCString encType;
             rv = encEnum->GetNext(encType);
-            if (NS_SUCCEEDED(rv) && !encType.IsEmpty())
-            {
+            if (NS_SUCCEEDED(rv) && !encType.IsEmpty()) {
               mExtProtSvc->ApplyDecodingForExtension(extension, encType,
                                                      &applyConversion);
             }
           }
         }
       }    
     }
 
     encChannel->SetApplyConversion( applyConversion );
   }
 
   // At this point, the child process has done everything it can usefully do
   // for OnStartRequest.
-  if (XRE_GetProcessType() == GeckoProcessType_Content)
-     return NS_OK;
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    return NS_OK;
+  }
 
   rv = SetUpTempFile(aChannel);
   if (NS_FAILED(rv)) {
     nsresult transferError = rv;
 
     rv = CreateFailedTransfer(aChannel && NS_UsePrivateBrowsing(aChannel));
 #ifdef PR_LOGGING
     if (NS_FAILED(rv)) {
@@ -1604,42 +1635,37 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
   // is one part of a multipart document).  Opening sniffed content in helper
   // apps by default introduces security holes that we'd rather not have.
 
   // So let's find out whether the user wants to be prompted.  If he does not,
   // check mReason and the preferred action to see what we should do.
 
   bool alwaysAsk = true;
   mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk);
-  if (alwaysAsk)
-  {
+  if (alwaysAsk) {
     // But we *don't* ask if this mimeInfo didn't come from
     // our user configuration datastore and the user has said
     // at some point in the distant past that they don't
     // want to be asked.  The latter fact would have been
     // stored in pref strings back in the old days.
 
     bool mimeTypeIsInDatastore = false;
     nsCOMPtr<nsIHandlerService> handlerSvc = do_GetService(NS_HANDLERSERVICE_CONTRACTID);
-    if (handlerSvc)
+    if (handlerSvc) {
       handlerSvc->Exists(mMimeInfo, &mimeTypeIsInDatastore);
-    if (!handlerSvc || !mimeTypeIsInDatastore)
-    {
+    }
+    if (!handlerSvc || !mimeTypeIsInDatastore) {
       nsAutoCString MIMEType;
       mMimeInfo->GetMIMEType(MIMEType);
-
-      if (!GetNeverAskFlagFromPref(NEVER_ASK_FOR_SAVE_TO_DISK_PREF, MIMEType.get()))
-      {
+      if (!GetNeverAskFlagFromPref(NEVER_ASK_FOR_SAVE_TO_DISK_PREF, MIMEType.get())) {
         // Don't need to ask after all.
         alwaysAsk = false;
         // Make sure action matches pref (save to disk).
         mMimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk);
-      }
-      else if (!GetNeverAskFlagFromPref(NEVER_ASK_FOR_OPEN_FILE_PREF, MIMEType.get()))
-      {
+      } else if (!GetNeverAskFlagFromPref(NEVER_ASK_FOR_OPEN_FILE_PREF, MIMEType.get())) {
         // Don't need to ask after all.
         alwaysAsk = false;
       }
     }
   }
 
   int32_t action = nsIMIMEInfo::saveToDisk;
   mMimeInfo->GetPreferredAction( &action );
@@ -1655,23 +1681,23 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
   // before this is irrelevant; override it
   if (mForceSave) {
     alwaysAsk = false;
     action = nsIMIMEInfo::saveToDisk;
   }
   
   if (alwaysAsk)
   {
-    // invoke the dialog!!!!! use mWindowContext as the window context parameter for the dialog request
-    mDialog = do_CreateInstance( NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv );
+    // Display the dialog
+    mDialog = do_CreateInstance(NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // this will create a reference cycle (the dialog holds a reference to us as
     // nsIHelperAppLauncher), which will be broken in Cancel or CreateTransfer.
-    rv = mDialog->Show( this, mWindowContext, mReason );
+    rv = mDialog->Show(this, GetDialogParent(), mReason);
 
     // what do we do if the dialog failed? I guess we should call Cancel and abort the load....
   }
   else
   {
 
     // We need to do the save/open immediately, then.
 #ifdef XP_WIN
@@ -1698,36 +1724,32 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
       } else {   // Paranoia is good here too, though this really should not happen
         NS_WARNING("GetDownloadInfo returned a null file after the temp file has been set up! ");
         action = nsIMIMEInfo::saveToDisk;
       }
     }
 
 #endif
     if (action == nsIMIMEInfo::useHelperApp ||
-        action == nsIMIMEInfo::useSystemDefault)
-    {
+        action == nsIMIMEInfo::useSystemDefault) {
         rv = LaunchWithApplication(nullptr, false);
-    }
-    else // Various unknown actions go here too
-    {
+    } else {
         rv = SaveToDisk(nullptr, false);
     }
   }
 
   return NS_OK;
 }
 
 // Convert error info into proper message text and send OnStatusChange
 // notification to the dialog progress listener or nsITransfer implementation.
 void nsExternalAppHandler::SendStatusChange(ErrorType type, nsresult rv, nsIRequest *aRequest, const nsAFlatString &path)
 {
     nsAutoString msgId;
-    switch(rv)
-    {
+    switch (rv) {
     case NS_ERROR_OUT_OF_MEMORY:
         // No memory
         msgId.AssignLiteral("noMemory");
         break;
 
     case NS_ERROR_FILE_DISK_FULL:
     case NS_ERROR_FILE_NO_DEVICE_SPACE:
         // Out of space on target volume.
@@ -1744,19 +1766,17 @@ void nsExternalAppHandler::SendStatusCha
           // Attempt to write without sufficient permissions.
 #if defined(ANDROID)
           // On Android (and Gonk), this means the SD card is present but
           // unavailable (read-only).
           msgId.AssignLiteral("SDAccessErrorCardReadOnly");
 #else
           msgId.AssignLiteral("accessError");
 #endif
-        }
-        else
-        {
+        } else {
           msgId.AssignLiteral("launchError");
         }
         break;
 
     case NS_ERROR_FILE_NOT_FOUND:
     case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST:
     case NS_ERROR_FILE_UNRECOGNIZED_PATH:
         // Helper app not found, let's verify this happened on launch
@@ -1771,18 +1791,17 @@ void nsExternalAppHandler::SendStatusCha
           msgId.AssignLiteral("SDAccessErrorCardMissing");
           break;
         }
 #endif
         // fall through
 
     default:
         // Generic read/write/launch error message.
-        switch(type)
-        {
+        switch (type) {
         case kReadError:
           msgId.AssignLiteral("readError");
           break;
         case kWriteError:
           msgId.AssignLiteral("writeError");
           break;
         case kLaunchError:
           msgId.AssignLiteral("launchError");
@@ -1794,76 +1813,69 @@ void nsExternalAppHandler::SendStatusCha
         ("Error: %s, type=%i, listener=0x%p, transfer=0x%p, rv=0x%08X\n",
          NS_LossyConvertUTF16toASCII(msgId).get(), type, mDialogProgressListener.get(), mTransfer.get(), rv));
     PR_LOG(nsExternalHelperAppService::mLog, PR_LOG_ERROR,
         ("       path='%s'\n", NS_ConvertUTF16toUTF8(path).get()));
 
     // Get properties file bundle and extract status string.
     nsCOMPtr<nsIStringBundleService> stringService =
         mozilla::services::GetStringBundleService();
-    if (stringService)
-    {
+    if (stringService) {
         nsCOMPtr<nsIStringBundle> bundle;
-        if (NS_SUCCEEDED(stringService->CreateBundle("chrome://global/locale/nsWebBrowserPersist.properties", getter_AddRefs(bundle))))
-        {
+        if (NS_SUCCEEDED(stringService->CreateBundle("chrome://global/locale/nsWebBrowserPersist.properties",
+                         getter_AddRefs(bundle)))) {
             nsXPIDLString msgText;
             const char16_t *strings[] = { path.get() };
-            if(NS_SUCCEEDED(bundle->FormatStringFromName(msgId.get(), strings, 1, getter_Copies(msgText))))
-            {
-              if (mDialogProgressListener)
-              {
+            if (NS_SUCCEEDED(bundle->FormatStringFromName(msgId.get(), strings, 1,
+                                                          getter_Copies(msgText)))) {
+              if (mDialogProgressListener) {
                 // We have a listener, let it handle the error.
                 mDialogProgressListener->OnStatusChange(nullptr, (type == kReadError) ? aRequest : nullptr, rv, msgText);
               } else if (mTransfer) {
                 mTransfer->OnStatusChange(nullptr, (type == kReadError) ? aRequest : nullptr, rv, msgText);
-              }
-              else
-              if (XRE_GetProcessType() == GeckoProcessType_Default) {
+              } else if (XRE_GetProcessType() == GeckoProcessType_Default) {
                 // We don't have a listener.  Simply show the alert ourselves.
                 nsresult qiRv;
-                nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mWindowContext, &qiRv));
+                nsCOMPtr<nsIPrompt> prompter(do_GetInterface(GetDialogParent(), &qiRv));
                 nsXPIDLString title;
                 bundle->FormatStringFromName(MOZ_UTF16("title"),
                                              strings,
                                              1,
                                              getter_Copies(title));
 
                 PR_LOG(nsExternalHelperAppService::mLog, PR_LOG_DEBUG,
-                       ("mWindowContext=0x%p, prompter=0x%p, qi rv=0x%08X, title='%s', msg='%s'",
-                       mWindowContext.get(),
+                       ("mContentContext=0x%p, prompter=0x%p, qi rv=0x%08X, title='%s', msg='%s'",
+                       mContentContext.get(),
                        prompter.get(),
                        qiRv,
                        NS_ConvertUTF16toUTF8(title).get(),
                        NS_ConvertUTF16toUTF8(msgText).get()));
 
                 // If we didn't have a prompter we will try and get a window
                 // instead, get it's docshell and use it to alert the user.
-                if (!prompter)
-                {
-                  nsCOMPtr<nsPIDOMWindow> window(do_GetInterface(mWindowContext));
-                  if (!window || !window->GetDocShell())
-                  {
+                if (!prompter) {
+                  nsCOMPtr<nsPIDOMWindow> window(do_GetInterface(GetDialogParent()));
+                  if (!window || !window->GetDocShell()) {
                     return;
                   }
 
                   prompter = do_GetInterface(window->GetDocShell(), &qiRv);
 
                   PR_LOG(nsExternalHelperAppService::mLog, PR_LOG_DEBUG,
-                         ("No prompter from mWindowContext, using DocShell, " \
+                         ("No prompter from mContentContext, using DocShell, " \
                           "window=0x%p, docShell=0x%p, " \
                           "prompter=0x%p, qi rv=0x%08X",
                           window.get(),
                           window->GetDocShell(),
                           prompter.get(),
                           qiRv));
 
                   // If we still don't have a prompter, there's nothing else we
                   // can do so just return.
-                  if (!prompter)
-                  {
+                  if (!prompter) {
                     PR_LOG(nsExternalHelperAppService::mLog, PR_LOG_ERROR,
                            ("No prompter from DocShell, no way to alert user"));
                     return;
                   }
                 }
 
                 // We should always have a prompter at this point.
                 prompter->Alert(title, msgText);
@@ -1875,41 +1887,40 @@ void nsExternalAppHandler::SendStatusCha
 
 NS_IMETHODIMP
 nsExternalAppHandler::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt,
                                       nsIInputStream * inStr,
                                       uint64_t sourceOffset, uint32_t count)
 {
   nsresult rv = NS_OK;
   // first, check to see if we've been canceled....
-  if (mCanceled || !mSaver) // then go cancel our underlying channel too
+  if (mCanceled || !mSaver) {
+    // then go cancel our underlying channel too
     return request->Cancel(NS_BINDING_ABORTED);
+  }
 
   // read the data out of the stream and write it to the temp file.
-  if (count > 0)
-  {
+  if (count > 0) {
     mProgress += count;
 
     nsCOMPtr<nsIStreamListener> saver = do_QueryInterface(mSaver);
     rv = saver->OnDataAvailable(request, aCtxt, inStr, sourceOffset, count);
-    if (NS_SUCCEEDED(rv))
-    {
+    if (NS_SUCCEEDED(rv)) {
       // Send progress notification.
       if (mTransfer) {
         mTransfer->OnProgressChange64(nullptr, request, mProgress,
                                       mContentLength, mProgress,
                                       mContentLength);
       }
-    }
-    else
-    {
+    } else {
       // An error occurred, notify listener.
       nsAutoString tempFilePath;
-      if (mTempFile)
+      if (mTempFile) {
         mTempFile->GetPath(tempFilePath);
+      }
       SendStatusChange(kReadError, rv, request, tempFilePath);
 
       // Cancel the download.
       Cancel(rv);
     }
   }
   return rv;
 }
@@ -1919,30 +1930,30 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
 {
   LOG(("nsExternalAppHandler::OnStopRequest\n"
        "  mCanceled=%d, mTransfer=0x%p, aStatus=0x%08X\n",
        mCanceled, mTransfer.get(), aStatus));
 
   mStopRequestIssued = true;
 
   // Cancel if the request did not complete successfully.
-  if (!mCanceled && NS_FAILED(aStatus))
-  {
+  if (!mCanceled && NS_FAILED(aStatus)) {
     // Send error notification.
     nsAutoString tempFilePath;
     if (mTempFile)
       mTempFile->GetPath(tempFilePath);
     SendStatusChange( kReadError, aStatus, request, tempFilePath );
 
     Cancel(aStatus);
   }
 
   // first, check to see if we've been canceled....
-  if (mCanceled || !mSaver)
+  if (mCanceled || !mSaver) {
     return NS_OK;
+  }
 
   return mSaver->Finish(NS_OK);
 }
 
 NS_IMETHODIMP
 nsExternalAppHandler::OnTargetChange(nsIBackgroundFileSaver *aSaver,
                                      nsIFile *aTarget)
 {
@@ -2178,24 +2189,23 @@ nsresult nsExternalAppHandler::SaveDesti
   else
     Cancel(NS_BINDING_ABORTED);
 
   return NS_OK;
 }
 
 void nsExternalAppHandler::RequestSaveDestination(const nsAFlatString &aDefaultFile, const nsAFlatString &aFileExtension)
 {
-  // invoke the dialog!!!!! use mWindowContext as the window context parameter for the dialog request
-  // Convert to use file picker? No, then embeddors could not do any sort of
+  // Display the dialog
+  // XXX Convert to use file picker? No, then embeddors could not do any sort of
   // "AutoDownload" w/o showing a prompt
   nsresult rv = NS_OK;
-  if (!mDialog)
-  {
+  if (!mDialog) {
     // Get helper app launcher dialog.
-    mDialog = do_CreateInstance( NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv );
+    mDialog = do_CreateInstance(NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv);
     if (rv != NS_OK) {
       Cancel(NS_BINDING_ABORTED);
       return;
     }
   }
 
   // we want to explicitly unescape aDefaultFile b4 passing into the dialog. we can't unescape
   // it because the dialog is implemented by a JS component which doesn't have a window so no unescape routine is defined...
@@ -2204,25 +2214,25 @@ void nsExternalAppHandler::RequestSaveDe
   // If we don't do this, users that close the helper app dialog while the file
   // picker is up would cause Cancel() to be called, and the dialog would be
   // released, which would release this object too, which would crash.
   // See Bug 249143
   nsIFile* fileToUse;
   nsRefPtr<nsExternalAppHandler> kungFuDeathGrip(this);
   nsCOMPtr<nsIHelperAppLauncherDialog> dlg(mDialog);
   rv = mDialog->PromptForSaveToFile(this,
-                                    mWindowContext,
+                                    GetDialogParent(),
                                     aDefaultFile.get(),
                                     aFileExtension.get(),
                                     mForceSave, &fileToUse);
 
   if (rv == NS_ERROR_NOT_AVAILABLE) {
     // we need to use the async version -> nsIHelperAppLauncherDialog.promptForSaveToFileAsync.
     rv = mDialog->PromptForSaveToFileAsync(this, 
-                                           mWindowContext,
+                                           GetDialogParent(),
                                            aDefaultFile.get(),
                                            aFileExtension.get(),
                                            mForceSave);
   } else {
     SaveDestinationAvailable(rv == NS_OK ? fileToUse : nullptr);
   }
 }
 
@@ -2329,24 +2339,22 @@ NS_IMETHODIMP nsExternalAppHandler::Laun
     PlatformLocalHandlerApp_t *handlerApp =
       new PlatformLocalHandlerApp_t(EmptyString(), aApplication);
     mMimeInfo->SetPreferredApplicationHandler(handlerApp);
   }
 
   // Now check if the file is local, in which case we won't bother with saving
   // it to a temporary directory and just launch it from where it is
   nsCOMPtr<nsIFileURL> fileUrl(do_QueryInterface(mSourceUrl));
-  if (fileUrl && mIsFileChannel)
-  {
+  if (fileUrl && mIsFileChannel) {
     Cancel(NS_BINDING_ABORTED);
     nsCOMPtr<nsIFile> file;
     nsresult rv = fileUrl->GetFile(getter_AddRefs(file));
 
-    if (NS_SUCCEEDED(rv))
-    {
+    if (NS_SUCCEEDED(rv)) {
       rv = mMimeInfo->LaunchWithFile(file);
       if (NS_SUCCEEDED(rv))
         return NS_OK;
     }
     nsAutoString path;
     if (file)
       file->GetPath(path);
     // If we get here, an error happened
@@ -2359,40 +2367,36 @@ NS_IMETHODIMP nsExternalAppHandler::Laun
   // was specified in mSuggestedFileName after the download is done prior to
   // launching the helper app.  So that any existing file of that name won't be
   // overwritten we call CreateUnique().  Also note that we use the same
   // directory as originally downloaded so nsDownload can rename in place
   // later.
   nsCOMPtr<nsIFile> fileToUse;
   (void) GetDownloadDirectory(getter_AddRefs(fileToUse));
 
-  if (mSuggestedFileName.IsEmpty())
-  {
+  if (mSuggestedFileName.IsEmpty()) {
     // Keep using the leafname of the temp file, since we're just starting a helper
     mSuggestedFileName = mTempLeafName;
   }
 
 #ifdef XP_WIN
   fileToUse->Append(mSuggestedFileName + mTempFileExtension);
 #else
   fileToUse->Append(mSuggestedFileName);  
 #endif
 
   nsresult rv = fileToUse->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
-  if(NS_SUCCEEDED(rv))
-  {
+  if(NS_SUCCEEDED(rv)) {
     mFinalFileDestination = do_QueryInterface(fileToUse);
     // launch the progress window now that the user has picked the desired action.
     rv = CreateTransfer();
     if (NS_FAILED(rv)) {
       Cancel(rv);
     }
-  }
-  else
-  {
+  } else {
     // Cancel the download and report an error.  We do not want to end up in
     // a state where it appears that we have a normal download that is
     // pointing to a file that we did not actually create.
     nsAutoString path;
     mTempFile->GetPath(path);
     SendStatusChange(kWriteError, rv, nullptr, path);
     Cancel(rv);
   }
@@ -2446,19 +2450,18 @@ void nsExternalAppHandler::ProcessAnyRef
 {
    // one last thing, try to see if the original window context supports a refresh interface...
    // Sometimes, when you download content that requires an external handler, there is
    // a refresh header associated with the download. This refresh header points to a page
    // the content provider wants the user to see after they download the content. How do we
    // pass this refresh information back to the caller? For now, try to get the refresh URI
    // interface. If the window context where the request originated came from supports this
    // then we can force it to process the refresh information (if there is any) from this channel.
-   if (mWindowContext && mOriginalChannel)
-   {
-     nsCOMPtr<nsIRefreshURI> refreshHandler (do_GetInterface(mWindowContext));
+   if (mContentContext && mOriginalChannel) {
+     nsCOMPtr<nsIRefreshURI> refreshHandler (do_GetInterface(mContentContext));
      if (refreshHandler) {
         refreshHandler->SetupRefreshURI(mOriginalChannel);
      }
      mOriginalChannel = nullptr;
    }
 }
 
 bool nsExternalAppHandler::GetNeverAskFlagFromPref(const char * prefName, const char * aContentType)
@@ -2475,28 +2478,28 @@ bool nsExternalAppHandler::GetNeverAskFl
   prefCString.BeginReading(start);
   prefCString.EndReading(end);
   return !CaseInsensitiveFindInReadable(nsDependentCString(aContentType),
                                         start, end);
 }
 
 nsresult nsExternalAppHandler::MaybeCloseWindow()
 {
-  nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mWindowContext);
+  nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mContentContext);
   NS_ENSURE_STATE(window);
 
   if (mShouldCloseWindow) {
     // Reset the window context to the opener window so that the dependent
     // dialogs have a parent
     nsCOMPtr<nsIDOMWindow> opener;
     window->GetOpener(getter_AddRefs(opener));
 
     bool isClosed;
     if (opener && NS_SUCCEEDED(opener->GetClosed(&isClosed)) && !isClosed) {
-      mWindowContext = do_GetInterface(opener);
+      mContentContext = do_GetInterface(opener);
 
       // Now close the old window.  Do it on a timer so that we don't run
       // into issues trying to close the window before it has fully opened.
       NS_ASSERTION(!mTimer, "mTimer was already initialized once!");
       mTimer = do_CreateInstance("@mozilla.org/timer;1");
       if (!mTimer) {
         return NS_ERROR_FAILURE;
       }
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -181,16 +181,24 @@ protected:
    * Array for the files that should be deleted
    */
   nsCOMArray<nsIFile> mTemporaryFilesList;
   /**
    * Array for the files that should be deleted (for the temporary files
    * added during the private browsing mode)
    */
   nsCOMArray<nsIFile> mTemporaryPrivateFilesList;
+
+private:
+  nsresult DoContentContentProcessHelper(const nsACString& aMimeContentType,
+                                         nsIRequest *aRequest,
+                                         nsIInterfaceRequestor *aContentContext,
+                                         bool aForceSave,
+                                         nsIInterfaceRequestor *aWindowContext,
+                                         nsIStreamListener ** aStreamListener);
 };
 
 /**
  * An external app handler is just a small little class that presents itself as
  * a nsIStreamListener. It saves the incoming data into a temp file. The handler
  * is bound to an application when it is created. When it receives an
  * OnStopRequest it launches the application using the temp file it has
  * stored the data into.  We create a handler every time we have to process
@@ -206,49 +214,68 @@ public:
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSIHELPERAPPLAUNCHER
   NS_DECL_NSICANCELABLE
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIBACKGROUNDFILESAVEROBSERVER
 
   /**
-   * @param aMIMEInfo      MIMEInfo object, representing the type of the
-   *                       content that should be handled
-   * @param aFileExtension The extension we need to append to our temp file,
-   *                       INCLUDING the ".". e.g. .mp3
-   * @param aWindowContext Window context, as passed to DoContent
-   * @param mExtProtSvc    nsExternalHelperAppService on creation
-   * @param aFileName      The filename to use
-   * @param aReason        A constant from nsIHelperAppLauncherDialog indicating
-   *                       why the request is handled by a helper app.
+   * @param aMIMEInfo       MIMEInfo object, representing the type of the
+   *                        content that should be handled
+   * @param aFileExtension  The extension we need to append to our temp file,
+   *                        INCLUDING the ".". e.g. .mp3
+   * @param aContentContext dom Window context, as passed to DoContent.
+   * @param aWindowContext  Top level window context used in dialog parenting,
+   *                        as passed to DoContent. This parameter may be null,
+   *                        in which case dialogs will be parented to
+   *                        aContentContext.
+   * @param mExtProtSvc     nsExternalHelperAppService on creation
+   * @param aFileName       The filename to use
+   * @param aReason         A constant from nsIHelperAppLauncherDialog indicating
+   *                        why the request is handled by a helper app.
    */
   nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo, const nsCSubstring& aFileExtension,
+                       nsIInterfaceRequestor * aContentContext,
                        nsIInterfaceRequestor * aWindowContext,
                        nsExternalHelperAppService * aExtProtSvc,
                        const nsAString& aFilename,
                        uint32_t aReason, bool aForceSave);
 
   /**
    * Clean up after the request was diverted to the parent process.
    */
   void DidDivertRequest(nsIRequest *request);
 
 protected:
   ~nsExternalAppHandler();
 
+  nsIInterfaceRequestor* GetDialogParent() {
+    return mWindowContext ? mWindowContext : mContentContext;
+  }
+
   nsCOMPtr<nsIFile> mTempFile;
   nsCOMPtr<nsIURI> mSourceUrl;
   nsString mTempFileExtension;
   nsString mTempLeafName;
 
   /**
    * The MIME Info for this load. Will never be null.
    */
   nsCOMPtr<nsIMIMEInfo> mMimeInfo;
+
+  /**
+   * The dom window associated with this request to handle content.
+   */
+  nsCOMPtr<nsIInterfaceRequestor> mContentContext;
+
+  /**
+   * If set, the parent window helper app dialogs and file pickers
+   * should use in parenting. If null, we use mContentContext.
+   */
   nsCOMPtr<nsIInterfaceRequestor> mWindowContext;
 
   /**
    * Used to close the window on a timer, to avoid any exceptions that are
    * thrown if we try to close the window before it's fully loaded.
    */
   nsCOMPtr<nsIDOMWindow> mWindowToClose;
   nsCOMPtr<nsITimer> mTimer;
--- a/uriloader/exthandler/nsIExternalHelperAppService.idl
+++ b/uriloader/exthandler/nsIExternalHelperAppService.idl
@@ -13,36 +13,41 @@ interface nsIFile;
 interface nsIMIMEInfo;
 interface nsIWebProgressListener2;
 interface nsIInterfaceRequestor;
 
 /**
  * The external helper app service is used for finding and launching
  * platform specific external applications for a given mime content type.
  */
-[scriptable, uuid(9e456297-ba3e-42b1-92bd-b7db014268cb)]
+[scriptable, uuid(1E4F3AE1-B737-431F-A95D-31FA8DA70199)]
 interface nsIExternalHelperAppService : nsISupports
 {
   /**
    * Binds an external helper application to a stream listener. The caller
    * should pump data into the returned stream listener. When the OnStopRequest
    * is issued, the stream listener implementation will launch the helper app
    * with this data.
    * @param aMimeContentType The content type of the incoming data
    * @param aRequest The request corresponding to the incoming data
-   * @param aWindowContext Use GetInterface to retrieve properties like the
-   *                       dom window or parent window...
-   *                       The service might need this in order to bring up dialogs.
+   * @param aContentContext Used in processing content document refresh
+   *  headers after target content is downloaded. Note in e10s land
+   *  this is likely a CPOW that points to a window in the child process.
    * @param aForceSave True to always save this content to disk, regardless of
-   *                   nsIMIMEInfo and other such influences.
+   *  nsIMIMEInfo and other such influences.
+   * @param aWindowContext Used in parenting helper app dialogs, usually
+   *  points to the parent browser window. This parameter may be null,
+   *  in which case dialogs will be parented to aContentContext.
    * @return A nsIStreamListener which the caller should pump the data into.
    */
-  nsIStreamListener doContent (in ACString aMimeContentType, in nsIRequest aRequest,
-                               in nsIInterfaceRequestor aWindowContext,
-                               in boolean aForceSave); 
+  nsIStreamListener doContent (in ACString aMimeContentType,
+                               in nsIRequest aRequest,
+                               in nsIInterfaceRequestor aContentContext,
+                               in boolean aForceSave,
+                               [optional] in nsIInterfaceRequestor aWindowContext); 
 
   /**
    * Returns true if data from a URL with this extension combination
    * is to be decoded from aEncodingType prior to saving or passing
    * off to helper apps, false otherwise.
    */
   boolean applyDecodingForExtension(in AUTF8String aExtension,
                                     in ACString aEncodingType);
--- a/widget/windows/nsColorPicker.cpp
+++ b/widget/windows/nsColorPicker.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsColorPicker.h"
 
 #include <shlwapi.h>
 
 #include "mozilla/AutoRestore.h"
 #include "nsIWidget.h"
+#include "nsString.h"
 #include "WidgetUtils.h"
 
 using namespace mozilla::widget;
 
 namespace
 {
 // Manages NS_NATIVE_TMP_WINDOW child windows. NS_NATIVE_TMP_WINDOWs are
 // temporary child windows of mParentWidget created to address RTL issues
@@ -85,65 +86,101 @@ BGRIntToRGBString(DWORD color, nsAString
 
   aResult.Assign('#');
   aResult.Append(ToHexString(r));
   aResult.Append(ToHexString(g));
   aResult.Append(ToHexString(b));
 }
 } // anonymous namespace
 
-AsyncColorChooser::AsyncColorChooser(const nsAString& aInitialColor,
+static AsyncColorChooser* gColorChooser;
+
+AsyncColorChooser::AsyncColorChooser(COLORREF aInitialColor,
                                      nsIWidget* aParentWidget,
                                      nsIColorPickerShownCallback* aCallback)
   : mInitialColor(aInitialColor)
+  , mColor(aInitialColor)
   , mParentWidget(aParentWidget)
   , mCallback(aCallback)
 {
 }
 
 NS_IMETHODIMP
 AsyncColorChooser::Run()
 {
   static COLORREF sCustomColors[16] = {0} ;
 
   MOZ_ASSERT(NS_IsMainThread(),
       "Color pickers can only be opened from main thread currently");
 
-  static bool sColorPickerOpen = false;
   // Allow only one color picker to be opened at a time, to workaround bug 944737
-  if (!sColorPickerOpen) {
-    mozilla::AutoRestore<bool> autoRestoreColorPickerOpen(sColorPickerOpen);
-    sColorPickerOpen = true;
+  if (!gColorChooser) {
+    mozilla::AutoRestore<AsyncColorChooser*> restoreColorChooser(gColorChooser);
+    gColorChooser = this;
 
     AutoDestroyTmpWindow adtw((HWND) (mParentWidget.get() ?
       mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
 
     CHOOSECOLOR options;
     options.lStructSize   = sizeof(options);
     options.hwndOwner     = adtw.get();
-    options.Flags         = CC_RGBINIT | CC_FULLOPEN;
-    options.rgbResult     = ColorStringToRGB(mInitialColor);
+    options.Flags         = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
+    options.rgbResult     = mInitialColor;
     options.lpCustColors  = sCustomColors;
+    options.lpfnHook      = HookProc;
 
-    if (ChooseColor(&options)) {
-      BGRIntToRGBString(options.rgbResult, mColor);
-    }
+    mColor = ChooseColor(&options) ? options.rgbResult : mInitialColor;
   } else {
     NS_WARNING("Currently, it's not possible to open more than one color "
                "picker at a time");
     mColor = mInitialColor;
   }
 
   if (mCallback) {
-    mCallback->Done(mColor);
+    nsAutoString colorStr;
+    BGRIntToRGBString(mColor, colorStr);
+    mCallback->Done(colorStr);
   }
 
   return NS_OK;
 }
 
+void
+AsyncColorChooser::Update(COLORREF aColor)
+{
+  if (mColor != aColor) {
+    mColor = aColor;
+
+    nsAutoString colorStr;
+    BGRIntToRGBString(mColor, colorStr);
+    mCallback->Update(colorStr);
+  }
+}
+
+/* static */ UINT_PTR CALLBACK
+AsyncColorChooser::HookProc(HWND aDialog, UINT aMsg,
+                            WPARAM aWParam, LPARAM aLParam)
+{
+  if (!gColorChooser) {
+    return 0;
+  }
+
+  if (aMsg == WM_CTLCOLORSTATIC) {
+    // The color picker does not expose a proper way to retrieve the current
+    // color, so we need to obtain it from the static control displaying the
+    // current color instead.
+    const int kCurrentColorBoxID = 709;
+    if ((HWND)aLParam == GetDlgItem(aDialog, kCurrentColorBoxID)) {
+      gColorChooser->Update(GetPixel((HDC)aWParam, 0, 0));
+    }
+  }
+
+  return 0;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // nsIColorPicker
 
 nsColorPicker::nsColorPicker()
 {
 }
 
 nsColorPicker::~nsColorPicker()
@@ -155,19 +192,21 @@ NS_IMPL_ISUPPORTS(nsColorPicker, nsIColo
 NS_IMETHODIMP
 nsColorPicker::Init(nsIDOMWindow* parent,
                     const nsAString& title,
                     const nsAString& aInitialColor)
 {
   NS_PRECONDITION(parent,
       "Null parent passed to colorpicker, no color picker for you!");
   mParentWidget =  WidgetUtils::DOMWindowToWidget(parent);
-  mInitialColor = aInitialColor;
+  mInitialColor = ColorStringToRGB(aInitialColor);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsColorPicker::Open(nsIColorPickerShownCallback* aCallback)
 {
   NS_ENSURE_ARG(aCallback);
-  nsCOMPtr<nsIRunnable> event = new AsyncColorChooser(mInitialColor, mParentWidget, aCallback);
+  nsCOMPtr<nsIRunnable> event = new AsyncColorChooser(mInitialColor,
+                                                      mParentWidget,
+                                                      aCallback);
   return NS_DispatchToMainThread(event);
 }
--- a/widget/windows/nsColorPicker.h
+++ b/widget/windows/nsColorPicker.h
@@ -7,49 +7,53 @@
 #ifndef nsColorPicker_h__
 #define nsColorPicker_h__
 
 #include <windows.h>
 #include <commdlg.h>
 
 #include "nsCOMPtr.h"
 #include "nsIColorPicker.h"
-#include "nsString.h"
 #include "nsThreadUtils.h"
 
 class nsIWidget;
 
 class AsyncColorChooser :
   public nsRunnable
 {
 public:
-  AsyncColorChooser(const nsAString& aInitialColor,
+  AsyncColorChooser(COLORREF aInitialColor,
                     nsIWidget* aParentWidget,
                     nsIColorPickerShownCallback* aCallback);
   NS_IMETHOD Run() MOZ_OVERRIDE;
 
 private:
-  nsString mInitialColor;
+  void Update(COLORREF aColor);
+
+  static UINT_PTR CALLBACK HookProc(HWND aDialog, UINT aMsg,
+                                    WPARAM aWParam, LPARAM aLParam);
+
+  COLORREF mInitialColor;
+  COLORREF mColor;
   nsCOMPtr<nsIWidget> mParentWidget;
   nsCOMPtr<nsIColorPickerShownCallback> mCallback;
-  nsString mColor;
 };
 
 class nsColorPicker :
   public nsIColorPicker
 {
   virtual ~nsColorPicker();
 
 public:
   nsColorPicker();
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD Init(nsIDOMWindow* parent, const nsAString& title,
                   const nsAString& aInitialColor);
   NS_IMETHOD Open(nsIColorPickerShownCallback* aCallback);
 
-protected:
-  nsString mInitialColor;
+private:
+  COLORREF mInitialColor;
   nsCOMPtr<nsIWidget> mParentWidget;
 };
 
 #endif // nsColorPicker_h__
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -144,28 +144,26 @@ bool sHooksActive = false;
 
 // Alas, we'd like to use mozilla::TimeStamp, but we can't, because it acquires
 // a lock!
 volatile bool sHasScheduledOneLowMemoryNotification = false;
 volatile PRIntervalTime sLastLowMemoryNotificationTime;
 
 // These are function pointers to the functions we wrap in Init().
 
-void* (WINAPI* sVirtualAllocOrig)
-  (LPVOID aAddress, SIZE_T aSize, DWORD aAllocationType, DWORD aProtect);
+void* (WINAPI* sVirtualAllocOrig)(LPVOID aAddress, SIZE_T aSize,
+                                  DWORD aAllocationType, DWORD aProtect);
 
-void* (WINAPI* sMapViewOfFileOrig)
-  (HANDLE aFileMappingObject, DWORD aDesiredAccess,
-   DWORD aFileOffsetHigh, DWORD aFileOffsetLow,
-   SIZE_T aNumBytesToMap);
+void* (WINAPI* sMapViewOfFileOrig)(HANDLE aFileMappingObject,
+                                   DWORD aDesiredAccess, DWORD aFileOffsetHigh,
+                                   DWORD aFileOffsetLow, SIZE_T aNumBytesToMap);
 
-HBITMAP (WINAPI* sCreateDIBSectionOrig)
-  (HDC aDC, const BITMAPINFO* aBitmapInfo,
-   UINT aUsage, VOID** aBits,
-   HANDLE aSection, DWORD aOffset);
+HBITMAP(WINAPI* sCreateDIBSectionOrig)(HDC aDC, const BITMAPINFO* aBitmapInfo,
+                                       UINT aUsage, VOID** aBits,
+                                       HANDLE aSection, DWORD aOffset);
 
 /**
  * Fire a memory pressure event if it's been long enough since the last one we
  * fired.
  */
 bool
 MaybeScheduleMemoryPressureEvent()
 {
--- a/xpcom/base/CodeAddressService.h
+++ b/xpcom/base/CodeAddressService.h
@@ -149,17 +149,18 @@ public:
       nsCodeAddressDetails details;
       {
         DescribeCodeAddressLock::Unlock();
         (void)NS_DescribeCodeAddress(const_cast<void*>(aPc), &details);
         DescribeCodeAddressLock::Lock();
       }
 
       const char* library = mLibraryStrings.Intern(details.library);
-      entry.Replace(aPc, details.function, library, details.loffset, details.filename, details.lineno);
+      entry.Replace(aPc, details.function, library, details.loffset,
+                    details.filename, details.lineno);
 
     } else {
       mNumCacheHits++;
     }
 
     MOZ_ASSERT(entry.mPc == aPc);
 
     uintptr_t entryPc = (uintptr_t)(entry.mPc);
new file mode 100644
--- /dev/null
+++ b/xpcom/base/CountingAllocatorBase.h
@@ -0,0 +1,138 @@
+/* -*- 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 CountingAllocatorBase_h
+#define CountingAllocatorBase_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
+#include "nsIMemoryReporter.h"
+
+namespace mozilla {
+
+// This CRTP class handles several details of wrapping allocators and should
+// be preferred to manually counting with MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC
+// and MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE.  The typical use is in a memory
+// reporter for a particular third party library:
+//
+//   class MyMemoryReporter : public CountingAllocatorBase<MyMemoryReporter>
+//   {
+//     ...
+//     NS_IMETHODIMP
+//     CollectReports(nsIHandleReportCallback* aHandleReport,
+//                    nsISupports* aData, bool aAnonymize)
+//     {
+//        return MOZ_COLLECT_REPORT(
+//          "explicit/path/to/somewhere", KIND_HEAP, UNITS_BYTES,
+//          MemoryAllocated(),
+//          "A description of what we are reporting."
+//     }
+//   };
+//
+//   ...somewhere later in the code...
+//   SetThirdPartyMemoryFunctions(MyMemoryReporter::CountingAlloc,
+//                                MyMemoryReporter::CountingFree);
+template<typename T>
+class CountingAllocatorBase
+{
+public:
+  CountingAllocatorBase()
+  {
+#ifdef DEBUG
+    // There must be only one instance of this class, due to |sAmount| being
+    // static.
+    static bool hasRun = false;
+    MOZ_ASSERT(!hasRun);
+    hasRun = true;
+#endif
+  }
+
+  static size_t
+  MemoryAllocated()
+  {
+    return sAmount;
+  }
+
+  static void*
+  CountingMalloc(size_t size)
+  {
+    void* p = malloc(size);
+    sAmount += MallocSizeOfOnAlloc(p);
+    return p;
+  }
+
+  static void*
+  CountingCalloc(size_t nmemb, size_t size)
+  {
+    void* p = calloc(nmemb, size);
+    sAmount += MallocSizeOfOnAlloc(p);
+    return p;
+  }
+
+  static void*
+  CountingRealloc(void* p, size_t size)
+  {
+    size_t oldsize = MallocSizeOfOnFree(p);
+    void *pnew = realloc(p, size);
+    if (pnew) {
+      size_t newsize = MallocSizeOfOnAlloc(pnew);
+      sAmount += newsize - oldsize;
+    } else if (size == 0) {
+      // We asked for a 0-sized (re)allocation of some existing pointer
+      // and received NULL in return.  0-sized allocations are permitted
+      // to either return NULL or to allocate a unique object per call (!).
+      // For a malloc implementation that chooses the second strategy,
+      // that allocation may fail (unlikely, but possible).
+      //
+      // Given a NULL return value and an allocation size of 0, then, we
+      // don't know if that means the original pointer was freed or if
+      // the allocation of the unique object failed.  If the original
+      // pointer was freed, then we have nothing to do here.  If the
+      // allocation of the unique object failed, the original pointer is
+      // still valid and we ought to undo the decrement from above.
+      // However, we have no way of knowing how the underlying realloc
+      // implementation is behaving.  Assuming that the original pointer
+      // was freed is the safest course of action.  We do, however, need
+      // to note that we freed memory.
+      sAmount -= oldsize;
+    } else {
+      // realloc failed.  The amount allocated hasn't changed.
+    }
+    return pnew;
+  }
+
+  // Some library code expects that realloc(x, 0) will free x, which is not
+  // the behavior of the version of jemalloc we're using, so this wrapped
+  // version of realloc is needed.
+  static void*
+  CountingFreeingRealloc(void* p, size_t size)
+  {
+    if (size == 0) {
+      CountingFree(p);
+      return nullptr;
+    }
+    return CountingRealloc(p, size);
+  }
+
+  static void
+  CountingFree(void* p)
+  {
+    sAmount -= MallocSizeOfOnFree(p);
+    free(p);
+  }
+
+private:
+  // |sAmount| can be (implicitly) accessed by multiple threads, so it
+  // must be thread-safe.
+  static Atomic<size_t> sAmount;
+
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
+};
+
+} // namespace mozilla
+
+#endif // CountingAllocatorBase_h
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -152,17 +152,18 @@ TraceWeakMappingChild(JSTracer* aTrc, vo
     return;
   }
 
   if (!xpc_IsGrayGCThing(thing) && !tracer->mCb.WantAllTraces()) {
     return;
   }
 
   if (AddToCCKind(aKind)) {
-    tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey, tracer->mKeyDelegate, thing);
+    tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey,
+                                tracer->mKeyDelegate, thing);
     tracer->mTracedAny = true;
   } else {
     JS_TraceChildren(aTrc, thing, aKind);
   }
 }
 
 struct NoteWeakMapsTracer : public js::WeakMapTracer
 {
@@ -300,17 +301,18 @@ struct Closure
   {
   }
 
   bool mCycleCollectionEnabled;
   nsCycleCollectionNoteRootCallback* mCb;
 };
 
 static void
-CheckParticipatesInCycleCollection(void* aThing, const char* aName, void* aClosure)
+CheckParticipatesInCycleCollection(void* aThing, const char* aName,
+                                   void* aClosure)
 {
   Closure* closure = static_cast<Closure*>(aClosure);
 
   if (closure->mCycleCollectionEnabled) {
     return;
   }
 
   if (AddToCCKind(js::GCThingTraceKind(aThing)) &&
@@ -341,35 +343,35 @@ NoteJSHolder(void* aHolder, nsScriptObje
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 JSGCThingParticipant::Traverse(void* aPtr,
                                nsCycleCollectionTraversalCallback& aCb)
 {
-  CycleCollectedJSRuntime* runtime = reinterpret_cast<CycleCollectedJSRuntime*>
-    (reinterpret_cast<char*>(this) -
-     offsetof(CycleCollectedJSRuntime, mGCThingCycleCollectorGlobal));
+  auto runtime = reinterpret_cast<CycleCollectedJSRuntime*>(
+    reinterpret_cast<char*>(this) - offsetof(CycleCollectedJSRuntime,
+                                             mGCThingCycleCollectorGlobal));
 
   runtime->TraverseGCThing(CycleCollectedJSRuntime::TRAVERSE_FULL,
                            aPtr, js::GCThingTraceKind(aPtr), aCb);
   return NS_OK;
 }
 
 // NB: This is only used to initialize the participant in
 // CycleCollectedJSRuntime. It should never be used directly.
 static JSGCThingParticipant sGCThingCycleCollectorGlobal;
 
 NS_IMETHODIMP
 JSZoneParticipant::Traverse(void* aPtr, nsCycleCollectionTraversalCallback& aCb)
 {
-  CycleCollectedJSRuntime* runtime = reinterpret_cast<CycleCollectedJSRuntime*>
-    (reinterpret_cast<char*>(this) -
-     offsetof(CycleCollectedJSRuntime, mJSZoneCycleCollectorGlobal));
+  auto runtime = reinterpret_cast<CycleCollectedJSRuntime*>(
+    reinterpret_cast<char*>(this) - offsetof(CycleCollectedJSRuntime,
+                                             mJSZoneCycleCollectorGlobal));
 
   MOZ_ASSERT(!aCb.WantAllTraces());
   JS::Zone* zone = static_cast<JS::Zone*>(aPtr);
 
   runtime->TraverseZone(zone, aCb);
   return NS_OK;
 }
 
@@ -484,17 +486,18 @@ CycleCollectedJSRuntime::CycleCollectedJ
   }
 
   if (!JS_AddExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this)) {
     MOZ_CRASH();
   }
   JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
   JS_SetGCCallback(mJSRuntime, GCCallback, this);
   JS::SetOutOfMemoryCallback(mJSRuntime, OutOfMemoryCallback, this);
-  JS::SetLargeAllocationFailureCallback(mJSRuntime, LargeAllocationFailureCallback, this);
+  JS::SetLargeAllocationFailureCallback(mJSRuntime,
+                                        LargeAllocationFailureCallback, this);
   JS_SetContextCallback(mJSRuntime, ContextCallback, this);
   JS_SetDestroyZoneCallback(mJSRuntime, XPCStringConvert::FreeZoneCache);
   JS_SetSweepZoneCallback(mJSRuntime, XPCStringConvert::ClearZoneCache);
 
   static js::DOMCallbacks DOMcallbacks = {
     InstanceClassHasProtoAtDepth
   };
   SetDOMCallbacks(mJSRuntime, &DOMcallbacks);
@@ -607,17 +610,18 @@ CycleCollectedJSRuntime::NoteGCThingJSCh
                                                nsCycleCollectionTraversalCallback& aCb) const
 {
   MOZ_ASSERT(mJSRuntime);
   TraversalTracer trc(mJSRuntime, aCb);
   JS_TraceChildren(&trc, aThing, aTraceKind);
 }
 
 void
-CycleCollectedJSRuntime::NoteGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj,
+CycleCollectedJSRuntime::NoteGCThingXPCOMChildren(const js::Class* aClasp,
+                                                  JSObject* aObj,
                                                   nsCycleCollectionTraversalCallback& aCb) const
 {
   MOZ_ASSERT(aClasp);
   MOZ_ASSERT(aClasp == js::GetObjectClass(aObj));
 
   if (NoteCustomGCThingXPCOMChildren(aClasp, aObj, aCb)) {
     // Nothing else to do!
     return;
@@ -760,17 +764,17 @@ CycleCollectedJSRuntime::GCCallback(JSRu
   CycleCollectedJSRuntime* self = static_cast<CycleCollectedJSRuntime*>(aData);
 
   MOZ_ASSERT(aRuntime == self->Runtime());
 
   self->OnGC(aStatus);
 }
 
 /* static */ void
-CycleCollectedJSRuntime::OutOfMemoryCallback(JSContext *aContext,
+CycleCollectedJSRuntime::OutOfMemoryCallback(JSContext* aContext,
                                              void* aData)
 {
   CycleCollectedJSRuntime* self = static_cast<CycleCollectedJSRuntime*>(aData);
 
   MOZ_ASSERT(JS_GetRuntime(aContext) == self->Runtime());
 
   self->OnOutOfMemory();
 }
@@ -1096,17 +1100,18 @@ IncrementalFinalizeRunnable::DeferredFin
 
 IncrementalFinalizeRunnable::IncrementalFinalizeRunnable(CycleCollectedJSRuntime* aRt,
                                                          nsTArray<nsISupports*>& aSupports,
                                                          DeferredFinalizerTable& aFinalizers)
   : mRuntime(aRt)
   , mFinalizeFunctionToRun(0)
 {
   this->mSupports.SwapElements(aSupports);
-  DeferredFinalizeFunctionHolder* function = mDeferredFinalizeFunctions.AppendElement();
+  DeferredFinalizeFunctionHolder* function =
+    mDeferredFinalizeFunctions.AppendElement();
   function->run = ReleaseSliceNow;
   function->data = &this->mSupports;
 
   // Enumerate the hashtable into our array.
   aFinalizers.Enumerate(DeferredFinalizerEnumerator, &mDeferredFinalizeFunctions);
 }
 
 IncrementalFinalizeRunnable::~IncrementalFinalizeRunnable()
@@ -1196,18 +1201,19 @@ CycleCollectedJSRuntime::FinalizeDeferre
   if (aType == FinalizeIncrementally) {
     NS_DispatchToCurrentThread(mFinalizeRunnable);
   } else {
     mFinalizeRunnable->ReleaseNow(false);
     MOZ_ASSERT(!mFinalizeRunnable);
   }
 }
 
-void 
-CycleCollectedJSRuntime::AnnotateAndSetOutOfMemory(OOMState *aStatePtr, OOMState aNewState)
+void
+CycleCollectedJSRuntime::AnnotateAndSetOutOfMemory(OOMState* aStatePtr,
+                                                   OOMState aNewState)
 {
   *aStatePtr = aNewState;
 #ifdef MOZ_CRASHREPORTER
   CrashReporter::AnnotateCrashReport(aStatePtr == &mOutOfMemoryState
                                      ? NS_LITERAL_CSTRING("JSOutOfMemory")
                                      : NS_LITERAL_CSTRING("JSLargeAllocationFailure"),
                                      aNewState == OOMState::Reporting
                                      ? NS_LITERAL_CSTRING("Reporting")
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -116,32 +116,23 @@ protected:
   CycleCollectedJSRuntime(JSRuntime* aParentRuntime,
                           uint32_t aMaxBytes,
                           uint32_t aMaxNurseryBytes);
   virtual ~CycleCollectedJSRuntime();
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   void UnmarkSkippableJSHolders();
 
-  virtual void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& aCb)
-  {
-  }
-  virtual void TraceAdditionalNativeGrayRoots(JSTracer* aTracer)
-  {
-  }
+  virtual void
+  TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& aCb) {}
+  virtual void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) {}
 
-  virtual void CustomGCCallback(JSGCStatus aStatus)
-  {
-  }
-  virtual void CustomOutOfMemoryCallback()
-  {
-  }
-  virtual void CustomLargeAllocationFailureCallback()
-  {
-  }
+  virtual void CustomGCCallback(JSGCStatus aStatus) {}
+  virtual void CustomOutOfMemoryCallback() {}
+  virtual void CustomLargeAllocationFailureCallback() {}
   virtual bool CustomContextCallback(JSContext* aCx, unsigned aOperation)
   {
     return true; // Don't block context creation.
   }
 
 private:
 
   void
@@ -186,18 +177,18 @@ private:
   static void
   TraverseObjectShim(void* aData, void* aThing);
 
   void TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb);
 
   static void TraceBlackJS(JSTracer* aTracer, void* aData);
   static void TraceGrayJS(JSTracer* aTracer, void* aData);
   static void GCCallback(JSRuntime* aRuntime, JSGCStatus aStatus, void* aData);
-  static void OutOfMemoryCallback(JSContext *aContext, void *aData);
-  static void LargeAllocationFailureCallback(void *aData);
+  static void OutOfMemoryCallback(JSContext* aContext, void* aData);
+  static void LargeAllocationFailureCallback(void* aData);
   static bool ContextCallback(JSContext* aCx, unsigned aOperation,
                               void* aData);
 
   virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
   void TraceNativeGrayRoots(JSTracer* aTracer);
 
   enum DeferredFinalizeType {
     FinalizeIncrementally,
@@ -235,17 +226,17 @@ public:
     // The condition has happened, but a GC cycle ended since then.
     //
     // GC is taken as a proxy for "we've been banging on the heap a good bit
     // now and haven't crashed; the OOM was probably handled correctly".
     Recovered
   MOZ_END_NESTED_ENUM_CLASS(OOMState)
 
 private:
-  void AnnotateAndSetOutOfMemory(OOMState *aStatePtr, OOMState aNewState);
+  void AnnotateAndSetOutOfMemory(OOMState* aStatePtr, OOMState aNewState);
   void OnGC(JSGCStatus aStatus);
   void OnOutOfMemory();
   void OnLargeAllocationFailure();
 
 public:
   void AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
   void RemoveJSHolder(void* aHolder);
 #ifdef DEBUG
--- a/xpcom/base/StaticPtr.h
+++ b/xpcom/base/StaticPtr.h
@@ -49,36 +49,27 @@ public:
 #endif
 
   StaticAutoPtr<T>& operator=(T* aRhs)
   {
     Assign(aRhs);
     return *this;
   }
 
-  T* get() const
-  {
-    return mRawPtr;
-  }
+  T* get() const { return mRawPtr; }
 
-  operator T*() const
-  {
-    return get();
-  }
+  operator T*() const { return get(); }
 
   T* operator->() const
   {
     MOZ_ASSERT(mRawPtr);
     return get();
   }
 
-  T& operator*() const
-  {
-    return *get();
-  }
+  T& operator*() const { return *get(); }
 
 private:
   // Disallow copy constructor, but only in debug mode.  We only define
   // a default constructor in debug mode (see above); if we declared
   // this constructor always, the compiler wouldn't generate a trivial
   // default constructor for us in non-debug mode.
 #ifdef DEBUG
   StaticAutoPtr(StaticAutoPtr<T>& aOther);
@@ -115,36 +106,27 @@ public:
     return *this;
   }
 
   StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs)
   {
     return (this = aRhs.mRawPtr);
   }
 
-  T* get() const
-  {
-    return mRawPtr;
-  }
+  T* get() const { return mRawPtr; }
 
-  operator T*() const
-  {
-    return get();
-  }
+  operator T*() const { return get(); }
 
   T* operator->() const
   {
     MOZ_ASSERT(mRawPtr);
     return get();
   }
 
-  T& operator*() const
-  {
-    return *get();
-  }
+  T& operator*() const { return *get(); }
 
 private:
   void AssignWithAddref(T* aNewPtr)
   {
     if (aNewPtr) {
       aNewPtr->AddRef();
     }
     AssignAssumingAddRef(aNewPtr);
--- a/xpcom/base/SystemMemoryReporter.cpp
+++ b/xpcom/base/SystemMemoryReporter.cpp
@@ -158,18 +158,19 @@ public:
 #define REPORT(_path, _amount, _desc) \
   REPORT_WITH_CLEANUP(_path, UNITS_BYTES, _amount, _desc, (void)0)
 
   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                             nsISupports* aData, bool aAnonymize)
   {
     // There is lots of privacy-sensitive data in /proc. Just skip this
     // reporter entirely when anonymization is required.
-    if (aAnonymize)
+    if (aAnonymize) {
       return NS_OK;
+    }
 
     if (!Preferences::GetBool("memory.system_memory_reporter")) {
       return NS_OK;
     }
 
     // Read relevant fields from /proc/meminfo.
     int64_t memTotal = 0, memFree = 0;
     nsresult rv = ReadMemInfo(&memTotal, &memFree);
@@ -208,40 +209,41 @@ public:
     return rv;
   }
 
 private:
   // These are the cross-cutting measurements across all processes.
   class ProcessSizes
   {
   public:
-    void Add(const nsACString &aKey, size_t aSize)
+    void Add(const nsACString& aKey, size_t aSize)
     {
       mTagged.Put(aKey, mTagged.Get(aKey) + aSize);
     }
 
-    void Report(nsIHandleReportCallback *aHandleReport, nsISupports *aData)
+    void Report(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
     {
       EnumArgs env = { aHandleReport, aData };
       mTagged.EnumerateRead(ReportSizes, &env);
     }
 
   private:
     nsDataHashtable<nsCStringHashKey, size_t> mTagged;
 
-    struct EnumArgs {
+    struct EnumArgs
+    {
       nsIHandleReportCallback* mHandleReport;
       nsISupports* mData;
     };
 
     static PLDHashOperator ReportSizes(nsCStringHashKey::KeyType aKey,
                                        size_t aAmount,
-                                       void *aUserArg)
+                                       void* aUserArg)
     {
-      const EnumArgs *envp = reinterpret_cast<const EnumArgs*>(aUserArg);
+      const EnumArgs* envp = reinterpret_cast<const EnumArgs*>(aUserArg);
 
       nsAutoCString path("processes/");
       path.Append(aKey);
 
       nsAutoCString desc("This is the sum of all processes' '");
       desc.Append(aKey);
       desc.AppendLiteral("' numbers.");
 
@@ -330,18 +332,18 @@ private:
                                     &processSizes, aTotalPss);
         fclose(f);
         if (NS_FAILED(rv)) {
           continue;
         }
 
         // Report the open file descriptors for this process.
         nsPrintfCString procFdPath("/proc/%s/fd", pidStr);
-        rv = CollectOpenFileReports(
-                  aHandleReport, aData, procFdPath, processName);
+        rv = CollectOpenFileReports(aHandleReport, aData, procFdPath,
+                                    processName);
         if (NS_FAILED(rv)) {
           break;
         }
       }
     }
     closedir(d);
 
     // Report the "processes/" tree.
@@ -942,22 +944,22 @@ private:
         } else {
           category = "";
           descriptionPrefix = "An uncategorized";
         }
 
 #undef CHECK_PREFIX
 
         const nsCString processName(aProcessName);
-        nsPrintfCString entryPath(
-            "open-fds/%s/%s%s/%s", processName.get(), category, linkPath, fd);
-        nsPrintfCString entryDescription(
-            "%s file descriptor opened by the process", descriptionPrefix);
-        REPORT_WITH_CLEANUP(
-            entryPath, UNITS_COUNT, 1, entryDescription, closedir(d));
+        nsPrintfCString entryPath("open-fds/%s/%s%s/%s",
+                                  processName.get(), category, linkPath, fd);
+        nsPrintfCString entryDescription("%s file descriptor opened by the process",
+                                         descriptionPrefix);
+        REPORT_WITH_CLEANUP(entryPath, UNITS_COUNT, 1, entryDescription,
+                            closedir(d));
       }
     }
 
     closedir(d);
     return NS_OK;
   }
 
   nsresult
@@ -968,18 +970,18 @@ private:
     // /sys/kernel/debug/kgsl/proc/<pid>/mem. This file format includes a
     // header and then entries with types as follows:
     //   gpuaddr useraddr size id  flags type usage sglen
     //   hexaddr hexaddr  int  int str   str  str   int
     // We care primarily about the usage and size.
 
     // For simplicity numbers will be uint64_t, strings 63 chars max.
     const char* const kScanFormat =
-        "%" SCNx64 " %" SCNx64 " %" SCNu64 " %" SCNu64
-        " %63s %63s %63s %" SCNu64;
+      "%" SCNx64 " %" SCNx64 " %" SCNu64 " %" SCNu64
+      " %63s %63s %63s %" SCNu64;
     const int kNumFields = 8;
     const size_t kStringSize = 64;
 
     DIR* d = opendir("/sys/kernel/debug/kgsl/proc/");
     if (!d) {
       if (NS_WARN_IF(errno != ENOENT && errno != EACCES)) {
         return NS_ERROR_FAILURE;
       }
--- a/xpcom/base/VisualEventTracer.cpp
+++ b/xpcom/base/VisualEventTracer.cpp
@@ -434,17 +434,18 @@ void
 Init()
 {
 #ifdef MOZ_VISUAL_EVENT_TRACER
   const char* logEvents = PR_GetEnv("MOZ_PROFILING_EVENTS");
   if (logEvents && *logEvents) {
     gEventFilter = EventFilter::Build(logEvents);
   }
 
-  PRStatus status = PR_NewThreadPrivateIndex(&gThreadPrivateIndex, &RecordBatch::Close);
+  PRStatus status = PR_NewThreadPrivateIndex(&gThreadPrivateIndex,
+                                             &RecordBatch::Close);
   if (status != PR_SUCCESS) {
     return;
   }
 
   gMonitor = new mozilla::Monitor("Profiler");
   if (!gMonitor) {
     return;
   }
@@ -492,18 +493,18 @@ Mark(uint32_t aType, void* aItem, const 
   if (aType == eNone) {
     return;
   }
 
   if (!CheckEventFilters(aType, aItem, aText)) { // Events use just aText
     return;
   }
 
-  RecordBatch* threadLogPrivate = static_cast<RecordBatch*>(
-    PR_GetThreadPrivate(gThreadPrivateIndex));
+  RecordBatch* threadLogPrivate =
+    static_cast<RecordBatch*>(PR_GetThreadPrivate(gThreadPrivateIndex));
   if (!threadLogPrivate) {
     threadLogPrivate = RecordBatch::Register();
     if (!threadLogPrivate) {
       return;
     }
 
     PR_SetThreadPrivate(gThreadPrivateIndex, threadLogPrivate);
   }
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -67,16 +67,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     ]
     if CONFIG['MOZ_DEBUG']:
         EXPORTS += ['pure.h']
         SOURCES += ['pure_api.c']
 
 EXPORTS.mozilla += [
     'AvailableMemoryTracker.h',
     'ClearOnShutdown.h',
+    'CountingAllocatorBase.h',
     'CycleCollectedJSRuntime.h',
     'Debug.h',
     'LinuxUtils.h',
     'nsMemoryInfoDumper.h',
     'StackWalk.h',
     'StaticMutex.h',
     'StaticPtr.h',
     'SystemMemoryReporter.h',
--- a/xpcom/base/nsConsoleService.cpp
+++ b/xpcom/base/nsConsoleService.cpp
@@ -29,17 +29,19 @@
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
 using namespace mozilla;
 
 NS_IMPL_ADDREF(nsConsoleService)
 NS_IMPL_RELEASE(nsConsoleService)
-NS_IMPL_CLASSINFO(nsConsoleService, nullptr, nsIClassInfo::THREADSAFE | nsIClassInfo::SINGLETON, NS_CONSOLESERVICE_CID)
+NS_IMPL_CLASSINFO(nsConsoleService, nullptr,
+                  nsIClassInfo::THREADSAFE | nsIClassInfo::SINGLETON,
+                  NS_CONSOLESERVICE_CID)
 NS_IMPL_QUERY_INTERFACE_CI(nsConsoleService, nsIConsoleService)
 NS_IMPL_CI_INTERFACE_GETTER(nsConsoleService, nsIConsoleService)
 
 static bool sLoggingEnabled = true;
 static bool sLoggingBuffered = true;
 
 nsConsoleService::nsConsoleService()
   : mMessages(nullptr)
@@ -52,17 +54,17 @@ nsConsoleService::nsConsoleService()
   // hm, but worry about circularity, bc we want to be able to report
   // prefs errs...
   mBufferSize = 250;
 }
 
 nsConsoleService::~nsConsoleService()
 {
   uint32_t i = 0;
-  while (i < mBufferSize && mMessages[i] != nullptr) {
+  while (i < mBufferSize && mMessages[i]) {
     NS_RELEASE(mMessages[i]);
     i++;
   }
 
   if (mMessages) {
     nsMemory::Free(mMessages);
   }
 }
@@ -261,17 +263,18 @@ nsConsoleService::LogStringMessage(const
     return NS_OK;
   }
 
   nsRefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage));
   return this->LogMessage(msg);
 }
 
 NS_IMETHODIMP
-nsConsoleService::GetMessageArray(uint32_t* aCount, nsIConsoleMessage*** aMessages)
+nsConsoleService::GetMessageArray(uint32_t* aCount,
+                                  nsIConsoleMessage*** aMessages)
 {
   nsIConsoleMessage** messageArray;
 
   /*
    * Lock the whole method, as we don't want anyone mucking with mCurrent or
    * mFull while we're copying out the buffer.
    */
   MutexAutoLock lock(mLock);
--- a/xpcom/base/nsConsoleService.h
+++ b/xpcom/base/nsConsoleService.h
@@ -48,18 +48,20 @@ public:
 
   enum OutputMode {
     SuppressLog,
     OutputToLog
   };
   virtual nsresult LogMessageWithMode(nsIConsoleMessage* aMessage,
                                       OutputMode aOutputMode);
 
-  typedef nsInterfaceHashtable<nsISupportsHashKey, nsIConsoleListener> ListenerHash;
-  void EnumerateListeners(ListenerHash::EnumReadFunction aFunction, void* aClosure);
+  typedef nsInterfaceHashtable<nsISupportsHashKey,
+                               nsIConsoleListener> ListenerHash;
+  void EnumerateListeners(ListenerHash::EnumReadFunction aFunction,
+                          void* aClosure);
 
 private:
   ~nsConsoleService();
 
   // Circular buffer of saved messages
   nsIConsoleMessage** mMessages;
 
   // How big?
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -378,17 +378,18 @@ public:
   {
     return !mSentinelAndBlocks[0].block &&
            !mSentinelAndBlocks[1].block;
   }
 #endif
 
 private:
   struct Block;
-  union PtrInfoOrBlock {
+  union PtrInfoOrBlock
+  {
     // Use a union to avoid reinterpret_cast and the ensuing
     // potential aliasing bugs.
     PtrInfo* ptrInfo;
     Block* block;
   };
   struct Block
   {
     enum { BlockSize = 16 * 1024 };
@@ -425,25 +426,19 @@ private:
   {
     return mSentinelAndBlocks[1].block;
   }
 
 public:
   class Iterator
   {
   public:
-    Iterator() : mPointer(nullptr)
-  {
-  }
-    explicit Iterator(PtrInfoOrBlock* aPointer) : mPointer(aPointer)
-  {
-  }
-    Iterator(const Iterator& aOther) : mPointer(aOther.mPointer)
-  {
-  }
+    Iterator() : mPointer(nullptr) {}
+    explicit Iterator(PtrInfoOrBlock* aPointer) : mPointer(aPointer) {}
+    Iterator(const Iterator& aOther) : mPointer(aOther.mPointer) {}
 
     Iterator& operator++()
     {
       if (!mPointer->ptrInfo) {
         // Null pointer is a sentinel for link to the next block.
         mPointer = (mPointer + 1)->block->mPointers;
       }
       ++mPointer;
@@ -958,17 +953,18 @@ CanonicalizeParticipant(void** aParti, n
     ToParticipant(nsparti, &xcp);
     *aParti = nsparti;
     *aCp = xcp;
   }
 }
 
 struct nsPurpleBufferEntry
 {
-  union {
+  union
+  {
     void* mObject;                        // when low bit unset
     nsPurpleBufferEntry* mNextInFreeList; // when low bit set
   };
 
   nsCycleCollectingAutoRefCnt* mRefCnt;
 
   nsCycleCollectionParticipant* mParticipant; // nullptr for nsISupports
 };
@@ -993,17 +989,17 @@ private:
       // Ensure Block is the right size (see above).
       static_assert(
         sizeof(Block) == 16384 ||       // 32-bit
         sizeof(Block) == 32768,         // 64-bit
         "ill-sized nsPurpleBuffer::Block"
       );
     }
 
-    template <class PurpleVisitor>
+    template<class PurpleVisitor>
     void VisitEntries(nsPurpleBuffer& aBuffer, PurpleVisitor& aVisitor)
     {
       nsPurpleBufferEntry* eEnd = ArrayEnd(mEntries);
       for (nsPurpleBufferEntry* e = mEntries; e != eEnd; ++e) {
         if (!(uintptr_t(e->mObject) & uintptr_t(1))) {
           aVisitor.Visit(aBuffer, e);
         }
       }
@@ -1022,17 +1018,17 @@ public:
     InitBlocks();
   }
 
   ~nsPurpleBuffer()
   {
     FreeBlocks();
   }
 
-  template <class PurpleVisitor>
+  template<class PurpleVisitor>
   void VisitEntries(PurpleVisitor& aVisitor)
   {
     for (Block* b = &mFirstBlock; b; b = b->mNext) {
       b->VisitEntries(*this, aVisitor);
     }
   }
 
   void InitBlocks()
@@ -1213,24 +1209,26 @@ nsPurpleBuffer::SelectPointers(CCGraphBu
 
   NS_ASSERTION(mCount == 0, "AddPurpleRoot failed");
   if (mCount == 0) {
     FreeBlocks();
     InitBlocks();
   }
 }
 
-enum ccPhase {
+enum ccPhase
+{
   IdlePhase,
   GraphBuildingPhase,
   ScanAndCollectWhitePhase,
   CleanupPhase
 };
 
-enum ccType {
+enum ccType
+{
   SliceCC,     /* If a CC is in progress, continue it. Otherwise, start a new one. */
   ManualCC,    /* Explicitly triggered. */
   ShutdownCC   /* Shutdown CC, used for finding leaks. */
 };
 
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
@@ -1350,17 +1348,17 @@ NS_IMPL_ISUPPORTS(nsCycleCollector, nsIM
 
 /**
  * GraphWalker is templatized over a Visitor class that must provide
  * the following two methods:
  *
  * bool ShouldVisitNode(PtrInfo const *pi);
  * void VisitNode(PtrInfo *pi);
  */
-template <class Visitor>
+template<class Visitor>
 class GraphWalker
 {
 private:
   Visitor mVisitor;
 
   void DoWalk(nsDeque& aQueue);
 
   void CheckedPush(nsDeque& aQueue, PtrInfo* aPi)
@@ -1423,38 +1421,38 @@ ToParticipant(nsISupports* aPtr, nsXPCOM
 {
   // We use QI to move from an nsISupports to an
   // nsXPCOMCycleCollectionParticipant, which is a per-class singleton helper
   // object that implements traversal and unlinking logic for the nsISupports
   // in question.
   CallQueryInterface(aPtr, aCp);
 }
 
-template <class Visitor>
+template<class Visitor>
 MOZ_NEVER_INLINE void
 GraphWalker<Visitor>::Walk(PtrInfo* aPi)
 {
   nsDeque queue;
   CheckedPush(queue, aPi);
   DoWalk(queue);
 }
 
-template <class Visitor>
+template<class Visitor>
 MOZ_NEVER_INLINE void
 GraphWalker<Visitor>::WalkFromRoots(CCGraph& aGraph)
 {
   nsDeque queue;
   NodePool::Enumerator etor(aGraph.mNodes);
   for (uint32_t i = 0; i < aGraph.mRootCount; ++i) {
     CheckedPush(queue, etor.GetNext());
   }
   DoWalk(queue);
 }
 
-template <class Visitor>
+template<class Visitor>
 MOZ_NEVER_INLINE void
 GraphWalker<Visitor>::DoWalk(nsDeque& aQueue)
 {
   // Use a aQueue to match the breadth-first traversal used when we
   // built the graph, for hopefully-better locality.
   while (aQueue.GetSize() > 0) {
     PtrInfo* pi = static_cast<PtrInfo*>(aQueue.PopFront());
 
@@ -1471,17 +1469,18 @@ GraphWalker<Visitor>::DoWalk(nsDeque& aQ
 
 struct CCGraphDescriber : public LinkedListElement<CCGraphDescriber>
 {
   CCGraphDescriber()
     : mAddress("0x"), mCnt(0), mType(eUnknown)
   {
   }
 
-  enum Type {
+  enum Type
+  {
     eRefCountedObject,
     eGCedObject,
     eGCMarkedObject,
     eEdge,
     eRoot,
     eGarbage,
     eUnknown
   };
@@ -1585,17 +1584,18 @@ private:
       fclose(mGCLog.mStream);
     }
     if (mCCLog.mStream) {
       MozillaUnRegisterDebugFILE(mCCLog.mStream);
       fclose(mCCLog.mStream);
     }
   }
 
-  struct FileInfo {
+  struct FileInfo
+  {
     const char* const mPrefix;
     nsCOMPtr<nsIFile> mFile;
     FILE* mStream;
 
     explicit FileInfo(const char* aPrefix) : mPrefix(aPrefix), mStream(nullptr) { }
   };
 
   /**
@@ -1622,19 +1622,17 @@ private:
       NS_NewNativeLocalFile(nsCString(env), /* followLinks = */ true,
                             &logFile);
     }
 
     // On Android or B2G, this function will open a file named
     // aFilename under a memory-reporting-specific folder
     // (/data/local/tmp/memory-reports). Otherwise, it will open a
     // file named aFilename under "NS_OS_TEMP_DIR".
-    nsresult rv = nsDumpUtils::OpenTempFile(
-                                            filename,
-                                            &logFile,
+    nsresult rv = nsDumpUtils::OpenTempFile(filename, &logFile,
                                             NS_LITERAL_CSTRING("memory-reports"));
     if (NS_FAILED(rv)) {
       NS_IF_RELEASE(logFile);
       return nullptr;
     }
 
     return dont_AddRef(logFile);
   }
@@ -1646,62 +1644,66 @@ private:
     // completes.  (We do this because we don't want scripts which poll
     // the filesystem looking for GC/CC dumps to grab a file before we're
     // finished writing to it.)
     nsAutoCString incomplete;
     incomplete += "incomplete-";
     incomplete += aLog->mPrefix;
     MOZ_ASSERT(!aLog->mFile);
     aLog->mFile = CreateTempFile(incomplete.get());
-    if (NS_WARN_IF(!aLog->mFile))
+    if (NS_WARN_IF(!aLog->mFile)) {
       return NS_ERROR_UNEXPECTED;
+    }
 
     MOZ_ASSERT(!aLog->mStream);
     aLog->mFile->OpenANSIFileDesc("w", &aLog->mStream);
-    if (NS_WARN_IF(!aLog->mStream))
+    if (NS_WARN_IF(!aLog->mStream)) {
       return NS_ERROR_UNEXPECTED;
+    }
     MozillaRegisterDebugFILE(aLog->mStream);
     return NS_OK;
   }
 
   nsresult CloseLog(FileInfo* aLog, const nsAString& aCollectorKind)
   {
     MOZ_ASSERT(aLog->mStream);
     MOZ_ASSERT(aLog->mFile);
 
     MozillaUnRegisterDebugFILE(aLog->mStream);
     fclose(aLog->mStream);
     aLog->mStream = nullptr;
 
     // Strip off "incomplete-".
     nsCOMPtr<nsIFile> logFileFinalDestination =
       CreateTempFile(aLog->mPrefix);
-    if (NS_WARN_IF(!logFileFinalDestination))
+    if (NS_WARN_IF(!logFileFinalDestination)) {
       return NS_ERROR_UNEXPECTED;
+    }
 
     nsAutoString logFileFinalDestinationName;
     logFileFinalDestination->GetLeafName(logFileFinalDestinationName);
-    if (NS_WARN_IF(logFileFinalDestinationName.IsEmpty()))
+    if (NS_WARN_IF(logFileFinalDestinationName.IsEmpty())) {
       return NS_ERROR_UNEXPECTED;
+    }
 
     aLog->mFile->MoveTo(/* directory */ nullptr, logFileFinalDestinationName);
 
     // Save the file path.
     aLog->mFile = logFileFinalDestination;
 
     // Log to the error console.
     nsCOMPtr<nsIConsoleService> cs =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     if (cs) {
       // Copy out the path.
       nsAutoString logPath;
       logFileFinalDestination->GetPath(logPath);
 
-      nsString msg = aCollectorKind
-        + NS_LITERAL_STRING(" Collector log dumped to ") + logPath;
+      nsString msg = aCollectorKind +
+        NS_LITERAL_STRING(" Collector log dumped to ") + logPath;
       cs->LogStringMessage(msg.get());
     }
     return NS_OK;
   }
 
   int32_t mProcessIdentifier;
   nsString mFilenameIdentifier;
   FileInfo mGCLog;
@@ -1839,17 +1841,17 @@ public:
               aMarked ? ".marked" : "", aObjectDescription);
     }
     if (mWantAfterProcessing) {
       CCGraphDescriber* d =  new CCGraphDescriber();
       mDescribers.insertBack(d);
       mCurrentAddress.AssignLiteral("0x");
       mCurrentAddress.AppendInt(aAddress, 16);
       d->mType = aMarked ? CCGraphDescriber::eGCMarkedObject :
-        CCGraphDescriber::eGCedObject;
+                           CCGraphDescriber::eGCedObject;
       d->mAddress = mCurrentAddress;
       d->mName.Append(aObjectDescription);
       if (aCompartmentAddress) {
         d->mCompartmentOrToAddress.AssignLiteral("0x");
         d->mCompartmentOrToAddress.AppendInt(aCompartmentAddress, 16);
       } else {
         d->mCompartmentOrToAddress.SetIsVoid(true);
       }
@@ -2351,17 +2353,18 @@ CCGraphBuilder::AddWeakMapNode(void* aNo
 
   if (JS::Zone* zone = MergeZone(aNode)) {
     return AddNode(zone, mJSZoneParticipant);
   }
   return AddNode(aNode, mJSParticipant);
 }
 
 NS_IMETHODIMP_(void)
-CCGraphBuilder::NoteWeakMapping(void* aMap, void* aKey, void* aKdelegate, void* aVal)
+CCGraphBuilder::NoteWeakMapping(void* aMap, void* aKey, void* aKdelegate,
+                                void* aVal)
 {
   // Don't try to optimize away the entry here, as we've already attempted to
   // do that in TraceWeakMapping in nsXPConnect.
   WeakMapping* mapping = mGraph.mWeakMaps.AppendElement();
   mapping->mMap = aMap ? AddWeakMapNode(aMap) : nullptr;
   mapping->mKey = aKey ? AddWeakMapNode(aKey) : nullptr;
   mapping->mKeyDelegate = aKdelegate ? AddWeakMapNode(aKdelegate) : mapping->mKey;
   mapping->mVal = aVal ? AddWeakMapNode(aVal) : nullptr;
@@ -2645,28 +2648,28 @@ public:
 
   virtual void Trace(JS::Heap<JS::Value>* aValue, const char* aName,
                      void* aClosure) const
   {
     JS::Value val = *aValue;
     if (val.isMarkable()) {
       void* thing = val.toGCThing();
       if (thing && xpc_GCThingIsGrayCCThing(thing)) {
-        MOZ_ASSERT(!js::gc::IsInsideNursery((js::gc::Cell *)thing));
+        MOZ_ASSERT(!js::gc::IsInsideNursery((js::gc::Cell*)thing));
         mCollector->GetJSPurpleBuffer()->mValues.AppendElement(val);
       }
     }
   }
 
   virtual void Trace(JS::Heap<jsid>* aId, const char* aName,
                      void* aClosure) const
   {
   }
 
-  void AppendJSObjectToPurpleBuffer(JSObject *obj) const
+  void AppendJSObjectToPurpleBuffer(JSObject* obj) const
   {
     if (obj && xpc_GCThingIsGrayCCThing(obj)) {
       MOZ_ASSERT(!js::gc::IsInsideNursery(JS::AsCell(obj)));
       mCollector->GetJSPurpleBuffer()->mObjects.AppendElement(obj);
     }
   }
 
   virtual void Trace(JS::Heap<JSObject*>* aObject, const char* aName,
@@ -2897,19 +2900,20 @@ struct ScanBlackVisitor
 private:
   uint32_t& mWhiteNodeCount;
   bool& mFailed;
 };
 
 static void
 FloodBlackNode(uint32_t& aWhiteNodeCount, bool& aFailed, PtrInfo* aPi)
 {
-    GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(aWhiteNodeCount, aFailed)).Walk(aPi);
-    MOZ_ASSERT(aPi->mColor == black || !aPi->WasTraversed(),
-               "FloodBlackNode should make aPi black");
+  GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(aWhiteNodeCount,
+                                                 aFailed)).Walk(aPi);
+  MOZ_ASSERT(aPi->mColor == black || !aPi->WasTraversed(),
+             "FloodBlackNode should make aPi black");
 }
 
 // Iterate over the WeakMaps.  If we mark anything while iterating
 // over the WeakMaps, we must iterate over all of the WeakMaps again.
 void
 nsCycleCollector::ScanWeakMaps()
 {
   bool anyChanged;
@@ -3006,23 +3010,26 @@ nsCycleCollector::ScanIncrementalRoots()
   // refcounted object is purple, it may have been AddRef'd during the current
   // ICC. (It may also have only been released.) If that is the case, we cannot
   // be sure that the set of things pointing to the object in the CC graph
   // is accurate. Therefore, for safety, we treat any purple objects as being
   // live during the current CC. We don't remove anything from the purple
   // buffer here, so these objects will be suspected and freed in the next CC
   // if they are garbage.
   bool failed = false;
-  PurpleScanBlackVisitor purpleScanBlackVisitor(mGraph, mListener, mWhiteNodeCount, failed);
+  PurpleScanBlackVisitor purpleScanBlackVisitor(mGraph, mListener,
+                                                mWhiteNodeCount, failed);
   mPurpleBuf.VisitEntries(purpleScanBlackVisitor);
   timeLog.Checkpoint("ScanIncrementalRoots::fix purple");
 
   bool hasJSRuntime = !!mJSRuntime;
-  nsCycleCollectionParticipant* jsParticipant = hasJSRuntime ? mJSRuntime->GCThingParticipant() : nullptr;
-  nsCycleCollectionParticipant* zoneParticipant = hasJSRuntime ? mJSRuntime->ZoneParticipant() : nullptr;
+  nsCycleCollectionParticipant* jsParticipant =
+    hasJSRuntime ? mJSRuntime->GCThingParticipant() : nullptr;
+  nsCycleCollectionParticipant* zoneParticipant =
+    hasJSRuntime ? mJSRuntime->ZoneParticipant() : nullptr;
   bool hasListener = !!mListener;
 
   NodePool::Enumerator etor(mGraph.mNodes);
   while (!etor.IsDone()) {
     PtrInfo* pi = etor.GetNext();
 
     // As an optimization, if an object has already been determined to be live,
     // don't consider it further.  We can't do this if there is a listener,
@@ -3258,29 +3265,31 @@ nsCycleCollector::CollectWhite()
 
   if (mBeforeUnlinkCB) {
     mBeforeUnlinkCB();
     timeLog.Checkpoint("CollectWhite::BeforeUnlinkCB");
   }
 
   for (uint32_t i = 0; i < count; ++i) {
     PtrInfo* pinfo = whiteNodes.ElementAt(i);
-    MOZ_ASSERT(pinfo->mParticipant, "Unlink shouldn't see objects removed from graph.");
+    MOZ_ASSERT(pinfo->mParticipant,
+               "Unlink shouldn't see objects removed from graph.");
     pinfo->mParticipant->Unlink(pinfo->mPointer);
 #ifdef DEBUG
     if (mJSRuntime) {
       mJSRuntime->AssertNoObjectsToTrace(pinfo->mPointer);
     }
 #endif
   }
   timeLog.Checkpoint("CollectWhite::Unlink");
 
   for (uint32_t i = 0; i < count; ++i) {
     PtrInfo* pinfo = whiteNodes.ElementAt(i);
-    MOZ_ASSERT(pinfo->mParticipant, "Unroot shouldn't see objects removed from graph.");
+    MOZ_ASSERT(pinfo->mParticipant,
+               "Unroot shouldn't see objects removed from graph.");
     pinfo->mParticipant->Unroot(pinfo->mPointer);
   }
   timeLog.Checkpoint("CollectWhite::Unroot");
 
   nsCycleCollector_dispatchDeferredDeletion(false);
   timeLog.Checkpoint("CollectWhite::dispatchDeferredDeletion");
 
   mIncrementalPhase = CleanupPhase;
@@ -3471,18 +3480,18 @@ nsCycleCollector::FixGrayBits(bool aForc
     CC_TELEMETRY(_NEED_GC, needGC);
     if (!needGC) {
       return;
     }
     mResults.mForcedGC = true;
   }
 
   TimeLog timeLog;
-  mJSRuntime->GarbageCollect(aForceGC ? JS::gcreason::SHUTDOWN_CC
-                                      : JS::gcreason::CC_FORCED);
+  mJSRuntime->GarbageCollect(aForceGC ? JS::gcreason::SHUTDOWN_CC :
+                                        JS::gcreason::CC_FORCED);
   timeLog.Checkpoint("GC()");
 }
 
 void
 nsCycleCollector::CleanupAfterCollection()
 {
   TimeLog timeLog;
   MOZ_ASSERT(mIncrementalPhase == CleanupPhase);
@@ -3738,17 +3747,18 @@ nsCycleCollector::BeginCollection(ccType
 
   // Set up the data structures for building the graph.
   mGraph.Init();
   mResults.Init();
   bool mergeZones = ShouldMergeZones(aCCType);
   mResults.mMergedZones = mergeZones;
 
   MOZ_ASSERT(!mBuilder, "Forgot to clear mBuilder");
-  mBuilder = new CCGraphBuilder(mGraph, mResults, mJSRuntime, mListener, mergeZones);
+  mBuilder = new CCGraphBuilder(mGraph, mResults, mJSRuntime, mListener,
+                                mergeZones);
 
   if (mJSRuntime) {
     mJSRuntime->TraverseRoots(*mBuilder);
     timeLog.Checkpoint("mJSRuntime->TraverseRoots()");
   }
 
   AutoRestore<bool> ar(mScanInProgress);
   MOZ_ASSERT(!mScanInProgress);
@@ -4100,17 +4110,17 @@ nsCycleCollector_forgetSkippable(bool aR
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
   PROFILER_LABEL("nsCycleCollector", "forgetSkippable",
-    js::ProfileEntry::Category::CC);
+                 js::ProfileEntry::Category::CC);
 
   TimeLog timeLog;
   data->mCollector->ForgetSkippable(aRemoveChildlessNodes,
                                     aAsyncSnowWhiteFreeing);
   timeLog.Checkpoint("ForgetSkippable()");
 }
 
 void
@@ -4150,33 +4160,33 @@ nsCycleCollector_collect(nsICycleCollect
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
   PROFILER_LABEL("nsCycleCollector", "collect",
-    js::ProfileEntry::Category::CC);
+                 js::ProfileEntry::Category::CC);
 
   SliceBudget unlimitedBudget;
   data->mCollector->Collect(ManualCC, unlimitedBudget, aManualListener);
 }
 
 void
 nsCycleCollector_collectSlice(int64_t aSliceTime)
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
   PROFILER_LABEL("nsCycleCollector", "collectSlice",
-    js::ProfileEntry::Category::CC);
+                 js::ProfileEntry::Category::CC);
 
   SliceBudget budget;
   if (aSliceTime >= 0) {
     budget = SliceBudget(SliceBudget::TimeBudget(aSliceTime));
   }
   data->mCollector->Collect(SliceCC, budget, nullptr);
 }
 
@@ -4185,17 +4195,17 @@ nsCycleCollector_collectSliceWork(int64_
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
   PROFILER_LABEL("nsCycleCollector", "collectSliceWork",
-    js::ProfileEntry::Category::CC);
+                 js::ProfileEntry::Category::CC);
 
   SliceBudget budget;
   if (aSliceWork >= 0) {
     budget = SliceBudget(SliceBudget::WorkBudget(aSliceWork));
   }
   data->mCollector->Collect(SliceCC, budget, nullptr);
 }
 
@@ -4230,17 +4240,17 @@ nsCycleCollector_finishAnyCurrentCollect
 void
 nsCycleCollector_shutdown()
 {
   CollectorData* data = sCollectorData.get();
 
   if (data) {
     MOZ_ASSERT(data->mCollector);
     PROFILER_LABEL("nsCycleCollector", "shutdown",
-      js::ProfileEntry::Category::CC);
+                   js::ProfileEntry::Category::CC);
 
     data->mCollector->Shutdown();
     data->mCollector = nullptr;
     if (!data->mRuntime) {
       delete data;
       sCollectorData.set(nullptr);
     }
   }
--- a/xpcom/base/nsDebugImpl.cpp
+++ b/xpcom/base/nsDebugImpl.cpp
@@ -231,17 +231,18 @@ static PRLogModuleInfo* gDebugLog;
 static void
 InitLog()
 {
   if (0 == gDebugLog) {
     gDebugLog = PR_NewLogModule("nsDebug");
   }
 }
 
-enum nsAssertBehavior {
+enum nsAssertBehavior
+{
   NS_ASSERT_UNINITIALIZED,
   NS_ASSERT_WARN,
   NS_ASSERT_SUSPEND,
   NS_ASSERT_STACK,
   NS_ASSERT_TRAP,
   NS_ASSERT_ABORT,
   NS_ASSERT_STACK_AND_ABORT
 };
@@ -506,17 +507,18 @@ RealBreak()
 // Abort() calls this function, don't call it!
 static void
 Break(const char* aMsg)
 {
 #if defined(_WIN32)
   static int ignoreDebugger;
   if (!ignoreDebugger) {
     const char* shouldIgnoreDebugger = getenv("XPCOM_DEBUG_DLG");
-    ignoreDebugger = 1 + (shouldIgnoreDebugger && !strcmp(shouldIgnoreDebugger, "1"));
+    ignoreDebugger =
+      1 + (shouldIgnoreDebugger && !strcmp(shouldIgnoreDebugger, "1"));
   }
   if ((ignoreDebugger == 2) || !::IsDebuggerPresent()) {
     DWORD code = IDRETRY;
 
     /* Create the debug dialog out of process to avoid the crashes caused by
      * Windows events leaking into our event loop from an in process dialog.
      * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg).
      * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792
@@ -582,18 +584,17 @@ static const nsDebugImpl kImpl;
 
 nsresult
 nsDebugImpl::Create(nsISupports* aOuter, const nsIID& aIID, void** aInstancePtr)
 {
   if (NS_WARN_IF(aOuter)) {
     return NS_ERROR_NO_AGGREGATION;
   }
 
-  return const_cast<nsDebugImpl*>(&kImpl)->
-    QueryInterface(aIID, aInstancePtr);
+  return const_cast<nsDebugImpl*>(&kImpl)->QueryInterface(aIID, aInstancePtr);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 nsresult
 NS_ErrorAccordingToNSPR()
 {
   PRErrorCode err = PR_GetError();
--- a/xpcom/base/nsDumpUtils.cpp
+++ b/xpcom/base/nsDumpUtils.cpp
@@ -470,18 +470,17 @@ nsDumpUtils::OpenTempFile(const nsACStri
     (*aFile)->Create(nsIFile::DIRECTORY_TYPE, 0777);
 
     nsAutoCString dirPath;
     rv = (*aFile)->GetNativePath(dirPath);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    while (chmod(dirPath.get(), 0777) == -1 && errno == EINTR)
-    {
+    while (chmod(dirPath.get(), 0777) == -1 && errno == EINTR) {
     }
   }
 #endif
 
   nsCOMPtr<nsIFile> file(*aFile);
 
   rv = file->AppendNative(aFilename);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -498,15 +497,14 @@ nsDumpUtils::OpenTempFile(const nsACStri
   // CreateUnique call above are not sufficient on Android, which runs with a
   // umask.
   nsAutoCString path;
   rv = file->GetNativePath(path);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  while (chmod(path.get(), 0666) == -1 && errno == EINTR)
-  {
+  while (chmod(path.get(), 0666) == -1 && errno == EINTR) {
   }
 #endif
 
   return NS_OK;
 }
--- a/xpcom/base/nsErrorService.cpp
+++ b/xpcom/base/nsErrorService.cpp
@@ -6,27 +6,29 @@
 
 #include "nsErrorService.h"
 #include "nsCRTGlue.h"
 #include "nsAutoPtr.h"
 
 NS_IMPL_ISUPPORTS(nsErrorService, nsIErrorService)
 
 nsresult
-nsErrorService::Create(nsISupports* aOuter, const nsIID& aIID, void** aInstancePtr)
+nsErrorService::Create(nsISupports* aOuter, const nsIID& aIID,
+                       void** aInstancePtr)
 {
   if (NS_WARN_IF(aOuter)) {
     return NS_ERROR_NO_AGGREGATION;
   }
   nsRefPtr<nsErrorService> serv = new nsErrorService();
   return serv->QueryInterface(aIID, aInstancePtr);
 }
 
 NS_IMETHODIMP
-nsErrorService::RegisterErrorStringBundle(int16_t aErrorModule, const char* aStringBundleURL)
+nsErrorService::RegisterErrorStringBundle(int16_t aErrorModule,
+                                          const char* aStringBundleURL)
 {
   mErrorStringBundleURLMap.Put(aErrorModule, new nsCString(aStringBundleURL));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsErrorService::UnregisterErrorStringBundle(int16_t aErrorModule)
 {
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -439,17 +439,16 @@ interface nsIMemoryReporterManager : nsI
                  out double jsMilliseconds, out double nonJSMilliseconds);
 };
 
 %{C++
 
 #include "js/TypeDecls.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
-#include "mozilla/Atomics.h"
 
 class nsPIDOMWindow;
 
 // nsIHandleReportCallback is a better name, but keep nsIMemoryReporterCallback
 // around for backwards compatibility.
 typedef nsIMemoryReporterCallback nsIHandleReportCallback;
 
 namespace mozilla {
@@ -569,140 +568,16 @@ void RunReportersForThisProcess();
       return moz_malloc_size_of(aPtr);                                        \
   }
 #define MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(fn)                                 \
   static size_t fn(const void* aPtr)                                          \
   {                                                                           \
       return moz_malloc_size_of(aPtr);                                        \
   }
 
-namespace mozilla {
-
-// This CRTP class handles several details of wrapping allocators and should
-// be preferred to manually counting with MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC
-// and MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE.  The typical use is in a memory
-// reporter for a particular third party library:
-//
-//   class MyMemoryReporter : public CountingAllocatorBase<MyMemoryReporter>
-//   {
-//     ...
-//     NS_IMETHODIMP
-//     CollectReports(nsIHandleReportCallback* aHandleReport,
-//                    nsISupports* aData, bool aAnonymize)
-//     {
-//        return MOZ_COLLECT_REPORT(
-//          "explicit/path/to/somewhere", KIND_HEAP, UNITS_BYTES,
-//          MemoryAllocated(),
-//          "A description of what we are reporting."
-//     }
-//   };
-//
-//   ...somewhere later in the code...
-//   SetThirdPartyMemoryFunctions(MyMemoryReporter::CountingAlloc,
-//                                MyMemoryReporter::CountingFree);
-template<typename T>
-class CountingAllocatorBase
-{
-public:
-  CountingAllocatorBase()
-  {
-#ifdef DEBUG
-    // There must be only one instance of this class, due to |sAmount| being
-    // static.
-    static bool hasRun = false;
-    MOZ_ASSERT(!hasRun);
-    hasRun = true;
-#endif
-  }
-
-  static size_t
-  MemoryAllocated()
-  {
-    return sAmount;
-  }
-
-  static void*
-  CountingMalloc(size_t size)
-  {
-    void* p = malloc(size);
-    sAmount += MallocSizeOfOnAlloc(p);
-    return p;
-  }
-
-  static void*
-  CountingCalloc(size_t nmemb, size_t size)
-  {
-    void* p = calloc(nmemb, size);
-    sAmount += MallocSizeOfOnAlloc(p);
-    return p;
-  }
-
-  static void*
-  CountingRealloc(void* p, size_t size)
-  {
-    size_t oldsize = MallocSizeOfOnFree(p);
-    void *pnew = realloc(p, size);
-    if (pnew) {
-      size_t newsize = MallocSizeOfOnAlloc(pnew);
-      sAmount += newsize - oldsize;
-    } else if (size == 0) {
-      // We asked for a 0-sized (re)allocation of some existing pointer
-      // and received NULL in return.  0-sized allocations are permitted
-      // to either return NULL or to allocate a unique object per call (!).
-      // For a malloc implementation that chooses the second strategy,
-      // that allocation may fail (unlikely, but possible).
-      //
-      // Given a NULL return value and an allocation size of 0, then, we
-      // don't know if that means the original pointer was freed or if
-      // the allocation of the unique object failed.  If the original
-      // pointer was freed, then we have nothing to do here.  If the
-      // allocation of the unique object failed, the original pointer is
-      // still valid and we ought to undo the decrement from above.
-      // However, we have no way of knowing how the underlying realloc
-      // implementation is behaving.  Assuming that the original pointer
-      // was freed is the safest course of action.  We do, however, need
-      // to note that we freed memory.
-      sAmount -= oldsize;
-    } else {
-      // realloc failed.  The amount allocated hasn't changed.
-    }
-    return pnew;
-  }
-
-  // Some library code expects that realloc(x, 0) will free x, which is not
-  // the behavior of the version of jemalloc we're using, so this wrapped
-  // version of realloc is needed.
-  static void*
-  CountingFreeingRealloc(void* p, size_t size)
-  {
-    if (size == 0) {
-      CountingFree(p);
-      return nullptr;
-    }
-    return CountingRealloc(p, size);
-  }
-
-  static void
-  CountingFree(void* p)
-  {
-    sAmount -= MallocSizeOfOnFree(p);
-    free(p);
-  }
-
-private:
-  // |sAmount| can be (implicitly) accessed by multiple threads, so it
-  // must be thread-safe.
-  static Atomic<size_t> sAmount;
-
-  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
-  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
-};
-
-}
-
 // This macro assumes the presence of appropriate |aHandleReport| and |aData|
 // variables.
 #define MOZ_COLLECT_REPORT(path, kind, units, amount, description)            \
   aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(path),           \
                           kind, units, amount,                                \
                           NS_LITERAL_CSTRING(description), aData)
 
 %}
--- a/xpcom/base/nsMacUtilsImpl.cpp
+++ b/xpcom/base/nsMacUtilsImpl.cpp
@@ -32,17 +32,18 @@ nsMacUtilsImpl::GetArchString(nsAString&
 
   CFArrayRef archList = ::CFBundleCopyExecutableArchitectures(mainBundle);
   if (!archList) {
     return NS_ERROR_FAILURE;
   }
 
   CFIndex archCount = ::CFArrayGetCount(archList);
   for (CFIndex i = 0; i < archCount; i++) {
-    CFNumberRef arch = static_cast<CFNumberRef>(::CFArrayGetValueAtIndex(archList, i));
+    CFNumberRef arch =
+      static_cast<CFNumberRef>(::CFArrayGetValueAtIndex(archList, i));
 
     int archInt = 0;
     if (!::CFNumberGetValue(arch, kCFNumberIntType, &archInt)) {
       ::CFRelease(archList);
       return NS_ERROR_FAILURE;
     }
 
     if (archInt == kCFBundleExecutableArchitecturePPC) {
--- a/xpcom/base/nsMemoryInfoDumper.cpp
+++ b/xpcom/base/nsMemoryInfoDumper.cpp
@@ -119,17 +119,18 @@ public:
 private:
   ~GCAndCCLogDumpRunnable() {}
 
   const nsString mIdentifier;
   const bool mDumpAllTraces;
   const bool mDumpChildProcesses;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED(GCAndCCLogDumpRunnable, nsRunnable, nsIDumpGCAndCCLogsCallback)
+NS_IMPL_ISUPPORTS_INHERITED(GCAndCCLogDumpRunnable, nsRunnable,
+                            nsIDumpGCAndCCLogsCallback)
 
 } // anonymous namespace
 
 #if defined(MOZ_SUPPORTS_RT_SIGNALS) // {
 namespace {
 
 /*
  * The following code supports dumping about:memory upon receiving a signal.
@@ -173,34 +174,34 @@ void doMemoryReport(const uint8_t aRecvS
   NS_DispatchToMainThread(runnable);
 }
 
 void doGCCCDump(const uint8_t aRecvSig)
 {
   LOG("SignalWatcher(sig %d) dispatching GC/CC log runnable.", aRecvSig);
   // Dump GC and CC logs (from the main thread).
   nsRefPtr<GCAndCCLogDumpRunnable> runnable =
-    new GCAndCCLogDumpRunnable(
-      /* identifier = */ EmptyString(),
-      /* allTraces = */ true,
-      /* dumpChildProcesses = */ true);
+    new GCAndCCLogDumpRunnable(/* identifier = */ EmptyString(),
+                               /* allTraces = */ true,
+                               /* dumpChildProcesses = */ true);
   NS_DispatchToMainThread(runnable);
 }
 
 } // anonymous namespace
 #endif // MOZ_SUPPORTS_RT_SIGNALS }
 
 #if defined(MOZ_SUPPORTS_FIFO) // {
 namespace {
 
 void
 doMemoryReport(const nsCString& aInputStr)
 {
   bool minimize = aInputStr.EqualsLiteral("minimize memory report");
-  LOG("FifoWatcher(command:%s) dispatching memory report runnable.", aInputStr.get());
+  LOG("FifoWatcher(command:%s) dispatching memory report runnable.",
+      aInputStr.get());
   nsRefPtr<DumpMemoryInfoToTempDirRunnable> runnable =
     new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(),
                                         /* anonymize = */ false,
                                         minimize);
   NS_DispatchToMainThread(runnable);
 }
 
 void
@@ -309,17 +310,18 @@ EnsureNonEmptyIdentifier(nsAString& aIde
   // generates and also the files generated by this process's children, allowing
   // us to identify which files are from the same memory report request.
   aIdentifier.AppendInt(static_cast<int64_t>(PR_Now()) / 1000000);
 }
 
 // Use XPCOM refcounting to fire |onFinish| when all reference-holders
 // (remote dump actors or the |DumpGCAndCCLogsToFile| activation itself)
 // have gone away.
-class nsDumpGCAndCCLogsCallbackHolder MOZ_FINAL : public nsIDumpGCAndCCLogsCallback
+class nsDumpGCAndCCLogsCallbackHolder MOZ_FINAL
+  : public nsIDumpGCAndCCLogsCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
   explicit nsDumpGCAndCCLogsCallbackHolder(nsIDumpGCAndCCLogsCallback* aCallback)
     : mCallback(aCallback)
   {
   }
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -1168,46 +1168,46 @@ nsMemoryReporterManager::GetReportsExten
                                            aHandleReport,
                                            aHandleReportData,
                                            aFinishReporting,
                                            aFinishReportingData,
                                            aDMDDumpIdent);
   }
 
   if (aMinimize) {
-    rv = MinimizeMemoryUsage(NS_NewRunnableMethod(this, &nsMemoryReporter