Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 11 Jun 2015 17:02:47 -0700
changeset 279169 8cf9d3e497f9de891ed01bfdf52668b4ec6c5738
parent 278917 9ebd530c5843150c20631a86bc8624da943098c0 (current diff)
parent 279168 bf40676095aac00fd78c37a9e8958ca4810fbc02 (diff)
child 279192 74ac345e777ad2a7a87b9aba543c4b9b07263940
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone41.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 inbound to central, a=merge
configure.in
mobile/android/chrome/content/browser.js
security/manager/ssl/tests/unit/test_cert_eku/ca.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_EP_NS_OS_SA_TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_NS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_OS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_SA-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-CA_TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_NS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_OS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_SA-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-EP_TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NONE-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_OS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_SA-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-NS_TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_SA-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-OS_TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-SA_TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/ee-EKU-TS-int-EKU-TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA_EP.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA_EP_NS_OS_SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA_NS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA_OS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA_SA.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-CA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-EP.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-EP_NS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-EP_OS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-EP_SA.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-EP_TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-NONE.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-NS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-NS_OS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-NS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-NS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-OS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-OS_SA.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-OS_TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-SA.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-SA_TS.der
security/manager/ssl/tests/unit/test_cert_eku/int-EKU-TS.der
toolkit/components/telemetry/Histograms.json
xpcom/glue/nsTHashtable.cpp
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -6,16 +6,17 @@
 
 #include "AccessibleWrap.h"
 
 #include "Accessible-inl.h"
 #include "ApplicationAccessibleWrap.h"
 #include "InterfaceInitFuncs.h"
 #include "nsAccUtils.h"
 #include "mozilla/a11y/PDocAccessible.h"
+#include "OuterDocAccessible.h"
 #include "ProxyAccessible.h"
 #include "RootAccessible.h"
 #include "nsMai.h"
 #include "nsMaiHyperlink.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "prprf.h"
 #include "nsStateMap.h"
@@ -91,17 +92,17 @@ static GType GetAtkTypeForMai(MaiInterfa
     case MAI_INTERFACE_DOCUMENT:
       return ATK_TYPE_DOCUMENT;
     case MAI_INTERFACE_IMAGE:
       return ATK_TYPE_IMAGE;
   }
   return G_TYPE_INVALID;
 }
 
-static const char* kNonUserInputEvent = ":system";
+#define NON_USER_EVENT ":system"
     
 static const GInterfaceInfo atk_if_infos[] = {
     {(GInterfaceInitFunc)componentInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr}, 
     {(GInterfaceInitFunc)actionInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)valueInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
@@ -823,36 +824,55 @@ getChildCountCB(AtkObject *aAtkObj)
     }
 
     return static_cast<gint>(accWrap->EmbeddedChildCount());
 }
 
 AtkObject *
 refChildCB(AtkObject *aAtkObj, gint aChildIndex)
 {
-    // aChildIndex should not be less than zero
-    if (aChildIndex < 0) {
+  // aChildIndex should not be less than zero
+  if (aChildIndex < 0) {
+    return nullptr;
+  }
+
+  AtkObject* childAtkObj = nullptr;
+  AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
+  if (accWrap) {
+    if (nsAccUtils::MustPrune(accWrap)) {
       return nullptr;
     }
 
-    AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
-    if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
-        return nullptr;
+    Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
+    if (accChild) {
+      childAtkObj = AccessibleWrap::GetAtkObject(accChild);
+    } else {
+      OuterDocAccessible* docOwner = accWrap->AsOuterDoc();
+      if (docOwner) {
+        ProxyAccessible* proxyDoc = docOwner->RemoteChildDoc();
+        if (proxyDoc)
+          childAtkObj = GetWrapperFor(proxyDoc);
+      }
     }
+  } else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    if (proxy->MustPruneChildren())
+      return nullptr;
 
-    Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
-    if (!accChild)
-        return nullptr;
+    ProxyAccessible* child = proxy->EmbeddedChildAt(aChildIndex);
+    if (child)
+      childAtkObj = GetWrapperFor(child);
+  } else {
+    return nullptr;
+  }
 
-    AtkObject* childAtkObj = AccessibleWrap::GetAtkObject(accChild);
+  NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
+  if (!childAtkObj)
+    return nullptr;
 
-    NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
-    if (!childAtkObj)
-        return nullptr;
-    g_object_ref(childAtkObj);
+  g_object_ref(childAtkObj);
 
   if (aAtkObj != childAtkObj->accessible_parent)
     atk_object_set_parent(childAtkObj, aAtkObj);
 
   return childAtkObj;
 }
 
 gint
@@ -1426,63 +1446,81 @@ MaiAtkObject::FireStateChangeEvent(uint6
             // Fire state change for first state if there is one to map
             atk_object_notify_state_change(&parent,
                                            gAtkStateMap[stateIndex].atkState,
                                            aEnabled);
         }
     }
 }
 
+#define OLD_TEXT_INSERTED "text_changed::insert"
+#define OLD_TEXT_REMOVED "text_changed::delete"
+static const char* oldTextChangeStrings[2][2] = {
+  { OLD_TEXT_REMOVED NON_USER_EVENT, OLD_TEXT_INSERTED NON_USER_EVENT },
+  { OLD_TEXT_REMOVED, OLD_TEXT_INSERTED }
+};
+
+#define TEXT_INSERTED "text-insert"
+#define TEXT_REMOVED "text-remove"
+#define NON_USER_DETAIL "::system"
+static const char* textChangedStrings[2][2] = {
+  { TEXT_REMOVED NON_USER_DETAIL, TEXT_INSERTED NON_USER_DETAIL },
+  { TEXT_REMOVED, TEXT_INSERTED}
+};
+
 nsresult
 AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
                                         AtkObject* aObject)
 {
     AccTextChangeEvent* event = downcast_accEvent(aEvent);
     NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
 
     int32_t start = event->GetStartOffset();
     uint32_t length = event->GetLength();
     bool isInserted = event->IsTextInserted();
     bool isFromUserInput = aEvent->IsFromUserInput();
-    char* signal_name = nullptr;
 
   if (gAvailableAtkSignals == eUnknown)
     gAvailableAtkSignals =
       g_signal_lookup("text-insert", G_OBJECT_TYPE(aObject)) ?
         eHaveNewAtkTextSignals : eNoNewAtkSignals;
 
   if (gAvailableAtkSignals == eNoNewAtkSignals) {
     // XXX remove this code and the gHaveNewTextSignals check when we can
     // stop supporting old atk since it doesn't really work anyway
     // see bug 619002
-    signal_name = g_strconcat(isInserted ? "text_changed::insert" :
-                              "text_changed::delete",
-                              isFromUserInput ? "" : kNonUserInputEvent, nullptr);
+    const char* signal_name =
+      oldTextChangeStrings[isFromUserInput][isInserted];
     g_signal_emit_by_name(aObject, signal_name, start, length);
   } else {
     nsAutoString text;
     event->GetModifiedText(text);
-    signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
-                              isFromUserInput ? "" : "::system", nullptr);
+    const char* signal_name =
+      textChangedStrings[isFromUserInput][isInserted];
     g_signal_emit_by_name(aObject, signal_name, start, length,
                           NS_ConvertUTF16toUTF8(text).get());
   }
 
-  g_free(signal_name);
   return NS_OK;
 }
 
+#define ADD_EVENT "children_changed::add"
+#define HIDE_EVENT "children_changed::remove"
+
+static const char *kMutationStrings[2][2] = {
+  { HIDE_EVENT NON_USER_EVENT, ADD_EVENT NON_USER_EVENT },
+  { HIDE_EVENT, ADD_EVENT },
+};
+
 nsresult
 AccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
                                      AtkObject* aObject, bool aIsAdded)
 {
     int32_t indexInParent = getIndexInParentCB(aObject);
     AtkObject *parentObject = getParentCB(aObject);
     NS_ENSURE_STATE(parentObject);
 
     bool isFromUserInput = aEvent->IsFromUserInput();
-    char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" :  "children_changed::remove",
-                                    isFromUserInput ? "" : kNonUserInputEvent, nullptr);
+    const char *signal_name = kMutationStrings[isFromUserInput][aIsAdded];
     g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, nullptr);
-    g_free(signal_name);
 
     return NS_OK;
 }
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -33,16 +33,17 @@ class AccGroupInfo;
 class ApplicationAccessible;
 class DocAccessible;
 class EmbeddedObjCollector;
 class HTMLImageMapAccessible;
 class HTMLLIAccessible;
 class HyperTextAccessible;
 class ImageAccessible;
 class KeyBinding;
+class OuterDocAccessible;
 class ProxyAccessible;
 class Relation;
 class RootAccessible;
 class TableAccessible;
 class TableCellAccessible;
 class TextLeafAccessible;
 class XULLabelAccessible;
 class XULTreeAccessible;
@@ -614,16 +615,19 @@ public:
 
   bool IsProxy() const { return mType == eProxyType; }
   ProxyAccessible* Proxy() const
   {
     MOZ_ASSERT(IsProxy());
     return mBits.proxy;
   }
 
+  bool IsOuterDoc() const { return mType == eOuterDocType; }
+  OuterDocAccessible* AsOuterDoc();
+
   bool IsProgress() const { return mType == eProgressType; }
 
   bool IsRoot() const { return mType == eRootType; }
   a11y::RootAccessible* AsRoot();
 
   bool IsSearchbox() const;
 
   bool IsSelect() const { return HasGenericType(eSelect); }
--- a/accessible/generic/OuterDocAccessible.cpp
+++ b/accessible/generic/OuterDocAccessible.cpp
@@ -3,16 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "OuterDocAccessible.h"
 
 #include "Accessible-inl.h"
 #include "nsAccUtils.h"
 #include "DocAccessible-inl.h"
+#include "mozilla/a11y/DocAccessibleParent.h"
+#include "mozilla/dom/TabParent.h"
 #include "Role.h"
 #include "States.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 using namespace mozilla;
@@ -21,16 +23,17 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 // OuterDocAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 OuterDocAccessible::
   OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
+  mType = eOuterDocType;
 }
 
 OuterDocAccessible::~OuterDocAccessible()
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
@@ -176,8 +179,29 @@ OuterDocAccessible::CacheChildren()
   // created. It will appended to outerdoc accessible children asynchronously.
   nsIDocument* outerDoc = mContent->GetCurrentDoc();
   if (outerDoc) {
     nsIDocument* innerDoc = outerDoc->GetSubDocumentFor(mContent);
     if (innerDoc)
       GetAccService()->GetDocAccessible(innerDoc);
   }
 }
+
+ProxyAccessible*
+OuterDocAccessible::RemoteChildDoc() const
+{
+  dom::TabParent* tab = dom::TabParent::GetFrom(GetContent());
+  if (!tab)
+    return nullptr;
+
+  // XXX Consider managing non top level remote documents with there parent
+  // document.
+  const nsTArray<PDocAccessibleParent*>& docs = tab->ManagedPDocAccessibleParent();
+  size_t docCount = docs.Length();
+  for (size_t i = 0; i < docCount; i++) {
+    auto doc = static_cast<DocAccessibleParent*>(docs[i]);
+    if (!doc->ParentDoc())
+      return doc;
+  }
+
+  MOZ_ASSERT(false, "no top level tab document?");
+  return nullptr;
+}
--- a/accessible/generic/OuterDocAccessible.h
+++ b/accessible/generic/OuterDocAccessible.h
@@ -5,16 +5,17 @@
 
 #ifndef MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_
 #define MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_
 
 #include "AccessibleWrap.h"
 
 namespace mozilla {
 namespace a11y {
+class ProxyAccessible;
 
 /**
  * Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
  * 
  * In these variable names, "outer" relates to the OuterDocAccessible as
  * opposed to the DocAccessibleWrap which is "inner". The outer node is
  * a something like tags listed above, whereas the inner node corresponds to
  * the inner document root.
@@ -22,16 +23,18 @@ namespace a11y {
 
 class OuterDocAccessible final : public AccessibleWrap
 {
 public:
   OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   NS_DECL_ISUPPORTS_INHERITED
 
+  ProxyAccessible* RemoteChildDoc() const;
+
   // Accessible
   virtual void Shutdown() override;
   virtual mozilla::a11y::role NativeRole() override;
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild) override;
 
   virtual void InvalidateChildren() override;
   virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override;
@@ -39,12 +42,17 @@ public:
 
 protected:
   virtual ~OuterDocAccessible() override;
 
   // Accessible
   virtual void CacheChildren() override;
 };
 
+inline OuterDocAccessible*
+Accessible::AsOuterDoc()
+{
+  return IsOuterDoc() ? static_cast<OuterDocAccessible*>(this) : nullptr;
+}
 } // namespace a11y
 } // namespace mozilla
 
 #endif  
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -1633,16 +1633,31 @@ DocAccessibleChild::RecvIndexOfEmbeddedC
   if (!parent || !child)
     return true;
 
   *aChildIdx = parent->GetIndexOfEmbeddedChild(child);
   return true;
 }
 
 bool
+DocAccessibleChild::RecvEmbeddedChildAt(const uint64_t& aID,
+                                        const uint32_t& aIdx,
+                                        uint64_t* aChildID)
+{
+  *aChildID = 0;
+
+  Accessible* acc = IdToAccessible(aID);
+  if (!acc)
+    return true;
+
+  *aChildID = reinterpret_cast<uintptr_t>(acc->GetEmbeddedChildAt(aIdx));
+  return true;
+}
+
+bool
 DocAccessibleChild::RecvChildAtPoint(const uint64_t& aID,
                                      const int32_t& aX,
                                      const int32_t& aY,
                                      const uint32_t& aWhich,
                                      uint64_t* aChild,
                                      bool* aOk)
 {
   *aChild = 0;
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -403,16 +403,19 @@ public:
                         double* aStep) override;
 
   virtual bool RecvTakeFocus(const uint64_t& aID) override;
 
   virtual bool RecvIndexOfEmbeddedChild(const uint64_t& aID,
                                         const uint64_t& aChildID,
                                         uint32_t* aChildIdx) override final;
 
+  virtual bool RecvEmbeddedChildAt(const uint64_t& aID, const uint32_t& aIdx,
+                                   uint64_t* aChildID) override final;
+
   virtual bool RecvChildAtPoint(const uint64_t& aID,
                                 const int32_t& aX,
                                 const int32_t& aY,
                                 const uint32_t& aWhich,
                                 uint64_t* aChild,
                                 bool* aOk) override;
 
   virtual bool RecvBounds(const uint64_t& aID, nsIntRect* aRect) override;
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -208,13 +208,16 @@ DocAccessibleParent::Destroy()
   mShutdown = true;
 
   uint32_t childDocCount = mChildDocs.Length();
   for (uint32_t i = childDocCount - 1; i < childDocCount; i--)
     mChildDocs[i]->Destroy();
 
   mAccessibles.EnumerateEntries(ShutdownAccessibles, nullptr);
   ProxyDestroyed(this);
-  mParentDoc ? mParentDoc->RemoveChildDoc(this)
-    : GetAccService()->RemoteDocShutdown(this);
+  if (mParentDoc)
+    mParentDoc->RemoveChildDoc(this);
+  else if (IsTopLevel())
+    GetAccService()->RemoteDocShutdown(this);
 }
-}
-}
+
+} // a11y
+} // mozilla
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -21,25 +21,29 @@ namespace a11y {
  * These objects live in the main process and comunicate with and represent
  * an accessible document in a content process.
  */
 class DocAccessibleParent : public ProxyAccessible,
     public PDocAccessibleParent
 {
 public:
   DocAccessibleParent() :
-    ProxyAccessible(this), mParentDoc(nullptr), mShutdown(false)
+    ProxyAccessible(this), mParentDoc(nullptr),
+    mTopLevel(false), mShutdown(false)
   { MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); }
   ~DocAccessibleParent()
   {
     MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible);
     MOZ_ASSERT(mChildDocs.Length() == 0);
     MOZ_ASSERT(!ParentDoc());
   }
 
+  void SetTopLevel() { mTopLevel = true; }
+  bool IsTopLevel() const { return mTopLevel; }
+
   /*
    * Called when a message from a document in a child process notifies the main
    * process it is firing an event.
    */
   virtual bool RecvEvent(const uint64_t& aID, const uint32_t& aType)
     override;
 
   virtual bool RecvShowEvent(const ShowEventData& aData) override;
@@ -146,15 +150,16 @@ private:
   nsTArray<DocAccessibleParent*> mChildDocs;
   DocAccessibleParent* mParentDoc;
 
   /*
    * Conceptually this is a map from IDs to proxies, but we store the ID in the
    * proxy object so we can't use a real map.
    */
   nsTHashtable<ProxyEntry> mAccessibles;
+  bool mTopLevel;
   bool mShutdown;
 };
 
 }
 }
 
 #endif
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -213,16 +213,18 @@ child:
   prio(high) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal);
   prio(high) sync MinValue(uint64_t aID) returns(double aValue);
   prio(high) sync MaxValue(uint64_t aID) returns(double aValue);
   prio(high) sync Step(uint64_t aID) returns(double aStep);
 
   prio(high) sync TakeFocus(uint64_t aID);
   prio(high) sync IndexOfEmbeddedChild(uint64_t aID, uint64_t aChildID)
     returns(uint32_t childIdx);
