Merge m-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Thu, 01 Jan 2015 14:19:27 -0800
changeset 247634 f9d49449c02d3c46b2fe17a956bed5f02cebe26f
parent 247607 5f175d03574164c352db89e2819953f0c2f165e9 (current diff)
parent 247633 dc2bd5df478e5b80a683314f10e42b13154595de (diff)
child 247637 13fe5ad0364df0d901ebfc32b802e427304dac6a
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c, a=merge
--- a/config/external/nss/nss.def
+++ b/config/external/nss/nss.def
@@ -675,8 +675,9 @@ VFY_Begin
 VFY_CreateContext
 VFY_DestroyContext
 VFY_End
 VFY_Update
 VFY_VerifyData
 VFY_VerifyDataDirect
 VFY_VerifyDataWithAlgorithmID
 _SGN_VerifyPKCS1DigestInfo
+PK11_PQG_ParamGenV2
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -1447,23 +1447,18 @@ NS_IMETHODIMP nsPermissionManager::GetEn
 NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
 {
   ENSURE_NOT_CHILD_PROCESS;
 
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     // The profile is about to change,
     // or is going away because the application is shutting down.
     mIsShuttingDown = true;
-    if (!nsCRT::strcmp(someData, MOZ_UTF16("shutdown-cleanse"))) {
-      // Clear the permissions file and close the db asynchronously
-      RemoveAllInternal(false);
-    } else {
-      RemoveAllFromMemory();
-      CloseDB(false);
-    }
+    RemoveAllFromMemory();
+    CloseDB(false);
   }
   else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
     // the profile has already changed; init the db from the new location
     InitDB(false);
   }
 
   return NS_OK;
 }
--- a/extensions/cookie/test/unit/head_cookies.js
+++ b/extensions/cookie/test/unit/head_cookies.js
@@ -75,23 +75,23 @@ function _observer(generator, topic) {
 
     this.generator = null;
     this.topic = null;
   }
 }
 
 // Close the cookie database. If a generator is supplied, it will be invoked
 // once the close is complete.
