Merge m-c to fx-team
authorWes Kocher <wkocher@mozilla.com>
Mon, 31 Mar 2014 21:03:15 -0700
changeset 176408 6e2ea7f24fd2533610125fa4ba112617082f6f06
parent 176407 0593a10769328f01cc492602b2d2d442f452b59e (current diff)
parent 176346 1417d180a1d8665b1a91b897d1cc4cc31e7980d4 (diff)
child 176409 ba893b9fd2af599f8ac9a63e17d7960dddf1e4d4
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone31.0a1
Merge m-c to fx-team
browser/app/profile/firefox.js
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 957865 - Non-clobbered ASAN builds were failing all mochitests after the clang upgrade
+Bug 989137 - /experiments needed clobber to build on OSX
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12408eb142739c7de87ab7ee0d0d2854d5c298f3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="15d69a6789c638709911507f74d25c0425963636">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <!-- Stock Android things -->
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12408eb142739c7de87ab7ee0d0d2854d5c298f3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "6c593455e3d1292120a6f3d41ec5d06bc91019f1", 
+    "revision": "f3575a1613e6c94fbc6b2ae01fd00130ee1b3f8a", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="15d69a6789c638709911507f74d25c0425963636">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="eee8caa81a368f0feace718201ed15a423812c18"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="874fe42b82e8d819d592690e74db91c07179e68c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="5b93c7150acac5f657675b91889d828cc2b532e3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="89c5816399e71bda92a8959b5b771c04d6672ea3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1357,16 +1357,18 @@ pref("social.sidebar.unload_timeout_ms",
 pref("dom.identity.enabled", false);
 
 // Turn on the CSP 1.0 parser for Content Security Policy headers
 pref("security.csp.speccompliant", true);
 
 // Block insecure active content on https pages
 pref("security.mixed_content.block_active_content", true);
 
+pref("security.use_mozillapkix_verification", true);
+
 // Override the Gecko-default value of false for Firefox.
 pref("plain_text.wrap_long_lines", true);
 
 // If this turns true, Moz*Gesture events are not called stopPropagation()
 // before content.
 pref("dom.debug.propagate_gesture_events_through_content", false);
 
 // The request URL of the GeoLocation backend.
--- a/netwerk/base/public/security-prefs.js
+++ b/netwerk/base/public/security-prefs.js
@@ -49,8 +49,10 @@ pref("security.ssl3.rsa_seed_sha", false
 pref("security.default_personal_cert",   "Ask Every Time");
 pref("security.remember_cert_checkbox_default_setting", true);
 pref("security.ask_for_password",        0);
 pref("security.password_lifetime",       30);
 
 pref("security.OCSP.enabled", 1);
 pref("security.OCSP.require", false);
 pref("security.OCSP.GET.enabled", false);
+
+pref("security.use_mozillapkix_verification", false);
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -173,62 +173,66 @@ HttpChannelChild::AssociateApplicationCa
   mLoadedFromApplicationCache = true;
   mApplicationCache->InitAsHandle(groupID, clientID);
 }
 
 class StartRequestEvent : public ChannelEvent
 {
  public:
   StartRequestEvent(HttpChannelChild* child,
+                    const nsresult& channelStatus,
                     const nsHttpResponseHead& responseHead,
                     const bool& useResponseHead,
                     const nsHttpHeaderArray& requestHeaders,
                     const bool& isFromCache,
                     const bool& cacheEntryAvailable,
                     const uint32_t& cacheExpirationTime,
                     const nsCString& cachedCharset,
                     const nsCString& securityInfoSerialization,
                     const NetAddr& selfAddr,
                     const NetAddr& peerAddr)
   : mChild(child)
+  , mChannelStatus(channelStatus)
   , mResponseHead(responseHead)
   , mRequestHeaders(requestHeaders)
   , mUseResponseHead(useResponseHead)
   , mIsFromCache(isFromCache)
   , mCacheEntryAvailable(cacheEntryAvailable)
   , mCacheExpirationTime(cacheExpirationTime)
   , mCachedCharset(cachedCharset)
   , mSecurityInfoSerialization(securityInfoSerialization)
   , mSelfAddr(selfAddr)
   , mPeerAddr(peerAddr)
   {}
 
   void Run()
   {
-    mChild->OnStartRequest(mResponseHead, mUseResponseHead, mRequestHeaders,
-                           mIsFromCache, mCacheEntryAvailable,
+    mChild->OnStartRequest(mChannelStatus, mResponseHead, mUseResponseHead,
+                           mRequestHeaders, mIsFromCache, mCacheEntryAvailable,
                            mCacheExpirationTime, mCachedCharset,
                            mSecurityInfoSerialization, mSelfAddr, mPeerAddr);
   }
  private:
   HttpChannelChild* mChild;
+  nsresult mChannelStatus;
   nsHttpResponseHead mResponseHead;
   nsHttpHeaderArray mRequestHeaders;
   bool mUseResponseHead;
   bool mIsFromCache;
   bool mCacheEntryAvailable;
   uint32_t mCacheExpirationTime;
   nsCString mCachedCharset;
   nsCString mSecurityInfoSerialization;
   NetAddr mSelfAddr;
   NetAddr mPeerAddr;
 };
 
 bool
-HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
+HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
+                                     const nsHttpResponseHead& responseHead,
                                      const bool& useResponseHead,
                                      const nsHttpHeaderArray& requestHeaders,
                                      const bool& isFromCache,
                                      const bool& cacheEntryAvailable,
                                      const uint32_t& cacheExpirationTime,
                                      const nsCString& cachedCharset,
                                      const nsCString& securityInfoSerialization,
                                      const NetAddr& selfAddr,
@@ -237,32 +241,34 @@ HttpChannelChild::RecvOnStartRequest(con
   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   // stage, as they are set in the listener's OnStartRequest.
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     "mFlushedForDiversion should be unset before OnStartRequest!");
   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     "mDivertingToParent should be unset before OnStartRequest!");
 
   if (mEventQ->ShouldEnqueue()) {
-    mEventQ->Enqueue(new StartRequestEvent(this, responseHead, useResponseHead,
-                                          requestHeaders, isFromCache,
-                                          cacheEntryAvailable,
-                                          cacheExpirationTime, cachedCharset,
-                                          securityInfoSerialization, selfAddr,
-                                          peerAddr));
+    mEventQ->Enqueue(new StartRequestEvent(this, channelStatus, responseHead,
+                                           useResponseHead, requestHeaders,
+                                           isFromCache, cacheEntryAvailable,
+                                           cacheExpirationTime, cachedCharset,
+                                           securityInfoSerialization, selfAddr,
+                                           peerAddr));
   } else {
-    OnStartRequest(responseHead, useResponseHead, requestHeaders, isFromCache,
-                   cacheEntryAvailable, cacheExpirationTime, cachedCharset,
-                   securityInfoSerialization, selfAddr, peerAddr);
+    OnStartRequest(channelStatus, responseHead, useResponseHead, requestHeaders,
+                   isFromCache, cacheEntryAvailable, cacheExpirationTime,
+                   cachedCharset, securityInfoSerialization, selfAddr,
+                   peerAddr);
   }
   return true;
 }
 
 void
-HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead,
+HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
+                                 const nsHttpResponseHead& responseHead,
                                  const bool& useResponseHead,
                                  const nsHttpHeaderArray& requestHeaders,
                                  const bool& isFromCache,
                                  const bool& cacheEntryAvailable,
                                  const uint32_t& cacheExpirationTime,
                                  const nsCString& cachedCharset,
                                  const nsCString& securityInfoSerialization,
                                  const NetAddr& selfAddr,
@@ -272,16 +278,20 @@ HttpChannelChild::OnStartRequest(const n
 
   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   // stage, as they are set in the listener's OnStartRequest.
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     "mFlushedForDiversion should be unset before OnStartRequest!");
   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     "mDivertingToParent should be unset before OnStartRequest!");
 
+  if (!mCanceled && NS_SUCCEEDED(mStatus)) {
+    mStatus = channelStatus;
+  }
+
   if (useResponseHead && !mCanceled)
     mResponseHead = new nsHttpResponseHead(responseHead);
 
   if (!securityInfoSerialization.IsEmpty()) {
     NS_DeserializeObject(securityInfoSerialization,
                          getter_AddRefs(mSecurityInfo));
   }
 
@@ -326,76 +336,90 @@ HttpChannelChild::OnStartRequest(const n
   mSelfAddr = selfAddr;
   mPeerAddr = peerAddr;
 }
 
 class TransportAndDataEvent : public ChannelEvent
 {
  public:
   TransportAndDataEvent(HttpChannelChild* child,
-                        const nsresult& status,
+                        const nsresult& channelStatus,
+                        const nsresult& transportStatus,
                         const uint64_t& progress,
                         const uint64_t& progressMax,
                         const nsCString& data,
                         const uint64_t& offset,
                         const uint32_t& count)
   : mChild(child)
-  , mStatus(status)
+  , mChannelStatus(channelStatus)
+  , mTransportStatus(transportStatus)
   , mProgress(progress)
   , mProgressMax(progressMax)
   , mData(data)
   , mOffset(offset)
   , mCount(count) {}
 
-  void Run() { mChild->OnTransportAndData(mStatus, mProgress, mProgressMax,
-                                          mData, mOffset, mCount); }
+  void Run()
+  {
+    mChild->OnTransportAndData(mChannelStatus, mTransportStatus, mProgress,
+                               mProgressMax, mData, mOffset, mCount);
+  }
  private:
   HttpChannelChild* mChild;
-  nsresult mStatus;
+  nsresult mChannelStatus;
+  nsresult mTransportStatus;
   uint64_t mProgress;
   uint64_t mProgressMax;
   nsCString mData;
   uint64_t mOffset;
   uint32_t mCount;
 };
 
 bool
-HttpChannelChild::RecvOnTransportAndData(const nsresult& status,
+HttpChannelChild::RecvOnTransportAndData(const nsresult& channelStatus,
+                                         const nsresult& transportStatus,
                                          const uint64_t& progress,
                                          const uint64_t& progressMax,
                                          const nsCString& data,
                                          const uint64_t& offset,
                                          const uint32_t& count)
 {
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
                      "Should not be receiving any more callbacks from parent!");
 
   if (mEventQ->ShouldEnqueue()) {
-    mEventQ->Enqueue(new TransportAndDataEvent(this, status, progress,
-                                              progressMax, data, offset,
-                                              count));
+    mEventQ->Enqueue(new TransportAndDataEvent(this, channelStatus,
+                                               transportStatus, progress,
+                                               progressMax, data, offset,
+                                               count));
   } else {
     MOZ_RELEASE_ASSERT(!mDivertingToParent,
                        "ShouldEnqueue when diverting to parent!");
 
-    OnTransportAndData(status, progress, progressMax, data, offset, count);
+    OnTransportAndData(channelStatus, transportStatus, progress, progressMax,
+                       data, offset, count);
   }
   return true;
 }
 
 void