+  prio(high) sync EmbeddedChildAt(uint64_t aID, uint32_t aChildIdx)
+    returns(uint64_t aChild);
   prio(high) sync ChildAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aWhich)
     returns(uint64_t aChild, bool aOk);
   prio(high) sync Bounds(uint64_t aID) returns(nsIntRect aRect);
 
   prio(high) sync Language(uint64_t aID) returns(nsString aLocale);
   prio(high) sync DocType(uint64_t aID) returns(nsString aType);
   prio(high) sync URL(uint64_t aID) returns(nsString aURL);
   prio(high) sync MimeType(uint64_t aID) returns(nsString aMime);
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -912,16 +912,24 @@ ProxyAccessible::IndexOfEmbeddedChild(co
 {
   uint64_t childID = aChild->mID;
   uint32_t childIdx;
   unused << mDoc->SendIndexOfEmbeddedChild(mID, childID, &childIdx);
   return childIdx;
 }
 
 ProxyAccessible*
+ProxyAccessible::EmbeddedChildAt(size_t aChildIdx)
+{
+  uint64_t childID;
+  unused << mDoc->SendEmbeddedChildAt(mID, aChildIdx, &childID);
+  return mDoc->GetAccessible(childID);
+}
+
+ProxyAccessible*
 ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
                               Accessible::EWhichChildAtPoint aWhichChild)
 {
   uint64_t childID = 0;
   bool ok = false;
   unused << mDoc->SendChildAtPoint(mID, aX, aY,
                                    static_cast<uint32_t>(aWhichChild),
                                    &childID, &ok);
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -44,16 +44,17 @@ public:
   { mChildren.InsertElementAt(aIdx, aChild); }
 
   uint32_t ChildrenCount() const { return mChildren.Length(); }
   ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
 
   // XXX evaluate if this is fast enough.
   size_t IndexInParent() const { return Parent()->mChildren.IndexOf(this); }
   int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
+  ProxyAccessible* EmbeddedChildAt(size_t aChildIdx);
   bool MustPruneChildren() const;
 
   void Shutdown();
 
   void SetChildDoc(DocAccessibleParent*);
 
   /**
    * Remove The given child.
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -595,23 +595,24 @@ struct RoleDescrComparator
 {
   // Do nothing. mozTextAccessible will.
 }
 
 - (NSString*)customDescription
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
-  AccessibleWrap* accWrap = [self getGeckoAccessible];
-  if (accWrap->IsDefunct())
+  nsAutoString desc;
+  if (AccessibleWrap* accWrap = [self getGeckoAccessible])
+    accWrap->Description(desc);
+  else if (ProxyAccessible* proxy = [self getProxyAccessible])
+    proxy->Description(desc);
+  else
     return nil;
 
-  nsAutoString desc;
-  accWrap->Description(desc);
-
   return nsCocoaUtils::ToNSString(desc);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (NSString*)help
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -999,16 +999,20 @@ pref("network.proxy.pac_generator", true
 
 // List of app origins to apply browsing traffic proxy setting, separated by
 // comma.  Specify '*' in the list to apply to all apps.
 pref("network.proxy.browsing.app_origins", "app://system.gaiamobile.org");
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
 
+// Enable Web Speech recognition API
+pref("media.webspeech.recognition.enable", true);
+pref("media.webspeech.service.default", "pocketsphinx");
+
 // Downloads API
 pref("dom.mozDownloads.enabled", true);
 pref("dom.downloads.max_retention_days", 7);
 
 // External Helper Application Handling
 //
 // All external helper application handling can require the docshell to be
 // active before allowing the external helper app service to handle content.
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -24,23 +24,22 @@ MOZ_CAPTIVEDETECT=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_NO_SMART_CARDS=1
 MOZ_APP_STATIC_INI=1
 NSS_DISABLE_DBM=1
 MOZ_NO_EV_CERTS=1
 MOZ_DISABLE_EXPORT_JS=1
 
-# Bug 1171082 - Broken on Windows B2G Desktop
-if test "$OS_TARGET" != "WINNT"; then
 MOZ_WEBSPEECH=1
+if test -n "$NIGHTLY_BUILD"; then
 MOZ_WEBSPEECH_MODELS=1
 MOZ_WEBSPEECH_POCKETSPHINX=1
+fi
 MOZ_WEBSPEECH_TEST_BACKEND=1
-fi # !WINNT
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
 MOZ_RAW=1
 MOZ_AUDIO_CHANNEL_MANAGER=1
 fi
 
 # use custom widget for html:select
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -1230,19 +1230,24 @@
                          oncommand="DeveloperToolbar.hide();"
                          tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
 #endif
    </toolbar>
   </vbox>
 
   <svg:svg height="0">
 #include tab-shape.inc.svg
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+    <svg:clipPath id="urlbar-clip-path" clipPathUnits="userSpaceOnUse">
+      <svg:path d="m 1,-5 l 0,50 l 10000,0 l 0,-50 z"/>
+    </svg:clipPath>
+#endif
     <svg:clipPath id="urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
 #ifndef XP_MACOSX
-      <svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22l10000,0 l 0,-50 l -10000,0 z"/>
+      <svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22 l 10000,0 l 0,-50 l -10000,0 z"/>
 #else
       <svg:path d="M -11,-5 a 16 16 0 0 1 0,34 l 10000,0 l 0,-34 l -10000,0 z"/>
 #endif
     </svg:clipPath>
   </svg:svg>
 
 </vbox>
 # <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck.
--- a/browser/devtools/performance/docs/markers.md
+++ b/browser/devtools/performance/docs/markers.md
@@ -102,24 +102,36 @@ a setTimeout.
   * "WebIDL dictionary creation"
   * "XBL \<constructor\>/\<destructor\> invocation"
   * "message manager script load"
   * "message handler script load"
   * "nsGlobalWindow report new global"
 
 ## GarbageCollection
 
-Emitted after a full GC has occurred (which will emit past incremental events).
+Emitted after a full GC cycle has completed (which is after any number of
+incremental slices).
 
 * DOMString causeName - The reason for a GC event to occur. A full list of
   GC reasons can be found [on MDN](https://developer.mozilla.org/en-US/docs/Tools/Debugger-API/Debugger.Memory#Debugger.Memory_Handler_Functions).
 * DOMString nonincremenetalReason - If the GC could not do an incremental
   GC (smaller, quick GC events), and we have to walk the entire heap and
   GC everything marked, then the reason listed here is why.
 
+## nsCycleCollector::Collect
+
+An `nsCycleCollector::Collect` marker is emitted for each incremental cycle
+collection slice and each non-incremental cycle collection.
+
+# nsCycleCollector::ForgetSkippable
+
+`nsCycleCollector::ForgetSkippable` is presented as "Cycle Collection", but in
+reality it is preparation/pre-optimization for cycle collection, and not the
+actual tracing of edges and collecting of cycles.
+
 ## ConsoleTime
 
 A marker generated via `console.time()` and `console.timeEnd()`.
 
 * DOMString causeName - the label passed into `console.time(label)` and
   `console.timeEnd(label)` if passed in.
 
 ## TimeStamp
--- a/browser/devtools/performance/modules/logic/marker-utils.js
+++ b/browser/devtools/performance/modules/logic/marker-utils.js
@@ -430,16 +430,23 @@ const Formatters = {
     return fields;
   },
 
   StylesFields: function (marker) {
     if ("restyleHint" in marker) {
       return { "Restyle Hint": marker.restyleHint.replace(/eRestyle_/g, "") };
     }
   },
+
+  CycleCollectionFields: function (marker) {
+    let Type = PREFS["show-platform-data"]
+        ? marker.name
+        : marker.name.replace(/nsCycleCollector::/g, "");
+    return { Type };
+  },
 };
 
 exports.getMarkerLabel = getMarkerLabel;
 exports.getMarkerClassName = getMarkerClassName;
 exports.getMarkerFields = getMarkerFields;
 exports.DOM = DOM;
 exports.CollapseFunctions = CollapseFunctions;
 exports.Formatters = Formatters;
--- a/browser/devtools/performance/modules/markers.js
+++ b/browser/devtools/performance/modules/markers.js
@@ -108,16 +108,30 @@ const TIMELINE_BLUEPRINT = {
     colorName: "graphs-red",
     collapseFunc: either(collapse.parent, collapse.child),
     label: Formatters.GCLabel,
     fields: [
       { property: "causeName", label: "Reason:" },
       { property: "nonincrementalReason", label: "Non-incremental Reason:" }
     ],
   },
+  "nsCycleCollector::Collect": {
+    group: 1,
+    colorName: "graphs-red",
+    collapseFunc: either(collapse.parent, collapse.child),
+    label: "Cycle Collection",
+    fields: Formatters.CycleCollectionFields,
+  },
+  "nsCycleCollector::ForgetSkippable": {
+    group: 1,
+    colorName: "graphs-red",
+    collapseFunc: either(collapse.parent, collapse.child),
+    label: "Cycle Collection",
+    fields: Formatters.CycleCollectionFields,
+  },
 
   /* Group 2 - User Controlled */
   "ConsoleTime": {
     group: 2,
     colorName: "graphs-grey",
     label: sublabelForProperty(L10N.getStr("timeline.label.consoleTime"), "causeName"),
     fields: [{
       property: "causeName",
--- a/browser/devtools/performance/test/browser.ini
+++ b/browser/devtools/performance/test/browser.ini
@@ -1,23 +1,25 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
+  doc_force_cc.html
   doc_force_gc.html
   doc_innerHTML.html
   doc_markers.html
   doc_simple-test.html
   head.js
 
 # Commented out tests are profiler tests
 # that need to be moved over to performance tool
 
 [browser_aaa-run-first-leaktest.js]
 [browser_marker-utils.js]
+[browser_markers-cycle-collection.js]
 [browser_markers-gc.js]
 [browser_markers-parse-html.js]
 [browser_markers-styles.js]
 [browser_markers-timestamp.js]
 [browser_perf-allocations-to-samples.js]
 [browser_perf-categories-js-calltree.js]
 [browser_perf-compatibility-01.js]
 [browser_perf-compatibility-02.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/test/browser_markers-cycle-collection.js
@@ -0,0 +1,50 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that we get "nsCycleCollector::Collect" and
+ * "nsCycleCollector::ForgetSkippable" markers when we force cycle collection.
+ */
+
+const TEST_URL = EXAMPLE_URL + "doc_force_cc.html"
+
+function waitForMarkerType(front, type) {
+  info("Waiting for marker of type = " + type);
+  const { promise, resolve } = Promise.defer();
+
+  const handler = (_, name, markers) => {
+    if (name !== "markers") {
+      return;
+    }
+
+    info("Got markers: " + JSON.stringify(markers, null, 2));
+
+    if (markers.some(m => m.name === type)) {
+      ok(true, "Found marker of type = " + type);
+      front.off("timeline-data", handler);
+      resolve();
+    }
+  };
+  front.on("timeline-data", handler);
+
+  return promise;
+}
+
+function* spawnTest () {
+  // This test runs very slowly on linux32 debug EC2 instances.
+  requestLongerTimeout(2);
+
+  let { target, front } = yield initBackend(TEST_URL);
+
+  yield front.startRecording({ withMarkers: true, withTicks: true });
+
+  yield Promise.all([
+    waitForMarkerType(front, "nsCycleCollector::Collect"),
+    waitForMarkerType(front, "nsCycleCollector::ForgetSkippable")
+  ]);
+  ok(true, "Got expected cycle collection events");
+
+  yield front.stopRecording();
+  yield removeTab(target.tab);
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/test/doc_force_cc.html
@@ -0,0 +1,29 @@
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!doctype html>
+
+<html>
+  <head>
+    <meta charset="utf-8"/>
+    <title>Performance tool + cycle collection test page</title>
+  </head>
+
+  <body>
+    <script type="text/javascript">
+    window.test = function () {
+      document.body.expando1 = { cycle: document.body };
+      SpecialPowers.Cu.forceCC();
+
+      document.body.expando2 = { cycle: document.body };
+      SpecialPowers.Cu.forceCC();
+
+      document.body.expando3 = { cycle: document.body };
+      SpecialPowers.Cu.forceCC();
+
+      setTimeout(window.test, 100);
+    };
+    test();
+    </script>
+  </body>
+
+</html>
--- a/browser/devtools/webide/test/chrome.ini
+++ b/browser/devtools/webide/test/chrome.ini
@@ -1,11 +1,11 @@
 [DEFAULT]
 tags = devtools
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || (os == "mac" && (os_version == "10.8" || os_version == "10.10") && debug) # Bug 1135315 - assertions
 support-files =
   app/index.html
   app/manifest.webapp
   app.zip
   addons/simulators.json
   addons/fxos_1_0_simulator-linux.xpi
   addons/fxos_1_0_simulator-linux64.xpi
   addons/fxos_1_0_simulator-win32.xpi
--- a/browser/devtools/webide/test/sidebars/chrome.ini
+++ b/browser/devtools/webide/test/sidebars/chrome.ini
@@ -1,11 +1,11 @@
 [DEFAULT]
 tags = devtools
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || (os == "mac" && (os_version == "10.8" || os_version == "10.10") && debug) # Bug 1135315 - assertions
 support-files =
   ../app/index.html
   ../app/manifest.webapp
   ../head.js
   ../device_front_shared.js
 
 [test_newapp.html]
 [test_import.html]
--- a/browser/modules/ProcessHangMonitor.jsm
+++ b/browser/modules/ProcessHangMonitor.jsm
@@ -308,13 +308,14 @@ let ProcessHangMonitor = {
 
   /**
    * Callback for when HANG_EXPIRATION_TIME has elapsed.
    */
   notify: function(timer) {
     for (let [otherReport, otherTimer] of this._activeReports) {
       if (otherTimer === timer) {
         this.removeReport(otherReport);
+        otherReport.userCanceled();
         break;
       }
     }
   },
 };
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -675,27 +675,27 @@ toolbarbutton[constrain-size="true"][cui
 
 :-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   -moz-margin-start: -4px;
   margin-top: 3px;
   margin-bottom: 3px;
 }
 
 #back-button {
-  padding-top: 3px;
-  padding-bottom: 3px;
-  -moz-padding-start: 5px;
-  -moz-padding-end: 0;
+  margin-top: 3px;
+  margin-bottom: 3px;
+  -moz-margin-start: 5px;
+  padding: 0;
   position: relative;
   z-index: 1;
-  border-radius: 0 10000px 10000px 0;
+  border-radius: 10000px;
 }
 
-#back-button:-moz-locale-dir(rtl) {
-  border-radius: 10000px 0 0 10000px;
+#back-button:not(:-moz-lwtheme) {
+  background-color: -moz-dialog;
 }
 
 #back-button > menupopup {
   margin-top: -1px;
 }
 
 #back-button > .toolbarbutton-icon {
   border-radius: 10000px;
@@ -889,23 +889,27 @@ toolbarbutton[constrain-size="true"][cui
 }
 
 @conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
 @conditionalForwardWithUrlbar@ {
+  clip-path: url("chrome://browser/content/browser.xul#urlbar-clip-path");
+  -moz-margin-start: -5px;
+}
+
+@conditionalForwardWithUrlbar@:-moz-lwtheme {
   clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
-  -moz-margin-start: -5px;
 }
 
 @conditionalForwardWithUrlbar@:-moz-locale-dir(rtl),
 @conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) {
-  /* let urlbar-back-button-clip-path clip the urlbar's right side for RTL */
+  /* Let clip-path clip the urlbar-wrapper's right side for RTL. */
   transform: scaleX(-1);
 }
 
 @conditionalForwardWithUrlbar@:-moz-locale-dir(rtl) {
   -moz-box-direction: reverse;
 }
 
 #urlbar-icons {
--- a/configure.in
+++ b/configure.in
@@ -5127,21 +5127,16 @@ else
     MOZ_SAMPLE_TYPE_FLOAT32=1
     AC_DEFINE(MOZ_SAMPLE_TYPE_FLOAT32)
     AC_SUBST(MOZ_SAMPLE_TYPE_FLOAT32)
 fi
 
 dnl ========================================================
 dnl = Disable Speech API pocketsphinx backend
 dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(webspeechpocketsphinx,
-[  --disable-webspeechpocketsphinx        Disable support for HTML Speech API Pocketsphinx Backend],
-    MOZ_WEBSPEECH_POCKETSPHINX=,
-    MOZ_WEBSPEECH_POCKETSPHINX=1)
-
 if test -n "$MOZ_WEBSPEECH_POCKETSPHINX"; then
     AC_DEFINE(MOZ_WEBSPEECH_POCKETSPHINX)
 fi
 
 AC_SUBST(MOZ_WEBSPEECH_POCKETSPHINX)
 
 dnl ========================================================
 dnl = Disable Speech API code
@@ -5173,21 +5168,16 @@ if test -n "$MOZ_WEBSPEECH_TEST_BACKEND"
     AC_DEFINE(MOZ_WEBSPEECH_TEST_BACKEND)
 fi
 
 AC_SUBST(MOZ_WEBSPEECH_TEST_BACKEND)
 
 dnl ========================================================
 dnl = Disable Speech API models
 dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(webspeechmodels,
-[  --disable-webspeechmodels        Disable support for HTML Speech API Models],
-    MOZ_WEBSPEECH_MODELS=,
-    MOZ_WEBSPEECH_MODELS=1)
-
 if test -z "$MOZ_WEBSPEECH"; then
 MOZ_WEBSPEECH_MODELS=
 fi
 
 if test -n "$MOZ_WEBSPEECH_MODELS"; then
     AC_DEFINE(MOZ_WEBSPEECH_MODELS)
 fi
 
new file mode 100644
--- /dev/null
+++ b/docshell/base/AutoTimelineMarker.cpp
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/AutoTimelineMarker.h"
+
+#include "MainThreadUtils.h"
+#include "nsDocShell.h"
+#include "mozilla/Move.h"
+
+namespace mozilla {
+
+bool
+AutoTimelineMarker::DocShellIsRecording(nsDocShell& aDocShell)
+{
+  bool isRecording = false;
+  if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
+    aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
+  }
+  return isRecording;
+}
+
+AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
+                                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+  : mDocShell(nullptr)
+  , mName(aName)
+{
+  MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
+  if (docShell && DocShellIsRecording(*docShell)) {
+    mDocShell = docShell;
+    mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
+  }
+}
+
+AutoTimelineMarker::~AutoTimelineMarker()
+{
+  if (mDocShell) {
+    mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
+  }
+}
+
+void
+AutoGlobalTimelineMarker::PopulateDocShells()
+{
+  const LinkedList<nsDocShell::ObservedDocShell>& docShells =
+    nsDocShell::GetObservedDocShells();
+  MOZ_ASSERT(!docShells.isEmpty());
+
+  for (const nsDocShell::ObservedDocShell* ds = docShells.getFirst();
+       ds;
+       ds = ds->getNext()) {
+    mOk = mDocShells.append(**ds);
+    if (!mOk) {
+      return;
+    }
+  }
+}
+
+AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName
+                                                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+  : mOk(true)
+  , mDocShells()
+  , mName(aName)
+{
+  MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (nsDocShell::gProfileTimelineRecordingsCount == 0) {
+    return;
+  }
+
+  PopulateDocShells();
+  if (!mOk) {
+    // If we don't successfully populate our vector with *all* docshells being
+    // observed, don't add markers to *any* of them.
+    return;
+  }
+
+  for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
+       !range.empty();
+       range.popFront()) {
+    range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
+  }
+}
+
+AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker()
+{
+  if (!mOk) {
+    return;
+  }
+
+  for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
+       !range.empty();
+       range.popFront()) {
+    range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
+  }
+}
+
+
+} // namespace mozilla
--- a/docshell/base/AutoTimelineMarker.h
+++ b/docshell/base/AutoTimelineMarker.h
@@ -3,74 +3,91 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AutoTimelineMarker_h__
 #define AutoTimelineMarker_h__
 
 #include "mozilla/GuardObjects.h"
-#include "mozilla/Move.h"
-#include "nsDocShell.h"
+#include "mozilla/Vector.h"
+
 #include "nsRefPtr.h"
 
+class nsIDocShell;
+class nsDocShell;
+
 namespace mozilla {
 
 // # AutoTimelineMarker
 //
 // An RAII class to trace some task in the platform by adding a start and end
 // timeline marker pair. These markers are then rendered in the devtools'
 // performance tool's waterfall graph.
 //
 // Example usage:
 //
 //     {
 //       AutoTimelineMarker marker(mDocShell, "Parse CSS");
 //       nsresult rv = ParseTheCSSFile(mFile);
 //       ...
 //     }
-
 class MOZ_STACK_CLASS AutoTimelineMarker
 {
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
 
   nsRefPtr<nsDocShell> mDocShell;
   const char* mName;
 
-  bool
-  DocShellIsRecording(nsDocShell& aDocShell)
-  {
-    bool isRecording = false;
-    if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
-      aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
-    }
-    return isRecording;
-  }
+  bool DocShellIsRecording(nsDocShell& aDocShell);
 
 public:
   explicit AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
-                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-    : mDocShell(nullptr)
-    , mName(aName)
-  {
-    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-
-    nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
-    if (docShell && DocShellIsRecording(*docShell)) {
-      mDocShell = docShell;
-      mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
-    }
-  }
-
-  ~AutoTimelineMarker()
-  {
-    if (mDocShell) {
-      mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
-    }
-  }
+                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+  ~AutoTimelineMarker();
 
   AutoTimelineMarker(const AutoTimelineMarker& aOther) = delete;
   void operator=(const AutoTimelineMarker& aOther) = delete;
 };
 
+// # AutoGlobalTimelineMarker
+//
+// Similar to `AutoTimelineMarker`, but adds its traced marker to all docshells,
+// not a single particular one. This is useful for operations that aren't
+// associated with any one particular doc shell, or when it isn't clear which
+// doc shell triggered the operation.
+//
+// Example usage:
+//
+//     {
+//       AutoGlobalTimelineMarker marker("Cycle Collection");
+//       nsCycleCollector* cc = GetCycleCollector();
+//       cc->Collect();
+//       ...
+//     }
+class MOZ_STACK_CLASS AutoGlobalTimelineMarker
+{
+  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
+
+  // True as long as no operation has failed, eg due to OOM.
+  bool mOk;
+
+  // The set of docshells that are being observed and will get markers.
+  mozilla::Vector<nsRefPtr<nsDocShell>> mDocShells;
+
+  // The name of the marker we are adding.
+  const char* mName;
+
+  void PopulateDocShells();
+
+public:
+  explicit AutoGlobalTimelineMarker(const char* aName
+                                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+
+  ~AutoGlobalTimelineMarker();
+
+  AutoGlobalTimelineMarker(const AutoGlobalTimelineMarker& aOther) = delete;
+  void operator=(const AutoGlobalTimelineMarker& aOther) = delete;
+};
+
 } // namespace mozilla
 
 #endif /* AutoTimelineMarker_h__ */
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -43,16 +43,17 @@ EXPORTS += [
 
 EXPORTS.mozilla += [
     'AutoTimelineMarker.h',
     'IHistory.h',
     'LoadContext.h',
 ]
 
 UNIFIED_SOURCES += [
+    'AutoTimelineMarker.cpp',
     'LoadContext.cpp',
     'nsAboutRedirector.cpp',
     'nsDefaultURIFixup.cpp',
     'nsDocShell.cpp',
     'nsDocShellEditorData.cpp',
     'nsDocShellEnumerator.cpp',
     'nsDocShellLoadInfo.cpp',
     'nsDocShellTransferableHooks.cpp',
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -195,16 +195,22 @@
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/URLSearchParams.h"
 #include "nsPerformance.h"
 
 #ifdef MOZ_TOOLKIT_SEARCH
 #include "nsIBrowserSearchService.h"
 #endif
 
+#include "mozIThirdPartyUtil.h"
+// Values for the network.cookie.cookieBehavior pref are documented in
+// nsCookieService.cpp
+#define COOKIE_BEHAVIOR_ACCEPT 0 // Allow all cookies.
+#define COOKIE_BEHAVIOR_REJECT_FOREIGN 1 // Reject all third-party cookies.
+
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
 //#define DEBUG_DOCSHELL_FOCUS
 #define DEBUG_PAGE_CACHE
 #endif
 
 #ifdef XP_WIN
@@ -939,17 +945,17 @@ nsDocShell::nsDocShell()
                   getpid(),
                   AssertedCast<unsigned long long>(mHistoryID));
   }
 #endif
 }
 
 nsDocShell::~nsDocShell()
 {
-  MOZ_ASSERT(!mProfileTimelineRecording);
+  MOZ_ASSERT(!IsObserved());
 
   Destroy();
 
   nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory));
   if (shPrivate) {
     shPrivate->SetRootDocShell(nullptr);
   }
 
@@ -2922,40 +2928,47 @@ nsDocShell::HistoryTransactionRemoved(in
     }
   }
 
   return NS_OK;
 }
 
 unsigned long nsDocShell::gProfileTimelineRecordingsCount = 0;
 