-function do_close_profile(generator, cleanse) {
+function do_close_profile(generator) {
   // Register an observer for db close.
   let obs = new _observer(generator, "cookie-db-closed");
 
   // Close the db.
   let service = Services.cookies.QueryInterface(Ci.nsIObserver);
-  service.observe(null, "profile-before-change", cleanse ? cleanse : "");
+  service.observe(null, "profile-before-change", "shutdown-persist");
 }
 
 // Load the cookie database. If a generator is supplied, it will be invoked
 // once the load is complete.
 function do_load_profile(generator) {
   // Register an observer for read completion.
   let obs = new _observer(generator, "cookie-db-read");
 
--- a/extensions/cookie/test/unit/test_cookies_persistence.js
+++ b/extensions/cookie/test/unit/test_cookies_persistence.js
@@ -69,25 +69,19 @@ function do_run_test() {
   // Again, but don't wait for the async close to complete. This should always
   // work, since we blocked on close above and haven't kicked off any writes
   // since then.
   do_close_profile();
   do_load_profile();
   do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
   do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
 
-  // cleanse them
-  do_close_profile(test_generator, "shutdown-cleanse");
-  yield;
-  do_load_profile();
-  do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
-  do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
-
   // test with cookies set to session-only
   Services.prefs.setIntPref("network.cookie.lifetimePolicy", 2);
+  Services.cookies.removeAll();
   do_set_cookies(uri1, channel1, false, [1, 2, 3, 4]);
   do_set_cookies(uri2, channel2, true, [1, 2, 3, 4]);
 
   // fake a profile change
   do_close_profile(test_generator);
   yield;
   do_load_profile();
   do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
--- a/extensions/cookie/test/unit/test_cookies_thirdparty_session.js
+++ b/extensions/cookie/test/unit/test_cookies_thirdparty_session.js
@@ -61,25 +61,19 @@ function do_run_test() {
 
   // fake a profile change
   do_close_profile(test_generator);
   yield;
   do_load_profile();
   do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
   do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
 
-  // cleanse them
-  do_close_profile(test_generator, "shutdown-cleanse");
-  yield;
-  do_load_profile();
-  do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
-  do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
-
   // test with third party cookies for session only.
   Services.prefs.setBoolPref("network.cookie.thirdparty.sessionOnly", true);
+  Services.cookies.removeAll();
   do_set_cookies(uri1, channel2, false, [1, 2, 3, 4]);
   do_set_cookies(uri2, channel1, true, [1, 2, 3, 4]);
 
   // fake a profile change
   do_close_profile(test_generator);
   yield;
   do_load_profile();
   do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -10,19 +10,16 @@
 #include <algorithm>
 #include "gfxDWriteFontList.h"
 #include "gfxContext.h"
 #include "gfxTextRun.h"
 #include <dwrite.h>
 
 #include "harfbuzz/hb.h"
 
-// Chosen this as to resemble DWrite's own oblique face style.
-#define OBLIQUE_SKEW_FACTOR 0.3
-
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 // This is also in gfxGDIFont.cpp. Would be nice to put it somewhere common,
 // but we can't declare it in the gfxFont.h or gfxFontUtils.h headers
 // because those are exported, and the cairo headers aren't.
 static inline cairo_antialias_t
 GetCairoAntialiasOption(gfxFont::AntialiasOption anAntialiasOption)
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -191,23 +191,21 @@ FT2FontEntry::CreateScaledFont(const gfx
     cairo_matrix_init_identity(&identityMatrix);
 
     // synthetic oblique by skewing via the font matrix
     bool needsOblique = !IsItalic() &&
             (aStyle->style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) &&
             aStyle->allowSyntheticStyle;
 
     if (needsOblique) {
-        const double kSkewFactor = 0.25;
-
         cairo_matrix_t style;
         cairo_matrix_init(&style,
                           1,                //xx
                           0,                //yx
-                          -1 * kSkewFactor,  //xy
+                          -1 * OBLIQUE_SKEW_FACTOR, //xy
                           1,                //yy
                           0,                //x0
                           0);               //y0
         cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
     }
 
     cairo_font_options_t *fontOptions = cairo_font_options_create();
 
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2266,16 +2266,28 @@ gfxFont::Measure(gfxTextRun *aTextRun,
         gfxRect fontBox(advanceMin, -metrics.mAscent,
                         advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
         metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox);
     }
     if (isRTL) {
         metrics.mBoundingBox -= gfxPoint(x, 0);
     }
 
+    // If the font may be rendered with a fake-italic effect, we need to allow
+    // for the top-right of the glyphs being skewed to the right, and the
+    // bottom-left being skewed further left.
+    if (mStyle.style != NS_FONT_STYLE_NORMAL && !mFontEntry->IsItalic()) {
+        gfxFloat extendLeftEdge =
+            ceil(OBLIQUE_SKEW_FACTOR * metrics.mBoundingBox.YMost());
+        gfxFloat extendRightEdge =
+            ceil(OBLIQUE_SKEW_FACTOR * -metrics.mBoundingBox.y);
+        metrics.mBoundingBox.width += extendLeftEdge + extendRightEdge;
+        metrics.mBoundingBox.x -= extendLeftEdge;
+    }
+
     if (baselineOffset != 0) {
         metrics.mAscent -= baselineOffset;
         metrics.mDescent += baselineOffset;
         metrics.mBoundingBox.y += baselineOffset;
     }
 
     metrics.mAdvanceWidth = x*direction;
     return metrics;
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -45,16 +45,24 @@ class gfxSkipChars;
 class gfxTextContextPaint;
 
 #define FONT_MAX_SIZE                  2000.0
 
 #define NO_FONT_LANGUAGE_OVERRIDE      0
 
 #define SMALL_CAPS_SCALE_FACTOR        0.8
 
+// The skew factor used for synthetic-italic [oblique] fonts;
+// we use a platform-dependent value to harmonize with the platform's own APIs.
+#ifdef XP_WIN
+#define OBLIQUE_SKEW_FACTOR  0.3
+#else
+#define OBLIQUE_SKEW_FACTOR  0.25
+#endif
+
 struct gfxTextRunDrawCallbacks;
 
 namespace mozilla {
 namespace gfx {
 class GlyphRenderingOptions;
 }
 }
 
--- a/gfx/thebes/gfxGDIFont.cpp
+++ b/gfx/thebes/gfxGDIFont.cpp
@@ -163,18 +163,16 @@ gfxGDIFont::Measure(gfxTextRun *aTextRun
         metrics.mBoundingBox.width > 0) {
         metrics.mBoundingBox.x -= aTextRun->GetAppUnitsPerDevUnit();
         metrics.mBoundingBox.width += aTextRun->GetAppUnitsPerDevUnit() * 3;
     }
 
     return metrics;
 }
 
-#define OBLIQUE_SKEW_FACTOR 0.3
-
 void
 gfxGDIFont::Initialize()
 {
     NS_ASSERTION(!mMetrics, "re-creating metrics? this will leak");
 
     LOGFONTW logFont;
 
     // Figure out if we want to do synthetic oblique styling.
--- a/gfx/thebes/gfxMacFont.cpp
+++ b/gfx/thebes/gfxMacFont.cpp
@@ -63,23 +63,21 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *a
     // synthetic oblique by skewing via the font matrix
     bool needsOblique =
         (mFontEntry != nullptr) &&
         (!mFontEntry->IsItalic() &&
          (mStyle.style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE))) &&
         mStyle.allowSyntheticStyle;
 
     if (needsOblique) {
-        double skewfactor = (needsOblique ? Fix2X(kATSItalicQDSkew) : 0);
-
         cairo_matrix_t style;
         cairo_matrix_init(&style,
                           1,                //xx
                           0,                //yx
-                          -1 * skewfactor,   //xy
+                          -1 * OBLIQUE_SKEW_FACTOR, //xy
                           1,                //yy
                           0,                //x0
                           0);               //y0
         cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
     }
 
     cairo_font_options_t *fontOptions = cairo_font_options_create();
 
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -266,16 +266,19 @@ private:
 #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);
   DECL_GFX_PREF(Live, "layers.dump-texture",                   LayersDumpTexture, bool, false);
+#ifdef MOZ_DUMP_PAINTING
+  DECL_GFX_PREF(Live, "layers.dump-decision",                  LayersDumpDecision, bool, false);
+#endif
 
   // 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);
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -1433,27 +1433,29 @@ gfxUtils::CopyAsDataURI(DrawTarget* aDT)
   RefPtr<SourceSurface> surface = aDT->Snapshot();
   if (surface) {
     CopyAsDataURI(surface);
   } else {
     NS_WARNING("Failed to get surface!");
   }
 }
 
-#ifdef MOZ_DUMP_PAINTING
-static bool sDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
-
 /* static */ bool
-gfxUtils::DumpPaintList() {
-  return sDumpPaintList || gfxPrefs::LayoutDumpDisplayList();
+gfxUtils::DumpDisplayList() {
+  return gfxPrefs::LayoutDumpDisplayList();
 }
 
+FILE *gfxUtils::sDumpPaintFile = stderr;
+
+#ifdef MOZ_DUMP_PAINTING
 bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT") != 0;
 bool gfxUtils::sDumpPaintingToFile = getenv("MOZ_DUMP_PAINT_TO_FILE") != 0;
-FILE *gfxUtils::sDumpPaintFile = nullptr;
+#else
+bool gfxUtils::sDumpPainting = false;
+bool gfxUtils::sDumpPaintingToFile = false;
 #endif
 
 namespace mozilla {
 namespace gfx {
 
 Color ToDeviceColor(Color aColor)
 {
   // aColor is pass-by-value since to get return value optimization goodness we
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -286,23 +286,21 @@ public:
     static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface);
 
     /**
      * Copy to the clipboard as a PNG encoded Data URL.
      */
     static void CopyAsDataURI(SourceSurface* aSourceSurface);
     static void CopyAsDataURI(DrawTarget* aDT);
 
-#ifdef MOZ_DUMP_PAINTING
-    static bool DumpPaintList();
+    static bool DumpDisplayList();
 
     static bool sDumpPainting;
     static bool sDumpPaintingToFile;
     static FILE* sDumpPaintFile;
-#endif
 };
 
 namespace mozilla {
 namespace gfx {
 
 /**
  * If the CMS mode is eCMSMode_All, these functions transform the passed
  * color to a device color using the transform returened by gfxPlatform::
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -354,16 +354,19 @@ MessageChannel::Connected() const
     // The transport layer allows us to send messages before
     // receiving the "connected" ack from the remote side.
     return (ChannelOpening == mChannelState || ChannelConnected == mChannelState);
 }
 
 bool
 MessageChannel::CanSend() const
 {
+    if (!mMonitor) {
+        return false;
+    }
     MonitorAutoLock lock(*mMonitor);
     return Connected();
 }
 
 void
 MessageChannel::Clear()
 {
     // Don't clear mWorkerLoopID; we use it in AssertLinkThread() and
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4195,26 +4195,26 @@ ParseNode::getConstantValue(ExclusiveCon
         vp.setBoolean(true);
         return true;
       case PNK_FALSE:
         vp.setBoolean(false);
         return true;
       case PNK_NULL:
         vp.setNull();
         return true;
-      case PNK_SPREAD:
-        return false;
       case PNK_CALLSITEOBJ:
       case PNK_ARRAY: {
         RootedValue value(cx);
         unsigned count;
         ParseNode *pn;
 
-        if (allowObjects == DontAllowObjects)
-            return false;
+        if (allowObjects == DontAllowObjects) {
+            vp.setMagic(JS_GENERIC_MAGIC);
+            return true;
+        }
         if (allowObjects == DontAllowNestedObjects)
             allowObjects = DontAllowObjects;
 
         if (getKind() == PNK_CALLSITEOBJ) {
             count = pn_count - 1;
             pn = pn_head->pn_next;
         } else {
             MOZ_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
@@ -4226,45 +4226,55 @@ ParseNode::getConstantValue(ExclusiveCon
         if (!obj)
             return false;
 
         unsigned idx = 0;
         RootedId id(cx);
         for (; pn; idx++, pn = pn->pn_next) {
             if (!pn->getConstantValue(cx, allowObjects, &value))
                 return false;
+            if (value.isMagic(JS_GENERIC_MAGIC)) {
+                vp.setMagic(JS_GENERIC_MAGIC);
+                return true;
+            }
             id = INT_TO_JSID(idx);
             if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
                 return false;
         }
         MOZ_ASSERT(idx == count);
 
         types::FixArrayType(cx, obj);
         vp.setObject(*obj);
         return true;
       }
       case PNK_OBJECT: {
         MOZ_ASSERT(isOp(JSOP_NEWINIT));
         MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
 
-        if (allowObjects == DontAllowObjects)
-            return false;
+        if (allowObjects == DontAllowObjects) {
+            vp.setMagic(JS_GENERIC_MAGIC);
+            return true;
+        }
         if (allowObjects == DontAllowNestedObjects)
             allowObjects = DontAllowObjects;
 
         gc::AllocKind kind = GuessObjectGCKind(pn_count);
         RootedPlainObject obj(cx,
             NewBuiltinClassInstance<PlainObject>(cx, kind, MaybeSingletonObject));
         if (!obj)
             return false;
 
         RootedValue value(cx), idvalue(cx);
         for (ParseNode *pn = pn_head; pn; pn = pn->pn_next) {
             if (!pn->pn_right->getConstantValue(cx, allowObjects, &value))
                 return false;
+            if (value.isMagic(JS_GENERIC_MAGIC)) {
+                vp.setMagic(JS_GENERIC_MAGIC);
+                return true;
+            }
 
             ParseNode *pnid = pn->pn_left;
             if (pnid->isKind(PNK_NUMBER)) {
                 idvalue = NumberValue(pnid->pn_dval);
             } else {
                 MOZ_ASSERT(pnid->isKind(PNK_NAME) || pnid->isKind(PNK_STRING));
                 MOZ_ASSERT(pnid->pn_atom != cx->names().proto);
                 idvalue = StringValue(pnid->pn_atom);
@@ -7186,38 +7196,39 @@ frontend::EmitTree(ExclusiveContext *cx,
                 // Bake in the object entirely if it will only be created once.
                 ok = EmitSingletonInitialiser(cx, bce, pn);
                 break;
             }
 
             // If the array consists entirely of primitive values, make a
             // template object with copy on write elements that can be reused
             // every time the initializer executes.
-            RootedValue value(cx);
-            if (bce->emitterMode != BytecodeEmitter::SelfHosting &&
-                pn->pn_count != 0 &&
-                pn->getConstantValue(cx, ParseNode::DontAllowNestedObjects, &value))
-            {
-                // Note: the type of the template object might not yet reflect
-                // that the object has copy on write elements. When the
-                // interpreter or JIT compiler fetches the template, it should
-                // use types::GetOrFixupCopyOnWriteObject to make sure the type
-                // for the template is accurate. We don't do this here as we
-                // want to use types::InitObject, which requires a finished
-                // script.
-                NativeObject *obj = &value.toObject().as<NativeObject>();
-                if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj))
+            if (bce->emitterMode != BytecodeEmitter::SelfHosting && pn->pn_count != 0) {
+                RootedValue value(cx);
+                if (!pn->getConstantValue(cx, ParseNode::DontAllowNestedObjects, &value))
                     return false;
-
-                ObjectBox *objbox = bce->parser->newObjectBox(obj);
-                if (!objbox)
-                    return false;
-
-                ok = EmitObjectOp(cx, objbox, JSOP_NEWARRAY_COPYONWRITE, bce);
-                break;
+                if (!value.isMagic(JS_GENERIC_MAGIC)) {
+                    // Note: the type of the template object might not yet reflect
+                    // that the object has copy on write elements. When the
+                    // interpreter or JIT compiler fetches the template, it should
+                    // use types::GetOrFixupCopyOnWriteObject to make sure the type
+                    // for the template is accurate. We don't do this here as we
+                    // want to use types::InitObject, which requires a finished
+                    // script.
+                    NativeObject *obj = &value.toObject().as<NativeObject>();
+                    if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj))
+                        return false;
+
+                    ObjectBox *objbox = bce->parser->newObjectBox(obj);
+                    if (!objbox)
+                        return false;
+
+                    ok = EmitObjectOp(cx, objbox, JSOP_NEWARRAY_COPYONWRITE, bce);
+                    break;
+                }
             }
         }
 
         ok = EmitArray(cx, bce, pn->pn_head, pn->pn_count);
         break;
 
        case PNK_ARRAYCOMP:
         ok = EmitArrayComp(cx, bce, pn);
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -831,17 +831,17 @@ class GCRuntime
      * stuff. At various times we check this counter and, if it has changed, we
      * run an immediate, non-incremental GC to clean up the dead
      * zones. This should happen very rarely.
      */
     unsigned objectsMarkedInDeadZones;
 
     bool poked;
 
-    volatile js::HeapState heapState;
+    mozilla::Atomic<js::HeapState> heapState;
 
     /*
      * ForkJoin workers enter and leave GC independently; this counter
      * tracks the number that are currently in GC.
      *
      * Technically this should be #ifdef JSGC_FJGENERATIONAL but that
      * affects the observed size of JSRuntime in problematic ways, see
      * note in vm/ThreadPool.h.
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -430,16 +430,25 @@ MarkRootRange(JSTracer *trc, size_t len,
 
 namespace js {
 namespace gc {
 
 template <typename T>
 static bool
 IsMarked(T **thingp)
 {
+    MOZ_ASSERT_IF(!ThingIsPermanentAtom(*thingp),
+                  CurrentThreadCanAccessRuntime((*thingp)->runtimeFromMainThread()));
+    return IsMarkedFromAnyThread(thingp);
+}
+
+template <typename T>
+static bool
+IsMarkedFromAnyThread(T **thingp)
+{
     MOZ_ASSERT(thingp);
     MOZ_ASSERT(*thingp);
     JSRuntime* rt = (*thingp)->runtimeFromAnyThread();
 #ifdef JSGC_FJGENERATIONAL
     // Must precede the case for GGC because IsInsideNursery()
     // will also be true for the ForkJoinNursery.
     if (rt->isFJMinorCollecting()) {
         ForkJoinContext *ctx = ForkJoinContext::current();
@@ -451,18 +460,18 @@ IsMarked(T **thingp)
 #endif
     {
         if (IsInsideNursery(*thingp)) {
             Nursery &nursery = rt->gc.nursery;
             return nursery.getForwardedPointer(thingp);
         }
     }
 
-    Zone *zone = (*thingp)->asTenured().zone();
-    if (!zone->isCollecting() || zone->isGCFinished())
+    Zone *zone = (*thingp)->asTenured().zoneFromAnyThread();
+    if (!zone->isCollectingFromAnyThread() || zone->isGCFinished())
         return true;
 #ifdef JSGC_COMPACTING
     if (zone->isGCCompacting() && IsForwarded(*thingp))
         *thingp = Forwarded(*thingp);
 #endif
     return (*thingp)->asTenured().isMarked();
 }
 
@@ -593,16 +602,22 @@ Mark##base##RootRange(JSTracer *trc, siz
                                                                                                   \
 bool                                                                                              \
 Is##base##Marked(type **thingp)                                                                   \
 {                                                                                                 \
     return IsMarked<type>(thingp);                                                                \
 }                                                                                                 \
                                                                                                   \
 bool                                                                                              \
+Is##base##MarkedFromAnyThread(BarrieredBase<type*> *thingp)                                       \
+{                                                                                                 \
+    return IsMarkedFromAnyThread<type>(thingp->unsafeGet());                                      \
+}                                                                                                 \
+                                                                                                  \
+bool                                                                                              \
 Is##base##Marked(BarrieredBase<type*> *thingp)                                                    \
 {                                                                                                 \
     return IsMarked<type>(thingp->unsafeGet());                                                   \
 }                                                                                                 \
                                                                                                   \
 bool                                                                                              \
 Is##base##AboutToBeFinalized(type **thingp)                                                       \
 {                                                                                                 \
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -92,16 +92,17 @@ namespace gc {
 #define DeclMarker(base, type)                                                                    \
 void Mark##base(JSTracer *trc, BarrieredBase<type*> *thing, const char *name);                    \
 void Mark##base##Root(JSTracer *trc, type **thingp, const char *name);                            \
 void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name);                     \
 void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type*> *thing, const char *name);       \
 void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name);            \
 bool Is##base##Marked(type **thingp);                                                             \
 bool Is##base##Marked(BarrieredBase<type*> *thingp);                                              \
+bool Is##base##MarkedFromAnyThread(BarrieredBase<type*> *thingp);                                 \
 bool Is##base##AboutToBeFinalized(type **thingp);                                                 \
 bool Is##base##AboutToBeFinalizedFromAnyThread(type **thingp);                                    \
 bool Is##base##AboutToBeFinalized(BarrieredBase<type*> *thingp);                                  \
 type *Update##base##IfRelocated(JSRuntime *rt, BarrieredBase<type*> *thingp);                     \
 type *Update##base##IfRelocated(JSRuntime *rt, type **thingp);
 
 DeclMarker(BaseShape, BaseShape)
 DeclMarker(BaseShape, UnownedBaseShape)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug1113980.js
@@ -0,0 +1,10 @@
+var p = Proxy.create({
+    getOwnPropertyDescriptor: function() {
+        return {value: 1, configurable: true, writable: true};
+    },
+    defineProperty: function() {
+    }
+}, null);
+
+var o = Object.create(p);
+o.a = 1;
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -177,18 +177,20 @@ js::SetPropertyIgnoringNamedGetter(JSCon
                 return false;
             if (!proxy->is<ProxyObject>() || proxy->as<ProxyObject>().handler() != handler)
                 return true;
             if (desc.isShared())
                 return true;
         }
         desc.value().set(vp.get());
 
-        if (descIsOwn)
-            return handler->defineProperty(cx, receiver, id, desc);
+        if (descIsOwn) {
+            MOZ_ASSERT(desc.object() == proxy);
+            return handler->defineProperty(cx, proxy, id, desc);
+        }
         return JSObject::defineGeneric(cx, receiver, id, desc.value(),
                                        desc.getter(), desc.setter(), desc.attributes());
     }
     desc.object().set(receiver);
     desc.value().set(vp.get());
     desc.setAttributes(JSPROP_ENUMERATE);
     desc.setGetter(nullptr);
     desc.setSetter(nullptr); // Pick up the class getter/setter.
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -768,17 +768,17 @@ RegExpCompartment::sweep(JSRuntime *rt)
         // restarted while in progress (i.e. performing a full GC in the
         // middle of an incremental GC) or if a RegExpShared referenced via the
         // stack is traced but is not in a zone being collected.
         //
         // Because of this we only treat the marked_ bit as a hint, and destroy
         // the RegExpShared if it was accidentally marked earlier but wasn't
         // marked by the current trace.
         bool keep = shared->marked() &&
-                    !IsStringAboutToBeFinalizedFromAnyThread(shared->source.unsafeGet());
+                    IsStringMarkedFromAnyThread(&shared->source);
         for (size_t i = 0; i < ArrayLength(shared->compilationArray); i++) {
             RegExpShared::RegExpCompilation &compilation = shared->compilationArray[i];
             if (compilation.jitCode &&
                 IsJitCodeAboutToBeFinalizedFromAnyThread(compilation.jitCode.unsafeGet()))
             {
                 keep = false;
             }
         }
--- a/layout/base/DisplayItemClip.cpp
+++ b/layout/base/DisplayItemClip.cpp
@@ -450,17 +450,16 @@ DisplayItemClip::NoClip()
 
 void
 DisplayItemClip::Shutdown()
 {
   delete gNoClip;
   gNoClip = nullptr;
 }
 
-#ifdef MOZ_DUMP_PAINTING
 nsCString
 DisplayItemClip::ToString() const
 {
   nsAutoCString str;
   if (mHaveClipRect) {
     str.AppendPrintf("%d,%d,%d,%d", mClipRect.x, mClipRect.y,
                      mClipRect.width, mClipRect.height);
     for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) {
@@ -468,11 +467,10 @@ DisplayItemClip::ToString() const
       str.AppendPrintf(" [%d,%d,%d,%d corners %d,%d,%d,%d,%d,%d,%d,%d]",
                        r.mRect.x, r.mRect.y, r.mRect.width, r.mRect.height,
                        r.mRadii[0], r.mRadii[1], r.mRadii[2], r.mRadii[3],
                        r.mRadii[4], r.mRadii[5], r.mRadii[6], r.mRadii[7]);
     }
   }
   return str;
 }
-#endif
 
 }
--- a/layout/base/DisplayItemClip.h
+++ b/layout/base/DisplayItemClip.h
@@ -159,19 +159,17 @@ public:
   const nsRect& GetClipRect() const
   {
     NS_ASSERTION(HasClip(), "No clip rect!");
     return mClipRect;
   }
 
   void MoveBy(nsPoint aPoint);
 
-#ifdef MOZ_DUMP_PAINTING
   nsCString ToString() const;
-#endif
 
   /**
    * Find the largest N such that the first N rounded rects in 'this' are
    * equal to the first N rounded rects in aOther, and N <= aMax.
    */
   uint32_t GetCommonRoundedRectCount(const DisplayItemClip& aOther,
                                      uint32_t aMax) const;
   uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); }
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -273,18 +273,20 @@ public:
 
 #ifdef MOZ_DUMP_PAINTING
   /**
    * Keep track of important decisions for debugging.
    */
   nsAutoCString mLog;
 
   #define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
-          pld->mLog.AppendPrintf("\t\t\t\t"); \
-          pld->mLog.AppendPrintf(__VA_ARGS__);
+          if (gfxPrefs::LayersDumpDecision()) { \
+            pld->mLog.AppendPrintf("\t\t\t\t"); \
+            pld->mLog.AppendPrintf(__VA_ARGS__); \
+          }
 #else
   #define FLB_LOG_PAINTED_LAYER_DECISION(...)
 #endif
 
   /**
    * Record that an item has been added to the PaintedLayer, so we
    * need to update our regions.
    * @param aVisibleRect the area of the item that's visible
@@ -4418,17 +4420,16 @@ FrameLayerBuilder::PaintItems(nsTArray<C
     }
 
     if (cdi->mInactiveLayerManager) {
       PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
     } else {
       nsIFrame* frame = cdi->mItem->Frame();
       frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
 #ifdef MOZ_DUMP_PAINTING
-
       if (gfxUtils::sDumpPainting) {
         DebugPaintItem(aDrawTarget, aPresContext, cdi->mItem, aBuilder);
       } else {
 #else
       {
 #endif
         cdi->mItem->Paint(aBuilder, aRC);
       }
@@ -4676,23 +4677,21 @@ FrameLayerBuilder::CheckDOMModified()
   mDetectedDOMModification = true;
   // Painting is not going to complete properly. There's not much
   // we can do here though. Invalidating the window to get another repaint
   // is likely to lead to an infinite repaint loop.
   NS_WARNING("Detected DOM modification during paint, bailing out!");
   return true;
 }
 
-#ifdef MOZ_DUMP_PAINTING
 /* static */ void
 FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml)
 {
   aManager->Dump(aStream, "", aDumpHtml);
 }
-#endif
 
 gfx::Rect
 CalculateBounds(const nsTArray<DisplayItemClip::RoundedRect>& aRects, int32_t A2D)
 {
   nsRect bounds = aRects[0].mRect;
   for (uint32_t i = 1; i < aRects.Length(); ++i) {
     bounds.UnionRect(bounds, aRects[i].mRect);
    }
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -263,23 +263,21 @@ public:
    */
   static void DrawPaintedLayer(PaintedLayer* aLayer,
                               gfxContext* aContext,
                               const nsIntRegion& aRegionToDraw,
                               mozilla::layers::DrawRegionClip aClip,
                               const nsIntRegion& aRegionToInvalidate,
                               void* aCallbackData);
 
-#ifdef MOZ_DUMP_PAINTING
   /**
    * Dumps this FrameLayerBuilder's retained layer manager's retained
    * layer tree. Defaults to dumping to stdout in non-HTML format.
    */
   static void DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml = false);
-#endif
 
   /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/
   /* These are only in the public section because they need
    * to be called by file-scope helper functions in FrameLayerBuilder.cpp.
    */
 
   /**
    * Record aItem as a display item that is rendered by aLayer.
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2047,27 +2047,25 @@ nsDisplaySolidColor::Paint(nsDisplayList
 {
   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   DrawTarget* drawTarget = aCtx->GetDrawTarget();
   Rect rect =
     NSRectToSnappedRect(mVisibleRect, appUnitsPerDevPixel, *drawTarget);
   drawTarget->FillRect(rect, ColorPattern(ToDeviceColor(mColor)));
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplaySolidColor::WriteDebugInfo(std::stringstream& aStream)
 {
   aStream << " (rgba "
           << (int)NS_GET_R(mColor) << ","
           << (int)NS_GET_G(mColor) << ","
           << (int)NS_GET_B(mColor) << ","
           << (int)NS_GET_A(mColor) << ")";
 }
-#endif
 
 static void
 RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
 {
   if (!aBuilder->IsInSubdocument() && !aBuilder->IsInTransform()) {
     nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
     nsRect borderBox(aFrame->GetOffsetTo(displayRoot), aFrame->GetSize());
     aBuilder->RegisterThemeGeometry(aFrame->StyleDisplay()->mAppearance,
@@ -2763,23 +2761,21 @@ nsDisplayThemedBackground::nsDisplayThem
 
 nsDisplayThemedBackground::~nsDisplayThemedBackground()
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   MOZ_COUNT_DTOR(nsDisplayThemedBackground);
 #endif
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayThemedBackground::WriteDebugInfo(std::stringstream& aStream)
 {
   aStream << " (themed, appearance:" << (int)mAppearance << ")";
 }
-#endif
 
 void
 nsDisplayThemedBackground::HitTest(nsDisplayListBuilder* aBuilder,
                                   const nsRect& aRect,
                                   HitTestState* aState,
                                   nsTArray<nsIFrame*> *aOutFrames)
 {
   // Assume that any point in our border rect is a hit.
@@ -2968,24 +2964,22 @@ nsDisplayBackgroundColor::HitTest(nsDisp
   if (!RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
     // aRect doesn't intersect our border-radius curve.
     return;
   }
 
   aOutFrames->AppendElement(mFrame);
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayBackgroundColor::WriteDebugInfo(std::stringstream& aStream)
 {
   aStream << " (rgba " << mColor.r << "," << mColor.g << ","
           << mColor.b << "," << mColor.a << ")";
 }
-#endif
 
 already_AddRefed<Layer>
 nsDisplayClearBackground::BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      const ContainerLayerParameters& aParameters)
 {
   nsRefPtr<ColorLayer> layer = static_cast<ColorLayer*>
     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
@@ -3093,31 +3087,29 @@ nsDisplayLayerEventRegions::AddFrame(nsD
 }
 
 void
 nsDisplayLayerEventRegions::AddInactiveScrollPort(const nsRect& aRect)
 {
   mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aRect);
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayLayerEventRegions::WriteDebugInfo(std::stringstream& aStream)
 {
   if (!mHitRegion.IsEmpty()) {
     AppendToString(aStream, mHitRegion, " (hitRegion ", ")");
   }
   if (!mMaybeHitRegion.IsEmpty()) {
     AppendToString(aStream, mMaybeHitRegion, " (maybeHitRegion ", ")");
   }
   if (!mDispatchToContentHitRegion.IsEmpty()) {
     AppendToString(aStream, mDispatchToContentHitRegion, " (dispatchToContentRegion ", ")");
   }
 }
-#endif
 
 nsDisplayCaret::nsDisplayCaret(nsDisplayListBuilder* aBuilder,
                                nsIFrame* aCaretFrame)
   : nsDisplayItem(aBuilder, aCaretFrame)
   , mCaret(aBuilder->GetCaret())
   , mBounds(aBuilder->GetCaretRect() + ToReferenceFrame())
 {
   MOZ_COUNT_CTOR(nsDisplayCaret);
@@ -3805,23 +3797,21 @@ bool nsDisplayOpacity::TryMerge(nsDispla
   if (aItem->Frame()->GetContent() != mFrame->GetContent())
     return false;
   if (aItem->GetClip() != GetClip())
     return false;
   MergeFromTrackingMergedFrames(static_cast<nsDisplayOpacity*>(aItem));
   return true;
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayOpacity::WriteDebugInfo(std::stringstream& aStream)
 {
   aStream << " (opacity " << mOpacity << ")";
 }
-#endif
 
 nsDisplayMixBlendMode::nsDisplayMixBlendMode(nsDisplayListBuilder* aBuilder,
                                              nsIFrame* aFrame, nsDisplayList* aList,
                                              uint32_t aFlags)
 : nsDisplayWrapList(aBuilder, aFrame, aList) {
   MOZ_COUNT_CTOR(nsDisplayMixBlendMode);
 }
 
@@ -4570,24 +4560,22 @@ nsDisplayScrollLayer::GetScrollLayerCoun
   // that it is processed last.
   NS_ABORT_IF_FALSE(hasCount, "nsDisplayScrollLayer should always be defined");
   return result;
 #else
   return reinterpret_cast<intptr_t>(props.Get(nsIFrame::ScrollLayerCount()));
 #endif
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayScrollLayer::WriteDebugInfo(std::stringstream& aStream)
 {
   aStream << " (scrollframe " << mScrollFrame
           << " scrolledFrame " << mScrolledFrame << ")";
 }
-#endif
 
 nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer(
   nsDisplayListBuilder* aBuilder,
   nsIFrame* aScrolledFrame,
   nsIFrame* aScrollFrame)
   : nsDisplayScrollLayer(aBuilder, aScrollFrame, aScrolledFrame, aScrollFrame)
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
@@ -5758,23 +5746,21 @@ bool nsDisplayTransform::UntransformVisi
   result = ToMatrix4x4(matrix.Inverse()).ProjectRectBounds(result);
   result = result.Intersect(childGfxBounds);
 
   *aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(ThebesRect(result), factor);
 
   return true;
 }
 
-#ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream)
 {
   AppendToString(aStream, GetTransform());
 }
-#endif
 
 nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
                                          nsIFrame* aFrame, nsDisplayList* aList)
     : nsDisplayWrapList(aBuilder, aFrame, aList),
       mEffectsBounds(aFrame->GetVisualOverflowRectRelativeToSelf())
 {
   MOZ_COUNT_CTOR(nsDisplaySVGEffects);
 }
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -94,24 +94,19 @@ typedef mozilla::EnumSet<mozilla::gfx::C
  * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
  *
  * Display item's coordinates are relative to their nearest reference frame ancestor.
  * Both the display root and any frame with a transform act as a reference frame
  * for their frame subtrees.
  */
 
 // All types are defined in nsDisplayItemTypes.h
-#ifdef MOZ_DUMP_PAINTING
 #define NS_DISPLAY_DECL_NAME(n, e) \
   virtual const char* Name() { return n; } \
   virtual Type GetType() { return e; }
-#else
-#define NS_DISPLAY_DECL_NAME(n, e) \
-  virtual Type GetType() { return e; }
-#endif
 
 /**
  * This manages a display list and is passed as a parameter to
  * nsIFrame::BuildDisplayList.
  * It contains the parameters that don't change from frame to frame and manages
  * the display list memory using a PLArena. It also establishes the reference
  * coordinate system for all display list items. Some of the parameters are
  * available from the prescontext/presshell, but we copy them into the builder
@@ -1373,25 +1368,23 @@ public:
    * Stores the given opacity value to be applied when drawing. Returns
    * false if this isn't supported for this display item.
    */
   virtual bool ApplyOpacity(nsDisplayListBuilder* aBuilder,
                             float aOpacity,
                             const DisplayItemClip* aClip) {
     return false;
   }
-  
-#ifdef MOZ_DUMP_PAINTING
+
   /**
    * For debugging and stuff
    */
   virtual const char* Name() = 0;
 
   virtual void WriteDebugInfo(std::stringstream& aStream) {}
-#endif
 
   nsDisplayItem* GetAbove() { return mAbove; }
 
   /**
    * Like ComputeVisibility, but does the work that nsDisplayList
    * does per-item:
    * -- Intersects GetBounds with aVisibleRegion and puts the result
    * in mVisibleRect
@@ -1944,19 +1937,17 @@ public:
 class nsDisplayGeneric : public nsDisplayItem {
 public:
   typedef void (* PaintCallback)(nsIFrame* aFrame, nsRenderingContext* aCtx,
                                  const nsRect& aDirtyRect, nsPoint aFramePt);
 
   nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                    PaintCallback aPaint, const char* aName, Type aType)
     : nsDisplayItem(aBuilder, aFrame), mPaint(aPaint)
-#ifdef MOZ_DUMP_PAINTING
       , mName(aName)
-#endif
       , mType(aType)
   {
     MOZ_COUNT_CTOR(nsDisplayGeneric);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayGeneric() {
     MOZ_COUNT_DTOR(nsDisplayGeneric);
   }
@@ -1973,19 +1964,17 @@ public:
       bool snap;
       return GetBounds(aBuilder, &snap);
     }
     return nsRect();
   }
 
 protected:
   PaintCallback mPaint;
-#ifdef MOZ_DUMP_PAINTING
   const char*   mName;
-#endif
   Type mType;
 };
 
 /**
  * Generic display item that can contain overflow. Use this in lieu of
  * nsDisplayGeneric if you have a frame that should use the visual overflow
  * rect of its frame when drawing items, instead of the frame's bounds.
  */
@@ -2199,19 +2188,17 @@ public:
     if (mColor != geometry->mColor) {
       bool dummy;
       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
       return;
     }
     ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
   }
 
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 
   NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
 
 private:
   nsRect  mBounds;
   nscolor mColor;
 };
 
@@ -2360,19 +2347,17 @@ public:
   {
     return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
   }
 
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion* aInvalidRegion) MOZ_OVERRIDE;
 
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 protected:
   nsRect GetBoundsInternal();
 
   void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
                      const nsRect& aBounds, nsRect* aClipRect);
 
   nsRect mBounds;
   nsITheme::Transparency mThemeTransparency;