-HttpChannelChild::OnTransportAndData(const nsresult& status,
+HttpChannelChild::OnTransportAndData(const nsresult& channelStatus,
+                                     const nsresult& transportStatus,
                                      const uint64_t progress,
                                      const uint64_t& progressMax,
                                      const nsCString& data,
                                      const uint64_t& offset,
                                      const uint32_t& count)
 {
   LOG(("HttpChannelChild::OnTransportAndData [this=%p]\n", this));
 
+  if (!mCanceled && NS_SUCCEEDED(mStatus)) {
+    mStatus = channelStatus;
+  }
+
   // For diversion to parent, just SendDivertOnDataAvailable.
   if (mDivertingToParent) {
     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
       "Should not be processing any more callbacks from parent!");
 
     SendDivertOnDataAvailable(data, offset, count);
     return;
   }
@@ -416,22 +440,22 @@ HttpChannelChild::OnTransportAndData(con
   // - JDUELL: may not need mStatus/mIsPending checks, given this is always called
   //   during OnDataAvailable, and we've already checked mCanceled.  Code
   //   dupe'd from nsHttpChannel
   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
       !(mLoadFlags & LOAD_BACKGROUND))
   {
     // OnStatus
     //
-    MOZ_ASSERT(status == NS_NET_STATUS_RECEIVING_FROM ||
-               status == NS_NET_STATUS_READING);
+    MOZ_ASSERT(transportStatus == NS_NET_STATUS_RECEIVING_FROM ||
+               transportStatus == NS_NET_STATUS_READING);
 
     nsAutoCString host;
     mURI->GetHost(host);
-    mProgressSink->OnStatus(this, nullptr, status,
+    mProgressSink->OnStatus(this, nullptr, transportStatus,
                             NS_ConvertUTF8toUTF16(host).get());
     // OnProgress
     //
     if (progress > 0) {
       MOZ_ASSERT(progress <= progressMax, "unexpected progress values");
       mProgressSink->OnProgress(this, nullptr, progress, progressMax);
     }
   }
@@ -458,60 +482,61 @@ HttpChannelChild::OnTransportAndData(con
     Cancel(rv);
   }
 }
 
 class StopRequestEvent : public ChannelEvent
 {
  public:
   StopRequestEvent(HttpChannelChild* child,
-                   const nsresult& statusCode)
+                   const nsresult& channelStatus)
   : mChild(child)
-  , mStatusCode(statusCode) {}
+  , mChannelStatus(channelStatus) {}
 
-  void Run() { mChild->OnStopRequest(mStatusCode); }
+  void Run() { mChild->OnStopRequest(mChannelStatus); }
  private:
   HttpChannelChild* mChild;
-  nsresult mStatusCode;
+  nsresult mChannelStatus;
 };
 
 bool
-HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode)
+HttpChannelChild::RecvOnStopRequest(const nsresult& channelStatus)
 {
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     "Should not be receiving any more callbacks from parent!");
 
   if (mEventQ->ShouldEnqueue()) {
-    mEventQ->Enqueue(new StopRequestEvent(this, statusCode));
+    mEventQ->Enqueue(new StopRequestEvent(this, channelStatus));
   } else {
     MOZ_ASSERT(!mDivertingToParent, "ShouldEnqueue when diverting to parent!");
 
-    OnStopRequest(statusCode);
+    OnStopRequest(channelStatus);
   }
   return true;
 }
 
 void
-HttpChannelChild::OnStopRequest(const nsresult& statusCode)
+HttpChannelChild::OnStopRequest(const nsresult& channelStatus)
 {
   LOG(("HttpChannelChild::OnStopRequest [this=%p status=%x]\n",
-           this, statusCode));
+           this, channelStatus));
 
   if (mDivertingToParent) {
     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
       "Should not be processing any more callbacks from parent!");
 
-    SendDivertOnStopRequest(statusCode);
+    SendDivertOnStopRequest(channelStatus);
     return;
   }
 
   mIsPending = false;
 