+mozilla::LinkedList<nsDocShell::ObservedDocShell>* nsDocShell::gObservedDocShells = nullptr;
+
 NS_IMETHODIMP
 nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
 {
   bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
   if (currentValue != aValue) {
     if (aValue) {
       ++gProfileTimelineRecordingsCount;
       UseEntryScriptProfiling();
-      mProfileTimelineRecording = true;
+
+      MOZ_ASSERT(!mObserved);
+      mObserved.reset(new ObservedDocShell(this));
+      GetOrCreateObservedDocShells().insertFront(mObserved.get());
     } else {
       --gProfileTimelineRecordingsCount;
       UnuseEntryScriptProfiling();
-      mProfileTimelineRecording = false;
+
+      mObserved.reset(nullptr);
+
       ClearProfileTimelineMarkers();
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue)
 {
-  *aValue = mProfileTimelineRecording;
+  *aValue = IsObserved();
   return NS_OK;
 }
 
 nsresult
 nsDocShell::PopProfileTimelineMarkers(
     JSContext* aCx,
     JS::MutableHandle<JS::Value> aProfileTimelineMarkers)
 {
@@ -3085,26 +3098,26 @@ nsDocShell::Now(DOMHighResTimeStamp* aWh
     (TimeStamp::Now() - TimeStamp::ProcessCreation(ignore)).ToMilliseconds();
   return NS_OK;
 }
 
 void
 nsDocShell::AddProfileTimelineMarker(const char* aName,
                                      TracingMetadata aMetaData)
 {
-  if (mProfileTimelineRecording) {
+  if (IsObserved()) {
     TimelineMarker* marker = new TimelineMarker(this, aName, aMetaData);
     mProfileTimelineMarkers.AppendElement(marker);
   }
 }
 
 void
 nsDocShell::AddProfileTimelineMarker(UniquePtr<TimelineMarker>&& aMarker)
 {
-  if (mProfileTimelineRecording) {
+  if (IsObserved()) {
     mProfileTimelineMarkers.AppendElement(Move(aMarker));
   }
 }
 
 NS_IMETHODIMP
 nsDocShell::SetWindowDraggingAllowed(bool aValue)
 {
   nsRefPtr<nsDocShell> parent = GetParentDocshell();
@@ -14039,16 +14052,42 @@ nsDocShell::ShouldPrepareForIntercept(ns
     return NS_OK;
   }
 
   nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (!swm) {
     return NS_OK;
   }
 
+  nsresult result;
+  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
+    do_GetService(THIRDPARTYUTIL_CONTRACTID, &result);
+  NS_ENSURE_SUCCESS(result, result);
+
+  if (mCurrentURI) {
+    nsAutoCString uriSpec;
+    mCurrentURI->GetSpec(uriSpec);
+    if (!(uriSpec.EqualsLiteral("about:blank"))) {
+      // Reject the interception of third-party iframes if the cookie behaviour
+      // is set to reject all third-party cookies (1). In case that this pref
+      // is not set or can't be read, we default to allow all cookies (0) as
+      // this is the default value in all.js.
+      bool isThirdPartyURI = true;
+      result = thirdPartyUtil->IsThirdPartyURI(mCurrentURI, aURI,
+                                               &isThirdPartyURI);
+      NS_ENSURE_SUCCESS(result, result);
+      if (isThirdPartyURI &&
+          (Preferences::GetInt("network.cookie.cookieBehavior",
+                               COOKIE_BEHAVIOR_ACCEPT) ==
+                               COOKIE_BEHAVIOR_REJECT_FOREIGN)) {
+        return NS_OK;
+      }
+    }
+  }
+
   if (aIsNavigate) {
     OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
     *aShouldIntercept = swm->IsAvailable(attrs, aURI);
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocument> doc = GetDocument();
   if (!doc) {
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -18,16 +18,17 @@
 #include "nsIContentViewerContainer.h"
 #include "nsIDOMStorageManager.h"
 #include "nsDocLoader.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "GeckoProfiler.h"
 #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
+#include "mozilla/LinkedList.h"
 #include "jsapi.h"
 
 // Helper Classes
 #include "nsCOMPtr.h"
 #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
@@ -261,16 +262,53 @@ public:
   // See nsIDocShell::recordProfileTimelineMarkers
   void AddProfileTimelineMarker(const char* aName, TracingMetadata aMetaData);
   void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>&& aMarker);
 
   // Global counter for how many docShells are currently recording profile
   // timeline markers
   static unsigned long gProfileTimelineRecordingsCount;
 
+  class ObservedDocShell : public mozilla::LinkedListElement<ObservedDocShell>
+  {
+  public:
+    explicit ObservedDocShell(nsDocShell* aDocShell)
+      : mDocShell(aDocShell)
+    { }
+
+    nsDocShell* operator*() const { return mDocShell.get(); }
+
+  private:
+    nsRefPtr<nsDocShell> mDocShell;
+  };
+
+private:
+  static mozilla::LinkedList<ObservedDocShell>* gObservedDocShells;
+
+  static mozilla::LinkedList<ObservedDocShell>& GetOrCreateObservedDocShells()
+  {
+    if (!gObservedDocShells) {
+      gObservedDocShells = new mozilla::LinkedList<ObservedDocShell>();
+    }
+    return *gObservedDocShells;
+  }
+
+  // Never null if timeline markers are being observed.
+  mozilla::UniquePtr<ObservedDocShell> mObserved;
+
+  // Return true if timeline markers are being observed for this docshell. False
+  // otherwise.
+  bool IsObserved() const { return !!mObserved; }
+
+public:
+  static const mozilla::LinkedList<ObservedDocShell>& GetObservedDocShells()
+  {
+    return GetOrCreateObservedDocShells();
+  }
+
   // Tell the favicon service that aNewURI has the same favicon as aOldURI.
   static void CopyFavicon(nsIURI* aOldURI,
                           nsIURI* aNewURI,
                           bool aInPrivateBrowsing);
 
 protected:
   virtual ~nsDocShell();
   virtual void DestroyChildren() override;
@@ -968,19 +1006,16 @@ private:
   nsTObserverArray<nsWeakPtr> mScrollObservers;
   nsCString mOriginalUriString;
   nsWeakPtr mOpener;
 
   // A depth count of how many times NotifyRunToCompletionStart
   // has been called without a matching NotifyRunToCompletionStop.
   uint32_t mJSRunToCompletionDepth;
 
-  // True if recording profiles.
-  bool mProfileTimelineRecording;
-
   nsTArray<mozilla::UniquePtr<TimelineMarker>> mProfileTimelineMarkers;
 
   // Get rid of all the timeline markers accumulated so far
   void ClearProfileTimelineMarkers();
 
   // Separate function to do the actual name (i.e. not _top, _self etc.)
   // searching for FindItemWithName.
   nsresult DoFindItemWithName(const char16_t* aName,
--- a/docshell/test/browser/frame-head.js
+++ b/docshell/test/browser/frame-head.js
@@ -66,16 +66,20 @@ this.timelineContentTest = function(test
       docShell.popProfileTimelineMarkers();
 
       info("Running the test setup function");
       let onMarkers = timelineWaitForMarkers(docShell, searchFor);
       setup(docShell);
       info("Waiting for new markers on the docShell");
       let markers = yield onMarkers;
 
+      // Cycle collection markers are non-deterministic, and none of these tests
+      // expect them to show up.
+      markers = markers.filter(m => m.name.indexOf("nsCycleCollector") === -1);
+
       info("Running the test check function");
       check(markers);
     }
 
     info("Stop recording");
     docShell.recordProfileTimelineMarkers = false;
     finish();
   });
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -181,17 +181,24 @@ TextInputProcessor::BeginInputTransactio
   // dispatching an event, it'll fail to steal its ownership.  Then, we should
   // not throw an exception, just return false.
   if (dispatcher->IsComposing() || dispatcher->IsDispatchingEvent()) {
     return NS_OK;
   }
 
   // This instance has finished preparing to link to the dispatcher.  Therefore,
   // let's forget the old dispatcher and purpose.
-  UnlinkFromTextEventDispatcher();
+  if (mDispatcher) {
+    mDispatcher->EndInputTransaction(this);
+    if (NS_WARN_IF(mDispatcher)) {
+      // Forcibly initialize the members if we failed to end the input
+      // transaction.
+      UnlinkFromTextEventDispatcher();
+    }
+  }
 
   if (aForTests) {
     rv = dispatcher->BeginInputTransactionForTests(this);
   } else {
     rv = dispatcher->BeginInputTransaction(this);
   }
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -134,19 +134,35 @@ URL::CreateObjectURL(const GlobalObject&
 }
 
 void
 URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
                      const objectURLOptions& aOptions,
                      nsAString& aResult,
                      ErrorResult& aError)
 {
-  CreateObjectURLInternal(aGlobal, &aSource,
-                          NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME), aOptions,
-                          aResult, aError);
+  nsCOMPtr<nsIPrincipal> principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
+
+  nsCString url;
+  nsresult rv = nsHostObjectProtocolHandler::
+    AddDataEntry(NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME),
+                 &aSource, principal, url);
+  if (NS_FAILED(rv)) {
+    aError.Throw(rv);
+    return;
+  }
+
+  nsCOMPtr<nsIRunnable> revocation = NS_NewRunnableFunction(
+    [url] {
+      nsHostObjectProtocolHandler::RemoveDataEntry(url);
+    });
+
+  nsContentUtils::RunInStableState(revocation.forget());
+
+  CopyASCIItoUTF16(url, aResult);
 }
 
 void
 URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
                              const nsACString& aScheme,
                              const objectURLOptions& aOptions,
                              nsAString& aResult, ErrorResult& aRv)
 {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -87,16 +87,17 @@
 #include "nsError.h"
 #include "nsFocusManager.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGenericHTMLFrameElement.h"
 #include "nsGkAtoms.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsHtml5Module.h"
 #include "nsHtml5StringParser.h"
+#include "nsIAppShell.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsICategoryManager.h"
 #include "nsIChannelEventSink.h"
 #include "nsICharsetDetectionObserver.h"
 #include "nsIChromeRegistry.h"
 #include "nsIConsoleService.h"
 #include "nsIContent.h"
 #include "nsIContentSecurityPolicy.h"
@@ -177,16 +178,17 @@
 #include "nsTextEditorState.h"
 #include "nsTextFragment.h"
 #include "nsTextNode.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsUnicodeProperties.h"
 #include "nsViewManager.h"
 #include "nsViewportInfo.h"
+#include "nsWidgetsCID.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsXULPopupManager.h"
 #include "xpcprivate.h" // nsXPConnect
 #include "HTMLSplitOnSpacesTokenizer.h"
 #include "nsContentTypeParser.h"
 
 #include "nsIBidiKeyboard.h"
 
@@ -332,16 +334,17 @@ static const nsAttrValue::EnumTable kAut
   #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
   { 0 }
 };
 
 namespace {
 
 static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
+static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 static PLDHashTable* sEventListenerManagersHash;
 
 class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter
 {
   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
 
   ~DOMEventListenerManagersHashReporter() {}
@@ -5143,16 +5146,30 @@ nsContentUtils::AddScriptRunner(nsIRunna
   }
   
   nsCOMPtr<nsIRunnable> run = aRunnable;
   run->Run();
 
   return true;
 }
 
+/* static */
+void
+nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable,
+                                 DispatchFailureHandling aHandling)
+{
+  nsCOMPtr<nsIRunnable> runnable = aRunnable;
+  nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+  if (!appShell) {
+    MOZ_ASSERT(aHandling == DispatchFailureHandling::IgnoreFailure);
+    return;
+  }
+  appShell->RunInStableState(runnable.forget());
+}
+
 void
 nsContentUtils::EnterMicroTask()
 {
   MOZ_ASSERT(NS_IsMainThread());
   ++sMicroTaskLevel;
 }
 
 void
@@ -7409,17 +7426,19 @@ nsContentUtils::TransferableToIPCTransfe
   }
 }
 
 mozilla::UniquePtr<char[]>
 nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
                                size_t* aLength, int32_t* aStride)
 {
   mozilla::gfx::DataSourceSurface::MappedSurface map;
-  aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map);
+  if (NS_WARN_IF(!aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map))) {
+    return nullptr;
+  }
   mozilla::gfx::IntSize size = aSurface->GetSize();
   mozilla::CheckedInt32 requiredBytes =
     mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);
   size_t maxBufLen = requiredBytes.isValid() ? requiredBytes.value() : 0;
   mozilla::gfx::SurfaceFormat format = aSurface->GetFormat();
 
   // Surface data handling is totally nuts. This is the magic one needs to
   // know to access the data.
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1572,16 +1572,37 @@ public:
   /**
    * Call this function if !IsSafeToRunScript() and we fail to run the script
    * (rather than using AddScriptRunner as we usually do). |aDocument| is
    * optional as it is only used for showing the URL in the console.
    */
   static void WarnScriptWasIgnored(nsIDocument* aDocument);
 
   /**
+   * Whether to assert that RunInStableState() succeeds, or ignore failure,
+   * which may happen late in shutdown.
+   */
+  enum class DispatchFailureHandling { AssertSuccess, IgnoreFailure };
+
+  /**
+   * Add a "synchronous section", in the form of an nsIRunnable run once the
+   * event loop has reached a "stable state". |aRunnable| must not cause any
+   * queued events to be processed (i.e. must not spin the event loop).
+   * We've reached a stable state when the currently executing task/event has
+   * finished, see
+   * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
+   * In practice this runs aRunnable once the currently executing event
+   * finishes. If called multiple times per task/event, all the runnables will
+   * be executed, in the order in which RunInStableState() was called.
+   */
+  static void RunInStableState(already_AddRefed<nsIRunnable> aRunnable,
+                               DispatchFailureHandling aHandling =
+                                 DispatchFailureHandling::AssertSuccess);
+
+  /**
    * Retrieve information about the viewport as a data structure.
    * This will return information in the viewport META data section
    * of the document. This can be used in lieu of ProcessViewportInfo(),
    * which places the viewport information in the document header instead
    * of returning it directly.
    *
    * @param aDisplayWidth width of the on-screen display area for this
    * document, in device pixels.
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1504,42 +1504,47 @@ nsDOMWindowUtils::CompareCanvases(nsIDOM
   if (aCanvas1 == nullptr ||
       aCanvas2 == nullptr ||
       retVal == nullptr)
     return NS_ERROR_FAILURE;
 
   RefPtr<DataSourceSurface> img1 = CanvasToDataSourceSurface(aCanvas1);
   RefPtr<DataSourceSurface> img2 = CanvasToDataSourceSurface(aCanvas2);
 
+  DataSourceSurface::ScopedMap map1(img1, DataSourceSurface::READ);
+  DataSourceSurface::ScopedMap map2(img2, DataSourceSurface::READ);
+
   if (img1 == nullptr || img2 == nullptr ||
+      !map1.IsMapped() || !map2.IsMapped() ||
       img1->GetSize() != img2->GetSize() ||
-      img1->Stride() != img2->Stride())
+      map1.GetStride() != map2.GetStride()) {
     return NS_ERROR_FAILURE;
+  }
 
   int v;
   IntSize size = img1->GetSize();
-  uint32_t stride = img1->Stride();
+  int32_t stride = map1.GetStride();
 
   // we can optimize for the common all-pass case
-  if (stride == (uint32_t) size.width * 4) {
-    v = memcmp(img1->GetData(), img2->GetData(), size.width * size.height * 4);
+  if (stride == size.width * 4) {
+    v = memcmp(map1.GetData(), map2.GetData(), size.width * size.height * 4);
     if (v == 0) {
       if (aMaxDifference)
         *aMaxDifference = 0;
       *retVal = 0;
       return NS_OK;
     }
   }
 
   uint32_t dc = 0;
   uint32_t different = 0;
 
   for (int j = 0; j < size.height; j++) {
-    unsigned char *p1 = img1->GetData() + j*stride;
-    unsigned char *p2 = img2->GetData() + j*stride;
+    unsigned char *p1 = map1.GetData() + j*stride;
+    unsigned char *p2 = map2.GetData() + j*stride;
     v = memcmp(p1, p2, stride);
 
     if (v) {
       for (int i = 0; i < size.width; i++) {
         if (*(uint32_t*) p1 != *(uint32_t*) p2) {
 
           different++;
 
@@ -3436,26 +3441,24 @@ nsDOMWindowUtils::DispatchEventToChromeO
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   NS_ENSURE_STATE(aTarget && aEvent);
   aEvent->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
   aTarget->DispatchEvent(aEvent, aRetVal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::RunInStableState(nsIRunnable *runnable)
+nsDOMWindowUtils::RunInStableState(nsIRunnable *aRunnable)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
-  nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
-  if (!appShell) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  return appShell->RunInStableState(runnable);
+  nsCOMPtr<nsIRunnable> runnable = aRunnable;
+  nsContentUtils::RunInStableState(runnable.forget());
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::RunBeforeNextEvent(nsIRunnable *runnable)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -706,27 +706,16 @@ nsIdentifierMapEntry::SizeOfExcludingThi
 class SubDocMapEntry : public PLDHashEntryHdr
 {
 public:
   // Both of these are strong references
   Element *mKey; // must be first, to look like PLDHashEntryStub
   nsIDocument *mSubDocument;
 };
 
-struct FindContentData
-{
-  explicit FindContentData(nsIDocument* aSubDoc)
-    : mSubDocument(aSubDoc), mResult(nullptr)
-  {
-  }
-
-  nsISupports *mSubDocument;
-  Element *mResult;
-};
-
 
 /**
  * A struct that holds all the information about a radio group.
  */
 struct nsRadioGroupStruct
 {
   nsRadioGroupStruct()
     : mRequiredRadioCount(0)
@@ -1854,32 +1843,16 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
   return Element::CanSkipInCC(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDocument)
   return Element::CanSkipThis(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 static PLDHashOperator
-SubDocTraverser(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number,
-                void *arg)
-{
-  SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
-  nsCycleCollectionTraversalCallback *cb =
-    static_cast<nsCycleCollectionTraversalCallback*>(arg);
-
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mKey");
-  cb->NoteXPCOMChild(entry->mKey);
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mSubDocument");
-  cb->NoteXPCOMChild(entry->mSubDocument);
-
-  return PL_DHASH_NEXT;
-}
-
-static PLDHashOperator
 RadioGroupsTraverser(const nsAString& aKey, nsRadioGroupStruct* aData,
                      void* aClosure)
 {
   nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
                                    "mRadioGroups entry->mSelectedRadioButton");
@@ -2028,17 +2001,27 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   }
 
   // Traverse animation components
   if (tmp->mAnimationController) {
     tmp->mAnimationController->Traverse(&cb);
   }
 
   if (tmp->mSubDocuments) {
-    PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
+    PLDHashTable::Iterator iter(tmp->mSubDocuments);
+    while (iter.HasMoreEntries()) {
+      auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
+
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+                                         "mSubDocuments entry->mKey");
+      cb.NoteXPCOMChild(entry->mKey);
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+                                         "mSubDocuments entry->mSubDocument");
+      cb.NoteXPCOMChild(entry->mSubDocument);
+    }
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
 
   // We own only the items in mDOMMediaQueryLists that have listeners;
   // this reference is managed by their AddListener and RemoveListener
   // methods.
   for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
@@ -4026,45 +4009,33 @@ nsDocument::GetSubDocumentFor(nsIContent
     if (entry) {
       return entry->mSubDocument;
     }
   }
 
   return nullptr;
 }
 
-static PLDHashOperator
-FindContentEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                      uint32_t number, void *arg)
-{
-  SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
-  FindContentData *data = static_cast<FindContentData*>(arg);
-
-  if (entry->mSubDocument == data->mSubDocument) {
-    data->mResult = entry->mKey;
-
-    return PL_DHASH_STOP;
-  }
-
-  return PL_DHASH_NEXT;
-}
-
 Element*
 nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
 {
   NS_ENSURE_TRUE(aDocument, nullptr);
 
   if (!mSubDocuments) {
     return nullptr;
   }
 
-  FindContentData data(aDocument);
-  PL_DHashTableEnumerate(mSubDocuments, FindContentEnumerator, &data);
-
-  return data.mResult;
+  PLDHashTable::Iterator iter(mSubDocuments);
+  while (iter.HasMoreEntries()) {
+    auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
+    if (entry->mSubDocument == aDocument) {
+      return entry->mKey;
+    }
+  }
+  return nullptr;
 }
 
 bool
 nsDocument::IsNodeOfType(uint32_t aFlags) const
 {
     return !(aFlags & ~eDOCUMENT);
 }
 
@@ -8734,55 +8705,32 @@ nsDocument::Sanitize()
 }
 
 struct SubDocEnumArgs
 {
   nsIDocument::nsSubDocEnumFunc callback;
   void *data;
 };
 
-static PLDHashOperator
-SubDocHashEnum(PLDHashTable *table, PLDHashEntryHdr *hdr,
-               uint32_t number, void *arg)
-{
-  SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
-  SubDocEnumArgs *args = static_cast<SubDocEnumArgs*>(arg);
-
-  nsIDocument *subdoc = entry->mSubDocument;
-  bool next = subdoc ? args->callback(subdoc, args->data) : true;
-
-  return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
-}
-
 void
 nsDocument::EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData)
 {
-  if (mSubDocuments) {
-    SubDocEnumArgs args = { aCallback, aData };
-    PL_DHashTableEnumerate(mSubDocuments, SubDocHashEnum, &args);
-  }
-}
-
-static PLDHashOperator
-CanCacheSubDocument(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                    uint32_t number, void *arg)
-{
-  SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
-  bool *canCacheArg = static_cast<bool*>(arg);
-
-  nsIDocument *subdoc = entry->mSubDocument;
-
-  // The aIgnoreRequest we were passed is only for us, so don't pass it on.
-  bool canCache = subdoc ? subdoc->CanSavePresentation(nullptr) : false;
-  if (!canCache) {
-    *canCacheArg = false;
-    return PL_DHASH_STOP;
-  }
-
-  return PL_DHASH_NEXT;
+  if (!mSubDocuments) {
+    return;
+  }
+
+  PLDHashTable::Iterator iter(mSubDocuments);
+  while (iter.HasMoreEntries()) {
+    auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
+    nsIDocument* subdoc = entry->mSubDocument;
+    bool next = subdoc ? aCallback(subdoc, aData) : true;
+    if (!next) {
+      break;
+    }
+  }
 }
 
 #ifdef DEBUG_bryner
 #define DEBUG_PAGE_CACHE
 #endif
 
 bool
 nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
@@ -8873,21 +8821,31 @@ nsDocument::CanSavePresentation(nsIReque
 #endif
 
   // Don't save presentations for documents containing MSE content, to
   // reduce memory usage.
   if (ContainsMSEContent()) {
     return false;
   }
 
-  bool canCache = true;
-  if (mSubDocuments)
-    PL_DHashTableEnumerate(mSubDocuments, CanCacheSubDocument, &canCache);
-
-  return canCache;
+  if (mSubDocuments) {
+    PLDHashTable::Iterator iter(mSubDocuments);
+    while (iter.HasMoreEntries()) {
+      auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
+      nsIDocument* subdoc = entry->mSubDocument;
+
+      // The aIgnoreRequest we were passed is only for us, so don't pass it on.
+      bool canCache = subdoc ? subdoc->CanSavePresentation(nullptr) : false;
+      if (!canCache) {
+        return false;
+      }
+    }
+  }
+
+  return true;
 }
 
 void
 nsDocument::Destroy()
 {
   // The ContentViewer wants to release the document now.  So, tell our content
   // to drop any references to the document so that it can be destroyed.
   if (mIsGoingAway)
--- a/dom/base/nsPropertyTable.cpp
+++ b/dom/base/nsPropertyTable.cpp
@@ -128,40 +128,26 @@ nsPropertyTable::Enumerate(nsPropertyOwn
       (PL_DHashTableSearch(&prop->mObjectValueMap, aObject));
     if (entry) {
       aCallback(const_cast<void*>(aObject.get()), prop->mName, entry->value,
                 aData);
     }
   }
 }
 