@@ -2423,19 +2408,17 @@ public:
       bool dummy;
       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
       return;
     }
     ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
   }
 
   NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 
 protected:
   const nsStyleBackground* mBackgroundStyle;
   gfxRGBA mColor;
 };
 
 class nsDisplayClearBackground : public nsDisplayItem
 {
@@ -2664,19 +2647,17 @@ public:
   // dispatch-to-content region, to ensure that APZ lets content create a
   // displayport.
   void AddInactiveScrollPort(const nsRect& aRect);
 
   const nsRegion& HitRegion() { return mHitRegion; }
   const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; }
   const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; }
 
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 
 private:
   // Relative to aFrame's reference frame.
   // These are the points that are definitely in the hit region.
   nsRegion mHitRegion;
   // These are points that may or may not be in the hit region. Only main-thread
   // event handling can tell for sure (e.g. because complex shapes are present).
   nsRegion mMaybeHitRegion;
@@ -2874,19 +2855,17 @@ public:
     // We don't need to compute an invalidation region since we have LayerTreeInvalidation
   }
   virtual bool ApplyOpacity(nsDisplayListBuilder* aBuilder,
                             float aOpacity,
                             const DisplayItemClip* aClip) MOZ_OVERRIDE;
   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
   bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder);
   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 
   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
 
 private:
   float mOpacity;
 };
 
 class nsDisplayMixBlendMode : public nsDisplayWrapList {
@@ -3172,19 +3151,17 @@ public:
   // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
   // number does not include nsDisplayScrollInfoLayers. If this number is not 1
   // after merging, all the nsDisplayScrollLayers should flatten away.
   intptr_t GetScrollLayerCount();
 
   virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
   virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
 
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 
   bool IsDisplayPortOpaque() { return mDisplayPortContentsOpaque; }
 
   static FrameMetrics ComputeFrameMetrics(nsIFrame* aForFrame,
                                           nsIFrame* aScrollFrame,
                                           const nsIFrame* aReferenceFrame,
                                           Layer* aLayer,
                                           ViewID aScrollParentId,
@@ -3583,19 +3560,17 @@ public:
    */
   bool MaybePrerender() const { return mMaybePrerender; }
   /**
    * Check if this element will be prerendered. This must be done after the
    * display list has been fully built.
    */
   bool ShouldPrerender(nsDisplayListBuilder* aBuilder);
 
-#ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(std::stringstream& aStream) MOZ_OVERRIDE;
-#endif
 
 private:
   void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
   void Init(nsDisplayListBuilder* aBuilder);
 
   static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
                                                          const nsPoint& aOrigin,
                                                          float aAppUnitsPerPixel,
--- a/layout/base/nsLayoutDebugger.cpp
+++ b/layout/base/nsLayoutDebugger.cpp
@@ -116,17 +116,16 @@ NS_IMETHODIMP
 nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation,
                                int32_t* aSizeInBytesResult)
 {
   *aSizeInBytesResult = 0;
   return NS_ERROR_FAILURE;
 }
 #endif
 
-#ifdef MOZ_DUMP_PAINTING
 std::ostream& operator<<(std::ostream& os, const nsPrintfCString& rhs) {
   os << rhs.get();
   return os;
 }
 
 static void
 PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
                    std::stringstream& aStream, uint32_t aIndent, bool aDumpHtml);