-  if (!mCanceled && NS_SUCCEEDED(mStatus))
-    mStatus = statusCode;
+  if (!mCanceled && NS_SUCCEEDED(mStatus)) {
+    mStatus = channelStatus;
+  }
 
   { // We must flush the queue before we Send__delete__
     // (although we really shouldn't receive any msgs after OnStop),
     // so make sure this goes out of scope before then.
     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
     mListener->OnStopRequest(this, mListenerContext, mStatus);
 
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -91,27 +91,29 @@ public:
   void AddIPDLReference();
   void ReleaseIPDLReference();
 
   bool IsSuspended();
 
   void FlushedForDiversion();
 
 protected:
-  bool RecvOnStartRequest(const nsHttpResponseHead& responseHead,
+  bool RecvOnStartRequest(const nsresult& channelStatus,
+                          const nsHttpResponseHead& responseHead,
                           const bool& useResponseHead,
                           const nsHttpHeaderArray& requestHeaders,
                           const bool& isFromCache,
                           const bool& cacheEntryAvailable,
                           const uint32_t& cacheExpirationTime,
                           const nsCString& cachedCharset,
                           const nsCString& securityInfoSerialization,
                           const NetAddr& selfAddr,
                           const NetAddr& peerAddr) MOZ_OVERRIDE;
-  bool RecvOnTransportAndData(const nsresult& status,
+  bool RecvOnTransportAndData(const nsresult& channelStatus,
+                              const nsresult& status,
                               const uint64_t& progress,
                               const uint64_t& progressMax,
                               const nsCString& data,
                               const uint64_t& offset,
                               const uint32_t& count) MOZ_OVERRIDE;
   bool RecvOnStopRequest(const nsresult& statusCode);
   bool RecvOnProgress(const uint64_t& progress, const uint64_t& progressMax) MOZ_OVERRIDE;
   bool RecvOnStatus(const nsresult& status) MOZ_OVERRIDE;
@@ -156,33 +158,35 @@ private:
   // diverting callbacks to parent.
   bool mSuspendSent;
 
   // true after successful AsyncOpen until OnStopRequest completes.
   bool RemoteChannelExists() { return mIPCOpen && !mKeptAlive; }
 
   void AssociateApplicationCache(const nsCString &groupID,
                                  const nsCString &clientID);
-  void OnStartRequest(const nsHttpResponseHead& responseHead,
+  void OnStartRequest(const nsresult& channelStatus,
+                      const nsHttpResponseHead& responseHead,
                       const bool& useResponseHead,
                       const nsHttpHeaderArray& requestHeaders,
                       const bool& isFromCache,
                       const bool& cacheEntryAvailable,
                       const uint32_t& cacheExpirationTime,
                       const nsCString& cachedCharset,
                       const nsCString& securityInfoSerialization,
                       const NetAddr& selfAddr,
                       const NetAddr& peerAddr);
-  void OnTransportAndData(const nsresult& status,
+  void OnTransportAndData(const nsresult& channelStatus,
+                          const nsresult& status,
                           const uint64_t progress,
                           const uint64_t& progressMax,
                           const nsCString& data,
                           const uint64_t& offset,
                           const uint32_t& count);
-  void OnStopRequest(const nsresult& statusCode);
+  void OnStopRequest(const nsresult& channelStatus);
   void OnProgress(const uint64_t& progress, const uint64_t& progressMax);
   void OnStatus(const nsresult& status);
   void FailedAsyncOpen(const nsresult& status);
   void HandleAsyncAbort();
   void Redirect1Begin(const uint32_t& newChannelId,
                       const URIParams& newUri,
                       const uint32_t& redirectFlags,
                       const nsHttpResponseHead& responseHead);
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -583,29 +583,32 @@ HttpChannelParent::OnStartRequest(nsIReq
     encodedChannel->SetApplyConversion(false);
 
   // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
   // It could be already released by nsHttpChannel at that time.
   nsCOMPtr<nsISupports> cacheEntry;
   chan->GetCacheToken(getter_AddRefs(cacheEntry));
   mCacheEntry = do_QueryInterface(cacheEntry);
 
+  nsresult channelStatus = NS_OK;
+  chan->GetStatus(&channelStatus);
 
   nsCString secInfoSerialization;
   nsCOMPtr<nsISupports> secInfoSupp;
   chan->GetSecurityInfo(getter_AddRefs(secInfoSupp));
   if (secInfoSupp) {
     mAssociatedContentSecurity = do_QueryInterface(secInfoSupp);
     nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
     if (secInfoSer)
       NS_SerializeToString(secInfoSer, secInfoSerialization);
   }
 
   if (mIPCClosed ||
-      !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(),
+      !SendOnStartRequest(channelStatus,
+                          responseHead ? *responseHead : nsHttpResponseHead(),
                           !!responseHead,
                           requestHead->Headers(),
                           isFromCache,
                           mCacheEntry ? true : false,
                           expirationTime, cachedCharset, secInfoSerialization,
                           mChannel->GetSelfAddr(), mChannel->GetPeerAddr()))
   {
     return NS_ERROR_UNEXPECTED;
@@ -645,23 +648,26 @@ HttpChannelParent::OnDataAvailable(nsIRe
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnDataAvailable if diverting is set!");
 
   nsCString data;
   nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
   if (NS_FAILED(rv))
     return rv;
 
+  nsresult channelStatus = NS_OK;
+  mChannel->GetStatus(&channelStatus);
+
   // OnDataAvailable is always preceded by OnStatus/OnProgress calls that set
   // mStoredStatus/mStoredProgress(Max) to appropriate values, unless
   // LOAD_BACKGROUND set.  In that case, they'll have garbage values, but
   // child doesn't use them.
-  if (mIPCClosed || !SendOnTransportAndData(mStoredStatus, mStoredProgress,
-                                            mStoredProgressMax, data, aOffset,
-                                            aCount)) {
+  if (mIPCClosed || !SendOnTransportAndData(channelStatus, mStoredStatus,
+                                            mStoredProgress, mStoredProgressMax,
+                                            data, aOffset, aCount)) {
     return NS_ERROR_UNEXPECTED;
   }
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIProgressEventSink
 //-----------------------------------------------------------------------------
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -75,37 +75,39 @@ parent:
   DivertOnStopRequest(nsresult statusCode);
 
   // Child has no more events/messages to divert to the parent.
   DivertComplete();
 
   __delete__();
 
 child:
-  OnStartRequest(nsHttpResponseHead  responseHead,
+  OnStartRequest(nsresult            channelStatus,
+                 nsHttpResponseHead  responseHead,
                  bool                useResponseHead,
                  nsHttpHeaderArray   requestHeaders,
                  bool                isFromCache,
                  bool                cacheEntryAvailable,
                  uint32_t            cacheExpirationTime,
                  nsCString           cachedCharset,
                  nsCString           securityInfoSerialization,
                  NetAddr             selfAddr,
                  NetAddr             peerAddr);
 
   // Combines a single OnDataAvailable and its associated OnProgress &
   // OnStatus calls into one IPDL message
-  OnTransportAndData(nsresult  status,
+  OnTransportAndData(nsresult  channelStatus,
+                     nsresult  transportStatus,
                      uint64_t  progress,
                      uint64_t  progressMax,
                      nsCString data,
                      uint64_t  offset,
                      uint32_t  count);
 
-  OnStopRequest(nsresult statusCode);
+  OnStopRequest(nsresult channelStatus);
 
   OnProgress(uint64_t progress, uint64_t progressMax);
 
   OnStatus(nsresult status);
 
   // Used to cancel child channel if we hit errors during creating and
   // AsyncOpen of nsHttpChannel on the parent.
   FailedAsyncOpen(nsresult status);
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -29,16 +29,17 @@ const SEC_ERROR_REVOKED_CERTIFICATE     
 const SEC_ERROR_UNKNOWN_ISSUER                          = SEC_ERROR_BASE +  13;
 const SEC_ERROR_BAD_DATABASE                            = SEC_ERROR_BASE +  18;
 const SEC_ERROR_UNTRUSTED_ISSUER                        = SEC_ERROR_BASE +  20; // -8172
 const SEC_ERROR_UNTRUSTED_CERT                          = SEC_ERROR_BASE +  21; // -8171
 const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE              = SEC_ERROR_BASE +  30; // -8162
 const SEC_ERROR_EXTENSION_VALUE_INVALID                 = SEC_ERROR_BASE +  34; // -8158
 const SEC_ERROR_EXTENSION_NOT_FOUND                     = SEC_ERROR_BASE +  35; // -8157
 const SEC_ERROR_CA_CERT_INVALID                         = SEC_ERROR_BASE +  36;
+const SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION              = SEC_ERROR_BASE +  41;
 const SEC_ERROR_INADEQUATE_KEY_USAGE                    = SEC_ERROR_BASE +  90; // -8102
 const SEC_ERROR_INADEQUATE_CERT_TYPE                    = SEC_ERROR_BASE +  91; // -8101
 const SEC_ERROR_CERT_NOT_IN_NAME_SPACE                  = SEC_ERROR_BASE + 112; // -8080
 const SEC_ERROR_OCSP_MALFORMED_REQUEST                  = SEC_ERROR_BASE + 120;
 const SEC_ERROR_OCSP_SERVER_ERROR                       = SEC_ERROR_BASE + 121;
 const SEC_ERROR_OCSP_TRY_SERVER_LATER                   = SEC_ERROR_BASE + 122;
 const SEC_ERROR_OCSP_REQUEST_NEEDS_SIG                  = SEC_ERROR_BASE + 123;
 const SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST               = SEC_ERROR_BASE + 124;
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js
@@ -38,16 +38,18 @@ function add_tests_in_mode(useMozillaPKI
   add_ocsp_test("ocsp-stapling-needssig.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-unauthorized.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-unknown.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-good-other.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-none.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-expired.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-expired-fresh-ca.example.com", Cr.NS_OK, false);
   add_ocsp_test("ocsp-stapling-skip-responseBytes.example.com", Cr.NS_OK, false);
+  add_ocsp_test("ocsp-stapling-critical-extension.example.com", Cr.NS_OK, false);
+  add_ocsp_test("ocsp-stapling-noncritical-extension.example.com", Cr.NS_OK, false);
 
   // Now test OCSP stapling
   // The following error codes are defined in security/nss/lib/util/SECerrs.h
 
   add_ocsp_test("ocsp-stapling-good.example.com", Cr.NS_OK, true);
 
   add_ocsp_test("ocsp-stapling-revoked.example.com",
                 getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE), true);
@@ -113,31 +115,38 @@ function add_tests_in_mode(useMozillaPKI
                 getXPCOMStatusFromNSS(SEC_ERROR_OCSP_MALFORMED_RESPONSE), true);
 
   // TODO(bug 979070): NSS can't handle this yet.
   if (useMozillaPKIX) {
     add_ocsp_test("ocsp-stapling-skip-responseBytes.example.com",
                   getXPCOMStatusFromNSS(SEC_ERROR_OCSP_MALFORMED_RESPONSE), true);
   }
 
+  add_ocsp_test("ocsp-stapling-critical-extension.example.com",
+                useMozillaPKIX
+                  ? getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION)
+                  : Cr.NS_OK, // TODO(bug 987426): NSS doesn't handle unknown critical extensions
+                true);
+  add_ocsp_test("ocsp-stapling-noncritical-extension.example.com", Cr.NS_OK, true);
+
   // ocsp-stapling-expired.example.com and
   // ocsp-stapling-expired-fresh-ca.example.com are handled in
   // test_ocsp_stapling_expired.js
 }
 
 function check_ocsp_stapling_telemetry() {
   let histogram = Cc["@mozilla.org/base/telemetry;1"]
                     .getService(Ci.nsITelemetry)
                     .getHistogramById("SSL_OCSP_STAPLING")
                     .snapshot();
   do_check_eq(histogram.counts[0], 2 * 0); // histogram bucket 0 is unused
-  do_check_eq(histogram.counts[1], 2 * 1); // 1 connection with a good response
-  do_check_eq(histogram.counts[2], 2 * 15); // 15 connections with no stapled resp.
+  do_check_eq(histogram.counts[1], 2 + 3); // 2 or 3 connections with a good response (bug 987426)
+  do_check_eq(histogram.counts[2], 2 * 17); // 17 connections with no stapled resp.
   do_check_eq(histogram.counts[3], 2 * 0); // 0 connections with an expired response
-  do_check_eq(histogram.counts[4], 12 + 11); // 12 or 11 connections with bad responses (bug 979070)
+  do_check_eq(histogram.counts[4], 13 + 11); // 13 or 11 connections with bad responses (bug 979070, bug 987426)
   run_next_test();
 }
 
 function run_test() {
   do_get_profile();
 
   let certDB = Cc["@mozilla.org/security/x509certdb;1"]
                   .getService(Ci.nsIX509CertDB);
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -33,16 +33,18 @@ const OCSPHost sOCSPHosts[] =
   { "ocsp-stapling-malformed.example.com", ORTMalformed, nullptr },
   { "ocsp-stapling-srverr.example.com", ORTSrverr, nullptr },
   { "ocsp-stapling-trylater.example.com", ORTTryLater, nullptr },
   { "ocsp-stapling-needssig.example.com", ORTNeedsSig, nullptr },
   { "ocsp-stapling-unauthorized.example.com", ORTUnauthorized, nullptr },
   { "ocsp-stapling-with-intermediate.example.com", ORTGood, "ocspEEWithIntermediate" },
   { "ocsp-stapling-bad-signature.example.com", ORTBadSignature, nullptr },
   { "ocsp-stapling-skip-responseBytes.example.com", ORTSkipResponseBytes, nullptr },
+  { "ocsp-stapling-critical-extension.example.com", ORTCriticalExtension, nullptr },
+  { "ocsp-stapling-noncritical-extension.example.com", ORTNoncriticalExtension, nullptr },
   { nullptr, ORTNull, nullptr }
 };
 
 int32_t
 DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
                   uint32_t aSrvNameArrSize, void *aArg)
 {
   const OCSPHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
@@ -4,16 +4,17 @@
 
 #include "OCSPCommon.h"
 
 #include <stdio.h>
 
 #include "ScopedNSSTypes.h"
 #include "TLSServer.h"
 #include "pkixtestutil.h"
+#include "secder.h"
 #include "secerr.h"
 
 using namespace mozilla;
 using namespace mozilla::test;
 using namespace mozilla::pkix::test;
 
 
 SECItemArray *
@@ -94,16 +95,43 @@ GetOCSPResponseForType(OCSPResponseType 
     context.certStatus = 1;
   }
   if (aORT == ORTUnknown) {
     context.certStatus = 2;
   }
   if (aORT == ORTBadSignature) {
     context.badSignature = true;
   }
+  OCSPResponseExtension extension;
+  if (aORT == ORTCriticalExtension || aORT == ORTNoncriticalExtension) {
+    SECItem oidItem = {
+      siBuffer,
+      nullptr,
+      0
+    };
+    // 1.3.6.1.4.1.13769.666.666.666 is the root of Mozilla's testing OID space
+    static const char* testExtensionOID = "1.3.6.1.4.1.13769.666.666.666.1.500.9.2";
+    if (SEC_StringToOID(aArena, &oidItem, testExtensionOID,
+                        PL_strlen(testExtensionOID)) != SECSuccess) {
+      return nullptr;
+    }
+    DERTemplate oidTemplate[2] = { { DER_OBJECT_ID, 0 }, { 0 } };
+    extension.id.data = nullptr;
+    extension.id.len = 0;
+    if (DER_Encode(aArena, &extension.id, oidTemplate, &oidItem)
+          != SECSuccess) {
+      return nullptr;
+    }
+    extension.critical = (aORT == ORTCriticalExtension);
+    static const uint8_t value[2] = { 0x05, 0x00 };
+    extension.value.data = const_cast<uint8_t*>(value);
+    extension.value.len = PR_ARRAY_SIZE(value);
+    extension.next = nullptr;
+    context.extensions = &extension;
+  }
 
   if (!context.signerCert) {
     context.signerCert = CERT_DupCertificate(context.issuerCert.get());
   }
 
   SECItem* response = CreateEncodedOCSPResponse(context);
   if (!response) {
     PrintPRError("CreateEncodedOCSPResponse failed");
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
@@ -24,17 +24,19 @@ enum OCSPResponseType
   ORTNone,             // no stapled response
   ORTEmpty,            // an empty stapled response
   ORTMalformed,        // the response from the responder was malformed
   ORTSrverr,           // the response indicates there was a server error
   ORTTryLater,         // the responder replied with "try again later"
   ORTNeedsSig,         // the response needs a signature
   ORTUnauthorized,     // the responder is not authorized for this certificate
   ORTBadSignature,     // the response has a signature that does not verify
-  ORTSkipResponseBytes // the response does not include responseBytes
+  ORTSkipResponseBytes, // the response does not include responseBytes
+  ORTCriticalExtension, // the response includes a critical extension
+  ORTNoncriticalExtension // the response includes an extension that is not critical
 };
 
 struct OCSPHost
 {
   const char *mHostName;
   OCSPResponseType mORT;
   const char *mAdditionalCertName; // useful for ORTGoodOtherCert, etc.
 };
--- a/security/pkix/lib/pkixcheck.cpp
+++ b/security/pkix/lib/pkixcheck.cpp
@@ -183,17 +183,23 @@ DecodeBasicConstraints(const SECItem* en
     return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
   }
 
   if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) {
     return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
   }
 
   bool isCA = false;
-  if (der::OptionalBoolean(input, isCA) != der::Success) {
+  // TODO(bug 989518): cA is by default false. According to DER, default
+  // values must not be explicitly encoded in a SEQUENCE. So, if this
+  // value is present and false, it is an encoding error. However, Go Daddy
+  // has issued many certificates with this improper encoding, so we can't
+  // enforce this yet (hence passing true for allowInvalidExplicitEncoding
+  // to der::OptionalBoolean).
+  if (der::OptionalBoolean(input, true, isCA) != der::Success) {
     return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
   }
   basicConstraints.isCA = isCA;
 
   if (input.Peek(der::INTEGER)) {
     SECItem pathLenConstraintEncoded;
     if (der::Integer(input, pathLenConstraintEncoded) != der::Success) {
       return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
--- a/security/pkix/lib/pkixder.h
+++ b/security/pkix/lib/pkixder.h
@@ -369,25 +369,28 @@ Boolean(Input& input, /*out*/ bool& valu
     default:
       PR_SetError(SEC_ERROR_BAD_DER, 0);
       return Failure;
   }
 }
 
 // This is for any BOOLEAN DEFAULT FALSE.
 // (If it is present and false, this is a bad encoding.)
+// TODO(bug 989518): For compatibility reasons, in some places we allow
+// invalid encodings with the explicit default value.
 inline Result
-OptionalBoolean(Input& input, /*out*/ bool& value)
+OptionalBoolean(Input& input, bool allowInvalidExplicitEncoding,
+                /*out*/ bool& value)
 {
   value = false;
   if (input.Peek(BOOLEAN)) {
     if (Boolean(input, value) != Success) {
       return Failure;
     }
-    if (!value) {
+    if (!allowInvalidExplicitEncoding && !value) {
       return Fail(SEC_ERROR_BAD_DER);
     }
   }
   return Success;
 }
 
 inline Result
 Enumerated(Input& input, uint8_t& value)
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -581,17 +581,18 @@ ResponseData(der::Input& input, Context&
   // empty response makes things unnecessarily complicated.
   if (der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
                     der::MustNotBeEmpty,
                     bind(SingleResponse, _1, ref(context))) != der::Success) {
     return der::Failure;
   }
 
   if (!input.AtEnd()) {
-    if (CheckExtensionsForCriticality(input) != der::Success) {
+    if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
+                    CheckExtensionsForCriticality) != der::Success) {
       return der::Failure;
     }
   }
 
   return der::Success;
 }
 
 // SingleResponse ::= SEQUENCE {
@@ -703,19 +704,19 @@ SingleResponse(der::Input& input, Contex
 
   if (context.time < SLOP) { // prevent underflow
     return der::Fail(SEC_ERROR_INVALID_ARGS);
   }
   if (context.time - SLOP > notAfter) {
     return der::Fail(SEC_ERROR_OCSP_OLD_RESPONSE);
   }
 
-
   if (!input.AtEnd()) {
-    if (CheckExtensionsForCriticality(input) != der::Success) {
+    if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
+                    CheckExtensionsForCriticality) != der::Success) {
       return der::Failure;
     }
   }
 
   if (context.thisUpdate) {
     *context.thisUpdate = thisUpdate;
   }
   if (context.validThrough) {
@@ -855,17 +856,17 @@ CheckExtensionForCriticality(der::Input&
     return der::Failure;
   }
   return input.Skip(toSkip);
 }
 
 static der::Result
 CheckExtensionsForCriticality(der::Input& input)
 {
-  return der::NestedOf(input, der::SEQUENCE | 1, der::SEQUENCE,
+  return der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
                        der::MustNotBeEmpty, CheckExtensionForCriticality);
 }
 
 //   1. The certificate identified in a received response corresponds to
 //      the certificate that was identified in the corresponding request;
 //   2. The signature on the response is valid;
 //   3. The identity of the signer matches the intended recipient of the
 //      request;
--- a/security/pkix/test/lib/pkixtestutil.cpp
+++ b/security/pkix/test/lib/pkixtestutil.cpp
@@ -124,16 +124,17 @@ OCSPResponseContext::OCSPResponseContext
   , thisUpdate(time)
   , nextUpdate(time + 10 * PR_USEC_PER_SEC)
   , includeNextUpdate(true)
   , certIDHashAlg(SEC_OID_SHA1)
   , certStatus(0)
   , revocationTime(0)
   , badSignature(false)
   , responderIDType(ByKeyHash)
+  , extensions(nullptr)
 {
 }
 
 static SECItem* ResponseBytes(OCSPResponseContext& context);
 static SECItem* BasicOCSPResponse(OCSPResponseContext& context);
 static SECItem* ResponseData(OCSPResponseContext& context);
 static SECItem* ResponderID(OCSPResponseContext& context);
 static SECItem* KeyHash(OCSPResponseContext& context);
@@ -394,16 +395,78 @@ BasicOCSPResponse(OCSPResponseContext& c
     return nullptr;
   }
   if (output.Add(signatureNested) != der::Success) {
     return nullptr;
   }
   return output.Squash(context.arena, der::SEQUENCE);
 }
 
+// Extension ::= SEQUENCE {
+//   id               OBJECT IDENTIFIER,
+//   critical         BOOLEAN DEFAULT FALSE
+//   value            OCTET STRING
+// }
+static SECItem*
+OCSPExtension(OCSPResponseContext& context, OCSPResponseExtension* extension)
+{
+  Output output;
+  if (output.Add(&extension->id) != der::Success) {
+    return nullptr;
+  }
+  if (extension->critical) {
+    static const uint8_t trueEncoded[3] = { 0x01, 0x01, 0xFF };
+    SECItem critical = {
+      siBuffer,
+      const_cast<uint8_t*>(trueEncoded),
+      PR_ARRAY_SIZE(trueEncoded)
+    };
+    if (output.Add(&critical) != der::Success) {
+      return nullptr;
+    }
+  }
+  SECItem* value = EncodeNested(context.arena, der::OCTET_STRING,
+                                &extension->value);
+  if (!value) {
+    return nullptr;
+  }
+  if (output.Add(value) != der::Success) {
+    return nullptr;
+  }
+  return output.Squash(context.arena, der::SEQUENCE);
+}
+
+// Extensions ::= [1] {
+//   SEQUENCE OF Extension
+// }
+static SECItem*
+Extensions(OCSPResponseContext& context)
+{
+  Output output;
+  for (OCSPResponseExtension* extension = context.extensions;
+       extension; extension = extension->next) {
+    SECItem* extensionEncoded = OCSPExtension(context, extension);
+    if (!extensionEncoded) {
+      return nullptr;
+    }
+    if (output.Add(extensionEncoded) != der::Success) {
+      return nullptr;
+    }
+  }
+  SECItem* extensionsEncoded = output.Squash(context.arena, der::SEQUENCE);
+  if (!extensionsEncoded) {
+    return nullptr;
+  }
+  return EncodeNested(context.arena,
+                      der::CONSTRUCTED |
+                      der::CONTEXT_SPECIFIC |
+                      1,
+                      extensionsEncoded);
+}
+
 // ResponseData ::= SEQUENCE {
 //    version             [0] EXPLICIT Version DEFAULT v1,
 //    responderID             ResponderID,
 //    producedAt              GeneralizedTime,
 //    responses               SEQUENCE OF SingleResponse,
 //    responseExtensions  [1] EXPLICIT Extensions OPTIONAL }
 SECItem*
 ResponseData(OCSPResponseContext& context)
@@ -421,27 +484,36 @@ ResponseData(OCSPResponseContext& contex
   if (!responses) {
     return nullptr;
   }
   SECItem* responsesNested = EncodeNested(context.arena, der::SEQUENCE,
                                           responses);
   if (!responsesNested) {
     return nullptr;
   }
+  SECItem* responseExtensions = nullptr;
+  if (context.extensions) {
+    responseExtensions = Extensions(context);
+  }
 
   Output output;
   if (output.Add(responderID) != der::Success) {
     return nullptr;
   }
   if (output.Add(producedAtEncoded) != der::Success) {
     return nullptr;
   }
   if (output.Add(responsesNested) != der::Success) {
     return nullptr;
   }
+  if (responseExtensions) {
+    if (output.Add(responseExtensions) != der::Success) {
+      return nullptr;
+    }
+  }
   return output.Squash(context.arena, der::SEQUENCE);
 }
 
 // ResponderID ::= CHOICE {
 //    byName              [1] Name,
 //    byKey               [2] KeyHash }
 // }
 SECItem*
--- a/security/pkix/test/lib/pkixtestutil.h
+++ b/security/pkix/test/lib/pkixtestutil.h
@@ -19,16 +19,25 @@
 #define mozilla_pkix_test__pkixtestutils_h
 
 #include "pkix/ScopedPtr.h"
 #include "pkix/pkixtypes.h"
 #include "seccomon.h"
 
 namespace mozilla { namespace pkix { namespace test {
 
+class OCSPResponseExtension
+{
+public:
+  SECItem id;
+  bool critical;
+  SECItem value;
+  OCSPResponseExtension* next;
+};
+
 class OCSPResponseContext
 {
 public:
   OCSPResponseContext(PLArenaPool* arena, CERTCertificate* cert, PRTime time);
 
   PLArenaPool* arena;
   // TODO(bug 980538): add a way to specify what certificates are included.
   pkix::ScopedCERTCertificate cert; // The subject of the OCSP response
@@ -48,16 +57,18 @@ public:
   PRTime revocationTime; // For certStatus == revoked
   bool badSignature; // If true, alter the signature to fail verification
 
   enum ResponderIDType {
     ByName = 1,
     ByKeyHash = 2
   };
   ResponderIDType responderIDType;
+
+  OCSPResponseExtension* extensions;
 };
 
 // The return value, if non-null, is owned by the arena in the context
 // and MUST NOT be freed.
 // This function does its best to respect the NSPR error code convention
 // (that is, if it returns null, calling PR_GetError() will return the
 // error of the failed operation). However, this is not guaranteed.
 SECItem* CreateEncodedOCSPResponse(OCSPResponseContext& context);
--- a/testing/marionette/marionette-elements.js
+++ b/testing/marionette/marionette-elements.js
@@ -115,17 +115,18 @@ ElementManager.prototype = {
       delete this.seenItems[id];
     }
     // use XPCNativeWrapper to compare elements; see bug 834266
     let wrappedWin = XPCNativeWrapper(win);
     if (!el ||
         !(XPCNativeWrapper(el).ownerDocument == wrappedWin.document) ||
         (XPCNativeWrapper(el).compareDocumentPosition(wrappedWin.document.documentElement) &
          DOCUMENT_POSITION_DISCONNECTED)) {
-      throw new ElementException("Stale element reference", 10, null);
+      throw new ElementException("The element reference is stale. Either the element " +
+                                 "is no longer attached to the DOM or the page has been refreshed.", 10, null);
     }
     return el;
   },
 
   /**
    * Convert values to primitives that can be transported over the
    * Marionette protocol.
    *