-struct PropertyEnumeratorData
-{
-  nsIAtom* mName;
-  NSPropertyFunc mCallBack;
-  void* mData;
-};
-
-static PLDHashOperator
-PropertyEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
-                   uint32_t aNumber, void* aArg)
-{
-  PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(aHdr);
-  PropertyEnumeratorData* data = static_cast<PropertyEnumeratorData*>(aArg);
-  data->mCallBack(const_cast<void*>(entry->key), data->mName, entry->value,
-                  data->mData);
-  return PL_DHASH_NEXT;
-}
-
 void
 nsPropertyTable::EnumerateAll(NSPropertyFunc aCallBack, void* aData)
 {
   for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
-    PropertyEnumeratorData data = { prop->mName, aCallBack, aData };
-    PL_DHashTableEnumerate(&prop->mObjectValueMap, PropertyEnumerator, &data);
+    PLDHashTable::Iterator iter(&prop->mObjectValueMap);
+    while (iter.HasMoreEntries()) {
+      auto entry = static_cast<PropertyListMapEntry*>(iter.NextEntry());
+      aCallBack(const_cast<void*>(entry->key), prop->mName, entry->value,
+                aData);
+    }
   }
 }
 
 void*
 nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
                                      nsIAtom    *aPropertyName,
                                      bool        aRemove,
                                      nsresult   *aResult)
@@ -289,35 +275,27 @@ nsPropertyTable::PropertyList::PropertyL
     mNext(nullptr)
 {
 }
 
 nsPropertyTable::PropertyList::~PropertyList()
 {
 }
 