@@ -153,22 +152,24 @@ PrintDisplayItemTo(nsDisplayListBuilder*
     nsLayoutUtils::GetAnimatedGeometryRootFor(aItem, aBuilder, nullptr)->
       GetOffsetToCrossDoc(aItem->ReferenceFrame());
   nscolor color;
   nsRect vis = aItem->GetVisibleRect();
   nsRect component = aItem->GetComponentAlphaBounds(aBuilder);
   nsDisplayList* list = aItem->GetChildren();
   const DisplayItemClip& clip = aItem->GetClip();
   nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
+#ifdef MOZ_DUMP_PAINTING
   if (aDumpHtml && aItem->Painted()) {
     nsCString string(aItem->Name());
     string.Append('-');
     string.AppendInt((uint64_t)aItem);
     aStream << nsPrintfCString("<a href=\"javascript:ViewImage('%s')\">", string.BeginReading());
   }
+#endif
   aStream << nsPrintfCString("%s p=0x%p f=0x%p(%s) %sbounds(%d,%d,%d,%d) layerBounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) %s",
           aItem->Name(), aItem, (void*)f, NS_ConvertUTF16toUTF8(fName).get(),
           (aItem->ZIndex() ? nsPrintfCString("z=%d ", aItem->ZIndex()).get() : ""),
           rect.x, rect.y, rect.width, rect.height,
           layerRect.x, layerRect.y, layerRect.width, layerRect.height,
           vis.x, vis.y, vis.width, vis.height,
           component.x, component.y, component.width, component.height,
           clip.ToString().get(),
@@ -192,33 +193,37 @@ PrintDisplayItemTo(nsDisplayListBuilder*
       aStream << NS_LossyConvertUTF16toASCII(aItem->Frame()->StyleDisplay()->mWillChange[i]).get();
     }
     aStream << ")";
   }
 
   // Display item specific debug info
   aItem->WriteDebugInfo(aStream);
 
+#ifdef MOZ_DUMP_PAINTING
   if (aDumpHtml && aItem->Painted()) {
     aStream << "</a>";
   }
+#endif
   uint32_t key = aItem->GetPerFrameKey();
   Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key);
   if (layer) {
     if (aDumpHtml) {
       aStream << nsPrintfCString(" <a href=\"#%p\">layer=%p</a>", layer, layer);
     } else {
       aStream << nsPrintfCString(" layer=0x%p", layer);
     }
   }
+#ifdef MOZ_DUMP_PAINTING
   if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
     nsCString str;
     (static_cast<nsDisplaySVGEffects*>(aItem))->PrintEffects(str);
     aStream << str.get();
   }
+#endif
   aStream << "\n";
 
   if (aDumpSublist && list) {
     PrintDisplayListTo(aBuilder, *list, aStream, aIndent+1, aDumpHtml);
   }
 }
 
 static void
@@ -258,16 +263,17 @@ void
 nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder,
                           const nsDisplayList& aList,
                           std::stringstream& aStream,
                           bool aDumpHtml)
 {
   PrintDisplayListTo(aBuilder, aList, aStream, 0, aDumpHtml);
 }
 
+#ifdef MOZ_DUMP_PAINTING
 static void
 PrintDisplayListSetItem(nsDisplayListBuilder* aBuilder,
                         const char* aItemName,
                         const nsDisplayList& aList,
                         std::stringstream& aStream,
                         bool aDumpHtml)
 {
   if (aDumpHtml) {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3098,35 +3098,39 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   builder.LeavePresShell(aFrame);
   Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME,
                                  startBuildDisplayList);
 
   if (builder.GetHadToIgnorePaintSuppression()) {
     willFlushRetainedLayers = true;
   }
 
-#ifdef MOZ_DUMP_PAINTING
-  FILE* savedDumpFile = gfxUtils::sDumpPaintFile;
 
   bool profilerNeedsDisplayList = profiler_feature_active("displaylistdump");
-  bool consoleNeedsDisplayList = gfxUtils::DumpPaintList() || gfxUtils::sDumpPainting;
-
-  UniquePtr<std::stringstream> ss = MakeUnique<std::stringstream>();
+  bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxUtils::sDumpPainting;
+#ifdef MOZ_DUMP_PAINTING
+  FILE* savedDumpFile = gfxUtils::sDumpPaintFile;
+#endif
+
+  UniquePtr<std::stringstream> ss;
   if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
+    ss = MakeUnique<std::stringstream>();
+#ifdef MOZ_DUMP_PAINTING
     if (gfxUtils::sDumpPaintingToFile) {
       nsCString string("dump-");
       string.AppendInt(gPaintCount);
       string.AppendLiteral(".html");
       gfxUtils::sDumpPaintFile = fopen(string.BeginReading(), "w");
     } else {
       gfxUtils::sDumpPaintFile = stderr;
     }
     if (gfxUtils::sDumpPaintingToFile) {
       *ss << "<html><head><script>var array = {}; function ViewImage(index) { window.location = array[index]; }</script></head><body>";
     }
+#endif
     *ss << nsPrintfCString("Painting --- before optimization (dirty %d,%d,%d,%d):\n",
             dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height).get();
     nsFrame::PrintDisplayList(&builder, list, *ss, gfxUtils::sDumpPaintingToFile);
     if (gfxUtils::sDumpPaintingToFile) {
       *ss << "<script>";
     } else {
       // Flush stream now to avoid reordering dump output relative to
       // messages dumped by PaintRoot below.
@@ -3134,17 +3138,16 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
         profiler_log(ss->str().c_str());
       } else {
         // Send to the console which will send to the profiler if required.
         fprint_stderr(gfxUtils::sDumpPaintFile, *ss);
       }
       ss = MakeUnique<std::stringstream>();
     }
   }
-#endif
 
   uint32_t flags = nsDisplayList::PAINT_DEFAULT;
   if (aFlags & PAINT_WIDGET_LAYERS) {
     flags |= nsDisplayList::PAINT_USE_WIDGET_LAYERS;
     if (willFlushRetainedLayers) {
       // The caller wanted to paint from retained layers, but set up
       // the paint in such a way that we can't use them.  We're going
       // to display something different from what we'd normally paint
@@ -3173,47 +3176,49 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   }
 
   TimeStamp paintStart = TimeStamp::Now();
   nsRefPtr<LayerManager> layerManager =
     list.PaintRoot(&builder, aRenderingContext, flags);
   Telemetry::AccumulateTimeDelta(Telemetry::PAINT_RASTERIZE_TIME,
                                  paintStart);
 
+  if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
 #ifdef MOZ_DUMP_PAINTING
-  if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
     if (gfxUtils::sDumpPaintingToFile) {
       *ss << "</script>";
     }
+#endif
     *ss << "Painting --- after optimization:\n";
     nsFrame::PrintDisplayList(&builder, list, *ss, gfxUtils::sDumpPaintingToFile);
 
     *ss << "Painting --- layer tree:\n";
     if (layerManager) {
       FrameLayerBuilder::DumpRetainedLayerTree(layerManager, *ss,
                                                gfxUtils::sDumpPaintingToFile);
     }
-    if (gfxUtils::sDumpPaintingToFile) {
-      *ss << "</body></html>";
-    }
 
     if (profilerNeedsDisplayList && !consoleNeedsDisplayList) {
       profiler_log(ss->str().c_str());
     } else {
       // Send to the console which will send to the profiler if required.
       fprint_stderr(gfxUtils::sDumpPaintFile, *ss);
     }
 
+#ifdef MOZ_DUMP_PAINTING
+    if (gfxUtils::sDumpPaintingToFile) {
+      *ss << "</body></html>";
+    }
     if (gfxUtils::sDumpPaintingToFile) {
       fclose(gfxUtils::sDumpPaintFile);
     }
     gfxUtils::sDumpPaintFile = savedDumpFile;
     gPaintCount++;
-  }
 #endif
+  }
 
   // Update the widget's opaque region information. This sets
   // glass boundaries on Windows. Also set up the window dragging region
   // and plugin clip regions and bounds.
   if ((aFlags & PAINT_WIDGET_LAYERS) &&
       !willFlushRetainedLayers &&
       !(aFlags & PAINT_DOCUMENT_RELATIVE)) {
     nsIWidget *widget = aFrame->GetNearestWidget();
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -726,17 +726,17 @@ public:
   static void ShowFrameBorders(bool aEnable);
   static bool GetShowFrameBorders();
 
   // Show frame border of event target
   static void ShowEventTargetFrameBorder(bool aEnable);
   static bool GetShowEventTargetFrameBorder();
 
 #endif
-#ifdef MOZ_DUMP_PAINTING
+
 public:
 
   static void PrintDisplayItem(nsDisplayListBuilder* aBuilder,
                                nsDisplayItem* aItem,
                                std::stringstream& aStream,
                                bool aDumpSublist = false,
                                bool aDumpHtml = false);
 
@@ -752,17 +752,16 @@ public:
                                const nsDisplayList& aList,
                                std::stringstream& aStream,
                                bool aDumpHtml = false);
   static void PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
                                   const nsDisplayListSet& aList,
                                   std::stringstream& aStream,
                                   bool aDumpHtml = false);
 
-#endif
 };
 
 // Start Display Reflow Debugging
 #ifdef DEBUG
 
   struct DR_cookie {
     DR_cookie(nsPresContext*          aPresContext,
               nsIFrame*                aFrame, 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1116480-1-fakeitalic-overflow-ref.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <meta name='viewport' content='initial-scale=1' />
+    <style>
+      @font-face {
+        font-family: test;
+        src: url(../fonts/dejavu-sans/DejaVuSans.ttf);
+      }
+
+      body {
+        font-family: test;
+      }
+
+      .container {
+        padding: 1rem 0 0.3rem;
+      }
+
+      .placeholder {
+        font-style: italic;
+        position: absolute;
+        font-size: 8em;
+      }
+    </style>
+  </head>
+  <body>
+    <div class='container'>
+      <div class='placeholder'>aI&#x301;z
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1116480-1-fakeitalic-overflow.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <meta name='viewport' content='initial-scale=1' />
+    <style>
+      @font-face {
+        font-family: test;
+        src: url(../fonts/dejavu-sans/DejaVuSans.ttf);
+      }
+
+      body {
+        font-family: test;
+      }
+
+      .container {
+        padding: 1rem 0 0.3rem;
+      }
+
+      .placeholder {
+        font-style: italic;
+        position: absolute;
+        font-size: 8em;
+      }
+    </style>
+  </head>
+  <body>
+    <div class='container'>
+      <div class='placeholder'>a&#x202e;I&#x301;&#x202c;z
+    </div>
+  </body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1845,8 +1845,9 @@ fails-if(Android) == 1062792-1.html 1062
 == 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html
 test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html
 == 1069716-1.html 1069716-1-ref.html
 == 1078262-1.html about:blank
 test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
 fuzzy-if(winWidget&&!layersGPUAccelerated,1,31) == 1081185-1.html 1081185-1-ref.html
 == 1097437-1.html 1097437-1-ref.html
 == 1105137-1.html 1105137-1-ref.html
+fuzzy-if(d2d,36,304) HTTP(..) == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow-ref.html
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2219,20 +2219,18 @@ pref("layout.testing.overlay-scrollbars.
 // are pending.
 pref("layout.interruptible-reflow.enabled", true);
 
 // pref to control browser frame rate, in Hz. A value <= 0 means choose
 // automatically based on knowledge of the platform (or 60Hz if no platform-
 // specific information is available).
 pref("layout.frame_rate", -1);
 
-// pref to dump the display list to the log. Useful for debugging invalidation problems.
-#ifdef MOZ_DUMP_PAINTING
+// pref to dump the display list to the log. Useful for debugging drawing.
 pref("layout.display-list.dump", false);
-#endif
 
 // pref to control precision of the frame rate timer. When true,
 // we use a "precise" timer, which means each notification fires
 // Nms after the start of the last notification. That means if the
 // processing of the notification is slow, the timer can fire immediately
 // after we've just finished processing the last notification, which might
 // lead to starvation problems.
 // When false, we use a "slack" timer which fires Nms after the *end*
--- a/netwerk/base/public/nsISiteSecurityService.idl
+++ b/netwerk/base/public/nsISiteSecurityService.idl
@@ -18,17 +18,17 @@ namespace mozilla
   {
     class Time;
   }
 }
 %}
 [ref] native nsCStringTArrayRef(nsTArray<nsCString>);
 [ref] native mozillaPkixTime(mozilla::pkix::Time);
 
-[scriptable, uuid(46555f70-3ab5-11e4-8613-180373d97f23)]
+[scriptable, uuid(e219eace-0e04-42ba-b203-58a8b327867c)]
 interface nsISiteSecurityService : nsISupports
 {
     const uint32_t HEADER_HSTS = 0;
     const uint32_t HEADER_HPKP = 1;
     const uint32_t HEADER_OMS = 2;
 
     /**
      * Parses a given HTTP header and records the results internally.
@@ -96,22 +96,16 @@ interface nsISiteSecurityService : nsISu
      * @param aFlags  options for this request as defined in nsISocketProvider:
      *                  NO_PERMANENT_STORAGE
      */
     boolean isSecureHost(in uint32_t aType,
                          in string aHost,
                          in uint32_t aFlags);
 
     /**
-     * Checks if the given security info is for a host with a broken
-     * transport layer (certificate errors like invalid CN).
-     */
-    boolean shouldIgnoreHeaders(in nsISupports aSecurityInfo);
-
-    /**
      * Checks whether or not the URI's hostname has a given security state set.
      * For example, for HSTS:
      * The URI is an HSTS URI if either the host has the HSTS state set, or one
      * of its super-domains has the HSTS "includeSubdomains" flag set.
      * NOTE: this function makes decisions based only on the
      * host contained in the URI, and disregards other portions of the URI
      * such as path and port.
      *
--- a/netwerk/protocol/app/AppProtocolHandler.cpp
+++ b/netwerk/protocol/app/AppProtocolHandler.cpp
@@ -140,20 +140,18 @@ NS_IMETHODIMP DummyChannel::GetZipEntry(
 NS_IMETHODIMP DummyChannel::EnsureChildFd()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP DummyChannel::Run()
 {
   nsresult rv = mListener->OnStartRequest(this, mListenerContext);
-  NS_ENSURE_SUCCESS(rv, rv);
   mPending = false;
   rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
-  NS_ENSURE_SUCCESS(rv, rv);
   if (mLoadGroup) {
     mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
   }
 
   mListener = nullptr;
   mListenerContext = nullptr;
   rv = SetNotificationCallbacks(nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -3261,17 +3261,19 @@ nsHttpChannel::OnCacheEntryAvailable(nsI
                                      nsIApplicationCache* aAppCache,
                                      nsresult status)
 {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsresult rv;
 
     LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p "
-         "new=%d appcache=%p status=%x]\n", this, entry, aNew, aAppCache, status));
+         "new=%d appcache=%p status=%x mAppCache=%p mAppCacheForWrite=%p]\n",
+         this, entry, aNew, aAppCache, status,
+         mApplicationCache.get(), mApplicationCacheForWrite.get()));
 
     // if the channel's already fired onStopRequest, then we should ignore
     // this event.
     if (!mIsPending) {
         mCacheInputStream.CloseAndRelease();
         return NS_OK;
     }
 
@@ -3371,36 +3373,41 @@ nsHttpChannel::OnOfflineCacheEntryAvaila
 {
     MOZ_ASSERT(!mApplicationCache || aAppCache == mApplicationCache);
     MOZ_ASSERT(!aNew || !aEntry || mApplicationCacheForWrite);
 
     mCacheEntriesToWaitFor &= ~WAIT_FOR_CACHE_ENTRY;
 
     nsresult rv;
 
-    if (!mApplicationCache)
-        mApplicationCache = aAppCache;
-
     if (NS_SUCCEEDED(aEntryStatus)) {
+        if (!mApplicationCache) {
+            mApplicationCache = aAppCache;
+        }
+
         // We successfully opened an offline cache session and the entry,
         // so indicate we will load from the offline cache.
         mLoadedFromApplicationCache = true;
         mCacheEntryIsReadOnly = true;
         mCacheEntry = aEntry;
         mCacheEntryIsWriteOnly = false;
 
         if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI && !mApplicationCacheForWrite) {
             Telemetry::Accumulate(Telemetry::HTTP_OFFLINE_CACHE_DOCUMENT_LOAD,
                                   true);
         }
 
         return NS_OK;
     }
 
     if (!mApplicationCacheForWrite && !mFallbackChannel) {
+        if (!mApplicationCache) {
+            mApplicationCache = aAppCache;
+        }
+
         // Check for namespace match.
         nsCOMPtr<nsIApplicationCacheNamespace> namespaceEntry;
         rv = mApplicationCache->GetMatchingNamespace(mSpec,
             getter_AddRefs(namespaceEntry));
         NS_ENSURE_SUCCESS(rv, rv);
 
         uint32_t namespaceType = 0;
         if (!namespaceEntry ||
--- a/security/apps/AppTrustDomain.cpp
+++ b/security/apps/AppTrustDomain.cpp
@@ -212,25 +212,25 @@ AppTrustDomain::GetCertTrust(EndEntityOr
   trustLevel = TrustLevel::InheritsTrust;
   return Success;
 }
 
 Result
 AppTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
                                  Input subjectPublicKeyInfo)
 {
-  return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
-                                           mMinimumNonECCBits, mPinArg);
+  return ::mozilla::pkix::VerifySignedDataNSS(signedData, subjectPublicKeyInfo,
+                                              mMinimumNonECCBits, mPinArg);
 }
 
 Result
 AppTrustDomain::DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
                           size_t digestBufLen)
 {
-  return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
+  return ::mozilla::pkix::DigestBufNSS(item, digestBuf, digestBufLen);
 }
 
 Result
 AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time,
                                 /*optional*/ const Input*,
                                 /*optional*/ const Input*)
 {
   // We don't currently do revocation checking. If we need to distrust an Apps
@@ -247,13 +247,13 @@ AppTrustDomain::IsChainValid(const DERAr
     return MapPRErrorCodeToResult(PR_GetError());
   }
   return Success;
 }
 
 Result
 AppTrustDomain::CheckPublicKey(Input subjectPublicKeyInfo)
 {
-  return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo,
-                                         mMinimumNonECCBits);
+  return ::mozilla::pkix::CheckPublicKeyNSS(subjectPublicKeyInfo,
+                                            mMinimumNonECCBits);
 }
 
 } } // namespace mozilla::psm
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -253,25 +253,25 @@ NSSCertDBTrustDomain::GetCertTrust(EndEn
   trustLevel = TrustLevel::InheritsTrust;
   return Success;
 }
 
 Result
 NSSCertDBTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
                                        Input subjectPublicKeyInfo)
 {
-  return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
-                                           mMinimumNonECCBits, mPinArg);
+  return ::mozilla::pkix::VerifySignedDataNSS(signedData, subjectPublicKeyInfo,
+                                              mMinimumNonECCBits, mPinArg);
 }
 
 Result
 NSSCertDBTrustDomain::DigestBuf(Input item,
                                 /*out*/ uint8_t* digestBuf, size_t digestBufLen)
 {
-  return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
+  return ::mozilla::pkix::DigestBufNSS(item, digestBuf, digestBufLen);
 }
 
 
 static PRIntervalTime
 OCSPFetchingTypeToTimeoutTime(NSSCertDBTrustDomain::OCSPFetching ocspFetching)
 {
   switch (ocspFetching) {
     case NSSCertDBTrustDomain::FetchOCSPForDVSoftFail:
@@ -695,18 +695,18 @@ NSSCertDBTrustDomain::IsChainValid(const
   }
 
   return Success;
 }
 
 Result
 NSSCertDBTrustDomain::CheckPublicKey(Input subjectPublicKeyInfo)
 {
-  return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo,
-                                         mMinimumNonECCBits);
+  return ::mozilla::pkix::CheckPublicKeyNSS(subjectPublicKeyInfo,
+                                            mMinimumNonECCBits);
 }
 
 namespace {
 
 static char*
 nss_addEscape(const char* string, char quote)
 {
   char* newString = 0;
--- a/security/manager/boot/src/nsSiteSecurityService.cpp
+++ b/security/manager/boot/src/nsSiteSecurityService.cpp
@@ -6,17 +6,16 @@
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Base64.h"
 #include "base64.h"
 #include "CertVerifier.h"
 #include "nsCRTGlue.h"
 #include "nsISSLStatus.h"
-#include "nsISSLStatusProvider.h"
 #include "nsISocketProvider.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsNSSComponent.h"
 #include "nsSecurityHeaderParser.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
@@ -960,49 +959,16 @@ nsSiteSecurityService::IsSecureHost(uint
 
     SSSLOG(("no HSTS data for %s found, walking up domain", subdomain));
   }
 
   // Use whatever we ended up with, which defaults to false.
   return NS_OK;
 }
 
-
-// Verify the trustworthiness of the security info (are there any cert errors?)
-NS_IMETHODIMP
-nsSiteSecurityService::ShouldIgnoreHeaders(nsISupports* aSecurityInfo,
-                                           bool* aResult)
-{
-  nsresult rv;
-  bool tlsIsBroken = false;
-  nsCOMPtr<nsISSLStatusProvider> sslprov = do_QueryInterface(aSecurityInfo);
-  NS_ENSURE_TRUE(sslprov, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsISSLStatus> sslstat;
-  rv = sslprov->GetSSLStatus(getter_AddRefs(sslstat));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(sslstat, NS_ERROR_FAILURE);
-
-  bool trustcheck;
-  rv = sslstat->GetIsDomainMismatch(&trustcheck);
-  NS_ENSURE_SUCCESS(rv, rv);
-  tlsIsBroken = tlsIsBroken || trustcheck;
-
-  rv = sslstat->GetIsNotValidAtThisTime(&trustcheck);
-  NS_ENSURE_SUCCESS(rv, rv);
-  tlsIsBroken = tlsIsBroken || trustcheck;
-
-  rv = sslstat->GetIsUntrusted(&trustcheck);
-  NS_ENSURE_SUCCESS(rv, rv);
-  tlsIsBroken = tlsIsBroken || trustcheck;
-
-  *aResult = tlsIsBroken;
-  return NS_OK;
-}
-
 NS_IMETHODIMP
 nsSiteSecurityService::ClearAll()
 {
   return mSiteStateStorage->Clear();
 }
 
 NS_IMETHODIMP
 nsSiteSecurityService::GetKeyPinsForHostname(const char* aHostname,
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_sts_privatebrowsing_perwindowpb.html
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_sts_privatebrowsing_perwindowpb.html
@@ -49,30 +49,38 @@
                      'nosts': 'INSECURE'}},
     'alreadysecure':
       {'url':     "https://test2.example.com" + STSPATH + "/verify.sjs",
         'expected': {'plain': 'SECURE',
                      'subdom': 'SECURE',
                      'nosts': 'SECURE'}},
   };
 
+  function whenDelayedStartupFinished(aWindow, aCallback) {
+    SpecialPowers.Services.obs.addObserver(function observer(aSubject, aTopic) {
+      if (aWindow == aSubject) {
+        SpecialPowers.Services.obs.removeObserver(observer, aTopic);
+        SimpleTest.executeSoon(aCallback);
+      }
+    }, "browser-delayed-startup-finished", false);
+  }
+
   function testOnWindow(aIsPrivate, aCallback) {
     var win = mainWindow.OpenBrowserWindow({private: aIsPrivate});
-    win.addEventListener("load", function onLoad() {
-      win.removeEventListener("load", onLoad, false);
+    whenDelayedStartupFinished(win, function () {
       win.gBrowser.addEventListener("DOMContentLoaded", function onInnerLoad() {
         if (win.content.location.href != CONTENT_PAGE) {
           win.gBrowser.loadURI(CONTENT_PAGE);
           return;
         }
         win.gBrowser.removeEventListener("DOMContentLoaded", onInnerLoad, true);
         SimpleTest.executeSoon(function() { aCallback(win); });
       }, true);
       win.gBrowser.loadURI(CONTENT_PAGE);
-    }, true);
+    });
   }
 
   function startRound(win, isPrivate, round) {
     currentround = round;
     testsleftinround = NUM_TEST_FRAMES;
     SimpleTest.info("TESTS LEFT IN ROUND " + currentround + ": " + testsleftinround);
     var frame = win.content.document.createElement("iframe");
     frame.setAttribute('id', 'ifr_bootstrap');
--- a/security/pkix/include/pkix/Input.h
+++ b/security/pkix/include/pkix/Input.h
@@ -119,17 +119,17 @@ public:
   // Don't use this. It is here because we have some "friend" functions that we
   // don't want to declare in this header file.
   const uint8_t* UnsafeGetData() const { return data; }
 
 private:
   const uint8_t* data;
   size_t len;
 
-  void operator=(const Input&) /* = delete */; // Use Init instead.
+  void operator=(const Input&) = delete; // Use Init instead.
 };
 
 inline bool
 InputsAreEqual(const Input& a, const Input& b)
 {
   return a.GetLength() == b.GetLength() &&
          !std::memcmp(a.UnsafeGetData(), b.UnsafeGetData(), a.GetLength());
 }
@@ -286,17 +286,17 @@ public:
 
   class Mark
   {
   private:
     friend class Reader;
     Mark(const Reader& input, const uint8_t* mark) : input(input), mark(mark) { }
     const Reader& input;
     const uint8_t* const mark;
-    void operator=(const Mark&) /* = delete */;
+    void operator=(const Mark&) = delete;
   };
 
   Mark GetMark() const { return Mark(*this, input); }
 
   Result GetInput(const Mark& mark, /*out*/ Input& item)
   {
     if (&mark.input != this || mark.mark > input) {
       return NotReached("invalid mark", Result::FATAL_ERROR_INVALID_ARGS);
@@ -315,18 +315,18 @@ private:
     input = data;
     end = data + len;
     return Success;
   }
 
   const uint8_t* input;
   const uint8_t* end;
 
-  Reader(const Reader&) /* = delete */;
-  void operator=(const Reader&) /* = delete */;
+  Reader(const Reader&) = delete;
+  void operator=(const Reader&) = delete;
 };
 
 inline bool
 InputContains(const Input& input, uint8_t toFind)
 {
   Reader reader(input);
   for (;;) {
     uint8_t b;
--- a/security/pkix/include/pkix/ScopedPtr.h
+++ b/security/pkix/include/pkix/ScopedPtr.h
@@ -64,18 +64,18 @@ public:
     return result;
   }
 
   void reset() { *this = nullptr; }
 
 protected:
   T* mValue;
 
-  ScopedPtr(const ScopedPtr&) /* = delete */;
-  void operator=(const ScopedPtr&) /* = delete */;
+  ScopedPtr(const ScopedPtr&) = delete;
+  void operator=(const ScopedPtr&) = delete;
 };
 
 template <typename T, void(&Destroyer)(T*)>
 inline bool
 operator==(T* a, const ScopedPtr<T, Destroyer>& b)
 {
   return a == b.get();
 }