-static PLDHashOperator
-DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                          uint32_t number, void *arg)
-{
-  nsPropertyTable::PropertyList *propList =
-      static_cast<nsPropertyTable::PropertyList*>(arg);
-  PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(hdr);
-
-  propList->mDtorFunc(const_cast<void*>(entry->key), propList->mName,
-                      entry->value, propList->mDtorData);
-  return PL_DHASH_NEXT;
-}
-
 void
 nsPropertyTable::PropertyList::Destroy()
 {
-  // Enumerate any remaining object/value pairs and destroy the value object
-  if (mDtorFunc)
-    PL_DHashTableEnumerate(&mObjectValueMap, DestroyPropertyEnumerator, this);
+  // Enumerate any remaining object/value pairs and destroy the value object.
+  if (mDtorFunc) {
+    PLDHashTable::Iterator iter(&mObjectValueMap);
+    while (iter.HasMoreEntries()) {
+      auto entry = static_cast<PropertyListMapEntry*>(iter.NextEntry());
+      mDtorFunc(const_cast<void*>(entry->key), mName, entry->value, mDtorData);
+    }
+  }
 }
 
 bool
 nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject)
 {
   PropertyListMapEntry *entry =
       static_cast<PropertyListMapEntry*>
                  (PL_DHashTableSearch(&mObjectValueMap, aObject));
--- a/dom/base/nsReferencedElement.cpp
+++ b/dom/base/nsReferencedElement.cpp
@@ -42,17 +42,17 @@ nsReferencedElement::Reset(nsIContent* a
     // assumes UTF-8 and doesn't handle UTF-8 errors.
     // https://bugzilla.mozilla.org/show_bug.cgi?id=951082
     CopyUTF8toUTF16(refPart, ref);
   }
   if (ref.IsEmpty())
     return;
 
   // Get the current document
-  nsIDocument *doc = aFromContent->GetComposedDoc();
+  nsIDocument *doc = aFromContent->OwnerDoc();
   if (!doc)
     return;
 
   nsIContent* bindingParent = aFromContent->GetBindingParent();
   if (bindingParent) {
     nsXBLBinding* binding = bindingParent->GetXBLBinding();
     if (binding) {
       bool isEqualExceptRef;
@@ -119,17 +119,17 @@ nsReferencedElement::Reset(nsIContent* a
 
   HaveNewDocument(doc, aWatch, ref);
 }
 
 void
 nsReferencedElement::ResetWithID(nsIContent* aFromContent, const nsString& aID,
                                  bool aWatch)
 {
-  nsIDocument *doc = aFromContent->GetComposedDoc();
+  nsIDocument *doc = aFromContent->OwnerDoc();
   if (!doc)
     return;
 
   // XXX Need to take care of XBL/XBL2
 
   if (aWatch) {
     nsCOMPtr<nsIAtom> atom = do_GetAtom(aID);
     if (!atom)
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -3200,16 +3200,22 @@ class IDLInterfaceMember(IDLObjectWithId
 
         if self.isAttr() or self.isMethod():
             if self.affects == "Everything" and self.dependsOn != "Everything":
                 raise WebIDLError("Interface member is flagged as affecting "
                                   "everything but not depending on everything. "
                                   "That seems rather unlikely.",
                                   [self.location])
 
+        if self.getExtendedAttribute("NewObject"):
+            if self.dependsOn == "Nothing" or self.dependsOn == "DOMState":
+                raise WebIDLError("A [NewObject] method is not idempotent, " 
+                                  "so it has to depend on something other than DOM state.",
+                                  [self.location])
+
     def _setDependsOn(self, dependsOn):
         if self.dependsOn != "Everything":
             raise WebIDLError("Trying to specify multiple different DependsOn, "
                               "Pure, or Constant extended attributes for "
                               "attribute", [self.location])
         if dependsOn not in IDLInterfaceMember.DependsOnValues:
             raise WebIDLError("Invalid [DependsOn=%s] on attribute" % dependsOn,
                               [self.location])
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -224,17 +224,20 @@ BrowserElementChild.prototype = {
       "unblock-modal-prompt": this._recvStopWaiting,
       "fire-ctx-callback": this._recvFireCtxCallback,
       "owner-visibility-change": this._recvOwnerVisibilityChange,
       "entered-fullscreen": this._recvEnteredFullscreen,
       "exit-fullscreen": this._recvExitFullscreen.bind(this),
       "activate-next-paint-listener": this._activateNextPaintListener.bind(this),
       "set-input-method-active": this._recvSetInputMethodActive.bind(this),
       "deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this),
-      "do-command": this._recvDoCommand
+      "do-command": this._recvDoCommand,
+      "find-all": this._recvFindAll.bind(this),
+      "find-next": this._recvFindNext.bind(this),
+      "clear-match": this._recvClearMatch.bind(this),
     }
 
     addMessageListener("browser-element-api:call", function(aMessage) {
       if (aMessage.data.msg_name in mmCalls) {
         return mmCalls[aMessage.data.msg_name].apply(self, arguments);
       }
     });
 
@@ -1235,16 +1238,67 @@ BrowserElementChild.prototype = {
 
   _recvDoCommand: function(data) {
     if (this._isCommandEnabled(data.json.command)) {
       this._selectionStateChangedTarget = null;
       docShell.doCommand(COMMAND_MAP[data.json.command]);
     }
   },
 
+  _initFinder: function() {
+    if (!this._finder) {
+      try {
+        this._findLimit = Services.prefs.getIntPref("accessibility.typeaheadfind.matchesCountLimit");
+      } catch (e) {
+        // Pref not available, assume 0, no match counting.
+        this._findLimit = 0;
+      }
+
+      let {Finder} = Components.utils.import("resource://gre/modules/Finder.jsm", {});
+      this._finder = new Finder(docShell);
+      this._finder.addResultListener({
+        onMatchesCountResult: (data) => {
+          sendAsyncMsg('findchange', {
+            active: true,
+            searchString: this._finder.searchString,
+            searchLimit: this._findLimit,
+            activeMatchOrdinal: data.current,
+            numberOfMatches: data.total
+          });
+        }
+      });
+    }
+  },
+
+  _recvFindAll: function(data) {
+    this._initFinder();
+    let searchString = data.json.searchString;
+    this._finder.caseSensitive = data.json.caseSensitive;
+    this._finder.fastFind(searchString, false, false);
+    this._finder.requestMatchesCount(searchString, this._findLimit, false);
+  },
+
+  _recvFindNext: function(data) {
+    if (!this._finder) {
+      debug("findNext() called before findAll()");
+      return;
+    }
+    this._finder.findAgain(data.json.backward, false, false);
+    this._finder.requestMatchesCount(this._finder.searchString, this._findLimit, false);
+  },
+
+  _recvClearMatch: function(data) {
+    if (!this._finder) {
+      debug("clearMach() called before findAll()");
+      return;
+    }
+    this._finder.removeSelection();
+    sendAsyncMsg('findchange', {active: false});
+  },
+
   _recvSetInputMethodActive: function(data) {
     let msgData = { id: data.json.id };
     if (!this._isContentWindowCreated) {
       if (data.json.args.isActive) {
         // To activate the input method, we should wait before the content
         // window is ready.
         this._pendingSetInputMethodActive.push(data);
         return;
--- a/dom/browser-element/BrowserElementParent.js
+++ b/dom/browser-element/BrowserElementParent.js
@@ -201,16 +201,17 @@ BrowserElementParent.prototype = {
       "fullscreen-origin-change": this._fullscreenOriginChange,
       "exited-dom-fullscreen": this._exitedDomFullscreen,
       "got-visible": this._gotDOMRequestResult,
       "visibilitychange": this._childVisibilityChange,
       "got-set-input-method-active": this._gotDOMRequestResult,
       "selectionstatechanged": this._handleSelectionStateChanged,
       "scrollviewchange": this._handleScrollViewChange,
       "caretstatechanged": this._handleCaretStateChanged,
+      "findchange": this._handleFindChange
     };
 
     let mmSecuritySensitiveCalls = {
       "showmodalprompt": this._handleShowModalPrompt,
       "contextmenu": this._fireCtxMenuEvent,
       "securitychange": this._fireEventFromMsg,
       "locationchange": this._fireEventFromMsg,
       "iconchange": this._fireEventFromMsg,
@@ -470,16 +471,22 @@ BrowserElementParent.prototype = {
   },
 
   _handleScrollViewChange: function(data) {
     let evt = this._createEvent("scrollviewchange", data.json,
                                 /* cancelable = */ false);
     this._frameElement.dispatchEvent(evt);
   },
 
+  _handleFindChange: function(data) {
+    let evt = this._createEvent("findchange", data.json,
+                                /* cancelable = */ false);
+    this._frameElement.dispatchEvent(evt);
+  },
+
   _createEvent: function(evtName, detail, cancelable) {
     // This will have to change if we ever want to send a CustomEvent with null
     // detail.  For now, it's OK.
     if (detail !== undefined && detail !== null) {
       detail = Cu.cloneInto(detail, this._window);
       return new this._window.CustomEvent('mozbrowser' + evtName,
                                           { bubbles: true,
                                             cancelable: cancelable,
@@ -641,16 +648,33 @@ BrowserElementParent.prototype = {
       });
     }
   }),
 
   getCanGoBack: defineDOMRequestMethod('get-can-go-back'),
   getCanGoForward: defineDOMRequestMethod('get-can-go-forward'),
   getContentDimensions: defineDOMRequestMethod('get-contentdimensions'),
 
+  findAll: defineNoReturnMethod(function(searchString, caseSensitivity) {
+    return this._sendAsyncMsg('find-all', {
+      searchString,
+      caseSensitive: caseSensitivity == Ci.nsIBrowserElementAPI.FIND_CASE_SENSITIVE
+    });
+  }),
+
+  findNext: defineNoReturnMethod(function(direction) {
+    return this._sendAsyncMsg('find-next', {
+      backward: direction == Ci.nsIBrowserElementAPI.FIND_BACKWARD
+    });
+  }),
+
+  clearMatch: defineNoReturnMethod(function() {
+    return this._sendAsyncMsg('clear-match');
+  }),
+
   goBack: defineNoReturnMethod(function() {
     this._sendAsyncMsg('go-back');
   }),
 
   goForward: defineNoReturnMethod(function() {
     this._sendAsyncMsg('go-forward');
   }),
 
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/browserElement_Find.js
@@ -0,0 +1,146 @@
+/* Any copyright is dedicated to the public domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Bug 1163961 - Test search API
+
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+browserElementTestHelpers.setEnabledPref(true);
+browserElementTestHelpers.addPermission();
+
+function runTest() {
+
+  let iframe = document.createElement('iframe');
+  iframe.setAttribute('mozbrowser', 'true');
+  iframe.src = 'data:text/html,foo bar foo XXX Foo BAR foobar foobar';
+
+  const once = (eventName) => {
+    return new Promise((resolve) => {
+      iframe.addEventListener(eventName, function onEvent(...args) {
+        iframe.removeEventListener(eventName, onEvent);
+        resolve(...args);
+      });
+    });
+  }
+
+  // Test if all key=>value pairs in o1 are present in o2.
+  const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]);
+
+  let testCount = 0;
+
+  once('mozbrowserloadend').then(() => {
+    iframe.findAll('foo', 'case-insensitive');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'foo',
+      searchLimit: 100,
+      activeMatchOrdinal: 1,
+      numberOfMatches: 5,
+    }), `test ${testCount++}`);
+    iframe.findNext('forward');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'foo',
+      searchLimit: 100,
+      activeMatchOrdinal: 2,
+      numberOfMatches: 5,
+    }), `test ${testCount++}`);
+    iframe.findNext('backward');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'foo',
+      searchLimit: 100,
+      activeMatchOrdinal: 1,
+      numberOfMatches: 5,
+    }), `test ${testCount++}`);
+    iframe.findAll('xxx', 'case-sensitive');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'xxx',
+      searchLimit: 100,
+      activeMatchOrdinal: 0,
+      numberOfMatches: 0,
+    }), `test ${testCount++}`);
+    iframe.findAll('bar', 'case-insensitive');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'bar',
+      searchLimit: 100,
+      activeMatchOrdinal: 1,
+      numberOfMatches: 4,
+    }), `test ${testCount++}`);
+    iframe.findNext('forward');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'bar',
+      searchLimit: 100,
+      activeMatchOrdinal: 2,
+      numberOfMatches: 4,
+    }), `test ${testCount++}`);
+    iframe.findNext('forward');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'bar',
+      searchLimit: 100,
+      activeMatchOrdinal: 3,
+      numberOfMatches: 4,
+    }), `test ${testCount++}`);
+    iframe.findNext('forward');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'bar',
+      searchLimit: 100,
+      activeMatchOrdinal: 4,
+      numberOfMatches: 4,
+    }), `test ${testCount++}`);
+    iframe.findNext('forward');
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: true,
+      searchString: 'bar',
+      searchLimit: 100,
+      activeMatchOrdinal: 1,
+      numberOfMatches: 4,
+    }), `test ${testCount++}`);
+    iframe.clearMatch();
+    return once('mozbrowserfindchange');
+  }).then(({detail}) => {
+    ok(c(detail, {
+      msg_name: "findchange",
+      active: false
+    }), `test ${testCount++}`);
+    SimpleTest.finish();
+  });
+
+  document.body.appendChild(iframe);
+
+}
+
+addEventListener('testready', runTest);
--- a/dom/browser-element/mochitest/mochitest-oop.ini
+++ b/dom/browser-element/mochitest/mochitest-oop.ini
@@ -2,16 +2,17 @@
 # Both the "inproc" and "oop" versions of OpenMixedProcess open remote frames,
 # so we don't run that test on platforms which don't support OOP tests.
 # OOP tests don't work on native-fennec (bug 774939).
 # Bug 960345 - Disabled on OSX debug for frequent crashes.
 skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
 support-files =
   browserElement_OpenMixedProcess.js
   file_browserElement_OpenMixedProcess.html
+  browserElement_Find.js
   browserElement_OpenTab.js
 
 [test_browserElement_oop_Viewmode.html]
 [test_browserElement_oop_ThemeColor.html]
 [test_browserElement_inproc_ErrorSecurity.html]
 skip-if = toolkit=='gonk'
 [test_browserElement_inproc_OpenMixedProcess.html]
 skip-if = toolkit=='gonk' || (toolkit == 'gonk' && !debug)
@@ -36,16 +37,17 @@ skip-if = (toolkit == 'gonk' && !debug)
 [test_browserElement_oop_DOMRequestError.html]
 [test_browserElement_oop_DataURI.html]
 [test_browserElement_oop_DisallowEmbedAppsInOOP.html]
 [test_browserElement_oop_DocumentFirstPaint.html]
 [test_browserElement_oop_Download.html]
 disabled = bug 1022281
 [test_browserElement_oop_ErrorSecurity.html]
 skip-if = (toolkit == 'gonk' && !debug)
+[test_browserElement_oop_Find.html]
 [test_browserElement_oop_FirstPaint.html]
 [test_browserElement_oop_ForwardName.html]
 [test_browserElement_oop_FrameWrongURI.html]
 skip-if = (toolkit == 'gonk' && !debug)
 [test_browserElement_oop_GetScreenshot.html]
 [test_browserElement_oop_GetScreenshotDppx.html]
 [test_browserElement_oop_Iconchange.html]
 [test_browserElement_oop_LoadEvents.html]
--- a/dom/browser-element/mochitest/mochitest.ini
+++ b/dom/browser-element/mochitest/mochitest.ini
@@ -24,16 +24,17 @@ support-files =
   browserElement_CopyPaste.js
   browserElement_DOMRequestError.js
   browserElement_DataURI.js
   browserElement_DisallowEmbedAppsInOOP.js
   browserElement_DocumentFirstPaint.js
   browserElement_Download.js
   browserElement_ErrorSecurity.js
   browserElement_ExposableURI.js
+  browserElement_Find.js
   browserElement_FirstPaint.js
   browserElement_ForwardName.js
   browserElement_FrameWrongURI.js
   browserElement_GetScreenshot.js
   browserElement_GetScreenshotDppx.js
   browserElement_Iconchange.js
   browserElement_LoadEvents.js
   browserElement_Manifestchange.js
@@ -154,16 +155,17 @@ skip-if = buildapp == 'b2g'
 [test_browserElement_inproc_DOMRequestError.html]
 [test_browserElement_inproc_DataURI.html]
 [test_browserElement_inproc_DisallowEmbedAppsInOOP.html]
 skip-if = os == "android" || toolkit == 'gonk' # embed-apps doesn't work in the mochitest app
 [test_browserElement_inproc_DocumentFirstPaint.html]
 [test_browserElement_inproc_Download.html]
 disabled = bug 1022281
 [test_browserElement_inproc_ExposableURI.html]
+[test_browserElement_inproc_Find.html]
 [test_browserElement_inproc_FirstPaint.html]
 [test_browserElement_inproc_ForwardName.html]
 [test_browserElement_inproc_FrameWrongURI.html]
 skip-if = (toolkit == 'gonk' && !debug)
 [test_browserElement_inproc_GetScreenshot.html]
 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
 [test_browserElement_inproc_GetScreenshotDppx.html]
 [test_browserElement_inproc_Iconchange.html]
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_Find.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1163961
+-->
+<head>
+  <title>Test for Bug 1163961</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a>
+
+<script type="application/javascript;version=1.7" src="browserElement_Find.js">
+</script>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_oop_Find.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1163961
+-->
+<head>
+  <title>Test for Bug 1163961</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a>
+
+<script type="application/javascript;version=1.7" src="browserElement_Find.js">
+</script>
+</body>
+</html>
+
--- a/dom/browser-element/nsIBrowserElementAPI.idl
+++ b/dom/browser-element/nsIBrowserElementAPI.idl
@@ -21,19 +21,25 @@ interface nsIBrowserElementNextPaintList
     { 0x651db7e3, 0x1734, 0x4536,                               \
       { 0xb1, 0x5a, 0x5b, 0x3a, 0xe6, 0x44, 0x13, 0x4c } }
 %}
 
 /**
  * Interface to the BrowserElementParent implementation. All methods
  * but setFrameLoader throw when the remote process is dead.
  */
-[scriptable, uuid(3811446f-90bb-42c1-b2b6-aae3603b61e1)]
+[scriptable, uuid(8ecb598c-f886-11e4-9915-778f934fbf93)]
 interface nsIBrowserElementAPI : nsISupports
 {
+  const long FIND_CASE_SENSITIVE = 0;
+  const long FIND_CASE_INSENSITIVE = 1;
+
+  const long FIND_FORWARD = 0;
+  const long FIND_BACKWARD = 1;
+
   void setFrameLoader(in nsIFrameLoader frameLoader);
 
   void setVisible(in boolean visible);
   nsIDOMDOMRequest getVisible();
   void setActive(in boolean active);
   boolean getActive();
 
   void sendMouseEvent(in DOMString type,
@@ -62,15 +68,19 @@ interface nsIBrowserElementAPI : nsISupp
   nsIDOMDOMRequest getScreenshot(in uint32_t width,
                                  in uint32_t height,
                                  [optional] in DOMString mimeType);
   void zoom(in float zoom);
   nsIDOMDOMRequest getCanGoBack();
   nsIDOMDOMRequest getCanGoForward();
   nsIDOMDOMRequest getContentDimensions();
 
+  void findAll(in DOMString searchString, in long caseSensitivity);
+  void findNext(in long direction);
+  void clearMatch();
+
   void addNextPaintListener(in nsIBrowserElementNextPaintListener listener);
   void removeNextPaintListener(in nsIBrowserElementNextPaintListener listener);
 
   nsIDOMDOMRequest setInputMethodActive(in boolean isActive);
 
   void setNFCFocus(in boolean isFocus);
 };
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2347,21 +2347,26 @@ private:
   nsIAtom* mFontLanguage;
   bool mExplicitLanguage;
   nsPresContext* mPresContext;
 };
 
 void
 CanvasRenderingContext2D::UpdateFilter()
 {
-  nsIPresShell* presShell = GetPresShell();
+  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell || presShell->IsDestroying()) {
     return;
   }
 
+  // The filter might reference an SVG filter that is declared inside this
+  // document. Flush frames so that we'll have an nsSVGFilterFrame to work
+  // with.
+  presShell->FlushPendingNotifications(Flush_Frames);
+
   CurrentState().filter =
     nsFilterInstance::GetFilterDescription(mCanvasElement,
       CurrentState().filterChain,
       CanvasUserSpaceMetrics(IntSize(mWidth, mHeight),
                              CurrentState().fontFont,
                              CurrentState().fontLanguage,
                              CurrentState().fontExplicitLanguage,
                              presShell->GetPresContext()),
@@ -4695,21 +4700,27 @@ CanvasRenderingContext2D::DrawWindow(nsG
   }
 
   nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
   unused << shell->RenderDocument(r, renderDocFlags, backgroundColor, thebes);
   if (drawDT) {
     RefPtr<SourceSurface> snapshot = drawDT->Snapshot();
     RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
 
+    DataSourceSurface::MappedSurface rawData;
+    if (NS_WARN_IF(!data->Map(DataSourceSurface::READ, &rawData))) {
+        error.Throw(NS_ERROR_FAILURE);
+        return;
+    }
     RefPtr<SourceSurface> source =
-      mTarget->CreateSourceSurfaceFromData(data->GetData(),
+      mTarget->CreateSourceSurfaceFromData(rawData.mData,
                                            data->GetSize(),
-                                           data->Stride(),
+                                           rawData.mStride,
                                            data->GetFormat());
+    data->Unmap();
 
     if (!source) {
       error.Throw(NS_ERROR_FAILURE);
       return;
     }
 
     mgfx::Rect destRect(0, 0, w, h);
     mgfx::Rect sourceRect(0, 0, sw, sh);
@@ -4974,22 +4985,23 @@ CanvasRenderingContext2D::GetImageDataAr
   if (!rightMost.isValid() || !bottomMost.isValid()) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
   IntRect srcRect(0, 0, mWidth, mHeight);
   IntRect destRect(aX, aY, aWidth, aHeight);
   IntRect srcReadRect = srcRect.Intersect(destRect);
   RefPtr<DataSourceSurface> readback;
+  DataSourceSurface::MappedSurface rawData;
   if (!srcReadRect.IsEmpty() && !mZero) {
     RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
     if (snapshot) {
       readback = snapshot->GetDataSurface();
     }
-    if (!readback || !readback->GetData()) {
+    if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   JS::Rooted<JSObject*> darray(aCx, JS_NewUint8ClampedArray(aCx, len.value()));
   if (!darray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -5001,18 +5013,18 @@ CanvasRenderingContext2D::GetImageDataAr
 
   IntRect dstWriteRect = srcReadRect;
   dstWriteRect.MoveBy(-aX, -aY);
 
   uint8_t* src;
   uint32_t srcStride;
 
   if (readback) {
-    srcStride = readback->Stride();
-    src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
+    srcStride = rawData.mStride;
+    src = rawData.mData + srcReadRect.y * srcStride + srcReadRect.x * 4;
   }
 
   JS::AutoCheckCannotGC nogc;
   uint8_t* data = JS_GetUint8ClampedArrayData(darray, nogc);
   if (!readback) {
     src = data;
     srcStride = aWidth * 4;
   }
@@ -5066,16 +5078,20 @@ CanvasRenderingContext2D::GetImageDataAr
       *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + g];
       *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + b];
       *dst++ = a;
     }
     src += srcStride - (dstWriteRect.width * 4);
     dst += (aWidth * 4) - (dstWriteRect.width * 4);
   }
 
+  if (readback) {
+    readback->Unmap();
+  }
+
   *aRetval = darray;
   return NS_OK;
 }
 
 void
 CanvasRenderingContext2D::EnsureErrorTarget()
 {
   if (sErrorTarget) {
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -879,16 +879,17 @@ protected:
                      miterLimit(10.0f),
                      globalAlpha(1.0f),
                      shadowBlur(0.0),
                      dashOffset(0.0f),
                      op(mozilla::gfx::CompositionOp::OP_OVER),
                      fillRule(mozilla::gfx::FillRule::FILL_WINDING),
                      lineCap(mozilla::gfx::CapStyle::BUTT),
                      lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
+                     filterString(MOZ_UTF16("none")),
                      imageSmoothingEnabled(true),
                      fontExplicitLanguage(false)
     { }
 
     ContextState(const ContextState& other)
         : fontGroup(other.fontGroup),
           fontLanguage(other.fontLanguage),
           fontFont(other.fontFont),
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -319,16 +319,17 @@ public:
 
     // -------------------------------------------------------------------------
     // Uniform Buffer Objects and Transform Feedback Buffers - WebGL2ContextUniforms.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size);
 */
+    virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) override;
     void GetIndexedParameter(GLenum target, GLuint index,
                              dom::Nullable<dom::OwningWebGLBufferOrLongLong>& retval);
     void GetUniformIndices(WebGLProgram* program,
                            const dom::Sequence<nsString>& uniformNames,
                            dom::Nullable< nsTArray<GLuint> >& retval);
     void GetActiveUniforms(WebGLProgram* program,
                            const dom::Sequence<GLuint>& uniformIndices, GLenum pname,
                            dom::Nullable< nsTArray<GLint> >& retval);
--- a/dom/canvas/WebGL2ContextSamplers.cpp
+++ b/dom/canvas/WebGL2ContextSamplers.cpp
@@ -31,16 +31,22 @@ WebGL2Context::DeleteSampler(WebGLSample
         return;
 
     if (!ValidateObjectAllowDeletedOrNull("deleteSampler", sampler))
         return;
 
     if (!sampler || sampler->IsDeleted())
         return;
 
+    for (int n = 0; n < mGLMaxTextureUnits; n++) {
+        if (mBoundSamplers[n] == sampler) {
+            mBoundSamplers[n] = nullptr;
+        }
+    }
+
     sampler->RequestDelete();
 }
 
 bool
 WebGL2Context::IsSampler(WebGLSampler* sampler)
 {
     if (IsContextLost())
         return false;
@@ -69,16 +75,18 @@ WebGL2Context::BindSampler(GLuint unit, 
 
     if (GLint(unit) >= mGLMaxTextureUnits)
         return ErrorInvalidValue("bindSampler: unit must be < %d", mGLMaxTextureUnits);
 
     if (sampler && sampler->IsDeleted())
         return ErrorInvalidOperation("bindSampler: binding deleted sampler");
 
     WebGLContextUnchecked::BindSampler(unit, sampler);
+
+    mBoundSamplers[unit] = sampler;
 }
 
 void
 WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param)
 {
     if (IsContextLost())
         return;
 
copy from dom/canvas/WebGLTimerQuery.h
copy to dom/canvas/WebGL2ContextState.cpp
--- a/dom/canvas/WebGLTimerQuery.h
+++ b/dom/canvas/WebGL2ContextState.cpp
@@ -1,49 +1,177 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGL_TIMER_QUERY_H_
-#define WEBGL_TIMER_QUERY_H_
-
-#include "nsWrapperCache.h"
-#include "WebGLObjectModel.h"
+#include "WebGL2Context.h"
+#include "WebGLContextUtils.h"
 
 namespace mozilla {
 
-class WebGLTimerQuery final
-  : public nsWrapperCache
-  , public WebGLRefCountedObject<WebGLTimerQuery>
-  , public WebGLContextBoundObject
+JS::Value
+WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
 {
-public:
-  static WebGLTimerQuery* Create(WebGLContext* webgl);
+  // The following cases are handled in WebGLContext::GetParameter():
+  //     case LOCAL_GL_MAX_COLOR_ATTACHMENTS:
+  //     case LOCAL_GL_MAX_DRAW_BUFFERS:
+  //     case LOCAL_GL_DRAW_BUFFERi:
+
+  if (IsContextLost())
+    return JS::NullValue();
+
+  MakeContextCurrent();
 
-  void Delete();
+  switch (pname) {
+    /* GLboolean */
+    case LOCAL_GL_RASTERIZER_DISCARD:
+    case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
+    case LOCAL_GL_SAMPLE_COVERAGE:
+    case LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED:
+    case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE:
+    case LOCAL_GL_UNPACK_SKIP_IMAGES:
+    case LOCAL_GL_UNPACK_SKIP_PIXELS:
+    case LOCAL_GL_UNPACK_SKIP_ROWS: {
+      realGLboolean b = 0;
+      gl->fGetBooleanv(pname, &b);
+      return JS::BooleanValue(bool(b));
+    }
+
+    /* GLenum */
+    case LOCAL_GL_READ_BUFFER: {
+      if (mBoundReadFramebuffer) {
+        GLint val = LOCAL_GL_NONE;
+        gl->fGetIntegerv(pname, &val);
+        return JS::Int32Value(val);
+      }
+
+      return JS::Int32Value(LOCAL_GL_BACK);
+    }
+
+    case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
+      /* fall through */
 
-  bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
-  GLenum Target() const { return mTarget; }
+    /* GLint */
+    case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
+    case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
+    case LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS:
+    case LOCAL_GL_MAX_ELEMENTS_INDICES:
+    case LOCAL_GL_MAX_ELEMENTS_VERTICES:
+    case LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+    case LOCAL_GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+    case LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+    case LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET:
+    case LOCAL_GL_MAX_SAMPLES:
+    case LOCAL_GL_MAX_TEXTURE_LOD_BIAS:
+    case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+    case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+    case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+    case LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS:
+    case LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+    case LOCAL_GL_MAX_VERTEX_UNIFORM_BLOCKS:
+    case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+    case LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET:
+    case LOCAL_GL_PACK_ROW_LENGTH:
+    case LOCAL_GL_PACK_SKIP_PIXELS:
+    case LOCAL_GL_PACK_SKIP_ROWS:
+    case LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+    case LOCAL_GL_UNPACK_IMAGE_HEIGHT:
+    case LOCAL_GL_UNPACK_ROW_LENGTH: {
+      GLint val;
+      gl->fGetIntegerv(pname, &val);
+      return JS::Int32Value(val);
+    }
 
-  WebGLContext* GetParentObject() const;
+    case LOCAL_GL_MAX_VARYING_COMPONENTS: {
+      // On OS X Core Profile this is buggy.  The spec says that the
+      // value is 4 * GL_MAX_VARYING_VECTORS
+      GLint val;
+      gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &val);
+      return JS::Int32Value(4*val);
+    }
 
-  // NS
-  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
+    /* GLint64 */
+    case LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL:
+      return JS::NumberValue(0); // TODO
+
+    case LOCAL_GL_MAX_ELEMENT_INDEX:
+      // GL_MAX_ELEMENT_INDEX becomes available in GL 4.3 or via ES3
+      // compatibility
+      if (!gl->IsSupported(gl::GLFeature::ES3_compatibility))
+        return JS::NumberValue(0);
+
+      /*** fall through to fGetInteger64v ***/
+
+    case LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+    case LOCAL_GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+    case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE: {
+      GLint64 val;
+      gl->fGetInteger64v(pname, &val);
+      return JS::DoubleValue(static_cast<double>(val));
+    }
 
-  const GLenum mGLName;
+
+    /* GLuint64 */
+    case LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT: {
+      GLuint64 val;
+      gl->fGetInteger64v(pname, (GLint64*) &val);
+      return JS::DoubleValue(static_cast<double>(val));
+    }
 
-  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTimerQuery)
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTimerQuery)
+    case LOCAL_GL_COPY_READ_BUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundCopyReadBuffer.get(), rv);
+
+    case LOCAL_GL_COPY_WRITE_BUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundCopyWriteBuffer.get(), rv);
+
+    case LOCAL_GL_PIXEL_PACK_BUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundPixelPackBuffer.get(), rv);
+
+    case LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundPixelUnpackBuffer.get(), rv);
 
-private:
-  explicit WebGLTimerQuery(WebGLContext* webgl, GLuint aName);
-  ~WebGLTimerQuery();
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
+
+    case LOCAL_GL_UNIFORM_BUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundUniformBuffer.get(), rv);
+
+    // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
+    case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv);
+
+    case LOCAL_GL_SAMPLER_BINDING:
+      return WebGLObjectAsJSValue(cx, mBoundSamplers[mActiveTexture].get(), rv);
+
+    case LOCAL_GL_TEXTURE_BINDING_2D_ARRAY:
+      // TODO: Implement gl.TEXTURE_2D_ARRAY
+      // return WebGLObjectAsJSValue(cx, mBound2DTextureArrays[mActiveTexture].get(), rv);
+      return JS::NullValue();
+
+    case LOCAL_GL_TEXTURE_BINDING_3D:
+      return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
 
-  GLenum mTarget;
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BINDING: {
+      WebGLTransformFeedback* tf =
+        (mBoundTransformFeedback != mDefaultTransformFeedback) ? mBoundTransformFeedback.get() : nullptr;
+      return WebGLObjectAsJSValue(cx, tf, rv);
+    }
 
-  friend class WebGLExtensionDisjointTimerQuery;
-};
+    case LOCAL_GL_VERTEX_ARRAY_BINDING: {
+      WebGLVertexArray* vao =
+        (mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
+      return WebGLObjectAsJSValue(cx, vao, rv);
+    }
+
+    case LOCAL_GL_VERSION:
+      return StringValue(cx, "WebGL 2.0", rv);
+
+    case LOCAL_GL_SHADING_LANGUAGE_VERSION:
+      return StringValue(cx, "WebGL GLSL ES 3.00", rv);
+
+    default:
+      return WebGLContext::GetParameter(cx, pname, rv);
+  }
+}
 
 } // namespace mozilla
-
-#endif // WEBGL_TIMER_QUERY_H_
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -320,16 +320,17 @@ WebGLContext::DestroyResourcesAndContext
     if (!gl)
         return;
 
     gl->MakeCurrent();
 
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
     mBound3DTextures.Clear();
+    mBoundSamplers.Clear();
     mBoundArrayBuffer = nullptr;
     mBoundCopyReadBuffer = nullptr;
     mBoundCopyWriteBuffer = nullptr;
     mBoundPixelPackBuffer = nullptr;
     mBoundPixelUnpackBuffer = nullptr;
     mBoundTransformFeedbackBuffer = nullptr;
     mBoundUniformBuffer = nullptr;
     mCurrentProgram = nullptr;
@@ -1944,16 +1945,17 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLCon
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
   mCanvasElement,
   mExtensions,
   mBound2DTextures,
   mBoundCubeMapTextures,
   mBound3DTextures,
+  mBoundSamplers,
   mBoundArrayBuffer,
   mBoundCopyReadBuffer,
   mBoundCopyWriteBuffer,
   mBoundPixelPackBuffer,
   mBoundPixelUnpackBuffer,
   mBoundTransformFeedbackBuffer,
   mBoundUniformBuffer,
   mCurrentProgram,
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -60,16 +60,26 @@ class nsIDocShell;
 #define MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS      16    // Page 164
 #define MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS        128   // Page 164
 #define MINVALUE_GL_MAX_VARYING_VECTORS               8     // Page 164
 #define MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS           8     // Page 164
 #define MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS    0     // Page 164
 #define MINVALUE_GL_MAX_RENDERBUFFER_SIZE             1024  // Different from the spec, which sets it to 1 on page 164
 #define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS  8     // Page 164
 
+/*
+ * WebGL-only GLenums
+ */
+#define LOCAL_GL_BROWSER_DEFAULT_WEBGL                       0x9244
+#define LOCAL_GL_CONTEXT_LOST_WEBGL                          0x9242
+#define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL               0x9247
+#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL          0x9243
+#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL                         0x9240
+#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL              0x9241
+
 namespace mozilla {
 
 class WebGLActiveInfo;
 class WebGLContextLossHandler;
 class WebGLBuffer;
 class WebGLExtensionBase;
 class WebGLFramebuffer;
 class WebGLObserver;
@@ -950,17 +960,17 @@ protected:
     WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery;
 
 // -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 public:
     void Disable(GLenum cap);
     void Enable(GLenum cap);
     bool GetStencilBits(GLint* out_stencilBits);
-    JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
+    virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
 
     void GetParameter(JSContext* cx, GLenum pname,
                       JS::MutableHandle<JS::Value> retval, ErrorResult& rv)
     {
         retval.set(GetParameter(cx, pname, rv));
     }
 
     void GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
@@ -1430,16 +1440,17 @@ protected:
                              TexType type, const GLvoid* data);
 
     void ForceLoseContext(bool simulateLoss = false);
     void ForceRestoreContext();
 
     nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
     nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
     nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
+    nsTArray<WebGLRefPtr<WebGLSampler> > mBoundSamplers;
 
     void ResolveTexturesForDraw() const;
 
     WebGLRefPtr<WebGLProgram> mCurrentProgram;
     RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
 
     uint32_t mMaxFramebufferColorAttachments;
 
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -53,28 +53,16 @@ WebGLContext::Enable(GLenum cap)
     {
         *trackingSlot = 1;
     }
 
     MakeContextCurrent();
     gl->fEnable(cap);
 }
 
-static JS::Value
-StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
-{
-    JSString* str = JS_NewStringCopyZ(cx, chars);
-    if (!str) {
-        rv.Throw(NS_ERROR_OUT_OF_MEMORY);
-        return JS::NullValue();
-    }
-
-    return JS::StringValue(str);
-}
-
 bool
 WebGLContext::GetStencilBits(GLint* out_stencilBits)
 {
     *out_stencilBits = 0;
     if (mBoundDrawFramebuffer) {
         if (mBoundDrawFramebuffer->HasDepthStencilConflict()) {
             // Error, we don't know which stencil buffer's bits to use
             ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
@@ -145,136 +133,99 @@ WebGLContext::GetParameter(JSContext* cx
             return JS::Int32Value(mGLMaxColorAttachments);
 
         } else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
             return JS::Int32Value(mGLMaxDrawBuffers);
 
         } else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
                    pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
         {
-            if (mBoundDrawFramebuffer) {
-                GLint iv = 0;
-                gl->fGetIntegerv(pname, &iv);
-                return JS::Int32Value(iv);
-            }
-
             GLint iv = 0;
             gl->fGetIntegerv(pname, &iv);
 
-            if (iv == GLint(LOCAL_GL_COLOR_ATTACHMENT0 + pname - LOCAL_GL_DRAW_BUFFER0)) {
+            if (mBoundDrawFramebuffer)
+                return JS::Int32Value(iv);
+
+            const GLint index = (pname - LOCAL_GL_DRAW_BUFFER0);
+            if (iv == LOCAL_GL_COLOR_ATTACHMENT0 + index)
                 return JS::Int32Value(LOCAL_GL_BACK);
-            }
 
             return JS::Int32Value(LOCAL_GL_NONE);
         }
     }
 
     if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
         if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
-            if (mBoundVertexArray == mDefaultVertexArray){
-                return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
-            }
-
-            return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
+            WebGLVertexArray* vao =
+                (mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
+            return WebGLObjectAsJSValue(cx, vao, rv);
         }
     }
 
     if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
         if (pname == LOCAL_GL_TIMESTAMP_EXT) {
             GLuint64 iv = 0;
             gl->fGetInteger64v(pname, (GLint64*) &iv);
-            return JS::NumberValue(uint64_t(iv));
+            // TODO: JS doesn't support 64-bit integers. Be lossy and
+            // cast to double (53 bits)
+            return JS::NumberValue(static_cast<double>(iv));
         } else if (pname == LOCAL_GL_GPU_DISJOINT_EXT) {
             // When disjoint isn't supported, leave as false.
-            realGLboolean disjoint = 0;
+            realGLboolean disjoint = LOCAL_GL_FALSE;
             if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
                 gl->fGetBooleanv(pname, &disjoint);
             }
             return JS::BooleanValue(bool(disjoint));
         }
     }
 
-    if (IsWebGL2()) {
+    // Privileged string params exposed by WEBGL_debug_renderer_info:
+    if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
         switch (pname) {
-        case LOCAL_GL_MAX_SAMPLES:
-        case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE:
-        case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: {
-            GLint val;
-            gl->fGetIntegerv(pname, &val);
-            return JS::NumberValue(uint32_t(val));
+        case UNMASKED_VENDOR_WEBGL:
+        case UNMASKED_RENDERER_WEBGL:
+            GLenum glstringname = LOCAL_GL_NONE;
+            if (pname == UNMASKED_VENDOR_WEBGL) {
+                glstringname = LOCAL_GL_VENDOR;
+            } else if (pname == UNMASKED_RENDERER_WEBGL) {
+                glstringname = LOCAL_GL_RENDERER;
+            }
+            const GLchar* string = (const GLchar*) gl->fGetString(glstringname);
+            return StringValue(cx, string, rv);
         }
-
-        case LOCAL_GL_TEXTURE_BINDING_3D:
-            return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
-
-        // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
-        case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv);
+    }
 
-        case LOCAL_GL_PIXEL_PACK_BUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundPixelPackBuffer.get(), rv);
-
-        case LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundPixelUnpackBuffer.get(), rv);
-
-        case LOCAL_GL_UNIFORM_BUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundUniformBuffer.get(), rv);
+    if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
+        if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
+            GLint i = 0;
+            gl->fGetIntegerv(pname, &i);
+            return JS::Int32Value(i);
+        }
+    }
 
-        case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
-
-        case LOCAL_GL_COPY_READ_BUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundCopyReadBuffer.get(), rv);
-
-        case LOCAL_GL_COPY_WRITE_BUFFER_BINDING:
-            return WebGLObjectAsJSValue(cx, mBoundCopyWriteBuffer.get(), rv);
+    if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
+        if (pname == LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) {
+            GLfloat f = 0.f;
+            gl->fGetFloatv(pname, &f);
+            return JS::NumberValue(f);
         }
     }
 
     switch (pname) {
         //
         // String params
         //
         case LOCAL_GL_VENDOR:
-            return StringValue(cx, "Mozilla", rv);
         case LOCAL_GL_RENDERER:
             return StringValue(cx, "Mozilla", rv);
-        case LOCAL_GL_VERSION: {
-            const char* version = 0;
-
-            if (IsWebGL2()) {
-                version = "WebGL 2.0";
-            } else {
-                version = "WebGL 1.0";
-            }
-
-            MOZ_ASSERT(version != 0);
-            return StringValue(cx, version, rv);
-        }
+        case LOCAL_GL_VERSION:
+            return StringValue(cx, "WebGL 1.0", rv);
         case LOCAL_GL_SHADING_LANGUAGE_VERSION:
             return StringValue(cx, "WebGL GLSL ES 1.0", rv);
 
-            // Privileged string params exposed by WEBGL_debug_renderer_info:
-        case UNMASKED_VENDOR_WEBGL:
-        case UNMASKED_RENDERER_WEBGL: {
-            // The privilege check is done in WebGLContext::IsExtensionSupported.
-            // So here we just have to check that the extension is enabled.
-            if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
-                break;
-            }
-            GLenum glstringname = LOCAL_GL_NONE;
-            if (pname == UNMASKED_VENDOR_WEBGL) {
-                glstringname = LOCAL_GL_VENDOR;
-            } else if (pname == UNMASKED_RENDERER_WEBGL) {
-                glstringname = LOCAL_GL_RENDERER;
-            }
-            const char* string = reinterpret_cast<const char*>(gl->fGetString(glstringname));
-            return StringValue(cx, string, rv);
-        }
-
         ////////////////////////////////
         // Single-value params
 
         // unsigned int
         case LOCAL_GL_CULL_FACE_MODE:
         case LOCAL_GL_FRONT_FACE:
         case LOCAL_GL_ACTIVE_TEXTURE:
         case LOCAL_GL_STENCIL_FUNC:
@@ -375,25 +326,16 @@ WebGLContext::GetParameter(JSContext* cx
         }
         case LOCAL_GL_ALPHA_BITS: {
             GLint i = 0;
             if (!mNeedsFakeNoAlpha) {
                 gl->fGetIntegerv(pname, &i);
             }
             return JS::Int32Value(i);
         }
-        case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
-            if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
-                GLint i = 0;
-                gl->fGetIntegerv(pname, &i);
-                return JS::Int32Value(i);
-            } else {
-                break;
-            }
-        }
         case LOCAL_GL_MAX_TEXTURE_SIZE:
             return JS::Int32Value(mGLMaxTextureSize);
 
         case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
             return JS::Int32Value(mGLMaxCubeMapTextureSize);
 
         case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
             return JS::Int32Value(mGLMaxRenderbufferSize);
@@ -412,48 +354,32 @@ WebGLContext::GetParameter(JSContext* cx
         case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS: {
             uint32_t length = mCompressedTextureFormats.Length();
             JSObject* obj = Uint32Array::Create(cx, this, length, mCompressedTextureFormats.Elements());
             if (!obj) {
                 rv = NS_ERROR_OUT_OF_MEMORY;
             }
             return JS::ObjectOrNullValue(obj);
         }
-        case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: {
-            if (!IsWebGL2()) {
-                break;
-            }
-            return JS::Int32Value(mGLMaxTransformFeedbackSeparateAttribs);
-        }
 
         // unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
         // javascript integer values. We just return them as doubles and javascript doesn't care.
-        case LOCAL_GL_STENCIL_BACK_VALUE_MASK: {
+        case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
             return JS::DoubleValue(mStencilValueMaskBack); // pass as FP value to allow large values such as 2^32-1.
-        }
-        case LOCAL_GL_STENCIL_BACK_WRITEMASK: {
+
+        case LOCAL_GL_STENCIL_BACK_WRITEMASK:
             return JS::DoubleValue(mStencilWriteMaskBack);
-        }
-        case LOCAL_GL_STENCIL_VALUE_MASK: {
+
+        case LOCAL_GL_STENCIL_VALUE_MASK:
             return JS::DoubleValue(mStencilValueMaskFront);
-        }
-        case LOCAL_GL_STENCIL_WRITEMASK: {
+
+        case LOCAL_GL_STENCIL_WRITEMASK:
             return JS::DoubleValue(mStencilWriteMaskFront);
-        }
 
         // float
-        case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: {
-            if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
-                GLfloat f = 0.f;
-                gl->fGetFloatv(pname, &f);
-                return JS::DoubleValue(f);
-            } else {
-                break;
-            }
-        }
         case LOCAL_GL_DEPTH_CLEAR_VALUE:
         case LOCAL_GL_LINE_WIDTH:
         case LOCAL_GL_POLYGON_OFFSET_FACTOR:
         case LOCAL_GL_POLYGON_OFFSET_UNITS:
         case LOCAL_GL_SAMPLE_COVERAGE_VALUE: {
             GLfloat f = 0.f;
             gl->fGetFloatv(pname, &f);
             return JS::DoubleValue(f);
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -70,16 +70,28 @@ TexImageTargetToTexTarget(TexImageTarget
         return LOCAL_GL_TEXTURE_CUBE_MAP;
     default:
         MOZ_ASSERT(false, "Bad texture target");
         // Should be caught by the constructor for TexTarget
         return LOCAL_GL_NONE;
     }
 }
 