--- a/security/pkix/include/pkix/bind.h
+++ b/security/pkix/include/pkix/bind.h
@@ -75,47 +75,47 @@ class Bind1
 {
 public:
   typedef R (&F)(P1&, B1&);
   Bind1(F f, B1& b1) : f(f), b1(b1) { }
   R operator()(P1& p1) const { return f(p1, b1); }
 private:
   F f;
   B1& b1;
-  void operator=(const Bind1&) /*= delete*/;
+  void operator=(const Bind1&) = delete;
 };
 
 template <typename R, typename P1, typename B1, typename B2>
 class Bind2
 {
 public:
   typedef R (&F)(P1&, B1&, B2&);
   Bind2(F f, B1& b1, B2& b2) : f(f), b1(b1), b2(b2) { }
   R operator()(P1& p1) const { return f(p1, b1, b2); }
 private:
   F f;
   B1& b1;
   B2& b2;
-  void operator=(const Bind2&) /*= delete*/;
+  void operator=(const Bind2&) = delete;
 };
 
 template <typename R, typename P1, typename B1, typename B2, typename B3>
 class Bind3
 {
 public:
   typedef R (&F)(P1&, B1, B2, B3&);
   Bind3(F f, B1& b1, B2& b2, B3& b3)
     : f(f), b1(b1), b2(b2), b3(b3) { }
   R operator()(P1& p1) const { return f(p1, b1, b2, b3); }
 private:
   F f;
   B1& b1;
   B2& b2;
   B3& b3;
-  void operator=(const Bind3&) /*= delete*/;
+  void operator=(const Bind3&) = delete;
 };
 
 template <typename R, typename P1, typename B1, typename B2, typename B3,
           typename B4>
 class Bind4
 {
 public:
   typedef R (&F)(P1&, B1, B2, B3&, B4&);
@@ -123,17 +123,17 @@ public:
     : f(f), b1(b1), b2(b2), b3(b3), b4(b4) { }
   R operator()(P1& p1) const { return f(p1, b1, b2, b3, b4); }
 private:
   F f;
   B1& b1;
   B2& b2;
   B3& b3;
   B4& b4;
-  void operator=(const Bind4&) /*= delete*/;
+  void operator=(const Bind4&) = delete;
 };
 
 template <typename R, typename C1, typename P1, typename P2, typename P3,
           typename P4>
 class BindToMemberFunction4
 {
 public:
   // XXX: C++ doesn't have reference-to-member function, only
@@ -143,17 +143,17 @@ public:
   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& that;
-  void operator=(const BindToMemberFunction4&) /*= delete*/;
+  void operator=(const BindToMemberFunction4&) = delete;
 };
 
 template <typename R, typename P1, typename B1, typename B2, typename B3,
           typename B4, typename B5>
 class Bind5
 {
 public:
   typedef R (&F)(P1&, B1, B2, B3, B4, B5);
@@ -162,17 +162,17 @@ public:
   R operator()(P1& p1) const { return f(p1, b1, b2, b3, b4, b5); }
 private:
   F f;
   B1 b1;
   B2 b2;
   B3 b3;
   B4 b4;
   B5 b5;
-  void operator=(const Bind5&) /*= delete*/;
+  void operator=(const Bind5&) = delete;
 };
 
 } // namespace internal
 
 template <typename R, typename P1, typename B1>
 inline internal::Bind1<R, P1, B1>
 bind(R (&f)(P1&, B1&), Placeholder1&, B1& b1)
 {
--- a/security/pkix/include/pkix/enumclass.h
+++ b/security/pkix/include/pkix/enumclass.h
@@ -20,23 +20,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef mozilla_pkix__enumclass_h
 #define mozilla_pkix__enumclass_h
 
-#if defined(_MSC_VER) && (_MSC_VER < 1700)
-// Microsoft added support for "enum class" in Visual C++ 2012. Before that,
-// Visual C++ has supported typed enums for longer than that, but using typed
-// enums results in C4480: nonstandard extension used: specifying underlying
-// type for enum.
-#define MOZILLA_PKIX_ENUM_CLASS  __pragma(warning(suppress: 4480)) enum
-#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 407)
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 407)
 // GCC before version 4.7 may crash when compiling code that static_casts a
 // value of scoped typed enum type. See
 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48106.
 #define MOZILLA_PKIX_ENUM_CLASS enum
 #else
 #define MOZILLA_PKIX_ENUM_CLASS enum class
 #define MOZILLA_PKIX_ENUM_CLASS_REALLY_IS_ENUM_CLASS
 #endif
--- a/security/pkix/include/pkix/pkixnss.h
+++ b/security/pkix/include/pkix/pkixnss.h
@@ -27,39 +27,39 @@
 
 #include "pkixtypes.h"
 #include "prerror.h"
 #include "seccomon.h"
 
 namespace mozilla { namespace pkix {
 
 // Verify the given signed data using the given public key.
-Result VerifySignedData(const SignedDataWithSignature& sd,
-                        Input subjectPublicKeyInfo,
-                        unsigned int minimumNonECCBits,
-                        void* pkcs11PinArg);
+Result VerifySignedDataNSS(const SignedDataWithSignature& sd,
+                           Input subjectPublicKeyInfo,
+                           unsigned int minimumNonECCBits,
+                           void* pkcs11PinArg);
 
 // Computes the SHA-1 hash of the data in the current item.
 //
 // item contains the data to hash.
 // digestBuf must point to a buffer to where the SHA-1 hash will be written.
 // digestBufLen must be 20 (the length of a SHA-1 hash,
 //              TrustDomain::DIGEST_LENGTH).
 //
 // TODO(bug 966856): Add SHA-2 support
 // TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
 // other, extensive, memory safety efforts in mozilla::pkix, and we should find
 // a way to provide a more-obviously-safe interface.
-Result DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
-                 size_t digestBufLen);
+Result DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf,
+                    size_t digestBufLen);
 
 // Checks, for RSA keys and DSA keys, that the modulus is at least the given
 // number of bits.
-Result CheckPublicKey(Input subjectPublicKeyInfo,
-                      unsigned int minimumNonECCBits);
+Result CheckPublicKeyNSS(Input subjectPublicKeyInfo,
+                         unsigned int minimumNonECCBits);
 
 Result MapPRErrorCodeToResult(PRErrorCode errorCode);
 PRErrorCode MapResultToPRErrorCode(Result result);
 
 // The error codes within each module must fit in 16 bits. We want these
 // errors to fit in the same module as the NSS errors but not overlap with
 // any of them. Converting an NSS SEC, NSS SSL, or PSM error to an NS error
 // involves negating the value of the error and then synthesizing an error
--- a/security/pkix/include/pkix/pkixtypes.h
+++ b/security/pkix/include/pkix/pkixtypes.h
@@ -75,18 +75,17 @@ MOZILLA_PKIX_ENUM_CLASS SignatureAlgorit
 
 struct SignedDataWithSignature
 {
 public:
   Input data;
   SignatureAlgorithm algorithm;
   Input signature;
 
-private:
-  void operator=(const SignedDataWithSignature&) /*= delete*/;
+  void operator=(const SignedDataWithSignature&) = delete;
 };
 
 MOZILLA_PKIX_ENUM_CLASS EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
 
 MOZILLA_PKIX_ENUM_CLASS KeyUsage : uint8_t {
   digitalSignature = 0,
   nonRepudiation   = 1,
   keyEncipherment  = 2,
@@ -143,18 +142,18 @@ public:
     : issuer(issuer)
     , issuerSubjectPublicKeyInfo(issuerSubjectPublicKeyInfo)
     , serialNumber(serialNumber)
   {
   }
   const Input issuer;
   const Input issuerSubjectPublicKeyInfo;
   const Input serialNumber;
-private:
-  void operator=(const CertID&) /*= delete*/;
+
+  void operator=(const CertID&) = delete;
 };
 
 class DERArray
 {
 public:
   // Returns the number of DER-encoded items in the array.
   virtual size_t GetLength() const = 0;
 
@@ -204,38 +203,36 @@ public:
     // constraints will be checked in addition to any any name constraints
     // contained in potentialIssuerDER.
     virtual Result Check(Input potentialIssuerDER,
             /*optional*/ const Input* additionalNameConstraints,
                  /*out*/ bool& keepGoing) = 0;
   protected:
     IssuerChecker();
     virtual ~IssuerChecker();
-  private:
-    IssuerChecker(const IssuerChecker&) /*= delete*/;
-    void operator=(const IssuerChecker&) /*= delete*/;
+
+    IssuerChecker(const IssuerChecker&) = delete;
+    void operator=(const IssuerChecker&) = delete;
   };
 
   // Search for a CA certificate with the given name. The implementation must
   // call checker.Check with the DER encoding of the potential issuer
   // certificate. The implementation must follow these rules:
   //
-  // * The subject name of the certificate given to checker.Check must be equal
-  //   to encodedIssuerName.
   // * The implementation must be reentrant and must limit the amount of stack
   //   space it uses; see the note on reentrancy and stack usage below.
-  // * When checker.Check does not return SECSuccess then immediately return
-  //   SECFailure.
-  // * When checker.Check returns SECSuccess and sets keepGoing = false, then
-  //   immediately return SECSuccess.
-  // * When checker.Check returns SECSuccess and sets keepGoing = true, then
+  // * When checker.Check does not return Success then immediately return its
+  //   return value.
+  // * When checker.Check returns Success and sets keepGoing = false, then
+  //   immediately return Success.
+  // * When checker.Check returns Success and sets keepGoing = true, then
   //   call checker.Check again with a different potential issuer certificate,
   //   if any more are available.
   // * When no more potential issuer certificates are available, return
-  //   SECSuccess.
+  //   Success.
   // * Don't call checker.Check with the same potential issuer certificate more
   //   than once in a given call of FindIssuer.
   // * The given time parameter may be used to filter out certificates that are
   //   not valid at the given time, or it may be ignored.
   //
   // Note on reentrancy and stack usage: checker.Check will attempt to
   // recursively build a certificate path from the potential issuer it is given
   // to a trusted root, as determined by this TrustDomain. That means that
@@ -250,44 +247,49 @@ public:
   //              [...]
   //                TrustDomain::FindIssuer
   //                  [...]
   //                    IssuerChecker::Check
   //                      [...]
   //
   // checker.Check is responsible for limiting the recursion to a reasonable
   // limit.
+  //
+  // checker.Check will verify that the subject's issuer field matches the
+  // potential issuer's subject field. It will also check that the potential
+  // issuer is valid at the given time. However, if the FindIssuer
+  // implementation has an efficient way of filtering potential issuers by name
+  // and/or validity period itself, then it is probably better for performance
+  // for it to do so.
   virtual Result FindIssuer(Input encodedIssuerName,
                             IssuerChecker& checker, Time time) = 0;
 
   // Called as soon as we think we have a valid chain but before revocation
   // checks are done. This function can be used to compute additional checks,
   // especilaly checks that require the entire certificate chain. This callback
   // can also be used to save a copy of the built certificate chain for later
   // use.
   //
   // This function may be called multiple times, regardless of whether it
-  // returns SECSuccess or SECFailure. It is guaranteed that BuildCertChain
-  // will not return SECSuccess unless the last call to IsChainValid returns
-  // SECSuccess. Further, it is guaranteed that when BuildCertChain returns
-  // SECSuccess the last chain passed to IsChainValid is the valid chain that
-  // should be used for further operations that require the whole chain.
+  // returns success or failure. It is guaranteed that BuildCertChain will not
+  // return Success unless the last call to IsChainValid returns Success. Further,
+  // it is guaranteed that when BuildCertChain returns Success the last chain
+  // passed to IsChainValid is the valid chain that should be used for further
+  // operations that require the whole chain.
   //
   // Keep in mind, in particular, that if the application saves a copy of the
   // certificate chain the last invocation of IsChainValid during a validation,
-  // it is still possible for BuildCertChain to fail (return SECFailure), in
-  // which case the application must not assume anything about the validity of
-  // the last certificate chain passed to IsChainValid; especially, it would be
-  // very wrong to assume that the certificate chain is valid.
+  // it is still possible for BuildCertChain to fail, in which case the
+  // application must not assume anything about the validity of the last
+  // certificate chain passed to IsChainValid; especially, it would be very
+  // wrong to assume that the certificate chain is valid.
   //
   // certChain.GetDER(0) is the trust anchor.
   virtual Result IsChainValid(const DERArray& certChain, Time time) = 0;
 
-  // issuerCertToDup is only non-const so CERT_DupCertificate can be called on
-  // it.
   virtual Result CheckRevocation(EndEntityOrCA endEntityOrCA,
                                  const CertID& certID, Time time,
                     /*optional*/ const Input* stapledOCSPresponse,
                     /*optional*/ const Input* aiaExtension) = 0;
 
   // Check that the key size, algorithm, and parameters of the given public key
   // are acceptable.
   //
@@ -317,16 +319,15 @@ public:
   // other, extensive, memory safety efforts in mozilla::pkix, and we should
   // find a way to provide a more-obviously-safe interface.
   static const size_t DIGEST_LENGTH = 20; // length of SHA-1 digest
   virtual Result DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
                            size_t digestBufLen) = 0;
 protected:
   TrustDomain() { }
 