+JS::Value
+StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
+{
+    JSString* str = JS_NewStringCopyZ(cx, chars);
+    if (!str) {
+        rv.Throw(NS_ERROR_OUT_OF_MEMORY);
+        return JS::NullValue();
+    }
+
+    return JS::StringValue(str);
+}
+
 GLComponents::GLComponents(TexInternalFormat internalformat)
 {
     TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
     mComponents = 0;
 
     switch (unsizedformat.get()) {
     case LOCAL_GL_RGBA:
     case LOCAL_GL_RGBA4:
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -51,16 +51,19 @@ size_t GetBitsPerTexel(TexInternalFormat
 //
 // This function converts the texture image target to the texture target a.k.a.
 // binding location. The returned binding location can be used to check that
 // the currently bound texture is appropriate for this texImageTarget.
 //
 // Returns GL_NONE if passed an invalid texture image target
 TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
 
+// Helper function to create a JS::Value from a C string
+JS::Value StringValue(JSContext* cx, const char* str, ErrorResult& rv);
+
 struct GLComponents
 {
     unsigned char mComponents;
 
     enum Components {
         Red     = (1 << 0),
         Green   = (1 << 1),
         Blue    = (1 << 2),
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -1750,16 +1750,17 @@ WebGLContext::InitAndValidateGL()
     mActiveTexture = 0;
     mEmitContextLostErrorOnce = true;
     mWebGLError = LOCAL_GL_NO_ERROR;
     mUnderlyingGLError = LOCAL_GL_NO_ERROR;
 
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
     mBound3DTextures.Clear();
+    mBoundSamplers.Clear();
 
     mBoundArrayBuffer = nullptr;
     mBoundTransformFeedbackBuffer = nullptr;
     mCurrentProgram = nullptr;
 
     mBoundDrawFramebuffer = nullptr;
     mBoundReadFramebuffer = nullptr;
     mBoundRenderbuffer = nullptr;
@@ -1793,16 +1794,17 @@ WebGLContext::InitAndValidateGL()
         GenerateWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!",
                         mGLMaxTextureUnits);
         return false;
     }
 
     mBound2DTextures.SetLength(mGLMaxTextureUnits);
     mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
     mBound3DTextures.SetLength(mGLMaxTextureUnits);
+    mBoundSamplers.SetLength(mGLMaxTextureUnits);
 
     if (MinCapabilityMode()) {
         mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;
         mGLMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
         mGLMaxRenderbufferSize = MINVALUE_GL_MAX_RENDERBUFFER_SIZE;
         mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
         mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
         mGLMaxSamples = 1;
--- a/dom/canvas/WebGLTimerQuery.h
+++ b/dom/canvas/WebGLTimerQuery.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef WEBGL_TIMER_QUERY_H_
 #define WEBGL_TIMER_QUERY_H_
 
+#include "GLConsts.h"
 #include "nsWrapperCache.h"
 #include "WebGLObjectModel.h"
 
 namespace mozilla {
 
 class WebGLTimerQuery final
   : public nsWrapperCache
   , public WebGLRefCountedObject<WebGLTimerQuery>
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -56,16 +56,17 @@ UNIFIED_SOURCES += [
     'WebGL2Context.cpp',
     'WebGL2ContextBuffers.cpp',
     'WebGL2ContextDraw.cpp',
     'WebGL2ContextFramebuffers.cpp',
     'WebGL2ContextMRTs.cpp',
     'WebGL2ContextPrograms.cpp',
     'WebGL2ContextQueries.cpp',
     'WebGL2ContextSamplers.cpp',
+    'WebGL2ContextState.cpp',
     'WebGL2ContextSync.cpp',
     'WebGL2ContextTextures.cpp',
     'WebGL2ContextTransformFeedback.cpp',
     'WebGL2ContextUniforms.cpp',
     'WebGL2ContextVAOs.cpp',
     'WebGLActiveInfo.cpp',
     'WebGLBuffer.cpp',
     'WebGLContext.cpp',
--- a/dom/canvas/test/mochitest.ini
+++ b/dom/canvas/test/mochitest.ini
@@ -244,8 +244,9 @@ skip-if = buildapp == 'mulet' || (builda
 [test_toDataURL_lowercase_ascii.html]
 [test_toDataURL_parameters.html]
 [test_windingRuleUndefined.html]
 [test_2d.fillText.gradient.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
 [test_2d_composite_canvaspattern_setTransform.html]
 [test_createPattern_broken.html]
 [test_setlinedash.html]
+[test_filter.html]
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/default-color.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'drop-shadow(0 10px)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/drop-shadow-transformed.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.scale(-1, -1);
+ctx.filter = 'drop-shadow(0 10px black)';
+ctx.fillRect(-75, -65, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/drop-shadow.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'drop-shadow(0 10px black)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/global-alpha-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.globalAlpha = 0.5;
+ctx.fillStyle = '#000';
+ctx.fillRect(25, 35, 50, 40);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/global-alpha.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'drop-shadow(0 10px black)';
+ctx.globalAlpha = 0.5;
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/global-composite-operation-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#000';
+ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
+ctx.fill();
+
+var tmp_canvas = canvas.cloneNode();
+var tmp_ctx = tmp_canvas.getContext('2d');
+tmp_ctx.fillStyle = '#0f0';
+tmp_ctx.fillRect(25, 25, 50, 50);
+tmp_ctx.fillStyle = '#000';
+tmp_ctx.fillRect(25, 65, 50, 10);
+
+ctx.globalCompositeOperation = 'source-in';
+ctx.drawImage(tmp_canvas, 0, 0);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/global-composite-operation.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#000';
+ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
+ctx.fill();
+
+ctx.filter = 'drop-shadow(0 10px black)';
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/liveness.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.font = '10px sans-serif';
+ctx.filter = 'drop-shadow(0 .5em black)';
+ctx.font = '20px sans-serif';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/multiple-drop-shadows.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.filter = 'drop-shadow(0 10px black) drop-shadow(10px 0 #ccc)';
+ctx.fillRect(20, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+ctx.fillStyle = '#000';
+ctx.fillRect(25, 65, 50, 10);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/reftest.list
@@ -0,0 +1,20 @@
+default-preferences pref(canvas.filters.enabled,true)
+
+== default-color.html ref.html
+== drop-shadow.html ref.html
+== drop-shadow-transformed.html ref.html
+== global-alpha.html global-alpha-ref.html
+== global-composite-operation.html global-composite-operation-ref.html
+== liveness.html ref.html
+== multiple-drop-shadows.html shadow-ref.html
+== shadow.html shadow-ref.html
+== subregion-fill-paint.html subregion-ref.html
+== subregion-stroke-paint.html subregion-ref.html
+== svg-bbox.html svg-bbox-ref.html
+== svg-inline.html ref.html
+== svg-liveness.html ref.html
+== svg-off-screen.html ref.html
+== units.html ref.html
+== units-em.html ref.html
+== units-ex.html ref.html
+== units-off-screen.html ref.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/shadow-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.shadowOffsetX = 10;
+ctx.shadowColor = '#ccc';
+ctx.fillRect(20, 25, 50, 40);
+ctx.fillStyle = '#000';
+ctx.fillRect(20, 65, 50, 10);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/shadow.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.filter = 'drop-shadow(0 10px black)';
+ctx.shadowOffsetX = 10;
+ctx.shadowColor = '#ccc';
+ctx.fillRect(20, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/subregion-fill-paint.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<body>
+<svg style="display: block; width: 0; height: 0">
+  <defs>
+    <filter id="merge" primitiveUnits="objectBoundingBox">
+      <feMerge x="25%" y="25%" width="50%" height="50%">
+        <feMergeNode in="SourceGraphic"/>
+        <feMergeNode in="FillPaint"/>
+      </feMerge>
+    </filter>
+  </defs>
+</svg>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'url(#merge)';
+ctx.fillStyle = '#0f0';
+ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
+ctx.fill();
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/subregion-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 50);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/subregion-stroke-paint.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<body>
+<svg style="display: block; width: 0; height: 0">
+  <defs>
+    <filter id="merge" primitiveUnits="objectBoundingBox">
+      <feMerge x="25%" y="25%" width="50%" height="50%">
+        <feMergeNode in="SourceGraphic"/>
+        <feMergeNode in="StrokePaint"/>
+      </feMerge>
+    </filter>
+  </defs>
+</svg>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'url(#merge)';
+ctx.strokeStyle = '#0f0';
+ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
+ctx.fill();
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/svg-bbox-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 100);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/svg-bbox.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<body>
+<svg style="display: block; width: 0; height: 0">
+  <defs>
+    <filter id="color-matrix">
+      <feColorMatrix type="matrix" in="SourceGraphic"
+        values="0 0 0 0 0 
+                0 0 0 0 255 
+                0 0 0 0 0 
+                0 0 0 0 255"/>
+    </filter>
+  </defs>
+</svg>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'url(#color-matrix)';
+ctx.fillStyle = '#fff';
+ctx.fillRect(25, 25, 50, 50);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/svg-inline.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<body>
+<svg style="display: block; width: 0; height: 0">
+  <defs>
+    <filter id="drop-shadow">
+      <feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
+      <feOffset dx="0" dy="10" result="offsetblur"/>
+      <feFlood flood-color="rgba(0,0,0,1)"/>
+      <feComposite in2="offsetblur" operator="in"/>
+      <feMerge>
+        <feMergeNode/>
+        <feMergeNode in="SourceGraphic"/>
+      </feMerge>
+    </filter>
+  </defs>
+</svg>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'url(#drop-shadow)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/svg-liveness.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+
+var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+svg.setAttribute('style', 'display: block; width: 0; height: 0');
+
+var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
+
+var dropShadowFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
+dropShadowFilter.setAttribute('id', 'drop-shadow');
+
+var gaussianFilter = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
+gaussianFilter.setAttribute('in', 'SourceAlpha');
+gaussianFilter.setAttribute('stdDeviation', '0');
+dropShadowFilter.appendChild(gaussianFilter);
+
+var offset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');
+offset.setAttribute('dx', '0');
+offset.setAttribute('dy', '0');
+offset.setAttribute('result', 'offsetblur');
+dropShadowFilter.appendChild(offset);
+
+var flood = document.createElementNS('http://www.w3.org/2000/svg', 'feFlood');
+flood.setAttribute('flood-color', 'rgba(0,0,0,1)');
+dropShadowFilter.appendChild(flood);
+
+var composite = document.createElementNS('http://www.w3.org/2000/svg', 'feComposite');
+composite.setAttribute('in2', 'offsetblur');
+composite.setAttribute('operator', 'in');
+dropShadowFilter.appendChild(composite);
+
+var merge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');
+var mergeNode = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
+merge.appendChild(mergeNode);
+
+var mergeNode = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
+mergeNode.setAttribute('in', 'SourceGraphic');
+merge.appendChild(mergeNode);
+dropShadowFilter.appendChild(merge);
+
+defs.appendChild(dropShadowFilter);
+svg.appendChild(defs);
+
+document.body.appendChild(svg);
+
+</script>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'url(#drop-shadow)';
+
+offset.setAttribute('dy', '10');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/svg-off-screen.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<body>
+<svg style="display: block; width: 0; height: 0">
+  <defs>
+    <filter id="drop-shadow">
+    <feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
+    <feOffset dx="0" dy="10" result="offsetblur"/>
+    <feFlood flood-color="rgba(0,0,0,1)"/>
+    <feComposite in2="offsetblur" operator="in"/>
+      <feMerge>
+        <feMergeNode/>
+        <feMergeNode in="SourceGraphic"/>
+      </feMerge>
+    </filter>
+  </defs>
+</svg>
+<script>
+
+var canvas = document.createElement('canvas');
+canvas.width = 100;
+canvas.height = 100;
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'url(#drop-shadow)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+document.body.appendChild(canvas);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/units-em.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.font = '20px sans-serif';
+ctx.filter = 'drop-shadow(0 .5em black)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 25, 40);
+
+canvas.style.fontSize = '5px';
+ctx.font = '4em sans-serif';
+ctx.filter = 'drop-shadow(0 .5em black)';
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/units-ex.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.font = '10px sans-serif';
+ctx.filter = 'drop-shadow(0 2ex black)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/units-off-screen.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+
+var canvas = document.createElement('canvas');
+canvas.width = 500;
+canvas.height = 500;
+canvas.style.width = '100px';
+canvas.style.height = '100px';
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'drop-shadow(0 50px black)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(125, 125, 250, 200);
+
+document.body.appendChild(canvas);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/units-pt.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'drop-shadow(0 10mm black)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(25, 25, 50, 40);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/reftest/filters/units.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="500" height="500" style="width: 100px; height: 100px"></canvas>
+<script>
+
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = 'drop-shadow(0 50px black)';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(125, 125, 250, 200);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/test_filter.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<script>
+
+SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
+
+  var canvas = document.createElement('canvas');
+  var ctx = canvas.getContext('2d');
+
+  is(ctx.filter, 'none', 'filter should intialy be set to \'none\'');
+  ctx.filter = 'blur(5px)';
+  is(ctx.filter, 'blur(5px)', 'valid filter should round-trip');
+
+  ctx.save();
+  ctx.filter = 'none';
+  is(ctx.filter, 'none', 'none should unset the filter');
+  ctx.restore();
+  is(ctx.filter, 'blur(5px)', 'filter should be part of the state');
+
+  ctx.filter = 'blur(10)';
+  is(ctx.filter, 'blur(5px)', 'invalid filter should be ignored');
+  ctx.filter = 'blur 10px';
+  is(ctx.filter, 'blur(5px)', 'syntax error should be ignored');
+
+  ctx.filter = 'inherit';
+  is(ctx.filter, 'blur(5px)', 'inherit should be ignored');
+  ctx.filter = 'initial';
+  is(ctx.filter, 'blur(5px)', 'initial should be ignored');
+
+  ctx.filter = '';
+  is(ctx.filter, 'blur(5px)', 'empty string should be ignored and not unset the filter');
+  ctx.filter = null;
+  is(ctx.filter, 'blur(5px)', 'null should be ignored and not unset the filter');
+  ctx.filter = undefined;
+  is(ctx.filter, 'blur(5px)', 'undefined should be ignored and not unset the filter');
+
+  SimpleTest.finish();
+  
+});
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
--- a/dom/events/test/test_all_synthetic_events.html
+++ b/dom/events/test/test_all_synthetic_events.html
@@ -422,16 +422,20 @@ const kEventConstructors = {
                                                                                   aProps.clientX, aProps.clientY,
                                                                                   aProps.ctrlKey, aProps.altKey, aProps.shiftKey, aProps.metaKey,
                                                                                   aProps.button, aProps.relatedTarget,
                                                                                   aProps.allowedDirections, aProps.direction, aProps.delta || 0.0,
                                                                                   aProps.clickCount);
                                                          return e;
                                                        },
                                              },
+  SpeechRecognitionError:                    { create: function (aName, aProps) {
+                                                         return new SpeechRecognitionError(aName, aProps);
+                                                       },
+                                             },
   SpeechRecognitionEvent:                    { create: function (aName, aProps) {
                                                          return new SpeechRecognitionEvent(aName, aProps);
                                                        },
                                              },
   SpeechSynthesisEvent:                      { create: function (aName, aProps) {
                                                          return new SpeechSynthesisEvent(aName, aProps);
                                                        },
                                              },
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -12,18 +12,16 @@
 #include "nsMappedAttributes.h"
 #include "nsSize.h"
 #include "nsIDocument.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsIScriptContext.h"
 #include "nsIURL.h"
 #include "nsIIOService.h"
 #include "nsIServiceManager.h"
-#include "nsIAppShell.h"
-#include "nsWidgetsCID.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsContainerFrame.h"
 #include "nsNodeInfoManager.h"
 #include "mozilla/MouseEvents.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIDOMWindow.h"
 #include "nsFocusManager.h"
@@ -48,18 +46,16 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 
 #include "nsLayoutUtils.h"
 
 #include "mozilla/Preferences.h"
 static const char *kPrefSrcsetEnabled = "dom.image.srcset.enabled";
 
-static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
-
 NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
 
 #ifdef DEBUG
 // Is aSubject a previous sibling of aNode.
 static bool IsPreviousSibling(nsINode *aSubject, nsINode *aNode)
 {
   if (aSubject == aNode) {
     return false;
@@ -877,25 +873,21 @@ void
 HTMLImageElement::QueueImageLoadTask()
 {
   // If loading is temporarily disabled, we don't want to queue tasks
   // that may then run when loading is re-enabled.
   if (!LoadingEnabled() || !this->OwnerDoc()->IsCurrentActiveDocument()) {
     return;
   }
 
-  // The task checks this to determine if it was the last queued event, so this
-  // implicitly cancels earlier tasks
-  mPendingImageLoadTask = new ImageLoadTask(this);
-  nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
-  if (appShell) {
-    appShell->RunInStableState(mPendingImageLoadTask);
-  } else {
-    MOZ_ASSERT(false, "expect appshell for HTMLImageElement");
-  }
+  nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this);
+  // The task checks this to determine if it was the last
+  // queued event, and so earlier tasks are implicitly canceled.
+  mPendingImageLoadTask = task;
+  nsContentUtils::RunInStableState(task.forget());
 }
 
 bool
 HTMLImageElement::HaveSrcsetOrInPicture()
 {
   if (IsSrcsetEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::srcset)) {
     return true;
   }
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -56,18 +56,16 @@
 #include "nsCORSListenerProxy.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsICachingChannel.h"
 #include "nsLayoutUtils.h"
 #include "nsVideoFrame.h"
 #include "Layers.h"
 #include <limits>
 #include "nsIAsyncVerifyRedirectCallback.h"
-#include "nsIAppShell.h"
-#include "nsWidgetsCID.h"
 #include "nsMediaFragmentURIParser.h"
 #include "nsURIHashKey.h"
 #include "nsJSUtils.h"
 #include "MediaStreamGraph.h"
 #include "nsIScriptError.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "mozilla/dom/MediaSource.h"
 #include "MediaMetadataManager.h"
@@ -753,23 +751,20 @@ public:
     // Silently cancel if our load has been cancelled.
     if (IsCancelled())
       return NS_OK;
     mRunnable->Run();
     return NS_OK;
   }
 };
 
-static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
-
 void HTMLMediaElement::RunInStableState(nsIRunnable* aRunnable)
 {
   nsCOMPtr<nsIRunnable> event = new nsSyncSection(this, aRunnable);
-  nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
-  appShell->RunInStableState(event);
+  nsContentUtils::RunInStableState(event.forget());
 }
 
 void HTMLMediaElement::QueueLoadFromSourceTask()
 {
   ChangeDelayLoadStatus(true);
   ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_LOADING);
   RunInStableState(
     NS_NewRunnableMethod(this, &HTMLMediaElement::LoadFromSourceChildren));
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -156,17 +156,22 @@ HTMLObjectElement::OnFocusBlurPlugin(Ele
   // Element that doesn't have a plugin running.  But if SetPluginFocused(true)
   // was just called for aElement while it had a plugin running, we want to
   // make sure nsIWidget::SetPluginFocused(false) gets called for it now, even
   // if aFocus is true.
   if (aFocus) {
     nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aElement);
     bool hasRunningPlugin = false;
     if (olc) {
-      olc->GetHasRunningPlugin(&hasRunningPlugin);
+      // nsIObjectLoadingContent::GetHasRunningPlugin() fails when
+      // nsContentUtils::IsCallerChrome() returns false (which it can do even
+      // when we're processing a trusted focus event).  We work around this by
+      // calling nsObjectLoadingContent::HasRunningPlugin() directly.
+      hasRunningPlugin =
+        static_cast<nsObjectLoadingContent*>(olc.get())->HasRunningPlugin();
     }
     if (!hasRunningPlugin) {
       aFocus = false;
     }
   }
 
   if (aFocus || aElement == sLastFocused) {
     if (!aFocus) {
--- a/dom/html/nsBrowserElement.cpp
+++ b/dom/html/nsBrowserElement.cpp
@@ -372,16 +372,72 @@ nsBrowserElement::GetContentDimensions(E
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
   return req.forget().downcast<DOMRequest>();
 }
 
 void
+nsBrowserElement::FindAll(const nsAString& aSearchString,
+                          BrowserFindCaseSensitivity aCaseSensitivity,
+                          ErrorResult& aRv)
+{
+  NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
+  NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
+
+  uint32_t caseSensitivity;
+  if (aCaseSensitivity == BrowserFindCaseSensitivity::Case_insensitive) {
+    caseSensitivity = nsIBrowserElementAPI::FIND_CASE_INSENSITIVE;
+  } else {
+    caseSensitivity = nsIBrowserElementAPI::FIND_CASE_SENSITIVE;
+  }
+
+  nsresult rv = mBrowserElementAPI->FindAll(aSearchString, caseSensitivity);
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+}
+
+void
+nsBrowserElement::FindNext(BrowserFindDirection aDirection,
+                          ErrorResult& aRv)
+{
+  NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
+  NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
+
+  uint32_t direction;
+  if (aDirection == BrowserFindDirection::Backward) {
+    direction = nsIBrowserElementAPI::FIND_BACKWARD;
+  } else {
+    direction = nsIBrowserElementAPI::FIND_FORWARD;
+  }
+
+  nsresult rv = mBrowserElementAPI->FindNext(direction);
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+}
+
+void
+nsBrowserElement::ClearMatch(ErrorResult& aRv)
+{
+  NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
+  NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
+
+  nsresult rv = mBrowserElementAPI->ClearMatch();
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+}
+
+void
 nsBrowserElement::AddNextPaintListener(BrowserElementNextPaintEventCallback& aListener,
                                        ErrorResult& aRv)
 {
   NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
 
   CallbackObjectHolder<BrowserElementNextPaintEventCallback,
                        nsIBrowserElementNextPaintListener> holder(&aListener);
   nsCOMPtr<nsIBrowserElementNextPaintListener> listener = holder.ToXPCOMCallback();
--- a/dom/html/nsBrowserElement.h
+++ b/dom/html/nsBrowserElement.h
@@ -15,16 +15,18 @@
 class nsFrameLoader;
 
 namespace mozilla {
 
 namespace dom {
 struct BrowserElementDownloadOptions;
 class BrowserElementNextPaintEventCallback;
 class DOMRequest;
+enum class BrowserFindCaseSensitivity: uint32_t;
+enum class BrowserFindDirection: uint32_t;
 } // namespace dom
 
 class ErrorResult;
 
 /**
  * A helper class for browser-element frames
  */
 class nsBrowserElement
@@ -75,16 +77,21 @@ public:
                 ErrorResult& aRv);
 
   void Zoom(float aZoom, ErrorResult& aRv);
 
   already_AddRefed<dom::DOMRequest> GetCanGoBack(ErrorResult& aRv);
   already_AddRefed<dom::DOMRequest> GetCanGoForward(ErrorResult& aRv);
   already_AddRefed<dom::DOMRequest> GetContentDimensions(ErrorResult& aRv);
 
+  void FindAll(const nsAString& aSearchString, dom::BrowserFindCaseSensitivity aCaseSensitivity,
+               ErrorResult& aRv);
+  void FindNext(dom::BrowserFindDirection aDirection, ErrorResult& aRv);
+  void ClearMatch(ErrorResult& aRv);
+
   void AddNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
                             ErrorResult& aRv);
   void RemoveNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
                                ErrorResult& aRv);
 
   already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive,
                                                          ErrorResult& aRv);
 
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -2513,16 +2513,17 @@ BackgroundCursorChild::HandleResponse(
   MOZ_ASSERT(mObjectStore);
   MOZ_ASSERT(!mStrongRequest);
   MOZ_ASSERT(!mStrongCursor);
 
   // XXX Fix this somehow...
   auto& response = const_cast<ObjectStoreCursorResponse&>(aResponse);
 
   StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
+  cloneReadInfo.mDatabase = mTransaction->Database();
 
   ConvertActorsToBlobs(mTransaction->Database(),
                        response.cloneInfo(),
                        cloneReadInfo.mFiles);
 
   nsRefPtr<IDBCursor> newCursor;
 
   if (mCursor) {
@@ -2574,16 +2575,17 @@ BackgroundCursorChild::HandleResponse(co
   MOZ_ASSERT(mIndex);
   MOZ_ASSERT(!mStrongRequest);
   MOZ_ASSERT(!mStrongCursor);
 
   // XXX Fix this somehow...
   auto& response = const_cast<IndexCursorResponse&>(aResponse);
 
   StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
+  cloneReadInfo.mDatabase = mTransaction->Database();
 
   ConvertActorsToBlobs(mTransaction->Database(),
                        aResponse.cloneInfo(),
                        cloneReadInfo.mFiles);
 
   nsRefPtr<IDBCursor> newCursor;
 
   if (mCursor) {
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -362,25 +362,24 @@ IDBFactory::AllowedForWindowInternal(nsP
   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
   MOZ_ASSERT(sop);
 
   nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
   if (NS_WARN_IF(!principal)) {
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  if (nsContentUtils::IsSystemPrincipal(principal)) {
-    principal.forget(aPrincipal);
-    return NS_OK;
+  bool isSystemPrincipal;
+  if (!AllowedForPrincipal(principal, &isSystemPrincipal)) {
+    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  bool isNullPrincipal;
-  if (NS_WARN_IF(NS_FAILED(principal->GetIsNullPrincipal(&isNullPrincipal))) ||
-      isNullPrincipal) {
-    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+  if (isSystemPrincipal) {
+    principal.forget(aPrincipal);
+    return NS_OK;
   }
 
   // Whitelist about:home, since it doesn't have a base domain it would not
   // pass the ThirdPartyUtil check, though it should be able to use indexedDB.
   bool skipThirdPartyCheck = false;
 
   nsCOMPtr<nsIURI> uri;
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(principal->GetURI(getter_AddRefs(uri))));
@@ -419,16 +418,46 @@ IDBFactory::AllowedForWindowInternal(nsP
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
   }
 
   principal.forget(aPrincipal);
   return NS_OK;
 }
 
+// static
+bool
+IDBFactory::AllowedForPrincipal(nsIPrincipal* aPrincipal,
+                                bool* aIsSystemPrincipal)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPrincipal);
+
+  if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) {
+    return false;
+  }
+
+  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
+    if (aIsSystemPrincipal) {
+      *aIsSystemPrincipal = true;
+    }
+    return true;
+  } else if (aIsSystemPrincipal) {
+    *aIsSystemPrincipal = false;
+  }
+
+  bool isNullPrincipal;
+  if (NS_WARN_IF(NS_FAILED(aPrincipal->GetIsNullPrincipal(&isNullPrincipal))) ||
+      isNullPrincipal) {
+    return false;
+  }
+
+  return true;
+}
+
 #ifdef DEBUG
 
 void
 IDBFactory::AssertIsOnOwningThread() const
 {
   MOZ_ASSERT(mOwningThread);
   MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
 }
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -100,16 +100,20 @@ public:
                   JS::Handle<JSObject*> aOwningObject,
                   const PrincipalInfo& aPrincipalInfo,
                   uint64_t aInnerWindowID,
                   IDBFactory** aFactory);
 
   static bool
   AllowedForWindow(nsPIDOMWindow* aWindow);
 
+  static bool
+  AllowedForPrincipal(nsIPrincipal* aPrincipal,
+                      bool* aIsSystemPrincipal = nullptr);
+
   void
   AssertIsOnOwningThread() const
 #ifdef DEBUG
   ;
 #else
   { }
 #endif
 
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -7,16 +7,18 @@ support-files =
   error_events_abort_transactions_iframe.html
   event_propagation_iframe.html
   exceptions_in_events_iframe.html
   file.js
   file_app_isolation.html
   file_app_isolation.js
   helpers.js
   leaving_page_iframe.html
+  service_worker.js
+  service_worker_client.html
   third_party_iframe1.html
   third_party_iframe2.html
   unit/test_add_put.js
   unit/test_add_twice_failure.js
   unit/test_advance.js
   unit/test_autoIncrement.js
   unit/test_autoIncrement_indexes.js
   unit/test_blob_file_backed.js
@@ -191,16 +193,19 @@ skip-if = (buildapp == 'b2g' && toolkit 
 # FileHandle is not supported in child processes.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
 [test_filehandle_compat.html]
 # FileHandle is not supported in child processes.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
 [test_filehandle_getFile.html]
 # FileHandle is not supported in child processes.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
+[test_filehandle_iteration.html]
+# FileHandle is not supported in child processes.
+skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
 [test_filehandle_lifetimes.html]
 # FileHandle is not supported in child processes.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
 [test_filehandle_lifetimes_nested.html]
 # FileHandle is not supported in child processes.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
 [test_filehandle_location.html]
 # FileHandle is not supported in child processes.
@@ -369,8 +374,10 @@ skip-if = buildapp == 'b2g' || buildapp 
 [test_webapp_clearBrowserData_inproc_oop.html]
 # The clearBrowserData tests are only supposed to run in the main process.
 # They currently time out on android.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'android'
 [test_webapp_clearBrowserData_oop_inproc.html]
 # The clearBrowserData tests are only supposed to run in the main process.
 # They currently time out on android.
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'android'
+[test_serviceworker.html]
+skip-if = buildapp == 'b2g'
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/service_worker.js
@@ -0,0 +1,10 @@
+onmessage = function(e) {
+  self.clients.matchAll().then(function(res) {
+    if (!res.length) {
+      dump("Error: no clients are currently controlled.\n");
+      return;
+    }
+    res[0].postMessage(indexedDB ? { available: true } :
+                                   { available: false });
+  });
+};
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/service_worker_client.html
@@ -0,0 +1,28 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>controlled page</title>
+<script class="testbody" type="text/javascript">
+  if (!parent) {
+      info("service_worker_client.html should not be launched directly!");
+  }
+
+  window.onload = function() {
+    navigator.serviceWorker.onmessage = function(msg) {
+      // Forward messages coming from the service worker to the test page.
+      parent.postMessage(msg.data, "*");
+    };
+    navigator.serviceWorker.ready.then(function(swr) {
+      parent.postMessage("READY", "*");
+    });
+  }
+</script>
+
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_filehandle_iteration.html
@@ -0,0 +1,77 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+  function testSteps()
+  {
+    const dbName = window.location.pathname;
+    const dbVersion = 1;
+    const objectStoreName = "foo";
+    const entryCount = 10;
+
+    let request = indexedDB.open(dbName, dbVersion);
+    request.onerror = errorHandler;
+    request.onupgradeneeded = grabEventAndContinueHandler;
+    request.onsuccess = unexpectedSuccessHandler;
+    let event = yield undefined;
+
+    is(event.type, "upgradeneeded", "Got correct event type");
+
+    let db = event.target.result;
+    db.onerror = errorHandler;
+
+    db.createObjectStore(objectStoreName, { autoIncrement: true });
+
+    request.onupgradeneeded = unexpectedSuccessHandler;
+    request.onsuccess = grabEventAndContinueHandler;
+    event = yield undefined;
+
+    is(event.type, "success", "Got correct event type");
+
+    request = db.createMutableFile("bar");
+    request.onsuccess = grabEventAndContinueHandler;
+    event = yield undefined;
+
+    let mutableFile = event.target.result;
+
+    let trans = db.transaction(objectStoreName, "readwrite");
+    let objectStore = trans.objectStore(objectStoreName);
+
+    for (let i = 0; i < entryCount; i++) {
+      request = objectStore.add(mutableFile);
+    }
+
+    let seenEntryCount = 0;
+
+    request = objectStore.openCursor().onsuccess = event => {
+      let cursor = event.target.result;
+      if (cursor) {
+        seenEntryCount++;
+        cursor.continue();
+      } else {
+        continueToNextStep();
+      }
+    }
+    yield undefined;
+
+    is(seenEntryCount, entryCount, "Correct entry count");
+
+    finishTest();
+    yield undefined;
+  }
+  </script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_serviceworker.html
@@ -0,0 +1,71 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1137245 - Allow IndexedDB usage in ServiceWorkers</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+  function simpleRegister() {
+    return navigator.serviceWorker.register("service_worker.js", {
+      scope: 'service_worker_client.html'
+    });
+  }
+
+  function testIndexedDBAvailable(sw) {
+    var p = new Promise(function(resolve, reject) {
+      window.onmessage = function(e) {
+        if (e.data === "READY") {
+          sw.active.postMessage("GO");
+          return;
+        }
+
+        if (!("available" in e.data)) {
+          ok(false, "Something went wrong");
+          reject();
+          return;
+        }
+
+        ok(e.data.available, "IndexedDB available in service worker.");
+        resolve();
+      }
+    });
+
+    var content = document.getElementById("content");
+    ok(content, "Parent exists.");
+
+    iframe = document.createElement("iframe");
+    iframe.setAttribute('src', "service_worker_client.html");
+    content.appendChild(iframe);
+
+    return p.then(() => content.removeChild(iframe));
+  }
+
+  function runTest() {
+    simpleRegister()
+      .then(testIndexedDBAvailable)
+      .then(SimpleTest.finish)
+      .catch(function(e) {
+        ok(false, "Some test failed with error " + e);
+        SimpleTest.finish();
+      });
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({"set": [
+    ["dom.serviceWorkers.enabled", true],
+    ["dom.serviceWorkers.testing.enabled", true]
+  ]}, runTest);
+</script>
+</pre>
+</body>
+</html>
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1699,19 +1699,21 @@ interface nsIDOMWindowUtils : nsISupport
    boolean isNodeDisabledForEvents(in nsIDOMNode aNode);
 
    /**
     * Setting paintFlashing to true will flash newly painted area.
     */
    attribute boolean paintFlashing;
 
    /**
-    * Allows running of a "synchronous section", in the form of an nsIRunnable
-    * once the event loop has reached a "stable state". We've reached a stable
-    * state when the currently executing task/event has finished, see:
+    * Add a "synchronous section", in the form of an nsIRunnable run once the
+    * event loop has reached a "stable state". |runnable| must not cause any
+    * queued events to be processed (i.e. must not spin the event loop).
+    * We've reached a stable state when the currently executing task/event has
+    * finished, see:
     * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
     * In practice this runs aRunnable once the currently executing event
     * finishes. If called multiple times per task/event, all the runnables will
     * be executed, in the order in which runInStableState() was called.
     *
     * XXX - This can wreak havoc if you're not using this for very simple
     * purposes, eg testing or setting a flag.
     */
--- a/dom/ipc/ContentBridgeChild.cpp
+++ b/dom/ipc/ContentBridgeChild.cpp
@@ -7,51 +7,64 @@
 #include "mozilla/dom/ContentBridgeChild.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/StructuredCloneUtils.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/ipc/InputStreamUtils.h"
+#include "nsIObserverService.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::jsipc;
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_ISUPPORTS(ContentBridgeChild, nsIContentChild)
+NS_IMPL_ISUPPORTS(ContentBridgeChild,
+                  nsIContentChild,
+                  nsIObserver)
 
 ContentBridgeChild::ContentBridgeChild(Transport* aTransport)
   : mTransport(aTransport)
 {}
 
 ContentBridgeChild::~ContentBridgeChild()
 {
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
 }
 
 void
 ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
 {
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    os->RemoveObserver(this, "content-child-shutdown");
+  }
   MessageLoop::current()->PostTask(
     FROM_HERE,
     NewRunnableMethod(this, &ContentBridgeChild::DeferredDestroy));
 }
 
 /*static*/ ContentBridgeChild*
 ContentBridgeChild::Create(Transport* aTransport, ProcessId aOtherPid)
 {
   nsRefPtr<ContentBridgeChild> bridge =
     new ContentBridgeChild(aTransport);
   bridge->mSelfRef = bridge;
 
   DebugOnly<bool> ok = bridge->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop());
   MOZ_ASSERT(ok);
+
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    os->AddObserver(bridge, "content-child-shutdown", false);
+  }
+
   return bridge;
 }
 
 void
 ContentBridgeChild::DeferredDestroy()
 {
   mSelfRef = nullptr;
   // |this| was just destroyed, hands off
@@ -162,10 +175,21 @@ ContentBridgeChild::AllocPBlobChild(cons
 }
 
 bool
 ContentBridgeChild::DeallocPBlobChild(PBlobChild* aActor)
 {
   return nsIContentChild::DeallocPBlobChild(aActor);
 }
 
+NS_IMETHODIMP
+ContentBridgeChild::Observe(nsISupports* aSubject,
+                             const char* aTopic,
+                             const char16_t* aData)
+{
+  if (!strcmp(aTopic, "content-child-shutdown")) {
+    Close();
+  }
+  return NS_OK;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentBridgeChild.h
+++ b/dom/ipc/ContentBridgeChild.h
@@ -4,27 +4,30 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_ContentBridgeChild_h
 #define mozilla_dom_ContentBridgeChild_h
 
 #include "mozilla/dom/PContentBridgeChild.h"
 #include "mozilla/dom/nsIContentChild.h"
+#include "nsIObserver.h"
 
 namespace mozilla {
 namespace dom {
 
 class ContentBridgeChild final : public PContentBridgeChild
                                , public nsIContentChild
+                               , public nsIObserver
 {
 public:
   explicit ContentBridgeChild(Transport* aTransport);
 
   NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
 
   static ContentBridgeChild*
   Create(Transport* aTransport, ProcessId aOtherProcess);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeferredDestroy();
 
   virtual bool RecvAsyncMessage(const nsString& aMsg,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2007,24 +2007,19 @@ ContentParent::ActorDestroy(ActorDestroy
                 // random child windows loaded in them.
                 //
                 // XXX would be nice if we could get both ...
                 if (!mAppManifestURL.IsEmpty()) {
                     crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
                                                        NS_ConvertUTF16toUTF8(mAppManifestURL));
                 }
 
-                if (mCreatedPairedMinidumps) {
-                    // We killed the child with KillHard, so two minidumps should already
-                    // exist - one for the content process, and one for the browser process.
-                    // The "main" minidump of this crash report is the content processes,
-                    // and we use GenerateChildData to annotate our crash report with
-                    // information about the child process.
-                    crashReporter->GenerateChildData(nullptr);
-                } else {
+                // if mCreatedPairedMinidumps is true, we've already generated
+                // parent/child dumps for dekstop crashes.
+                if (!mCreatedPairedMinidumps) {
                     crashReporter->GenerateCrashReport(this, nullptr);
                 }
 
                 nsAutoString dumpID(crashReporter->ChildDumpID());
                 props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
             }
 #endif
         }
@@ -2060,17 +2055,17 @@ ContentParent::ActorDestroy(ActorDestroy
     ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
     nsTArray<ContentParentId> childIDArray =
         cpm->GetAllChildProcessById(this->ChildID());
     for(uint32_t i = 0; i < childIDArray.Length(); i++) {
         ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
         MessageLoop::current()->PostTask(
             FROM_HERE,
             NewRunnableMethod(cp, &ContentParent::ShutDownProcess,
-                              CLOSE_CHANNEL));
+                              SEND_SHUTDOWN_MESSAGE));
     }
     cpm->RemoveContentProcess(this->ChildID());
 }
 
 void
 ContentParent::NotifyTabDestroying(PBrowserParent* aTab)
 {
     // There can be more than one PBrowser for a given app process
@@ -3383,47 +3378,43 @@ ContentParent::KillHard(const char* aRea
     // to crash our process - more details in bug 890840.
     if (mCalledKillHard) {
         return;
     }
     mCalledKillHard = true;
     mForceKillTimer = nullptr;
 
 #if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
+    // We're about to kill the child process associated with this content.
+    // Something has gone wrong to get us here, so we generate a minidump
+    // of the parent and child for submission to the crash server.
     if (ManagedPCrashReporterParent().Length() > 0) {
         CrashReporterParent* crashReporter =
             static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
-
-        // We're about to kill the child process associated with this
-        // ContentParent. Something has gone wrong to get us here,
-        // so we generate a minidump to be potentially submitted in
-        // a crash report. ContentParent::ActorDestroy is where the
-        // actual report gets generated, once the child process has
-        // finally died.
-        if (crashReporter->GeneratePairedMinidump(this)) {
-            mCreatedPairedMinidumps = true;
-            // GeneratePairedMinidump created two minidumps for us - the main
-            // one is for the content process we're about to kill, and the other
-            // one is for the main browser process. That second one is the extra
-            // minidump tagging along, so we have to tell the crash reporter that
-            // it exists and is being appended.
-            nsAutoCString additionalDumps("browser");
-            crashReporter->AnnotateCrashReport(
-                NS_LITERAL_CSTRING("additional_minidumps"),
-                additionalDumps);
-            if (IsKillHardAnnotationSet()) {
-              crashReporter->AnnotateCrashReport(
-                  NS_LITERAL_CSTRING("kill_hard"),
-                  GetKillHardAnnotation());
-            }
-            nsDependentCString reason(aReason);
-            crashReporter->AnnotateCrashReport(
-                NS_LITERAL_CSTRING("ipc_channel_error"),
-                reason);
+        // GeneratePairedMinidump creates two minidumps for us - the main
+        // one is for the content process we're about to kill, and the other
+        // one is for the main browser process. That second one is the extra
+        // minidump tagging along, so we have to tell the crash reporter that
+        // it exists and is being appended.
+        nsAutoCString additionalDumps("browser");
+        crashReporter->AnnotateCrashReport(
+            NS_LITERAL_CSTRING("additional_minidumps"),
+            additionalDumps);
+        if (IsKillHardAnnotationSet()) {
+          crashReporter->AnnotateCrashReport(
+              NS_LITERAL_CSTRING("kill_hard"),
+              GetKillHardAnnotation());
         }
+        nsDependentCString reason(aReason);
+        crashReporter->AnnotateCrashReport(
+            NS_LITERAL_CSTRING("ipc_channel_error"),
+            reason);
+
+        // Generate the report and insert into the queue for submittal.
+        mCreatedPairedMinidumps = crashReporter->GenerateCompleteMinidump(this);
     }
 #endif
     ProcessHandle otherProcessHandle;
     if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle)) {
         NS_ERROR("Failed to open child process when attempting kill.");
         return;
     }
 
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -106,16 +106,21 @@ CrashReporterParent::GenerateCrashReport
     return GenerateChildData(processNotes);
 }
 
 bool
 CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
 {
     MOZ_ASSERT(mInitialized);
 
+    if (mChildDumpID.IsEmpty()) {
+      NS_WARNING("problem with GenerateChildData: no child dump id yet!");
+      return false;
+    }
+
     nsAutoCString type;
     switch (mProcessType) {
         case GeckoProcessType_Content:
             type = NS_LITERAL_CSTRING("content");
             break;
         case GeckoProcessType_Plugin:
         case GeckoProcessType_GMPlugin:
             type = NS_LITERAL_CSTRING("plugin");
@@ -125,24 +130,45 @@ CrashReporterParent::GenerateChildData(c
             break;
     }
     mNotes.Put(NS_LITERAL_CSTRING("ProcessType"), type);
 
     char startTime[32];
     snprintf_literal(startTime, "%lld", static_cast<long long>(mStartTime));
     mNotes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime));
 
-    if (!mAppNotes.IsEmpty())
+    if (!mAppNotes.IsEmpty()) {
         mNotes.Put(NS_LITERAL_CSTRING("Notes"), mAppNotes);
+    }
 
+    // Append these notes to the end of the extra file based on the current
+    // dump id we obtained from CreatePairedMinidumps.
     bool ret = CrashReporter::AppendExtraData(mChildDumpID, mNotes);
-    if (ret && processNotes)
+    if (ret && processNotes) {
         ret = CrashReporter::AppendExtraData(mChildDumpID, *processNotes);
-    if (!ret)
+    }
+
+    if (!ret) {
         NS_WARNING("problem appending child data to .extra");
+    }
+
+    FinalizeChildData();
+    return ret;
+}
+
+void
+CrashReporterParent::FinalizeChildData()
+{
+    MOZ_ASSERT(mInitialized);
+
+    if (NS_IsMainThread()) {
+        // Inline, this is the main thread. Get this done.
+        NotifyCrashService();
+        return;
+    }
 
     nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
     class NotifyOnMainThread : public nsRunnable
     {
     public:
         explicit NotifyOnMainThread(CrashReporterParent* aCR)
             : mCR(aCR)
         { }
@@ -150,23 +176,23 @@ CrashReporterParent::GenerateChildData(c
         NS_IMETHOD Run() {
             mCR->NotifyCrashService();
             return NS_OK;
         }
     private:
         CrashReporterParent* mCR;
     };
     SyncRunnable::DispatchToThread(mainThread, new NotifyOnMainThread(this));
-    return ret;
 }
 
 void
 CrashReporterParent::NotifyCrashService()
 {
     MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(!mChildDumpID.IsEmpty());
 
     nsCOMPtr<nsICrashService> crashService =
         do_GetService("@mozilla.org/crashservice;1");
     if (!crashService) {
         return;
     }
 
     int32_t processType;
@@ -196,13 +222,14 @@ CrashReporterParent::NotifyCrashService(
             break;
         default:
             NS_ERROR("unknown process type");
             return;
     }
 
     crashService->AddCrash(processType, crashType, mChildDumpID);
     Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, telemetryKey, 1);
+    mNotes.Clear();
 }
 #endif
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/CrashReporterParent.h
+++ b/dom/ipc/CrashReporterParent.h
@@ -24,59 +24,132 @@ class CrashReporterParent :
 #ifdef MOZ_CRASHREPORTER
   typedef CrashReporter::AnnotationTable AnnotationTable;
 #endif
 public:
   CrashReporterParent();
   virtual ~CrashReporterParent();
 
 #ifdef MOZ_CRASHREPORTER
-  /* Attempt to generate a parent/child pair of minidumps from the given
-     toplevel actor in the event of a hang. Returns true if successful,
-     false otherwise.
-  */
+
+  /*
+   * Attempt to create a bare-bones crash report, along with extra process-
+   * specific annotations present in the given AnnotationTable.
+   *
+   * @returns true if successful, false otherwise.
+   */
+  template<class Toplevel>
+  bool
+  GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
+
+  /*
+   * Attempt to generate a parent/child pair of minidumps from the given
+   * toplevel actor. This calls CrashReporter::CreateMinidumpsAndPair to
+   * generate the minidumps. Crash reporter annotations set prior to this
+   * call will be saved via PairedDumpCallbackExtra into an .extra file
+   * under the proper crash id. AnnotateCrashReport annotations are not
+   * set in this call, use GenerateChildData.
+   *
+   * @returns true if successful, false otherwise.
+   */
   template<class Toplevel>
   bool
   GeneratePairedMinidump(Toplevel* t);
 
-  /* Attempt to create a bare-bones crash report, along with extra process-
-     specific annotations present in the given AnnotationTable. Returns true if
-     successful, false otherwise.
-  */
+  /*
+   * Attempts to take a minidump of the current process and pair that with
+   * a named minidump handed in by the caller.
+   *
+   * @param aTopLevel - top level actor this reporter is associated with.
+   * @param aMinidump - the minidump to associate with.
+   * @param aPairName - the name of the additional minidump.
+   * @returns true if successful, false otherwise.
+   */
   template<class Toplevel>
   bool
-  GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
+  GenerateMinidumpAndPair(Toplevel* aTopLevel, nsIFile* aMinidump,
+                          const nsACString& aPairName);
 
   /**
-   * Add the .extra data for an existing crash report.
+   * Apply child process annotations to an existing paired mindump generated
+   * with GeneratePairedMinidump.
+   *
+   * Be careful about calling generate apis immediately after this call,
+   * see FinalizeChildData.
+   *
+   * @param processNotes (optional) - Additional notes to append. Annotations
+   *   stored in mNotes will also be applied. processNotes can be null.
+   * @returns true if successful, false otherwise.
    */
   bool
   GenerateChildData(const AnnotationTable* processNotes);
 
+  /**
+   * Handles main thread finalization tasks after a report has been
+   * generated. Does the following:
+   *  - register the finished report with the crash service manager
+   *  - records telemetry related data about crashes
+   *
+   * Be careful about calling generate apis immediately after this call,
+   * if this api is called on a non-main thread it will fire off a runnable
+   * to complete its work async.
+   */
+  void
+  FinalizeChildData();
+
+  /*
+   * Attempt to generate a full paired dump complete with any child
+   * annoations, and finalizes the report. Note this call is only valid
+   * on the main thread. Calling on a background thread will fail.
+   *
+   * @returns true if successful, false otherwise.
+   */
+  template<class Toplevel>
+  bool
+  GenerateCompleteMinidump(Toplevel* t);
+
+  /**
+   * Submits a raw minidump handed in, calls GenerateChildData. Used
+   * by plugins.
+   *
+   * @returns true if successful, false otherwise.
+   */
   bool
   GenerateCrashReportForMinidump(nsIFile* minidump,
                                  const AnnotationTable* processNotes);
 
-  /* Instantiate a new crash reporter actor from a given parent that manages
-     the protocol.
-  */
+  /*
+   * Instantiate a new crash reporter actor from a given parent that manages
+   * the protocol.
+   *
+   * @returns true if successful, false otherwise.
+   */
   template<class Toplevel>
   static bool CreateCrashReporter(Toplevel* actor);
-#endif
-  /* Initialize this reporter with data from the child process */
+#endif // MOZ_CRASHREPORTER
+
+  /*
+   * Initialize this reporter with data from the child process.
+   */
   void
-    SetChildData(const NativeThreadId& id, const uint32_t& processType);
+  SetChildData(const NativeThreadId& id, const uint32_t& processType);
 
-  /* Returns the ID of the child minidump.
-     GeneratePairedMinidump or GenerateCrashReport must be called first.
-  */
+  /*
+   * Returns the ID of the child minidump.
+   * GeneratePairedMinidump or GenerateCrashReport must be called first.
+   */
   const nsString& ChildDumpID() {
     return mChildDumpID;
   }
 
+  /*
+   * Add an annotation to our internally tracked list of annotations.
+   * Callers must apply these notes using GenerateChildData otherwise
+   * the notes will get dropped.
+   */
   void
   AnnotateCrashReport(const nsCString& key, const nsCString& data);
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual bool
     RecvAnnotateCrashReport(const nsCString& key, const nsCString& data) override {
@@ -94,18 +167,20 @@ public:
   NotifyCrashService();
 #endif
 
 #ifdef MOZ_CRASHREPORTER
   AnnotationTable mNotes;
 #endif
   nsCString mAppNotes;
   nsString mChildDumpID;
+  // stores the child main thread id
   NativeThreadId mMainThread;
   time_t mStartTime;
+  // stores the child process type
   uint32_t mProcessType;
   bool mInitialized;
 };
 
 #ifdef MOZ_CRASHREPORTER
 template<class Toplevel>
 inline bool
 CrashReporterParent::GeneratePairedMinidump(Toplevel* t)
@@ -115,39 +190,100 @@ CrashReporterParent::GeneratePairedMinid
   child = t->Process()->GetChildTask();
 #else
   if (!base::OpenPrivilegedProcessHandle(t->OtherPid(), &child.rwget())) {
     NS_WARNING("Failed to open child process handle.");
     return false;
   }
 #endif
   nsCOMPtr<nsIFile> childDump;
-  if (CrashReporter::CreatePairedMinidumps(child,
-                                           mMainThread,
-                                           getter_AddRefs(childDump)) &&
+  if (CrashReporter::CreateMinidumpsAndPair(child,
+                                            mMainThread,
+                                            NS_LITERAL_CSTRING("browser"),
+                                            nullptr, // pair with a dump of this process and thread
+                                            getter_AddRefs(childDump)) &&
       CrashReporter::GetIDFromMinidump(childDump, mChildDumpID)) {
     return true;
   }
   return false;
 }
 
 template<class Toplevel>
 inline bool
+CrashReporterParent::GenerateMinidumpAndPair(Toplevel* aTopLevel,
+                                             nsIFile* aMinidumpToPair,
+                                             const nsACString& aPairName)
+{
+  mozilla::ipc::ScopedProcessHandle childHandle;
+#ifdef XP_MACOSX
+  childHandle = aTopLevel->Process()->GetChildTask();
+#else
+  if (!base::OpenPrivilegedProcessHandle(aTopLevel->OtherPid(), &childHandle.rwget())) {
+    NS_WARNING("Failed to open child process handle.");
+    return false;
+  }
+#endif
+  nsCOMPtr<nsIFile> targetDump;
+  if (CrashReporter::CreateMinidumpsAndPair(childHandle,
+                                            mMainThread, // child thread id
+                                            aPairName,
+                                            aMinidumpToPair,
+                                            getter_AddRefs(targetDump)) &&
+      CrashReporter::GetIDFromMinidump(targetDump, mChildDumpID)) {
+    return true;
+  }
+  return false;
+}
+
+template<class Toplevel>
+inline bool
 CrashReporterParent::GenerateCrashReport(Toplevel* t,
                                          const AnnotationTable* processNotes)
 {
   nsCOMPtr<nsIFile> crashDump;
   if (t->TakeMinidump(getter_AddRefs(crashDump), nullptr) &&
       CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
     return GenerateChildData(processNotes);
   }
   return false;
 }
 
 template<class Toplevel>
+inline bool
+CrashReporterParent::GenerateCompleteMinidump(Toplevel* t)
+{
+  mozilla::ipc::ScopedProcessHandle child;
+  if (!NS_IsMainThread()) {
+    NS_WARNING("GenerateCompleteMinidump can't be called on non-main thread.");
+    return false;
+  }
+
+#ifdef XP_MACOSX
+  child = t->Process()->GetChildTask();
+#else
+  if (!base::OpenPrivilegedProcessHandle(t->OtherPid(), &child.rwget())) {
+    NS_WARNING("Failed to open child process handle.");
+    return false;
+  }
+#endif
+  nsCOMPtr<nsIFile> childDump;
+  if (CrashReporter::CreateMinidumpsAndPair(child,
+                                            mMainThread,
+                                            NS_LITERAL_CSTRING("browser"),
+                                            nullptr, // pair with a dump of this process and thread
+                                            getter_AddRefs(childDump)) &&
+      CrashReporter::GetIDFromMinidump(childDump, mChildDumpID)) {
+    GenerateChildData(nullptr);
+    FinalizeChildData();
+    return true;
+  }
+  return false;
+}
+
+template<class Toplevel>
 /* static */ bool
 CrashReporterParent::CreateCrashReporter(Toplevel* actor)
 {
 #ifdef MOZ_CRASHREPORTER
   NativeThreadId id;
   uint32_t processType;
   PCrashReporterParent* p =
       actor->CallPCrashReporterConstructor(&id, &processType);
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -17,16 +17,19 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
 
 #include "nsIFrameLoader.h"
 #include "nsIHangReport.h"
 #include "nsITabParent.h"
 #include "nsPluginHost.h"
 #include "nsThreadUtils.h"
+#ifdef MOZ_CRASHREPORTER
+#include "nsExceptionHandler.h"
+#endif
 
 #include "base/task.h"
 #include "base/thread.h"
 
 #ifdef XP_WIN
 // For IsDebuggerPresent()
 #include <windows.h>
 #endif
@@ -144,30 +147,39 @@ public:
 
   NS_IMETHOD GetPluginName(nsACString& aPluginName) override;
 
   NS_IMETHOD TerminateScript() override;
   NS_IMETHOD BeginStartingDebugger() override;
   NS_IMETHOD EndStartingDebugger() override;
   NS_IMETHOD TerminatePlugin() override;
   NS_IMETHOD TerminateProcess() override;
+  NS_IMETHOD UserCanceled() override;
 
   NS_IMETHOD IsReportForBrowser(nsIFrameLoader* aFrameLoader, bool* aResult) override;
 
-  void Clear() { mContentParent = nullptr; mActor = nullptr; }
+  // Called on xpcom shutdown
+  void Clear() {
+    mContentParent = nullptr;
+    mActor = nullptr;
+  }
 
   void SetHangData(const HangData& aHangData) { mHangData = aHangData; }
+  void SetBrowserDumpId(nsAutoString& aId) {
+    mBrowserDumpId = aId;
+  }
 
 private:
   ~HangMonitoredProcess() {}
 
   // Everything here is main thread-only.
   HangMonitorParent* mActor;
   ContentParent* mContentParent;
   HangData mHangData;
+  nsAutoString mBrowserDumpId;
 };
 
 class HangMonitorParent
   : public PProcessHangMonitorParent
 {
 public:
   explicit HangMonitorParent(ProcessHangMonitor* aMonitor);
   virtual ~HangMonitorParent();
@@ -180,16 +192,17 @@ public:
 
   void SetProcess(HangMonitoredProcess* aProcess) { mProcess = aProcess; }
 
   void Shutdown();
 
   void TerminateScript();
   void BeginStartingDebugger();
   void EndStartingDebugger();
+  void CleanupPluginHang(uint32_t aPluginId, bool aRemoveFiles);
 
   MessageLoop* MonitorLoop() { return mHangMonitor->MonitorLoop(); }
 
  private:
   void ShutdownOnThread();
 
   const nsRefPtr<ProcessHangMonitor> mHangMonitor;
 
@@ -199,16 +212,19 @@ public:
   // This field is only accessed on the hang thread.
   bool mIPCOpen;
 
   Monitor mMonitor;
 
   // Must be accessed with mMonitor held.
   nsRefPtr<HangMonitoredProcess> mProcess;
   bool mShutdownDone;
+  // Map from plugin ID to crash dump ID. Protected by mBrowserCrashDumpHashLock.
+  nsDataHashtable<nsUint32HashKey, nsString> mBrowserCrashDumpIds;
+  Mutex mBrowserCrashDumpHashLock;
 };
 
 } // namespace
 
 template<>
 struct RunnableMethodTraits<HangMonitorChild>
 {
   typedef HangMonitorChild Class;
@@ -384,32 +400,35 @@ HangMonitorChild::IsDebuggerStartupCompl
   }
 
   return false;
 }
 
 void
 HangMonitorChild::NotifyPluginHang(uint32_t aPluginId)
 {
+  // main thread in the child
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   mSentReport = true;
 
+  // bounce to background thread
   MonitorLoop()->PostTask(
     FROM_HERE,
     NewRunnableMethod(this,
                       &HangMonitorChild::NotifyPluginHangAsync,
                       aPluginId));
 }
 
 void
 HangMonitorChild::NotifyPluginHangAsync(uint32_t aPluginId)
 {
   MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
 
+  // bounce back to parent on background thread
   if (mIPCOpen) {
     unused << SendHangEvidence(PluginHangData(aPluginId));
   }
 }
 
 void
 HangMonitorChild::ClearHang()
 {
@@ -425,17 +444,18 @@ HangMonitorChild::ClearHang()
 }
 
 /* HangMonitorParent implementation */
 
 HangMonitorParent::HangMonitorParent(ProcessHangMonitor* aMonitor)
  : mHangMonitor(aMonitor),
    mIPCOpen(true),
    mMonitor("HangMonitorParent lock"),
-   mShutdownDone(false)
+   mShutdownDone(false),
+   mBrowserCrashDumpHashLock("mBrowserCrashDumpIds lock")
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   mReportHangs = mozilla::Preferences::GetBool("dom.ipc.reportProcessHangs", false);
 }
 
 HangMonitorParent::~HangMonitorParent()
 {
   // For some reason IPDL doesn't autmatically delete the channel for a
@@ -496,60 +516,89 @@ HangMonitorParent::Open(Transport* aTran
 
   DebugOnly<bool> ok = PProcessHangMonitorParent::Open(aTransport, aPid, aIOLoop);
   MOZ_ASSERT(ok);
 }
 
 class HangObserverNotifier final : public nsRunnable
 {
 public:
-  HangObserverNotifier(HangMonitoredProcess* aProcess, const HangData& aHangData)
+  HangObserverNotifier(HangMonitoredProcess* aProcess,
+                       const HangData& aHangData,
+                       const nsString& aBrowserDumpId)
     : mProcess(aProcess),
-      mHangData(aHangData)
+      mHangData(aHangData),
+      mBrowserDumpId(aBrowserDumpId)
   {}
 
   NS_IMETHOD
   Run()
   {
+    // chrome process, main thread
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     mProcess->SetHangData(mHangData);
+    mProcess->SetBrowserDumpId(mBrowserDumpId);
 
     nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
     observerService->NotifyObservers(mProcess, "process-hang-report", nullptr);
     return NS_OK;
   }
 
 private:
   nsRefPtr<HangMonitoredProcess> mProcess;
   HangData mHangData;
+  nsAutoString mBrowserDumpId;
 };
 
 bool
 HangMonitorParent::RecvHangEvidence(const HangData& aHangData)
 {
+  // chrome process, background thread
   MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());