-private:
-  TrustDomain(const TrustDomain&) /* = delete */;
-  void operator=(const TrustDomain&) /* = delete */;
+  TrustDomain(const TrustDomain&) = delete;
+  void operator=(const TrustDomain&) = delete;
 };
 
 } } // namespace mozilla::pkix
 
 #endif // mozilla_pkix__pkixtypes_h
--- a/security/pkix/lib/pkixbuild.cpp
+++ b/security/pkix/lib/pkixbuild.cpp
@@ -79,18 +79,18 @@ private:
   /*optional*/ Input const* const stapledOCSPResponse;
   const unsigned int subCACount;
   const Result deferredSubjectError;
 
   Result RecordResult(Result currentResult, /*out*/ bool& keepGoing);
   Result result;
   bool resultWasSet;
 
-  PathBuildingStep(const PathBuildingStep&) /*= delete*/;
-  void operator=(const PathBuildingStep&) /*= delete*/;
+  PathBuildingStep(const PathBuildingStep&) = delete;
+  void operator=(const PathBuildingStep&) = delete;
 };
 
 Result
 PathBuildingStep::RecordResult(Result newResult, /*out*/ bool& keepGoing)
 {
   if (newResult == Result::ERROR_UNTRUSTED_CERT) {
     newResult = Result::ERROR_UNTRUSTED_ISSUER;
   } else if (newResult == Result::ERROR_EXPIRED_CERTIFICATE) {
@@ -134,18 +134,27 @@ PathBuildingStep::Check(Input potentialI
 {
   BackCert potentialIssuer(potentialIssuerDER, EndEntityOrCA::MustBeCA,
                            &subject);
   Result rv = potentialIssuer.Init();
   if (rv != Success) {
     return RecordResult(rv, keepGoing);
   }
 
-  // RFC5280 4.2.1.1. Authority Key Identifier
-  // RFC5280 4.2.1.2. Subject Key Identifier
+  // Simple TrustDomain::FindIssuers implementations may pass in all possible
+  // CA certificates without any filtering. Because of this, we don't consider
+  // a mismatched name to be an error. Instead, we just pretend that any
+  // certificate without a matching name was never passed to us. In particular,
+  // we treat the case where the TrustDomain only asks us to check CA
+  // certificates with mismatched names as equivalent to the case where the
+  // TrustDomain never called Check() at all.
+  if (!InputsAreEqual(potentialIssuer.GetSubject(), subject.GetIssuer())) {
+    keepGoing = true;
+    return Success;
+  }
 
   // Loop prevention, done as recommended by RFC4158 Section 5.2
   // TODO: this doesn't account for subjectAltNames!
   // TODO(perf): This probably can and should be optimized in some way.
   bool loopDetected = false;
   for (const BackCert* prev = potentialIssuer.childCert;
        !loopDetected && prev != nullptr; prev = prev->childCert) {
     if (InputsAreEqual(potentialIssuer.GetSubjectPublicKeyInfo(),
--- a/security/pkix/lib/pkixder.h
+++ b/security/pkix/lib/pkixder.h
@@ -161,19 +161,16 @@ Nested(Reader& input, uint8_t tag, Decod
   }
   return End(nested);
 }
 
 template <typename Decoder>
 inline Result
 Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
 {
-  // XXX: This doesn't work (in VS2010):
-  // return Nested(input, outerTag, bind(Nested, _1, innerTag, decoder));
-
   Reader nestedInput;
   Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
   if (rv != Success) {
     return rv;
   }
   rv = Nested(nestedInput, innerTag, decoder);
   if (rv != Success) {
     return rv;
--- a/security/pkix/lib/pkixnss.cpp
+++ b/security/pkix/lib/pkixnss.cpp
@@ -34,17 +34,17 @@
 #include "pkix/ScopedPtr.h"
 #include "secerr.h"
 #include "sslerr.h"
 
 namespace mozilla { namespace pkix {
 
 typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey> ScopedSECKeyPublicKey;
 
-Result
+static Result
 CheckPublicKeySize(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
                    /*out*/ ScopedSECKeyPublicKey& publicKey)
 {
   SECItem subjectPublicKeyInfoSECItem =
     UnsafeMapInputToSECItem(subjectPublicKeyInfo);
   ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
     spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&subjectPublicKeyInfoSECItem));
   if (!spki) {
@@ -54,46 +54,46 @@ CheckPublicKeySize(Input subjectPublicKe
   if (!publicKey) {
     return MapPRErrorCodeToResult(PR_GetError());
   }
 
   switch (publicKey.get()->keyType) {
     case ecKey:
       // TODO(bug 1077790): We should check which curve.
       return Success;
-    case dsaKey: // fall through
     case rsaKey:
       if (SECKEY_PublicKeyStrengthInBits(publicKey.get()) < minimumNonECCBits) {
         return Result::ERROR_INADEQUATE_KEY_SIZE;
       }
       break;
-    case nullKey:
-    case fortezzaKey:
-    case dhKey:
-    case keaKey:
-    case rsaPssKey:
-    case rsaOaepKey:
+    case dsaKey: // fall through
+    case nullKey: // fall through
+    case fortezzaKey: // fall through
+    case dhKey: // fall through
+    case keaKey: // fall through
+    case rsaPssKey: // fall through
+    case rsaOaepKey: // fall through
     default:
       return Result::ERROR_UNSUPPORTED_KEYALG;
   }
 
   return Success;
 }
 
 Result
-CheckPublicKey(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits)
+CheckPublicKeyNSS(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits)
 {
   ScopedSECKeyPublicKey unused;
   return CheckPublicKeySize(subjectPublicKeyInfo, minimumNonECCBits, unused);
 }
 
 Result
-VerifySignedData(const SignedDataWithSignature& sd,
-                 Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
-                 void* pkcs11PinArg)
+VerifySignedDataNSS(const SignedDataWithSignature& sd,
+                    Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
+                    void* pkcs11PinArg)
 {
   SECOidTag pubKeyAlg;
   SECOidTag digestAlg;
   switch (sd.algorithm) {
     case SignatureAlgorithm::ecdsa_with_sha512:
       pubKeyAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
       digestAlg = SEC_OID_SHA512;
       break;
@@ -120,20 +120,20 @@ VerifySignedData(const SignedDataWithSig
     case SignatureAlgorithm::rsa_pkcs1_with_sha256:
       pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
       digestAlg = SEC_OID_SHA256;
       break;
     case SignatureAlgorithm::rsa_pkcs1_with_sha1:
       pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
       digestAlg = SEC_OID_SHA1;
       break;
-    case SignatureAlgorithm::unsupported_algorithm:
+    case SignatureAlgorithm::unsupported_algorithm: // fall through
     default:
-      PR_NOT_REACHED("unknown signature algorithm");
-      return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
+      return NotReached("unknown signature algorithm",
+                        Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
   }
 
   Result rv;
   ScopedSECKeyPublicKey pubKey;
   rv = CheckPublicKeySize(subjectPublicKeyInfo, minimumNonECCBits, pubKey);
   if (rv != Success) {
     return rv;
   }
@@ -154,23 +154,22 @@ VerifySignedData(const SignedDataWithSig
   if (srv != SECSuccess) {
     return MapPRErrorCodeToResult(PR_GetError());
   }
 
   return Success;
 }
 
 Result
-DigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
+DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
 {
   static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
                 "TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
   if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
-    PR_NOT_REACHED("invalid hash length");
-    return Result::FATAL_ERROR_INVALID_ARGS;
+    return NotReached("invalid hash length", Result::FATAL_ERROR_INVALID_ARGS);
   }
   SECItem itemSECItem = UnsafeMapInputToSECItem(item);
   if (itemSECItem.len >
         static_cast<decltype(itemSECItem.len)>(
           std::numeric_limits<int32_t>::max())) {
     PR_NOT_REACHED("large items should not be possible here");
     return Result::FATAL_ERROR_INVALID_ARGS;
   }
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -66,19 +66,18 @@ public:
   const CertID& certID;
   const Time time;
   const uint16_t maxLifetimeInDays;
   CertStatus certStatus;
   Time* thisUpdate;
   Time* validThrough;
   bool expired;
 
-private:
-  Context(const Context&); // delete
-  void operator=(const Context&); // delete
+  Context(const Context&) = delete;
+  void operator=(const Context&) = delete;
 };
 
 // Verify that potentialSigner is a valid delegated OCSP response signing cert
 // according to RFC 6960 section 4.2.2.2.
 static Result
 CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
                             BackCert& potentialSigner,
                             Input issuerSubject,
--- a/security/pkix/lib/pkixutil.h
+++ b/security/pkix/lib/pkixutil.h
@@ -138,18 +138,18 @@ private:
   Input keyUsage;
   Input nameConstraints;
   Input subjectAltName;
   Input criticalNetscapeCertificateType;
 
   Result RememberExtension(Reader& extnID, const Input& extnValue,
                            bool critical, /*out*/ bool& understood);
 
-  BackCert(const BackCert&) /* = delete */;
-  void operator=(const BackCert&); /* = delete */;
+  BackCert(const BackCert&) = delete;
+  void operator=(const BackCert&) = delete;
 };
 
 class NonOwningDERArray : public DERArray
 {
 public:
   NonOwningDERArray()
     : numItems(0)
   {
@@ -178,18 +178,18 @@ public:
   }
 
   // Public so we can static_assert on this. Keep in sync with MAX_SUBCA_COUNT.
   static const size_t MAX_LENGTH = 8;
 private:
   Input items[MAX_LENGTH]; // avoids any heap allocations
   size_t numItems;
 
-  NonOwningDERArray(const NonOwningDERArray&) /* = delete*/;
-  void operator=(const NonOwningDERArray&) /* = delete*/;
+  NonOwningDERArray(const NonOwningDERArray&) = delete;
+  void operator=(const NonOwningDERArray&) = delete;
 };
 
 inline unsigned int
 DaysBeforeYear(unsigned int year)
 {
   assert(year <= 9999);
   return ((year - 1u) * 365u)
        + ((year - 1u) / 4u)    // leap years are every 4 years,
--- a/security/pkix/moz.build
+++ b/security/pkix/moz.build
@@ -25,18 +25,16 @@ TEST_DIRS += [
     'test/gtest',
     'test/lib',
 ]
 
 CXXFLAGS += ['-Wall']
 # -Wall with Visual C++ enables too many problematic warnings
 if CONFIG['_MSC_VER']:
   CXXFLAGS += [
-    '-wd4480', # nonstandard extension used: specifying underlying type for
-               # enum 'enum'
     '-wd4514', # 'function': unreferenced inline function has been removed
     '-wd4668', # 'symbol' is not defined as a preprocessor macro...
     '-wd4710', # 'function': function not inlined
     '-wd4711', # function 'function' selected for inline expansion
     '-wd4820', # 'bytes' bytes padding added after construct 'member_name'
   ]
 
 FAIL_ON_WARNINGS = True
--- a/security/pkix/test/gtest/pkixbuild_tests.cpp
+++ b/security/pkix/test/gtest/pkixbuild_tests.cpp
@@ -27,29 +27,29 @@
 #include "pkix/pkix.h"
 #include "pkixgtest.h"
 #include "pkixtestutil.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::test;
 
 static ByteString
-CreateCert(const char* issuerCN,
-           const char* subjectCN,
+CreateCert(const char* issuerCN, // null means "empty name"
+           const char* subjectCN, // null means "empty name"
            EndEntityOrCA endEntityOrCA,
            /*optional modified*/ std::map<ByteString, ByteString>*
              subjectDERToCertDER = nullptr)
 {
   static long serialNumberValue = 0;
   ++serialNumberValue;
   ByteString serialNumber(CreateEncodedSerialNumber(serialNumberValue));
   EXPECT_FALSE(ENCODING_FAILED(serialNumber));
 
-  ByteString issuerDER(CNToDERName(issuerCN));
-  ByteString subjectDER(CNToDERName(subjectCN));
+  ByteString issuerDER(issuerCN ? CNToDERName(issuerCN) : Name(ByteString()));
+  ByteString subjectDER(subjectCN ? CNToDERName(subjectCN) : Name(ByteString()));
 
   ByteString extensions[2];
   if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
     extensions[0] =
       CreateEncodedBasicConstraints(true, nullptr,
                                     ExtensionCriticality::Critical);
     EXPECT_FALSE(ENCODING_FAILED(extensions[0]));
   }
@@ -356,8 +356,213 @@ TEST_F(pkixbuild, NoRevocationCheckingFo
   ASSERT_EQ(Result::ERROR_EXPIRED_CERTIFICATE,
             BuildCertChain(expiredCertTrustDomain, cert, Now(),
                            EndEntityOrCA::MustBeEndEntity,
                            KeyUsage::noParticularKeyUsageRequired,
                            KeyPurposeId::id_kp_serverAuth,
                            CertPolicyId::anyPolicy,
                            nullptr));
 }
+
+class DSSTrustDomain : public TrustDomain
+{
+public:
+  virtual Result GetCertTrust(EndEntityOrCA, const CertPolicyId&,
+                              Input, /*out*/ TrustLevel& trustLevel)
+  {
+    trustLevel = TrustLevel::TrustAnchor;
+    return Success;
+  }
+
+  virtual Result FindIssuer(Input, IssuerChecker&, Time)
+  {
+    ADD_FAILURE();
+    return Result::FATAL_ERROR_LIBRARY_FAILURE;
+  }
+
+  virtual Result CheckRevocation(EndEntityOrCA, const CertID&, Time,
+                                 /*optional*/ const Input*,
+                                 /*optional*/ const Input*)
+  {
+    ADD_FAILURE();
+    return Result::FATAL_ERROR_LIBRARY_FAILURE;
+  }
+
+  virtual Result IsChainValid(const DERArray&, Time)
+  {
+    return Success;
+  }
+
+  virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
+                                  Input subjectPublicKeyInfo)
+  {
+    ADD_FAILURE();
+    return Result::FATAL_ERROR_LIBRARY_FAILURE;
+  }
+
+  virtual Result DigestBuf(Input, /*out*/uint8_t*, size_t)
+  {
+    ADD_FAILURE();
+    return Result::FATAL_ERROR_LIBRARY_FAILURE;
+  }
+
+  virtual Result CheckPublicKey(Input subjectPublicKeyInfo)
+  {
+    return TestCheckPublicKey(subjectPublicKeyInfo);
+  }
+};
+
+class pkixbuild_DSS : public ::testing::Test { };
+
+TEST_F(pkixbuild_DSS, DSSEndEntityKeyNotAccepted)
+{
+  DSSTrustDomain trustDomain;
+
+  ByteString serialNumber(CreateEncodedSerialNumber(1));
+  ASSERT_FALSE(ENCODING_FAILED(serialNumber));
+
+  ByteString subjectDER(CNToDERName("DSS"));
+  ASSERT_FALSE(ENCODING_FAILED(subjectDER));
+  ScopedTestKeyPair subjectKey(GenerateDSSKeyPair());
+  ASSERT_TRUE(subjectKey);
+
+  ByteString issuerDER(CNToDERName("RSA"));
+  ASSERT_FALSE(ENCODING_FAILED(issuerDER));
+  ScopedTestKeyPair issuerKey(CloneReusedKeyPair());
+  ASSERT_TRUE(issuerKey);
+
+  ByteString cert(CreateEncodedCertificate(v3, sha256WithRSAEncryption,
+                                           serialNumber, issuerDER,
+                                           oneDayBeforeNow, oneDayAfterNow,
+                                           subjectDER, *subjectKey, nullptr,
+                                           *issuerKey, sha256WithRSAEncryption));
+  ASSERT_FALSE(ENCODING_FAILED(cert));
+  Input certDER;
+  ASSERT_EQ(Success, certDER.Init(cert.data(), cert.length()));
+
+  ASSERT_EQ(Result::ERROR_UNSUPPORTED_KEYALG,
+            BuildCertChain(trustDomain, certDER, Now(),
+                           EndEntityOrCA::MustBeEndEntity,
+                           KeyUsage::noParticularKeyUsageRequired,
+                           KeyPurposeId::id_kp_serverAuth,
+                           CertPolicyId::anyPolicy,
+                           nullptr/*stapledOCSPResponse*/));
+}
+
+class IssuerNameCheckTrustDomain : public TrustDomain
+{
+public:
+  IssuerNameCheckTrustDomain(const ByteString& issuer, bool expectedKeepGoing)
+    : issuer(issuer)
+    , expectedKeepGoing(expectedKeepGoing)
+  {
+  }
+
+  virtual Result GetCertTrust(EndEntityOrCA endEntityOrCA,
+                              const CertPolicyId&, Input,
+                              /*out*/ TrustLevel& trustLevel)
+  {
+    trustLevel = endEntityOrCA == EndEntityOrCA::MustBeCA
+               ? TrustLevel::TrustAnchor
+               : TrustLevel::InheritsTrust;
+    return Success;
+  }
+
+  virtual Result FindIssuer(Input subjectCert, IssuerChecker& checker, Time)
+  {
+    Input issuerInput;
+    EXPECT_EQ(Success, issuerInput.Init(issuer.data(), issuer.length()));
+    bool keepGoing;
+    EXPECT_EQ(Success,
+              checker.Check(issuerInput, nullptr /*additionalNameConstraints*/,
+                            keepGoing));
+    EXPECT_EQ(expectedKeepGoing, keepGoing);
+    return Success;
+  }
+
+  virtual Result CheckRevocation(EndEntityOrCA, const CertID&, Time,
+                                 /*optional*/ const Input*,
+                                 /*optional*/ const Input*)
+  {
+    return Success;
+  }
+
+  virtual Result IsChainValid(const DERArray&, Time)
+  {
+    return Success;
+  }
+
+  virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
+                                  Input subjectPublicKeyInfo)
+  {
+    return TestVerifySignedData(signedData, subjectPublicKeyInfo);
+  }
+
+  virtual Result DigestBuf(Input, /*out*/uint8_t*, size_t)
+  {
+    ADD_FAILURE();
+    return Result::FATAL_ERROR_LIBRARY_FAILURE;
+  }
+
+  virtual Result CheckPublicKey(Input subjectPublicKeyInfo)
+  {
+    return TestCheckPublicKey(subjectPublicKeyInfo);
+  }
+
+private:
+  const ByteString issuer;
+  const bool expectedKeepGoing;
+};
+
+struct IssuerNameCheckParams
+{
+  const char* subjectIssuerCN; // null means "empty name"
+  const char* issuerSubjectCN; // null means "empty name"
+  bool matches;
+};
+
+static const IssuerNameCheckParams ISSUER_NAME_CHECK_PARAMS[] =
+{
+  { "foo", "foo", true },
+  { "foo", "bar", false },
+  { "f", "foo", false }, // prefix
+  { "foo", "f", false }, // prefix
+  { "foo", "Foo", false }, // case sensitive
+  { "", "", true },
+  { nullptr, nullptr, true }, // XXX(bug 1115718)
+};
+
+class pkixbuild_IssuerNameCheck
+  : public ::testing::Test
+  , public ::testing::WithParamInterface<IssuerNameCheckParams>
+{
+};
+
+TEST_P(pkixbuild_IssuerNameCheck, MatchingName)
+{
+  const IssuerNameCheckParams& params(GetParam());
+
+  ByteString issuerCertDER(CreateCert(params.issuerSubjectCN,
+                                      params.issuerSubjectCN,
+                                      EndEntityOrCA::MustBeCA, nullptr));
+  ASSERT_FALSE(ENCODING_FAILED(issuerCertDER));
+
+  ByteString subjectCertDER(CreateCert(params.subjectIssuerCN, "end-entity",
+                                       EndEntityOrCA::MustBeEndEntity,
+                                       nullptr));
+  ASSERT_FALSE(ENCODING_FAILED(subjectCertDER));
+
+  Input subjectCertDERInput;
+  ASSERT_EQ(Success, subjectCertDERInput.Init(subjectCertDER.data(),
+                                              subjectCertDER.length()));
+
+  IssuerNameCheckTrustDomain trustDomain(issuerCertDER, !params.matches);
+  ASSERT_EQ(params.matches ? Success : Result::ERROR_UNKNOWN_ISSUER,
+            BuildCertChain(trustDomain, subjectCertDERInput, Now(),
+                           EndEntityOrCA::MustBeEndEntity,
+                           KeyUsage::noParticularKeyUsageRequired,
+                           KeyPurposeId::id_kp_serverAuth,
+                           CertPolicyId::anyPolicy,
+                           nullptr/*stapledOCSPResponse*/));
+}
+
+INSTANTIATE_TEST_CASE_P(pkixbuild_IssuerNameCheck, pkixbuild_IssuerNameCheck,
+                        testing::ValuesIn(ISSUER_NAME_CHECK_PARAMS));
--- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
+++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
@@ -81,19 +81,18 @@ public:
     return TestDigestBuf(item, digestBuf, digestBufLen);
   }
 
   virtual Result CheckPublicKey(Input subjectPublicKeyInfo)
   {
     return TestCheckPublicKey(subjectPublicKeyInfo);
   }
 
-private:
-  OCSPTestTrustDomain(const OCSPTestTrustDomain&) /*delete*/;
-  void operator=(const OCSPTestTrustDomain&) /*delete*/;
+  OCSPTestTrustDomain(const OCSPTestTrustDomain&) = delete;
+  void operator=(const OCSPTestTrustDomain&) = delete;
 };
 
 namespace {
 char const* const rootName = "Test CA 1";
 void deleteCertID(CertID* certID) { delete certID; }
 } // unnamed namespace
 
 class pkixocsp_VerifyEncodedResponse : public ::testing::Test
--- a/security/pkix/test/lib/pkixtestnss.cpp
+++ b/security/pkix/test/lib/pkixtestnss.cpp
@@ -24,16 +24,17 @@
 
 #include "pkixtestutil.h"
 
 #include <limits>
 
 #include "cryptohi.h"
 #include "keyhi.h"
 #include "nss.h"
+#include "pk11pqg.h"
 #include "pk11pub.h"
 #include "pkix/pkixnss.h"
 #include "pkixder.h"
 #include "prinit.h"
 #include "secerr.h"
 #include "secitem.h"
 
 namespace mozilla { namespace pkix { namespace test {
@@ -207,23 +208,16 @@ GenerateKeyPairInner()
     static const uint8_t RANDOM_NUMBER[] = { 4, 4, 4, 4, 4, 4, 4, 4 };
     if (PK11_RandomUpdate((void*) &RANDOM_NUMBER,
                           sizeof(RANDOM_NUMBER)) != SECSuccess) {
       break;
     }
   }
 
   abort();
-#if defined(_MSC_VER) && (_MSC_VER < 1700)
-  // Older versions of MSVC don't know that abort() never returns, so silence
-  // its warning by adding a redundant and never-reached return. But, only do
-  // it for that ancient compiler, because some other compilers will rightly
-  // warn that the return statement is unreachable.
-  return nullptr;
-#endif
 }
 
 } // unnamed namespace
 
 TestKeyPair*
 GenerateKeyPair()
 {
   InitNSSIfNeeded();
@@ -236,16 +230,63 @@ CloneReusedKeyPair()
   static PRCallOnceType initCallOnce;
   if (PR_CallOnce(&initCallOnce, InitReusedKeyPair) != PR_SUCCESS) {
     abort();
   }
   assert(reusedKeyPair);
   return reusedKeyPair->Clone();
 }
 
+TestKeyPair*
+GenerateDSSKeyPair()
+{
+  InitNSSIfNeeded();
+
+  ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
+  if (!slot) {
+    return nullptr;
+  }
+
+  PQGParams* pqgParamsTemp = nullptr;
+  PQGVerify* pqgVerify = nullptr;
+  if (PK11_PQG_ParamGenV2(2048u, 256u, 256u / 8u, &pqgParamsTemp, &pqgVerify)
+        != SECSuccess) {
+    return nullptr;
+  }
+  PK11_PQG_DestroyVerify(pqgVerify);
+  ScopedPtr<PQGParams, PK11_PQG_DestroyParams> params(pqgParamsTemp);
+
+  SECKEYPublicKey* publicKeyTemp = nullptr;
+  ScopedSECKEYPrivateKey
+    privateKey(PK11_GenerateKeyPair(slot.get(), CKM_DSA_KEY_PAIR_GEN,
+                                    params.get(), &publicKeyTemp, false, true,
+                                    nullptr));
+  if (!privateKey) {
+    return nullptr;
+  }
+  ScopedSECKEYPublicKey publicKey(publicKeyTemp);
+
+  ScopedSECItem spkiDER(SECKEY_EncodeDERSubjectPublicKeyInfo(publicKey.get()));
+  if (!spkiDER) {
+    return nullptr;
+  }
+
+  ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
+    spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
+  if (!spki) {
+    return nullptr;
+  }
+
+  SECItem spkDER = spki->subjectPublicKey;
+  DER_ConvertBitString(&spkDER); // bits to bytes
+  return CreateTestKeyPair(ByteString(spkiDER->data, spkiDER->len),
+                           ByteString(spkDER.data, spkDER.len),
+                           privateKey.release());
+}
+
 ByteString
 SHA1(const ByteString& toHash)
 {
   InitNSSIfNeeded();
 
   uint8_t digestBuf[SHA1_LENGTH];
   SECStatus srv = PK11_HashBuf(SEC_OID_SHA1, digestBuf, toHash.data(),
                                static_cast<int32_t>(toHash.length()));
@@ -254,28 +295,28 @@ SHA1(const ByteString& toHash)
   }
   return ByteString(digestBuf, sizeof(digestBuf));
 }
 
 Result
 TestCheckPublicKey(Input subjectPublicKeyInfo)
 {
   InitNSSIfNeeded();
-  return CheckPublicKey(subjectPublicKeyInfo, MINIMUM_TEST_KEY_BITS);
+  return CheckPublicKeyNSS(subjectPublicKeyInfo, MINIMUM_TEST_KEY_BITS);
 }
 
 Result
 TestVerifySignedData(const SignedDataWithSignature& signedData,
                      Input subjectPublicKeyInfo)
 {
   InitNSSIfNeeded();
-  return VerifySignedData(signedData, subjectPublicKeyInfo,
-                          MINIMUM_TEST_KEY_BITS, nullptr);
+  return VerifySignedDataNSS(signedData, subjectPublicKeyInfo,
+                             MINIMUM_TEST_KEY_BITS, nullptr);
 }
 
 Result
 TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
 {
   InitNSSIfNeeded();
-  return DigestBuf(item, digestBuf, digestBufLen);
+  return DigestBufNSS(item, digestBuf, digestBufLen);
 }
 
 } } } // namespace mozilla::pkix::test
--- a/security/pkix/test/lib/pkixtestutil.h
+++ b/security/pkix/test/lib/pkixtestutil.h
@@ -242,22 +242,23 @@ public:
   virtual TestKeyPair* Clone() const = 0;
 protected:
   TestKeyPair(const ByteString& spki, const ByteString& spk)
     : subjectPublicKeyInfo(spki)
     , subjectPublicKey(spk)
   {
   }
 
-  TestKeyPair(const TestKeyPair&) /*= delete*/;
-  void operator=(const TestKeyPair&) /*= delete*/;
+  TestKeyPair(const TestKeyPair&) = delete;
+  void operator=(const TestKeyPair&) = delete;
 };
 
 TestKeyPair* CloneReusedKeyPair();
 TestKeyPair* GenerateKeyPair();
+TestKeyPair* GenerateDSSKeyPair();
 inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
 typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
 
 ByteString SHA1(const ByteString& toHash);
 
 Result TestCheckPublicKey(Input subjectPublicKeyInfo);
 Result TestVerifySignedData(const SignedDataWithSignature& signedData,
                             Input subjectPublicKeyInfo);