Merge autoland to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Thu, 10 Oct 2019 12:25:36 +0300
changeset 497153 f20fa8068ec25d685914a5945f2c54e36c89bc65
parent 497151 cad27f93a9869351457fc5d5290777420068e173 (current diff)
parent 497087 c4dedd2d757cca0313d4e25c64169e48173774d2 (diff)
child 497154 484a51c401efaa45353406c850788743a70727a7
child 497155 0086ca7236d5ca14613f5c09c02c50f17de00797
push id97692
push userccoroiu@mozilla.com
push dateThu, 10 Oct 2019 16:34:07 +0000
treeherderautoland@b0adb7067dff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone71.0a1
first release with
nightly linux32
f20fa8068ec2 / 71.0a1 / 20191010092637 / files
nightly linux64
f20fa8068ec2 / 71.0a1 / 20191010092637 / files
nightly mac
f20fa8068ec2 / 71.0a1 / 20191010092637 / files
nightly win32
f20fa8068ec2 / 71.0a1 / 20191010092637 / files
nightly win64
f20fa8068ec2 / 71.0a1 / 20191010092637 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central a=merge
devtools/server/startup/debug-new-process.js
testing/web-platform/meta/css/css-writing-modes/wm-propagation-body-scroll-offset-vertical-lr.html.ini
testing/web-platform/meta/css/css-writing-modes/wm-propagation-body-scroll-offset-vertical-rl.html.ini
third_party/rust/num-derive/build.rs
third_party/rust/target-lexicon-0.4.0/.cargo-checksum.json
third_party/rust/target-lexicon-0.4.0/Cargo.toml
third_party/rust/target-lexicon-0.4.0/LICENSE
third_party/rust/target-lexicon-0.4.0/README.md
third_party/rust/target-lexicon-0.4.0/build.rs
third_party/rust/target-lexicon-0.4.0/examples/misc.rs
third_party/rust/target-lexicon-0.4.0/src/host.rs
third_party/rust/target-lexicon-0.4.0/src/lib.rs
third_party/rust/target-lexicon-0.4.0/src/parse_error.rs
third_party/rust/target-lexicon-0.4.0/src/targets.rs
third_party/rust/target-lexicon-0.4.0/src/triple.rs
toolkit/components/satchel/AutoCompletePopup.jsm
toolkit/modules/AutoCompletePopupContent.jsm
tools/profiler/tests/browser/browser_test_profile_pushstate_page_info.js
tools/profiler/tests/browser/browser_test_profile_replacestate_page_info.js
tools/profiler/tests/browser/single_frame_pushstate.html
tools/profiler/tests/browser/single_frame_replacestate.html
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -155,17 +155,17 @@ dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "autocfg"
-version = "0.1.2"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "backtrace"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -696,59 +696,60 @@ version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser"
-version = "0.25.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cssparser-macros 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.25.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser-macros 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cstr"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cstr-macros 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cstr-macros 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cstr-macros"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb"
 version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1163,17 +1164,17 @@ dependencies = [
  "zip 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "nsstring 0.1.0",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.21.0",
@@ -1667,17 +1668,17 @@ dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2024,22 +2025,22 @@ dependencies = [
 name = "nsstring-gtest"
 version = "0.1.0"
 dependencies = [
  "nsstring 0.1.0",
 ]
 
 [[package]]
 name = "num-derive"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "num-integer"
 version = "0.1.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2073,22 +2074,22 @@ name = "num_cpus"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "object"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "opaque-debug"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -2147,20 +2148,20 @@ dependencies = [
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke-derive 0.2.0",
 ]
 
 [[package]]
 name = "peek-poke-derive"
 version = "0.2.0"
 dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "peeking_take_while"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -2284,17 +2285,17 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "profiler_helper"
 version = "0.1.0"
 dependencies = [
  "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "object 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "object 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "pulse"
 version = "0.2.0"
@@ -2331,17 +2332,17 @@ dependencies = [
  "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand"
 version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2349,17 +2350,17 @@ dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "rand_chacha"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand_core"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2410,17 +2411,17 @@ dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "rand_pcg"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand_xorshift"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2657,17 +2658,17 @@ dependencies = [
  "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "selectors"
 version = "0.21.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
@@ -2907,33 +2908,33 @@ name = "style"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
- "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2970,33 +2971,33 @@ dependencies = [
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
  "to_shmem 0.0.1",
  "to_shmem_derive 0.0.1",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.21.0",
@@ -3051,26 +3052,16 @@ dependencies = [
  "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "target-lexicon"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "target-lexicon"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3164,17 +3155,17 @@ dependencies = [
  "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "to_shmem"
 version = "0.0.1"
 dependencies = [
- "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "to_shmem_derive"
@@ -3821,17 +3812,17 @@ dependencies = [
 "checksum app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774"
 "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
 "checksum atomic 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c210c1f4db048cda477b652d170572d84c9640695835f17663595d3bd543fc28"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
 "checksum audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1e4aab7f57d8334168073cd0d0f11c7d1f7f3aabef84a1733a42629d0da80c"
 "checksum authenticator 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ec149e5d5d4caa2c9ead53a8ce1ea9c4204c388c65bf3b96c2d1dc0fcf4aeb66"
-"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
+"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
 "checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
 "checksum binjs_meta 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9a0da2208ceb785c1626fa8b7d250d2e5546ae230294b4a998e4f818c1768e"
 "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
@@ -3869,20 +3860,20 @@ dependencies = [
 "checksum cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
 "checksum cranelift-frontend 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
 "checksum cranelift-wasm 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
 "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
 "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
 "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
 "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
 "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
-"checksum cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a921abc45ea75c2c817d951caeda31b94539d09a6b5e8d58a857b3b35c9c3894"
-"checksum cssparser-macros 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b16e382d9b983fdb9ac6a36b37fdeb84ce3ea81f749febfee3463cfa7f24275e"
+"checksum cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fbe18ca4efb9ba3716c6da66cc3d7e673bf59fa576353011f48c4cfddbdd740e"
+"checksum cssparser-macros 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5bb1c84e87c717666564ec056105052331431803d606bd45529b28547b611eef"
 "checksum cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b6557bdb1dc9647eae1cf7f5601b14cd45fc3c7ccf2df618387416fe542da6ea"
-"checksum cstr-macros 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0f12dd847ec773fc98d75edba5394cb87d0f35e7ee548a4c81849ca6374b3d48"
+"checksum cstr-macros 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cd670e5ff58768ef624207fb95709ce63b8d05573fb9a05165f0eef471ea6a3a"
 "checksum cubeb 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "50f6a746cc3a80bdc96203e617d3bfc8988169c012c85c4ca4f1bad7862441bc"
 "checksum cubeb-backend 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "54c14a298d865c7f454dd809b2feb1fdb361b0a143f8ed2ea0b3a9becfa0a2ea"
 "checksum cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "20c6cde72d3505dc4f2452e0378b970b03d1fddf3ad8ac1b98dcb65fc7721907"
 "checksum cubeb-sys 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "318d9b60d6d5de52f815882ab5405adedc0ac7e91414950eff27a440c2860a3b"
 "checksum darling 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe629a532efad5526454efb0700f86d5ad7ff001acb37e431c8bf017a432a8e"
 "checksum darling_core 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ee54512bec54b41cf2337a22ddfadb53c7d4c738494dc2a186d7b037ad683b85"
 "checksum darling_macro 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cd3e432e52c0810b72898296a69d66b1d78d1517dff6cde7a130557a55a62c1"
 "checksum dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e1b39f3f6aa3d4a1522c4f0f9f1e9e9167bd93740a8690874caa7cf8ce47d7"
@@ -3973,23 +3964,23 @@ dependencies = [
 "checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
 "checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
 "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
 "checksum murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
 "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
 "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
-"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
+"checksum num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746"
 "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
 "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
 "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
 "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
 "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
-"checksum object 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec45bc6b810c6ee998e22953fbf387a40fcbf5014dcbb9e5ba9a09a81ee15"
+"checksum object 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81afbc5773e99efe9533d8a539dfac37e531dcd0f4eeb41584bae03ccf76d4c2"
 "checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682"
 "checksum ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0015e9e8e28ee20c581cfbfe47c650cedeb9ed0721090e0b7ebb10b9cdbcc2"
 "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
 "checksum packed_simd 0.3.3 (git+https://github.com/hsivonen/packed_simd?branch=rust_1_32)" = "<none>"
 "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
 "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
@@ -4071,17 +4062,16 @@ dependencies = [
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum svg_fmt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c666f0fed8e1e20e057af770af9077d72f3d5a33157b8537c1475dd8ffd6d32b"
 "checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"
 "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
 "checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203"
-"checksum target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0ab4982b8945c35cc1c46a83a9094c414f6828a099ce5dcaa8ee2b04642dcb"
 "checksum target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7975cb2c6f37d77b190bc5004a2bb015971464756fde9514651a525ada2a741a"
 "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 "checksum thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73fdf4b84c65a85168477b7fb6c498e0716bc9487fba24623389ea7f51708044"
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1627,19 +1627,19 @@ pref("browser.contentblocking.report.loc
 // Enable Protections report's Monitor card by default.
 pref("browser.contentblocking.report.monitor.enabled", true);
 
 // Disable Protections report's Proxy card by default.
 pref("browser.contentblocking.report.proxy.enabled", false);
 
 pref("browser.contentblocking.report.monitor.url", "https://monitor.firefox.com/?entrypoint=protection_report_monitor&utm_source=about-protections");
 pref("browser.contentblocking.report.monitor.sign_in_url", "https://monitor.firefox.com/oauth/init?entrypoint=protection_report_monitor&utm_source=about-protections&email=");
-pref("browser.contentblocking.report.lockwise.url", "https://lockwise.firefox.com/?entrypoint=protection_report_lockwise&utm_source=about-protections");
+pref("browser.contentblocking.report.lockwise.url", "https://lockwise.firefox.com/");
 pref("browser.contentblocking.report.manage_devices.url", "https://accounts.firefox.com/settings/clients");
-pref("browser.contentblocking.report.proxy_extension.url", "https://fpn.firefox.com/browser?entrypoint=protection_report_proxy&utm_source=about-protections");
+pref("browser.contentblocking.report.proxy_extension.url", "https://fpn.firefox.com/browser");
 
 // Protection Report's SUMO urls
 pref("browser.contentblocking.report.monitor.how_it_works.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/monitor-faq");
 pref("browser.contentblocking.report.lockwise.how_it_works.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/password-manager-report");
 pref("browser.contentblocking.report.social.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/social-media-tracking-report");
 pref("browser.contentblocking.report.cookie.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/cross-site-tracking-report");
 pref("browser.contentblocking.report.tracker.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/tracking-content-report");
 pref("browser.contentblocking.report.fingerprinter.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/fingerprinters-report");
@@ -1779,16 +1779,17 @@ pref("extensions.pocket.site", "getpocke
 
 pref("signon.generation.available", true);
 pref("signon.generation.enabled", true);
 pref("signon.schemeUpgrades", true);
 pref("signon.privateBrowsingCapture.enabled", true);
 pref("signon.showAutoCompleteFooter", true);
 pref("signon.management.page.enabled", true);
 pref("signon.management.page.breach-alerts.enabled", true);
+pref("signon.management.page.sort", "name");
 pref("signon.management.overrideURI", "about:logins?filter=%DOMAIN%");
 #ifdef NIGHTLY_BUILD
   // Bug 1563330 tracks shipping this by default.
   pref("signon.showAutoCompleteOrigins", true);
   pref("signon.includeOtherSubdomainsInLookup", true);
 #endif
 // The utm_creative value is appended within the code (specific to the location on
 // where it is clicked). Be sure that if these two prefs are updated, that
--- a/browser/base/content/test/performance/browser_startup_content.js
+++ b/browser/base/content/test/performance/browser_startup_content.js
@@ -40,16 +40,17 @@ const whitelist = {
     "resource://gre/modules/sessionstore/SessionHistory.jsm",
 
     // Browser front-end
     "resource:///actors/AboutReaderChild.jsm",
     "resource:///actors/BrowserTabChild.jsm",
     "resource:///modules/ContentMetaHandler.jsm",
     "resource:///actors/LinkHandlerChild.jsm",
     "resource:///actors/SearchTelemetryChild.jsm",
+    "resource://gre/actors/AutoCompleteChild.jsm",
     "resource://gre/modules/ActorChild.jsm",
     "resource://gre/modules/ActorManagerChild.jsm",
     "resource://gre/modules/E10SUtils.jsm",
     "resource://gre/modules/Readerable.jsm",
 
     // Telemetry
     "resource://gre/modules/TelemetryController.jsm", // bug 1470339
     "resource://gre/modules/TelemetryUtils.jsm", // bug 1470339
--- a/browser/base/content/test/permissions/browser_permissions_event_telemetry.js
+++ b/browser/base/content/test/permissions/browser_permissions_event_telemetry.js
@@ -13,17 +13,16 @@ async function showPermissionPrompt(brow
     PopupNotifications.panel,
     "popupshown"
   );
 
   await ContentTask.spawn(browser, null, function() {
     E10SUtils.wrapHandlingUserInput(content, true, () => {
       // We need to synthesize the click instead of calling .click(),
       // otherwise the document will not correctly register the user gesture.
-      let EventUtils = ContentTaskUtils.getEventUtils(content);
       let notificationButton = content.document.getElementById(
         "desktop-notification"
       );
       EventUtils.synthesizeMouseAtCenter(
         notificationButton,
         { isSynthesized: false },
         content
       );
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -150,16 +150,17 @@ let LEGACY_ACTORS = {
         AboutLoginsImport: { wantUntrusted: true },
         AboutLoginsInit: { wantUntrusted: true },
         AboutLoginsGetHelp: { wantUntrusted: true },
         AboutLoginsOpenMobileAndroid: { wantUntrusted: true },
         AboutLoginsOpenMobileIos: { wantUntrusted: true },
         AboutLoginsOpenPreferences: { wantUntrusted: true },
         AboutLoginsOpenSite: { wantUntrusted: true },
         AboutLoginsRecordTelemetryEvent: { wantUntrusted: true },
+        AboutLoginsSortChanged: { wantUntrusted: true },
         AboutLoginsSyncEnable: { wantUntrusted: true },
         AboutLoginsSyncOptions: { wantUntrusted: true },
         AboutLoginsUpdateLogin: { wantUntrusted: true },
       },
       messages: [
         "AboutLogins:AllLogins",
         "AboutLogins:LoginAdded",
         "AboutLogins:LoginModified",
@@ -464,17 +465,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
     "resource:///modules/aboutpages/AboutNetErrorHandler.jsm",
   AboutPrivateBrowsingHandler:
     "resource:///modules/aboutpages/AboutPrivateBrowsingHandler.jsm",
   AboutProtectionsHandler:
     "resource:///modules/aboutpages/AboutProtectionsHandler.jsm",
   AddonManager: "resource://gre/modules/AddonManager.jsm",
   AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.jsm",
   AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
-  AutoCompletePopup: "resource://gre/modules/AutoCompletePopup.jsm",
   Blocklist: "resource://gre/modules/Blocklist.jsm",
   BookmarkHTMLUtils: "resource://gre/modules/BookmarkHTMLUtils.jsm",
   BookmarkJSONUtils: "resource://gre/modules/BookmarkJSONUtils.jsm",
   BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
   BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
   ContextualIdentityService:
     "resource://gre/modules/ContextualIdentityService.jsm",
   Corroborate: "resource://gre/modules/Corroborate.jsm",
@@ -618,16 +618,17 @@ const listeners = {
     "AboutLogins:Import": ["AboutLoginsParent"],
     "AboutLogins:MasterPasswordRequest": ["AboutLoginsParent"],
     "AboutLogins:OpenFAQ": ["AboutLoginsParent"],
     "AboutLogins:GetHelp": ["AboutLoginsParent"],
     "AboutLogins:OpenPreferences": ["AboutLoginsParent"],
     "AboutLogins:OpenMobileAndroid": ["AboutLoginsParent"],
     "AboutLogins:OpenMobileIos": ["AboutLoginsParent"],
     "AboutLogins:OpenSite": ["AboutLoginsParent"],
+    "AboutLogins:SortChanged": ["AboutLoginsParent"],
     "AboutLogins:Subscribe": ["AboutLoginsParent"],
     "AboutLogins:SyncEnable": ["AboutLoginsParent"],
     "AboutLogins:SyncOptions": ["AboutLoginsParent"],
     "AboutLogins:UpdateLogin": ["AboutLoginsParent"],
     "Content:Click": ["ContentClick"],
     ContentSearch: ["ContentSearch"],
     "PictureInPicture:Request": ["PictureInPicture"],
     "PictureInPicture:Close": ["PictureInPicture"],
@@ -1611,17 +1612,16 @@ BrowserGlue.prototype = {
         if (removalSuccessful && uninstalledValue == "True") {
           this._resetProfileNotification("uninstall");
         }
       }
     }
 
     this._checkForOldBuildUpdates();
 
-    AutoCompletePopup.init();
     // Check if Sync is configured
     if (Services.prefs.prefHasUserValue("services.sync.username")) {
       WeaveService.init();
     }
 
     PageThumbs.init();
 
     NewTabUtils.init();
@@ -1872,17 +1872,16 @@ BrowserGlue.prototype = {
       this.pingCentre.uninit();
     }
 
     PageThumbs.uninit();
     NewTabUtils.uninit();
     AboutNetErrorHandler.uninit();
     AboutPrivateBrowsingHandler.uninit();
     AboutProtectionsHandler.uninit();
-    AutoCompletePopup.uninit();
 
     Normandy.uninit();
     RFPHelper.uninit();
   },
 
   // Set up a listener to enable/disable the screenshots extension
   // based on its preference.
   _monitorScreenshotsPref() {
--- a/browser/components/aboutlogins/AboutLoginsChild.jsm
+++ b/browser/components/aboutlogins/AboutLoginsChild.jsm
@@ -64,16 +64,17 @@ class AboutLoginsChild extends ActorChil
             };
 
             messageManager.sendAsyncMessage(
               "AboutLogins:MasterPasswordRequest"
             );
           },
           // Default to enabled just in case a search is attempted before we get a response.
           masterPasswordEnabled: true,
+          passwordRevealVisible: true,
         };
         waivedContent.AboutLoginsUtils = Cu.cloneInto(
           AboutLoginsUtils,
           waivedContent,
           {
             cloneFunctions: true,
           }
         );
@@ -104,16 +105,20 @@ class AboutLoginsChild extends ActorChil
         break;
       }
       case "AboutLoginsDismissBreachAlert": {
         this.mm.sendAsyncMessage("AboutLogins:DismissBreachAlert", {
           login: event.detail,
         });
         break;
       }
+      case "AboutLoginsGetHelp": {
+        this.mm.sendAsyncMessage("AboutLogins:GetHelp");
+        break;
+      }
       case "AboutLoginsHideFooter": {
         this.mm.sendAsyncMessage("AboutLogins:HideFooter");
         break;
       }
       case "AboutLoginsImport": {
         this.mm.sendAsyncMessage("AboutLogins:Import");
         break;
       }
@@ -124,20 +129,16 @@ class AboutLoginsChild extends ActorChil
         break;
       }
       case "AboutLoginsOpenMobileIos": {
         this.mm.sendAsyncMessage("AboutLogins:OpenMobileIos", {
           source: event.detail,
         });
         break;
       }
-      case "AboutLoginsGetHelp": {
-        this.mm.sendAsyncMessage("AboutLogins:GetHelp");
-        break;
-      }
       case "AboutLoginsOpenPreferences": {
         this.mm.sendAsyncMessage("AboutLogins:OpenPreferences");
         break;
       }
       case "AboutLoginsOpenSite": {
         this.mm.sendAsyncMessage("AboutLogins:OpenSite", {
           login: event.detail,
         });
@@ -175,16 +176,20 @@ class AboutLoginsChild extends ActorChil
           );
         } catch (ex) {
           Cu.reportError(
             "AboutLoginsChild: error recording telemetry event: " + ex.message
           );
         }
         break;
       }
+      case "AboutLoginsSortChanged": {
+        this.mm.sendAsyncMessage("AboutLogins:SortChanged", event.detail);
+        break;
+      }
       case "AboutLoginsSyncEnable": {
         this.mm.sendAsyncMessage("AboutLogins:SyncEnable");
         break;
       }
       case "AboutLoginsSyncOptions": {
         this.mm.sendAsyncMessage("AboutLogins:SyncOptions");
         break;
       }
@@ -221,16 +226,18 @@ class AboutLoginsChild extends ActorChil
         break;
       case "AboutLogins:SetBreaches":
         this.sendToContent("SetBreaches", message.data);
         break;
       case "AboutLogins:Setup":
         this.sendToContent("Setup", message.data);
         Cu.waiveXrays(this.content).AboutLoginsUtils.masterPasswordEnabled =
           message.data.masterPasswordEnabled;
+        Cu.waiveXrays(this.content).AboutLoginsUtils.passwordRevealVisible =
+          message.data.passwordRevealVisible;
         break;
       case "AboutLogins:ShowLoginItemError":
         this.sendToContent("ShowLoginItemError", message.data);
         break;
       case "AboutLogins:SyncState":
         this.sendToContent("SyncState", message.data);
         break;
       case "AboutLogins:UpdateBreaches":
--- a/browser/components/aboutlogins/AboutLoginsParent.jsm
+++ b/browser/components/aboutlogins/AboutLoginsParent.jsm
@@ -246,16 +246,20 @@ var AboutLoginsParent = {
           breachesByLoginGUID
         );
         break;
       }
       case "AboutLogins:HideFooter": {
         Services.prefs.setBoolPref(HIDE_MOBILE_FOOTER_PREF, true);
         break;
       }
+      case "AboutLogins:SortChanged": {
+        Services.prefs.setCharPref("signon.management.page.sort", message.data);
+        break;
+      }
       case "AboutLogins:SyncEnable": {
         message.target.ownerGlobal.gSync.openFxAEmailFirstPage(
           "password-manager"
         );
         break;
       }
       case "AboutLogins:SyncOptions": {
         message.target.ownerGlobal.gSync.openFxAManagePage("password-manager");
@@ -403,19 +407,26 @@ var AboutLoginsParent = {
 
           const selectedBadgeLanguages = {
             appStoreBadgeLanguage,
             playStoreBadgeLanguage,
           };
 
           messageManager.sendAsyncMessage("AboutLogins:Setup", {
             logins,
+            selectedSort: Services.prefs.getCharPref(
+              "signon.management.page.sort",
+              "name"
+            ),
             syncState,
             selectedBadgeLanguages,
             masterPasswordEnabled: LoginHelper.isMasterPasswordSet(),
+            passwordRevealVisible: Services.policies.isAllowed(
+              "passwordReveal"
+            ),
           });
 
           await this._sendAllLoginRelatedObjects(logins, messageManager);
         } catch (ex) {
           if (ex.result != Cr.NS_ERROR_NOT_INITIALIZED) {
             throw ex;
           }
 
--- a/browser/components/aboutlogins/LoginBreaches.jsm
+++ b/browser/components/aboutlogins/LoginBreaches.jsm
@@ -111,18 +111,20 @@ this.LoginBreaches = {
             breach,
             dismissedBreachAlertsByLoginGUID
           )
         ) {
           continue;
         }
 
         let breachAlertURL = new URL(breach.Name, baseBreachAlertURL);
-        breachAlertURL.searchParams.set("utm_campaign", "Desktop");
-        breachAlertURL.searchParams.set("utm_medium", "InProduct");
+        breachAlertURL.searchParams.set("utm_source", "firefox-desktop");
+        breachAlertURL.searchParams.set("utm_medium", "referral");
+        breachAlertURL.searchParams.set("utm_campaign", "about-logins");
+        breachAlertURL.searchParams.set("utm_content", "about-logins");
         breach.breachAlertURL = breachAlertURL.href;
         breachesByLoginGUID.set(login.guid, breach);
       }
     }
     Services.telemetry.scalarSet(
       "pwmgr.potentially_breached_passwords",
       breachesByLoginGUID.size
     );
--- a/browser/components/aboutlogins/content/aboutLogins.css
+++ b/browser/components/aboutlogins/content/aboutLogins.css
@@ -49,20 +49,16 @@ login-item[data-editing="true"] + login-
   display: none;
 }
 
 login-intro,
 login-item {
   grid-area: login;
 }
 
-login-item {
-  max-width: 700px;
-}
-
 #branding-logo {
   flex-basis: var(--sidebar-width);
   flex-shrink: 0;
   height: 32px;
   -moz-context-properties: fill;
   fill: #20123a;
 }
 
--- a/browser/components/aboutlogins/content/aboutLogins.html
+++ b/browser/components/aboutlogins/content/aboutLogins.html
@@ -80,20 +80,20 @@
     <template id="login-list-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-list.css">
       <div class="meta">
         <label for="login-sort">
           <span data-l10n-id="login-list-sort-label-text"></span>
           <select id="login-sort">
-            <option name="name" data-l10n-id="login-list-name-option" value="name"/>
-            <option name="last-user" data-l10n-id="login-list-last-used-option" value="last-used"/>
-            <option name="last-changed" data-l10n-id="login-list-last-changed-option" value="last-changed"/>
-            <option name="breached" data-l10n-id="login-list-breached-option" value="breached" hidden/>
+            <option name="name" data-l10n-id="login-list-name-option" value="name">
+            <option name="last-used" data-l10n-id="login-list-last-used-option" value="last-used">
+            <option name="last-changed" data-l10n-id="login-list-last-changed-option" value="last-changed">
+            <option name="breached" data-l10n-id="login-list-breached-option" value="breached" hidden>
           </select>
         </label>
         <span class="count" data-l10n-id="login-list-count" data-l10n-args='{"count": 0}'></span>
       </div>
       <!-- This container is to work around bug 1569292 -->
       <div class="container">
         <ol role="listbox" tabindex="0" data-l10n-id="login-list"></ol>
         <div class="intro">
@@ -141,103 +141,105 @@
         </ul>
       </section>
     </template>
 
     <template id="login-item-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-item.css">
-      <div class="error-message">
-        <span class="error-message-text" data-l10n-id="about-logins-error-message-default"></span>
-        <span class="error-message-link">
-          <a data-l10n-name="duplicate-link" href=""></a>
-        </span>
-      </div>
-      <div class="breach-alert">
-        <img class="breach-icon" src="chrome://global/skin/icons/warning.svg"/>
-        <span class="breach-alert-text" data-l10n-id="breach-alert-text"></span>
-        <a class="breach-alert-link" data-l10n-id="breach-alert-link" href="#" rel="noreferrer" target="_blank"></a>
-        <button class="dismiss-breach-alert" data-l10n-id="breach-alert-dismiss">
-          <img class="dismiss-breach-alert-icon" src="chrome://global/skin/icons/close.svg"/>
-        </button>
-      </div>
-      <div class="header">
-        <div class="login-item-favicon-wrapper">
-          <img class="login-item-favicon" src=""/>
+      <div class="container">
+        <div class="error-message">
+          <span class="error-message-text" data-l10n-id="about-logins-error-message-default"></span>
+          <span class="error-message-link">
+            <a data-l10n-name="duplicate-link" href=""></a>
+          </span>
         </div>
-        <h2 class="title">
-          <span class="login-item-title"></span>
-          <span class="new-login-title" data-l10n-id="login-item-new-login-title"></span>
-        </h2>
-        <button class="edit-button ghost-button" data-l10n-id="login-item-edit-button"></button>
-        <button class="delete-button ghost-button" data-l10n-id="login-item-delete-button"></button>
-      </div>
-      <form>
-        <div class="detail-row">
-          <label class="detail-cell">
-            <span class="origin-label field-label" data-l10n-id="login-item-origin-label"></span>
-            <!-- Default text inputs to readonly to reduce jumping of the field
-                 size on page load since it always starts readonly. -->
-            <input type="url"
-                   name="origin"
-                   class="origin-input"
-                   required
-                   data-l10n-id="login-item-origin"
-                   dir="auto"
-                   readonly/>
-          </label>
+        <div class="breach-alert">
+          <img class="breach-icon" src="chrome://global/skin/icons/warning.svg"/>
+          <span class="breach-alert-text" data-l10n-id="breach-alert-text"></span>
+          <a class="breach-alert-link" data-l10n-id="breach-alert-link" href="#" rel="noreferrer" target="_blank"></a>
+          <button class="dismiss-breach-alert" data-l10n-id="breach-alert-dismiss">
+            <img class="dismiss-breach-alert-icon" src="chrome://global/skin/icons/close.svg"/>
+          </button>
         </div>
-        <div class="detail-row">
-          <div class="detail-row-contents">
+        <div class="header">
+          <div class="login-item-favicon-wrapper">
+            <img class="login-item-favicon" src=""/>
+          </div>
+          <h2 class="title">
+            <span class="login-item-title"></span>
+            <span class="new-login-title" data-l10n-id="login-item-new-login-title"></span>
+          </h2>
+          <button class="edit-button ghost-button" data-l10n-id="login-item-edit-button"></button>
+          <button class="delete-button ghost-button" data-l10n-id="login-item-delete-button"></button>
+        </div>
+        <form>
+          <div class="detail-row">
             <label class="detail-cell">
-              <span class="username-label field-label" data-l10n-id="login-item-username-label"></span>
-              <input type="text"
-                     name="username"
-                     data-l10n-id="login-item-username"
-                     dir="ltr"
-                     readonly/>
+              <span class="origin-label field-label" data-l10n-id="login-item-origin-label"></span>
+              <!-- Default text inputs to readonly to reduce jumping of the field
+                  size on page load since it always starts readonly. -->
+              <input type="url"
+                    name="origin"
+                    class="origin-input"
+                    required
+                    data-l10n-id="login-item-origin"
+                    dir="auto"
+                    readonly/>
             </label>
-            <button class="copy-button copy-username-button" data-copy-login-property="username" data-telemetry-object="username" type="button">
-              <span class="copied-button-text" data-l10n-id="login-item-copied-username-button-text"></span>
-              <span class="copy-button-text" data-l10n-id="login-item-copy-username-button-text"></span>
-            </button>
+          </div>
+          <div class="detail-row">
+            <div class="detail-row-contents">
+              <label class="detail-cell">
+                <span class="username-label field-label" data-l10n-id="login-item-username-label"></span>
+                <input type="text"
+                      name="username"
+                      data-l10n-id="login-item-username"
+                      dir="ltr"
+                      readonly/>
+              </label>
+              <button class="copy-button copy-username-button" data-copy-login-property="username" data-telemetry-object="username" type="button">
+                <span class="copied-button-text" data-l10n-id="login-item-copied-username-button-text"></span>
+                <span class="copy-button-text" data-l10n-id="login-item-copy-username-button-text"></span>
+              </button>
+            </div>
           </div>
-        </div>
-        <div class="detail-row">
-          <div class="detail-row-contents">
-            <label class="detail-cell">
-              <span class="password-label field-label" data-l10n-id="login-item-password-label"></span>
-              <div class="reveal-password-wrapper">
-                <input type="password"
-                       name="password"
-                       autocomplete="off"
-                       dir="ltr"
-                       required
-                       readonly/>
-                <input type="checkbox"
-                       class="reveal-password-checkbox"
-                       data-l10n-id="login-item-password-reveal-checkbox"/>
-              </div>
-            </label>
-            <button class="copy-button copy-password-button" data-copy-login-property="password" data-telemetry-object="password" type="button">
-              <span class="copied-button-text" data-l10n-id="login-item-copied-password-button-text"></span>
-              <span class="copy-button-text" data-l10n-id="login-item-copy-password-button-text"></span>
-            </button>
+          <div class="detail-row">
+            <div class="detail-row-contents">
+              <label class="detail-cell">
+                <span class="password-label field-label" data-l10n-id="login-item-password-label"></span>
+                <div class="reveal-password-wrapper">
+                  <input type="password"
+                        name="password"
+                        autocomplete="off"
+                        dir="ltr"
+                        required
+                        readonly/>
+                  <input type="checkbox"
+                        class="reveal-password-checkbox"
+                        data-l10n-id="login-item-password-reveal-checkbox"/>
+                </div>
+              </label>
+              <button class="copy-button copy-password-button" data-copy-login-property="password" data-telemetry-object="password" type="button">
+                <span class="copied-button-text" data-l10n-id="login-item-copied-password-button-text"></span>
+                <span class="copy-button-text" data-l10n-id="login-item-copy-password-button-text"></span>
+              </button>
+            </div>
           </div>
-        </div>
-        <div class="form-actions-row">
-          <button class="save-changes-button" type="submit"></button>
-          <button class="cancel-button" data-l10n-id="login-item-cancel-button" type="button"></button>
-        </div>
-        <p class="time-created meta-info" data-l10n-id="login-item-time-created" data-l10n-args='{"timeCreated": 0}'></p>
-        <p class="time-changed meta-info" data-l10n-id="login-item-time-changed" data-l10n-args='{"timeChanged": 0}'></p>
-        <p class="time-used meta-info" data-l10n-id="login-item-time-used" data-l10n-args='{"timeUsed": 0}'></p>
-      </form>
-      <login-footer hidden></login-footer>
+          <div class="form-actions-row">
+            <button class="save-changes-button" type="submit"></button>
+            <button class="cancel-button" data-l10n-id="login-item-cancel-button" type="button"></button>
+          </div>
+          <p class="time-created meta-info" data-l10n-id="login-item-time-created" data-l10n-args='{"timeCreated": 0}'></p>
+          <p class="time-changed meta-info" data-l10n-id="login-item-time-changed" data-l10n-args='{"timeChanged": 0}'></p>
+          <p class="time-used meta-info" data-l10n-id="login-item-time-used" data-l10n-args='{"timeUsed": 0}'></p>
+        </form>
+        <login-footer hidden></login-footer>
+      </div>
     </template>
 
     <template id="login-filter-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-filter.css">
       <input data-l10n-id="login-filter" class="filter" type="text" dir="auto"/>
     </template>
--- a/browser/components/aboutlogins/content/aboutLogins.js
+++ b/browser/components/aboutlogins/content/aboutLogins.js
@@ -76,16 +76,17 @@ window.addEventListener("AboutLoginsChro
       break;
     }
     case "Setup": {
       handleAllLogins(event.detail.value.logins);
       gElements.loginFooter.showStoreIconsForLocales(
         event.detail.value.selectedBadgeLanguages
       );
       handleSyncState(event.detail.value.syncState);
+      gElements.loginList.setSortDirection(event.detail.value.selectedSort);
       document.documentElement.classList.add("initialized");
       break;
     }
     case "ShowLoginItemError": {
       gElements.loginItem.showLoginItemError(event.detail.value);
       break;
     }
     case "SyncState": {
--- a/browser/components/aboutlogins/content/components/confirmation-dialog.css
+++ b/browser/components/aboutlogins/content/components/confirmation-dialog.css
@@ -1,9 +1,13 @@
-.overlay {
+/* 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/. */
+
+ .overlay {
   position: fixed;
   z-index: 1;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
   /* TODO: this color is used in the about:preferences overlay, but
            why isn't it declared as a variable? */
@@ -67,16 +71,17 @@
 .content,
 .buttons {
   text-align: center;
   padding: 16px 32px;
 }
 
 .buttons {
   display: flex;
+  justify-content: space-between;
 }
 
 .buttons.macosx > .confirm-button {
   order: 1;
 }
 
 .buttons > button {
   min-width: 140px;
--- a/browser/components/aboutlogins/content/components/fxaccounts-button.css
+++ b/browser/components/aboutlogins/content/components/fxaccounts-button.css
@@ -43,29 +43,20 @@
 .fxaccount-avatar {
   display: inline-block;
   vertical-align: middle;
   background-image: var(--avatar-url),
     url(chrome://browser/skin/fxa/avatar-color.svg);
   background-position: center;
   background-repeat: no-repeat;
   background-size: cover;
-  border: 1px solid var(--in-content-border-color);
   border-radius: 1000px;
   width: 32px;
   height: 32px;
 }
 
-.fxaccounts-avatar-button:hover .fxaccount-avatar {
-  border-color: var(--in-content-border-hover);
-}
-
-.fxaccounts-avatar-button:hover:active .fxaccount-avatar {
-  border-color: var(--in-content-border-active);
-}
-
 .fxaccounts-avatar-button:hover {
   background-color: transparent !important;
 }
 
 .fxaccounts-avatar-button:hover > .fxaccount-email {
   text-decoration: underline;
 }
--- a/browser/components/aboutlogins/content/components/login-item.css
+++ b/browser/components/aboutlogins/content/components/login-item.css
@@ -1,16 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :host {
-  padding: 40px;
-  display: flex;
-  flex-direction: column;
+  overflow: auto;
 
   --reveal-checkbox-opacity: .8;
   --reveal-checkbox-opacity-hover: .6;
   --reveal-checkbox-opacity-active: 1;
   --success-color: #00c100;
   --edit-delete-button-color: #4a4a4f;
 }
 
@@ -21,16 +19,23 @@
   }
 }
 @supports not (-moz-bool-pref("browser.in-content.dark-mode")) {
   :host {
     --in-content-deemphasized-text: #737373;
   }
 }
 
+.container {
+  max-width: 700px;
+  padding: 40px;
+  display: flex;
+  flex-direction: column;
+}
+
 form {
   flex-grow: 1;
 }
 
 :host([data-editing]) .edit-button,
 :host([data-editing]) .copy-button,
 :host([data-editing]) login-footer,
 :host([data-is-new-login].no-logins) .cancel-button,
@@ -292,17 +297,17 @@ input[name="password"] {
   padding-inline-end: 92px;
   margin-block-end: 40px;
   position: relative;
 }
 
 .breach-alert-link {
   color: inherit;
   text-decoration: underline;
-  font-weight: 500;
+  font-weight: 600;
 }
 
 .breach-icon {
   position: absolute;
   inset-block-start: 10px;
   inset-inline-start: 10px;
   -moz-context-properties: fill;
   fill: var(--red-90);
@@ -315,21 +320,28 @@ input[name="password"] {
   position: absolute;
   inset-inline-end: 12px;
   inset-block-start: 12px;
   min-width: auto;
   min-height: auto;
   line-height: 0;
 }
 
-.dismiss-breach-alert,
-.dismiss-breach-alert:hover {
+.dismiss-breach-alert {
   background-color: transparent;
 }
 
+.dismiss-breach-alert:enabled:hover {
+  background-color: var(--grey-90-a20);
+}
+
+.dismiss-breach-alert:enabled:hover:active {
+  background-color: var(--grey-90-a30);
+}
+
 .dismiss-breach-alert-icon {
   -moz-context-properties: fill, fill-opacity;
   fill-opacity: 0;
   fill: currentColor;
   width: 16px;
   height: 16px;
 }
 
--- a/browser/components/aboutlogins/content/components/login-item.js
+++ b/browser/components/aboutlogins/content/components/login-item.js
@@ -155,16 +155,17 @@ export default class LoginItem extends H
     } else {
       // reset the src and alt attributes if the currently selected favicon doesn't have a favicon
       this._favicon.src = "";
       this._favicon.hidden = true;
       this._faviconWrapper.classList.remove("hide-default-favicon");
     }
 
     this._title.textContent = this._login.title;
+    this._title.title = this._login.title;
     this._originInput.defaultValue = this._login.origin || "";
     this._usernameInput.defaultValue = this._login.username || "";
     if (this._login.password) {
       // We use .value instead of .defaultValue since the latter updates the
       // content attribute making the password easily viewable with Inspect
       // Element even when Master Password is enabled. This is only run when
       // the password is non-empty since setting the field to an empty value
       // would mark the field as 'dirty' for form validation and thus trigger
@@ -722,16 +723,24 @@ export default class LoginItem extends H
     } else {
       delete this.dataset.editing;
       // Only reset the reveal checkbox when exiting 'edit' mode
       this._revealCheckbox.checked = false;
     }
   }
 
   _updatePasswordRevealState() {
+    if (
+      window.AboutLoginsUtils &&
+      window.AboutLoginsUtils.passwordRevealVisible === false
+    ) {
+      this._revealCheckbox.hidden = true;
+      return;
+    }
+
     let titleId = this._revealCheckbox.checked
       ? "login-item-password-reveal-checkbox-hide"
       : "login-item-password-reveal-checkbox-show";
     document.l10n.setAttributes(this._revealCheckbox, titleId);
 
     let { checked } = this._revealCheckbox;
     let inputType = checked ? "text" : "password";
     this._passwordInput.type = inputType;
--- a/browser/components/aboutlogins/content/components/login-list.css
+++ b/browser/components/aboutlogins/content/components/login-list.css
@@ -26,16 +26,20 @@
   padding-inline-start: 0;
   padding-inline-end: 16px;
   min-height: initial;
   font: inherit;
   font-weight: 600;
   color: var(--in-content-text-color) !important;
 }
 
+#login-sort:hover {
+  background-color: var(--in-content-button-background);
+}
+
 #login-sort > option {
   font-weight: normal;
 }
 
 #login-sort:-moz-focusring { /* This is a workaround due to Bug 1580935 */
   color: transparent !important;
   fill: var(--in-content-text-color);
   text-shadow: 0 0 0 var(--in-content-text-color);
--- a/browser/components/aboutlogins/content/components/login-list.js
+++ b/browser/components/aboutlogins/content/components/login-list.js
@@ -169,16 +169,22 @@ export default class LoginList extends H
           extra,
         });
         break;
       }
       case "change": {
         this._applySortAndScrollToTop();
         const extra = { sort_key: this._sortSelect.value };
         recordTelemetryEvent({ object: "list", method: "sort", extra });
+        document.dispatchEvent(
+          new CustomEvent("AboutLoginsSortChanged", {
+            bubbles: true,
+            detail: this._sortSelect.value,
+          })
+        );
         break;
       }
       case "AboutLoginsClearSelection": {
         if (!this._loginGuidsSortedOrder.length) {
           return;
         }
 
         let firstVisibleListItem = this._list.querySelector(
@@ -286,28 +292,17 @@ export default class LoginList extends H
       return map;
     }, {});
     this._applySort();
     this._list.textContent = "";
     this._list.appendChild(this._blankLoginListItem);
     this.render();
 
     if (!this._selectedGuid || !this._logins[this._selectedGuid]) {
-      // Select the first visible login after any possible filter is applied.
-      let firstVisibleListItem = this._list.querySelector(
-        ".login-list-item[data-guid]:not([hidden])"
-      );
-      if (firstVisibleListItem) {
-        let { login } = this._logins[firstVisibleListItem.dataset.guid];
-        window.dispatchEvent(
-          new CustomEvent("AboutLoginsInitialLoginSelected", {
-            detail: login,
-          })
-        );
-      }
+      this._selectFirstVisibleLogin();
     }
   }
 
   addFavicons(favicons) {
     for (let favicon in favicons) {
       let { login, listItem } = this._logins[favicon];
       favicon = favicons[favicon];
       if (favicon && login.title) {
@@ -359,16 +354,22 @@ export default class LoginList extends H
       this._breachesByLoginGUID = new Map();
     }
     for (const [guid, breach] of [...breachesByLoginGUID]) {
       this._breachesByLoginGUID.set(guid, breach);
     }
     this.setBreaches(this._breachesByLoginGUID);
   }
 
+  setSortDirection(sortDirection) {
+    this._sortSelect.value = sortDirection;
+    this._applySortAndScrollToTop();
+    this._selectFirstVisibleLogin();
+  }
+
   /**
    * @param {login} login A login that was added to storage.
    */
   loginAdded(login) {
     this._logins[login.guid] = { login };
     this._loginGuidsSortedOrder.push(login.guid);
     this._applySort();
 
@@ -581,16 +582,35 @@ export default class LoginList extends H
     }
     event.preventDefault();
     this._list.setAttribute("aria-activedescendant", newlyFocusedItem.id);
     activeDescendant.classList.remove("keyboard-selected");
     newlyFocusedItem.classList.add("keyboard-selected");
     newlyFocusedItem.scrollIntoView({ block: "nearest" });
   }
 
+  /**
+   * Selects the first visible login as part of the initial load of the page,
+   * which will bypass any focus changes that occur during manual login
+   * selection.
+   */
+  _selectFirstVisibleLogin() {
+    let firstVisibleListItem = this._list.querySelector(
+      ".login-list-item[data-guid]:not([hidden])"
+    );
+    if (firstVisibleListItem) {
+      let { login } = this._logins[firstVisibleListItem.dataset.guid];
+      window.dispatchEvent(
+        new CustomEvent("AboutLoginsInitialLoginSelected", {
+          detail: login,
+        })
+      );
+    }
+  }
+
   _setListItemAsSelected(listItem) {
     let oldSelectedItem = this._list.querySelector(".selected");
     if (oldSelectedItem) {
       oldSelectedItem.classList.remove("selected");
       oldSelectedItem.removeAttribute("aria-selected");
     }
     this.classList.toggle("create-login-selected", !listItem.dataset.guid);
     this._blankLoginListItem.hidden = !!listItem.dataset.guid;
--- a/browser/components/aboutlogins/moz.build
+++ b/browser/components/aboutlogins/moz.build
@@ -2,17 +2,17 @@
 # vim: set filetype=python:
 # 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/.
 
 JAR_MANIFESTS += ['jar.mn']
 
 with Files('**'):
-    BUG_COMPONENT = ('Toolkit', 'Password Manager')
+    BUG_COMPONENT = ('Firefox', 'about:logins')
 
 EXTRA_JS_MODULES += [
     'AboutLoginsParent.jsm',
     'LoginBreaches.jsm',
 ]
 
 FINAL_TARGET_FILES.actors += [
     'AboutLoginsChild.jsm',
--- a/browser/components/aboutlogins/tests/browser/browser.ini
+++ b/browser/components/aboutlogins/tests/browser/browser.ini
@@ -16,16 +16,17 @@ skip-if = asan || debug || verify # bug 
 [browser_copyToClipboardButton.js]
 [browser_createLogin.js]
 [browser_deleteLogin.js]
 [browser_dismissFooter.js]
 [browser_fxAccounts.js]
 [browser_loginItemErrors.js]
 skip-if = debug # Bug 1577710
 [browser_loginListChanges.js]
+[browser_loginSortOrderRestored.js]
 [browser_masterPassword.js]
 skip-if = (os == 'linux') # bug 1569789
 [browser_noLoginsView.js]
 [browser_openFiltered.js]
 [browser_openImport.js]
 skip-if = (os != "win" && os != "mac") # import is only available on Windows and macOS
 [browser_openPreferences.js]
 [browser_openPreferencesExternal.js]
--- a/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
+++ b/browser/components/aboutlogins/tests/browser/browser_aaa_eventTelemetry_run_first.js
@@ -164,16 +164,19 @@ add_task(async function test_telemetry_e
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginSort = content.document
       .querySelector("login-list")
       .shadowRoot.querySelector("#login-sort");
     loginSort.selectedIndex = 1;
     loginSort.dispatchEvent(new content.Event("change", { bubbles: true }));
   });
   await LoginTestUtils.telemetry.waitForEventCount(14);
+  registerCleanupFunction(() => {
+    Services.prefs.clearUserPref("signon.management.page.sort");
+  });
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     let loginFilter = content.document.querySelector("login-filter");
     let input = loginFilter.shadowRoot.querySelector("input");
     input.setUserInput("test");
   });
   await LoginTestUtils.telemetry.waitForEventCount(15);
 
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutlogins/tests/browser/browser_loginSortOrderRestored.js
@@ -0,0 +1,87 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+ChromeUtils.import("resource://testing-common/TelemetryTestUtils.jsm", this);
+ChromeUtils.import("resource://testing-common/LoginTestUtils.jsm", this);
+
+add_task(async function setup() {
+  TEST_LOGIN2.QueryInterface(Ci.nsILoginMetaInfo).timePasswordChanged = 1;
+  TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
+  info(`TEST_LOGIN1 added with guid=${TEST_LOGIN1.guid}`);
+  TEST_LOGIN2 = await addLogin(TEST_LOGIN2);
+  info(`TEST_LOGIN2 added with guid=${TEST_LOGIN2.guid}`);
+  registerCleanupFunction(() => {
+    Services.logins.removeAllLogins();
+    Services.prefs.clearUserPref("signon.management.page.sort");
+  });
+});
+
+add_task(async function test_sort_order_persisted() {
+  await BrowserTestUtils.withNewTab(
+    {
+      gBrowser,
+      url: "about:logins",
+    },
+    async function(browser) {
+      await ContentTask.spawn(
+        browser,
+        [TEST_LOGIN1, TEST_LOGIN2],
+        async function([testLogin1, testLogin2]) {
+          let loginList = Cu.waiveXrays(
+            content.document.querySelector("login-list")
+          );
+          is(
+            loginList._sortSelect.value,
+            "name",
+            "default selected sort should be 'name'"
+          );
+          is(
+            loginList._list.querySelector(
+              ".login-list-item[data-guid]:not([hidden])"
+            ).dataset.guid,
+            testLogin2.guid,
+            "the first login should be TEST_LOGIN2 since they are sorted by origin"
+          );
+
+          loginList._sortSelect.value = "last-changed";
+          loginList._sortSelect.dispatchEvent(
+            new content.Event("change", { bubbles: true })
+          );
+          is(
+            loginList._list.querySelector(
+              ".login-list-item[data-guid]:not([hidden])"
+            ).dataset.guid,
+            testLogin1.guid,
+            "the first login should be TEST_LOGIN1 since it has the most recent timePasswordChanged value"
+          );
+        }
+      );
+    }
+  );
+
+  await BrowserTestUtils.withNewTab(
+    {
+      gBrowser,
+      url: "about:logins",
+    },
+    async function(browser) {
+      await ContentTask.spawn(browser, TEST_LOGIN1, async function(testLogin1) {
+        let loginList = Cu.waiveXrays(
+          content.document.querySelector("login-list")
+        );
+        is(
+          loginList._sortSelect.value,
+          "last-changed",
+          "selected sort should be restored to 'last-changed'"
+        );
+        is(
+          loginList._list.querySelector(
+            ".login-list-item[data-guid]:not([hidden])"
+          ).dataset.guid,
+          testLogin1.guid,
+          "the first login should still be TEST_LOGIN1 since it has the most recent timePasswordChanged value"
+        );
+      });
+    }
+  );
+});
--- a/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
+++ b/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
@@ -127,17 +127,17 @@ add_task(async function test_breachedLog
   );
   Assert.strictEqual(
     breachesByLoginGUID.size,
     1,
     "Should be 1 breached login: " + BREACHED_LOGIN.origin
   );
   Assert.strictEqual(
     breachesByLoginGUID.get(BREACHED_LOGIN.guid).breachAlertURL,
-    "https://monitor.firefox.com/breach-details/Breached?utm_campaign=Desktop&utm_medium=InProduct",
+    "https://monitor.firefox.com/breach-details/Breached?utm_source=firefox-desktop&utm_medium=referral&utm_campaign=about-logins&utm_content=about-logins",
     "Breach alert link should be equal to the breachAlertURL"
   );
 });
 
 add_task(async function test_notBreachedSubdomain() {
   Services.logins.addLogin(NOT_BREACHED_SUBDOMAIN_LOGIN);
 
   const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -107,31 +107,47 @@ var Policies = {
       if ("NTLM" in param) {
         setDefaultPref(
           "network.automatic-ntlm-auth.trusted-uris",
           param.NTLM.join(", "),
           locked
         );
       }
       if ("AllowNonFQDN" in param) {
-        if (param.AllowNonFQDN.NTLM) {
+        if ("NTLM" in param.AllowNonFQDN) {
           setDefaultPref(
             "network.automatic-ntlm-auth.allow-non-fqdn",
             param.AllowNonFQDN.NTLM,
             locked
           );
         }
-        if (param.AllowNonFQDN.SPNEGO) {
+        if ("SPNEGO" in param.AllowNonFQDN) {
           setDefaultPref(
             "network.negotiate-auth.allow-non-fqdn",
             param.AllowNonFQDN.SPNEGO,
             locked
           );
         }
       }
+      if ("AllowProxies" in param) {
+        if ("NTLM" in param.AllowProxies) {
+          setDefaultPref(
+            "network.automatic-ntlm-auth.allow-proxies",
+            param.AllowProxies.NTLM,
+            locked
+          );
+        }
+        if ("SPNEGO" in param.AllowProxies) {
+          setDefaultPref(
+            "network.negotiate-auth.allow-proxies",
+            param.AllowProxies.SPNEGO,
+            locked
+          );
+        }
+      }
     },
   },
 
   BlockAboutAddons: {
     onBeforeUIStartup(manager, param) {
       if (param) {
         blockAboutPage(manager, "about:addons", true);
       }
@@ -445,16 +461,24 @@ var Policies = {
   DisableMasterPasswordCreation: {
     onBeforeUIStartup(manager, param) {
       if (param) {
         manager.disallowFeature("createMasterPassword");
       }
     },
   },
 
+  DisablePasswordReveal: {
+    onBeforeUIStartup(manager, param) {
+      if (param) {
+        manager.disallowFeature("passwordReveal");
+      }
+    },
+  },
+
   DisablePocket: {
     onBeforeAddons(manager, param) {
       if (param) {
         setAndLockPref("extensions.pocket.enabled", false);
       }
     },
   },
 
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -49,16 +49,28 @@
               "type": "boolean"
             },
 
             "NTLM": {
               "type": "boolean"
             }
           }
         },
+        "AllowProxies": {
+          "type": "object",
+          "properties": {
+            "SPNEGO": {
+              "type": "boolean"
+            },
+
+            "NTLM": {
+              "type": "boolean"
+            }
+          }
+        },
         "Locked": {
           "type": "boolean"
         }
       }
     },
 
     "BlockAboutAddons": {
       "type": "boolean"
@@ -206,16 +218,20 @@
     "DisableFormHistory": {
       "type": "boolean"
     },
 
     "DisableMasterPasswordCreation": {
       "type": "boolean"
     },
 
+    "DisablePasswordReveal": {
+      "type": "boolean"
+    },
+
     "DisablePocket": {
       "type": "boolean"
     },
 
     "DisablePrivateBrowsing": {
       "type": "boolean"
     },
 
@@ -660,44 +676,75 @@
           "type": "boolean"
         }
       }
     },
 
     "Preferences": {
       "type": "object",
       "properties": {
+        "accessibility.force_disabled": {
+          "type": "number",
+          "enum": [-1, 0, 1]
+        },
         "app.update.auto": {
           "type": "boolean"
         },
+        "browser.bookmarks.autoExportHTML": {
+          "type": "boolean"
+        },
+        "browser.bookmarks.file": {
+          "type": "string"
+        },
+        "browser.places.importBookmarksHTML": {
+          "type": "boolean"
+        },
+        "browser.bookmarks.restore_default_bookmarks": {
+          "type": "boolean"
+        },
         "browser.cache.disk.enable": {
           "type": "boolean"
         },
         "browser.fixup.dns_first_for_single_words": {
           "type": "boolean"
         },
+        "browser.safebrowsing.phishing.enabled": {
+          "type": "boolean"
+        },
+        "browser.safebrowsing.malware.enabled": {
+          "type": "boolean"
+        },
         "browser.search.update": {
           "type": "boolean"
         },
         "browser.tabs.warnOnClose": {
           "type": "boolean"
         },
         "browser.cache.disk.parent_directory": {
           "type": "string"
         },
+        "browser.slowStartup.notificationDisabled": {
+          "type": "boolean"
+        },
+        "browser.taskbar.previews.enable": {
+          "type": "boolean"
+        },
+        "browser.urlbar.suggest.bookmark": {
+          "type": "boolean"
+        },
         "browser.urlbar.suggest.openpage": {
           "type": "boolean"
         },
         "browser.urlbar.suggest.history": {
           "type": "boolean"
         },
         "datareporting.policy.dataSubmissionPolicyBypassNotification": {
           "type": "boolean"
         },
-        "browser.urlbar.suggest.bookmark": {
+        "dom.allow_scripts_to_close_windows": {
           "type": "boolean"
         },
         "dom.disable_window_flip": {
           "type": "boolean"
         },
         "dom.disable_window_move_resize": {
           "type": "boolean"
         },
@@ -705,43 +752,61 @@
           "type": "boolean"
         },
         "dom.keyboardevent.keypress.hack.dispatch_non_printable_keys.addl": {
           "type": "string"
         },
         "dom.keyboardevent.keypress.hack.use_legacy_keycode_and_charcode.addl": {
           "type": "string"
         },
+        "extensions.blocklist.enabled": {
+          "type": "boolean"
+        },
         "extensions.getAddons.showPane": {
           "type": "boolean"
         },
+        "geo.enabled": {
+          "type": "boolean"
+        },
+        "intl.accept_languages": {
+          "type": "string"
+        },
+        "media.eme.enabled": {
+          "type": "boolean"
+        },
         "media.gmp-gmpopenh264.enabled": {
           "type": "boolean"
         },
         "media.gmp-widevinecdm.enabled": {
           "type": "boolean"
         },
         "network.dns.disableIPv6": {
           "type": "boolean"
         },
         "network.IDN_show_punycode": {
           "type": "boolean"
         },
         "places.history.enabled": {
           "type": "boolean"
         },
+        "print.save_print_settings": {
+          "type": "boolean"
+        },
         "privacy.file_unique_origin": {
           "type": "boolean"
         },
         "security.default_personal_cert": {
           "type": "string"
         },
         "security.ssl.errorReporting.enabled": {
           "type": "boolean"
         },
+        "security.mixed_content.block_active_content": {
+          "type": "boolean"
+        },
         "ui.key.menuAccessKeyFocuses": {
           "type": "boolean"
         }
       }
     },
 
     "PromptForDownloadLocation": {
       "type": "boolean"
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
@@ -11,17 +11,17 @@ async function isExtensionLocked(win, ad
     let doc = win.getHtmlBrowser().contentDocument;
     await win.htmlBrowserLoaded;
     return doc.querySelector(`addon-card[addon-id="${addonID}"]`);
   }, `Get addon-card for "${addonID}"`);
   let disableBtn = addonCard.querySelector(
     'panel-item[action="toggle-disabled"]'
   );
   let removeBtn = addonCard.querySelector('panel-item[action="remove"]');
-  ok(removeBtn.hidden, "Remove button should be hidden");
+  ok(removeBtn.disabled, "Remove button should be disabled");
   ok(disableBtn.hidden, "Disable button should be hidden");
 }
 
 add_task(async function test_addon_install() {
   let installPromise = wait_for_addon_install();
   await setupPolicyEngineWithJson({
     policies: {
       Extensions: {
--- a/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
@@ -116,47 +116,59 @@ const POLICIES_TESTS = [
       Authentication: {
         SPNEGO: ["a.com", "b.com"],
         Delegated: ["a.com", "b.com"],
         NTLM: ["a.com", "b.com"],
         AllowNonFQDN: {
           SPNEGO: true,
           NTLM: true,
         },
+        AllowProxies: {
+          SPNEGO: false,
+          NTLM: false,
+        },
       },
     },
     lockedPrefs: {
       "network.negotiate-auth.trusted-uris": "a.com, b.com",
       "network.negotiate-auth.delegation-uris": "a.com, b.com",
       "network.automatic-ntlm-auth.trusted-uris": "a.com, b.com",
       "network.automatic-ntlm-auth.allow-non-fqdn": true,
       "network.negotiate-auth.allow-non-fqdn": true,
+      "network.automatic-ntlm-auth.allow-proxies": false,
+      "network.negotiate-auth.allow-proxies": false,
     },
   },
 
   // POLICY: Authentication (unlocked)
   {
     policies: {
       Authentication: {
         SPNEGO: ["a.com", "b.com"],
         Delegated: ["a.com", "b.com"],
         NTLM: ["a.com", "b.com"],
         AllowNonFQDN: {
           SPNEGO: true,
           NTLM: true,
         },
+        AllowProxies: {
+          SPNEGO: false,
+          NTLM: false,
+        },
         Locked: false,
       },
     },
     unlockedPrefs: {
       "network.negotiate-auth.trusted-uris": "a.com, b.com",
       "network.negotiate-auth.delegation-uris": "a.com, b.com",
       "network.automatic-ntlm-auth.trusted-uris": "a.com, b.com",
       "network.automatic-ntlm-auth.allow-non-fqdn": true,
       "network.negotiate-auth.allow-non-fqdn": true,
+      "network.automatic-ntlm-auth.allow-proxies": false,
+      "network.negotiate-auth.allow-proxies": false,
     },
   },
 
   // POLICY: Certificates (true)
   {
     policies: {
       Certificates: {
         ImportEnterpriseRoots: true,
--- a/browser/components/originattributes/test/browser/browser.ini
+++ b/browser/components/originattributes/test/browser/browser.ini
@@ -97,14 +97,13 @@ fail-if = fission
 skip-if = fission
 [browser_clientAuth.js]
 skip-if = verify
 [browser_cacheAPI.js]
 fail-if = fission
 [browser_permissions.js]
 fail-if = fission
 [browser_postMessage.js]
-skip-if = fission
 [browser_sanitize.js]
 fail-if = fission
 skip-if = (os == 'win') || (os == "mac" && os_version == "10.14") || (os == "linux" && bits == 64) #Bug 1544810
 [browser_windowOpenerRestriction.js]
 fail-if = fission
--- a/browser/components/originattributes/test/browser/browser_postMessage.js
+++ b/browser/components/originattributes/test/browser/browser_postMessage.js
@@ -38,41 +38,41 @@ async function runTestWithOptions(
 
   // Use window.open() in the tab to open the sender tab. The sender tab
   // will send a message through postMessage to window.opener.
   let senderTabPromise = BrowserTestUtils.waitForNewTab(
     gBrowser,
     senderURL,
     true
   );
-  ContentTask.spawn(tab.linkedBrowser, senderURL, aSenderPath => {
+  SpecialPowers.spawn(tab.linkedBrowser, [senderURL], aSenderPath => {
     content.open(aSenderPath, "_blank");
   });
 
   // Wait and get the tab of the sender tab.
   let senderTab = await senderTabPromise;
 
   // The postMessage should be blocked when the first parties are different with
   // the following two cases. First, it is using a non-star target origin.
   // Second, it is using the star target origin and the pref
   // 'privacy.firstparty.isolate.block_post_message' is true.
   let shouldBlock = aDifferentFPD && (!aStarTargetOrigin || aBlockAcrossFPD);
 
-  await ContentTask.spawn(tab.linkedBrowser, shouldBlock, async aValue => {
+  await SpecialPowers.spawn(tab.linkedBrowser, [shouldBlock], async aValue => {
     await new Promise(resolve => {
       content.addEventListener("message", function eventHandler(aEvent) {
         if (aEvent.data === "Self") {
           if (aValue) {
-            is(
+            Assert.equal(
               content.document.getElementById("display").innerHTML,
               "",
               "It should not get a message from other OA."
             );
           } else {
-            is(
+            Assert.equal(
               content.document.getElementById("display").innerHTML,
               "Message",
               "It should get a message from the same OA."
             );
           }
 
           content.removeEventListener("message", eventHandler);
           resolve();
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -364,18 +364,16 @@ async function setupPaymentDialog(
         return;
       }
       while (field.value) {
         EventUtils.sendKey("BACK_SPACE", content.window);
       }
       EventUtils.sendString(value, content.window);
     };
   });
-  await injectEventUtilsInContentTask(frame);
-  info("helper functions injected into frame");
 
   return { win, requestId, frame };
 }
 
 /**
  * Open a merchant tab with the given merchantTaskFn to create a PaymentRequest
  * and then open the associated PaymentRequest dialog in a new tab and run the
  * associated dialogTaskFn. The same taskArgs are passed to both functions.
@@ -923,47 +921,8 @@ async function fillInCardForm(frame, aCa
             options.setPersistCheckedValue
         );
         Cu.waiveXrays(persistCheckbox).checked = options.setPersistCheckedValue;
       }
     },
     { card: aCard, options: aOptions }
   );
 }
-
-// The JSDoc validator does not support @returns tags in abstract functions or
-// star functions without return statements.
-/* eslint-disable valid-jsdoc */
-/**
- * Inject `EventUtils` helpers into ContentTask scope.
- *
- * This helper is automatically exposed to mochitest browser tests,
- * but is missing from content task scope.
- * You should call this method only once per <browser> tag
- *
- * @param {xul:browser} browser
- *        Reference to the browser in which we load content task
- */
-/* eslint-enable valid-jsdoc */
-async function injectEventUtilsInContentTask(browser) {
-  await spawnPaymentDialogTask(browser, async function injectEventUtils() {
-    if ("EventUtils" in this) {
-      return;
-    }
-
-    const EventUtils = (this.EventUtils = {});
-
-    EventUtils.window = {};
-    EventUtils.parent = EventUtils.window;
-    /* eslint-disable camelcase */
-    EventUtils._EU_Ci = Ci;
-    EventUtils._EU_Cc = Cc;
-    /* eslint-enable camelcase */
-    // EventUtils' `sendChar` function relies on the navigator to synthetize events.
-    EventUtils.navigator = content.navigator;
-    EventUtils.KeyboardEvent = content.KeyboardEvent;
-
-    Services.scriptloader.loadSubScript(
-      "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
-      EventUtils
-    );
-  });
-}
--- a/browser/components/preferences/connection.js
+++ b/browser/components/preferences/connection.js
@@ -365,16 +365,17 @@ var gConnectionsDialog = {
     return undefined;
   },
 
   getProxyControls() {
     let controlGroup = document.getElementById("networkProxyType");
     return [
       ...controlGroup.querySelectorAll(":scope > radio"),
       ...controlGroup.querySelectorAll("label"),
+      ...controlGroup.querySelectorAll("input"),
       ...controlGroup.querySelectorAll("checkbox"),
       ...document.querySelectorAll("#networkProxySOCKSVersion > radio"),
       ...document.querySelectorAll("#ConnectionsDialogPane > checkbox"),
     ];
   },
 
   // Update the UI to show/hide the extension controlled message for
   // proxy settings.
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -2310,27 +2310,47 @@ var gMainPane = {
         case Ci.nsIHandlerInfo.handleInternally:
           if (internalMenuItem) {
             menu.selectedItem = internalMenuItem;
           } else {
             Cu.reportError("No menu item defined to set!");
           }
           break;
         case Ci.nsIHandlerInfo.useSystemDefault:
-          menu.selectedItem = defaultMenuItem;
+          // We might not have a default item if we're not aware of an
+          // OS-default handler for this type:
+          menu.selectedItem = defaultMenuItem || askMenuItem;
           break;
         case Ci.nsIHandlerInfo.useHelperApp:
           if (preferredApp) {
-            menu.selectedItem = possibleAppMenuItems.filter(v =>
+            let preferredItem = possibleAppMenuItems.find(v =>
               v.handlerApp.equals(preferredApp)
-            )[0];
+            );
+            if (preferredItem) {
+              menu.selectedItem = preferredItem;
+            } else {
+              // This shouldn't happen, but let's make sure we end up with a
+              // selected item:
+              let possible = possibleAppMenuItems
+                .map(v => v.handlerApp && v.handlerApp.name)
+                .join(", ");
+              Cu.reportError(
+                new Error(
+                  `Preferred handler for ${
+                    handlerInfo.type
+                  } not in list of possible handlers!? (List: ${possible})`
+                )
+              );
+              menu.selectedItem = askMenuItem;
+            }
           }
           break;
         case kActionUsePlugin:
-          menu.selectedItem = pluginMenuItem;
+          // The plugin may have been removed, if so, select 'always ask':
+          menu.selectedItem = pluginMenuItem || askMenuItem;
           break;
         case Ci.nsIHandlerInfo.saveToDisk:
           menu.selectedItem = saveMenuItem;
           break;
       }
     }
   },
 
@@ -3064,16 +3084,20 @@ class HandlerListItem {
       [null, APP_ICON_ATTR_NAME, actionIconClass],
       [
         ".actionIcon",
         "src",
         actionIconClass ? null : this.handlerInfoWrapper.actionIcon,
       ],
     ]);
     const selectedItem = this.node.querySelector("[selected=true]");
+    if (!selectedItem) {
+      Cu.reportError("No selected item for " + this.handlerInfoWrapper.type);
+      return;
+    }
     const { id, args } = document.l10n.getAttributes(selectedItem);
     localizeElement(this.node.querySelector(".actionDescription"), {
       id: id + "-label",
       args,
     });
     localizeElement(this.node.querySelector(".actionsMenu"), { id, args });
   }
 
@@ -3163,21 +3187,22 @@ class HandlerInfoWrapper {
    * than one object presents the same description, "disambiguateDescription"
    * is set and we annotate the duplicate descriptions with the type itself
    * to help users distinguish between those types.
    */
   get typeDescription() {
     if (this.disambiguateDescription) {
       const description = this.description;
       if (description.id) {
+        // Pass through the arguments:
+        let { args = {} } = description;
+        args.type = this.type;
         return {
           id: description.id + "-with-type",
-          args: {
-            type: this.type,
-          },
+          args,
         };
       }
 
       return {
         id: "applications-type-description-with-type",
         args: {
           "type-description": description.raw,
           type: this.type,
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -414,18 +414,18 @@ var gPrivacyPane = {
       "change",
       gPrivacyPane.networkCookieBehaviorReadPrefs.bind(gPrivacyPane)
     );
     Preferences.get("browser.privatebrowsing.autostart").on(
       "change",
       gPrivacyPane.networkCookieBehaviorReadPrefs.bind(gPrivacyPane)
     );
 
-    setEventListener("a11yPrivacyCheckbox", "command", function() {
-      return gPrivacyPane.updateA11yPrefs(this.checked);
+    setEventListener("a11yPrivacyCheckbox", "command", ev => {
+      this.updateA11yPrefs(ev.target.checked);
     });
 
     setEventListener(
       "trackingProtectionExceptions",
       "command",
       gPrivacyPane.showTrackingProtectionExceptions
     );
 
--- a/browser/components/preferences/in-content/tests/browser_extension_controlled.js
+++ b/browser/components/preferences/in-content/tests/browser_extension_controlled.js
@@ -1031,17 +1031,17 @@ add_task(async function testExtensionCon
       function getProxyControls() {
         let controlGroup = doc.getElementById("networkProxyType");
         let manualControlContainer = controlGroup.querySelector("#proxy-grid");
         return {
           manualControls: [
             ...manualControlContainer.querySelectorAll(
               "label[data-l10n-id]:not([control=networkProxyNone])"
             ),
-            ...manualControlContainer.querySelectorAll("textbox"),
+            ...manualControlContainer.querySelectorAll("input"),
             ...manualControlContainer.querySelectorAll("checkbox"),
             ...doc.querySelectorAll("#networkProxySOCKSVersion > radio"),
           ],
           pacControls: [doc.getElementById("networkProxyAutoconfigURL")],
           otherControls: [
             doc.querySelector("label[control=networkProxyNone]"),
             doc.getElementById("networkProxyNone"),
             ...controlGroup.querySelectorAll(":scope > radio"),
--- a/browser/components/tests/unit/test_distribution.js
+++ b/browser/components/tests/unit/test_distribution.js
@@ -34,17 +34,20 @@ AddonTestUtils.createAppInfo(
 add_task(async function setup() {
   await AddonTestUtils.promiseStartupManager();
 });
 
 // This test causes BrowserGlue to start but not fully initialise, when the
 // AddonManager shuts down BrowserGlue will then try to uninit which will
 // cause AutoComplete.jsm to throw an error.
 // TODO: Fix in https://bugzilla.mozilla.org/show_bug.cgi?id=1543112.
-PromiseTestUtils.whitelistRejectionsGlobally(/Component returned failure code/);
+PromiseTestUtils.whitelistRejectionsGlobally(/A request was aborted/);
+PromiseTestUtils.whitelistRejectionsGlobally(
+  /The operation failed for reasons unrelated/
+);
 
 const TOPICDATA_DISTRIBUTION_CUSTOMIZATION = "force-distribution-customization";
 const TOPIC_BROWSERGLUE_TEST = "browser-glue-test";
 
 /**
  * Copy the engine-distribution.xml engine to a fake distribution
  * created in the profile, and registered with the directory service.
  * Create an empty en-US directory to make sure it isn't used.
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -345,34 +345,27 @@ let ProfileAutocomplete = {
           break;
         }
         this._fillFromAutocompleteRow(FormAutofillContent.activeInput);
         break;
       }
     }
   },
 
-  _frameMMFromWindow(contentWindow) {
-    return contentWindow.docShell.messageManager;
+  getActorFromWindow(contentWindow) {
+    return contentWindow.getWindowGlobalChild().getActor("AutoComplete");
   },
 
   _getSelectedIndex(contentWindow) {
-    let mm = this._frameMMFromWindow(contentWindow);
-    let selectedIndexResult = mm.sendSyncMessage(
-      "FormAutoComplete:GetSelectedIndex",
-      {}
-    );
-    if (
-      selectedIndexResult.length != 1 ||
-      !Number.isInteger(selectedIndexResult[0])
-    ) {
+    let actor = this.getActorFromWindow(contentWindow);
+    if (!actor) {
       throw new Error("Invalid autocomplete selectedIndex");
     }
 
-    return selectedIndexResult[0];
+    return actor.selectedIndex;
   },
 
   _fillFromAutocompleteRow(focusedInput) {
     this.debug("_fillFromAutocompleteRow:", focusedInput);
     let formDetails = FormAutofillContent.activeFormDetails;
     if (!formDetails) {
       // The observer notification is for a different frame.
       return;
--- a/browser/extensions/formautofill/api.js
+++ b/browser/extensions/formautofill/api.js
@@ -18,16 +18,21 @@ ChromeUtils.defineModuleGetter(
   "FormAutofill",
   "resource://formautofill/FormAutofill.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
   "formAutofillParent",
   "resource://formautofill/FormAutofillParent.jsm"
 );
+ChromeUtils.defineModuleGetter(
+  this,
+  "AutoCompleteParent",
+  "resource://gre/actors/AutoCompleteParent.jsm"
+);
 
 XPCOMUtils.defineLazyServiceGetter(
   this,
   "resProto",
   "@mozilla.org/network/protocol;1?name=resource",
   "nsISubstitutingProtocolHandler"
 );
 
@@ -45,18 +50,17 @@ function insertStyleSheet(domWindow, url
 
   if (CACHED_STYLESHEETS.has(domWindow)) {
     CACHED_STYLESHEETS.get(domWindow).push(styleSheet);
   } else {
     CACHED_STYLESHEETS.set(domWindow, [styleSheet]);
   }
 }
 
-function onMaybeOpenPopup(evt) {
-  let domWindow = evt.target.ownerGlobal;
+function onMaybeOpenPopup(domWindow) {
   if (CACHED_STYLESHEETS.has(domWindow)) {
     // This window already has autofill stylesheets.
     return;
   }
 
   insertStyleSheet(domWindow, "chrome://formautofill/content/formautofill.css");
   insertStyleSheet(
     domWindow,
@@ -159,20 +163,17 @@ this.formautofill = class extends Extens
       );
     } else {
       Services.prefs.clearUserPref(
         "services.sync.engine.creditcards.available"
       );
     }
 
     // Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
-    Services.mm.addMessageListener(
-      "FormAutoComplete:MaybeOpenPopup",
-      onMaybeOpenPopup
-    );
+    AutoCompleteParent.addPopupStateListener(onMaybeOpenPopup);
 
     formAutofillParent.init().catch(Cu.reportError);
     Services.mm.loadFrameScript(
       "chrome://formautofill/content/FormAutofillFrameScript.js",
       true,
       true
     );
   }
@@ -188,20 +189,17 @@ this.formautofill = class extends Extens
     this.chromeHandle = null;
 
     if (this.autofillManifest) {
       Components.manager.removeBootstrappedManifestLocation(
         this.autofillManifest
       );
     }
 
-    Services.mm.removeMessageListener(
-      "FormAutoComplete:MaybeOpenPopup",
-      onMaybeOpenPopup
-    );
+    AutoCompleteParent.removePopupStateListener(onMaybeOpenPopup);
 
     for (let win of Services.wm.getEnumerator("navigator:browser")) {
       let cachedStyleSheets = CACHED_STYLESHEETS.get(win);
 
       if (!cachedStyleSheets) {
         continue;
       }
 
--- a/browser/extensions/formautofill/content/FormAutofillFrameScript.js
+++ b/browser/extensions/formautofill/content/FormAutofillFrameScript.js
@@ -26,26 +26,63 @@ ChromeUtils.defineModuleGetter(
   "FormAutofillContent",
   "resource://formautofill/FormAutofillContent.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
   "FormAutofillUtils",
   "resource://formautofill/FormAutofillUtils.jsm"
 );
+ChromeUtils.defineModuleGetter(
+  this,
+  "AutoCompleteChild",
+  "resource://gre/actors/AutoCompleteChild.jsm"
+);
 
 /**
  * Handles content's interactions for the frame.
  */
 var FormAutofillFrameScript = {
   _nextHandleElement: null,
   _alreadyDOMContentLoaded: false,
   _hasDOMContentLoadedHandler: false,
   _hasPendingTask: false,
 
+  popupStateListener(messageName, data, target) {
+    if (!content || !FormAutofill.isAutofillEnabled) {
+      return;
+    }
+
+    const doc = target.document;
+    const { chromeEventHandler } = doc.ownerGlobal.docShell;
+
+    switch (messageName) {
+      case "FormAutoComplete:PopupClosed": {
+        FormAutofillContent.onPopupClosed(data.selectedRowStyle);
+        Services.tm.dispatchToMainThread(() => {
+          chromeEventHandler.removeEventListener(
+            "keydown",
+            FormAutofillContent._onKeyDown,
+            true
+          );
+        });
+
+        break;
+      }
+      case "FormAutoComplete:PopupOpened": {
+        chromeEventHandler.addEventListener(
+          "keydown",
+          FormAutofillContent._onKeyDown,
+          true
+        );
+        break;
+      }
+    }
+  },
+
   _doIdentifyAutofillFields() {
     if (this._hasPendingTask) {
       return;
     }
     this._hasPendingTask = true;
 
     setTimeout(() => {
       FormAutofillContent.identifyAutofillFields(this._nextHandleElement);
@@ -56,36 +93,46 @@ var FormAutofillFrameScript = {
       sendAsyncMessage("FormAutofill:FieldsIdentified");
       FormAutofillContent.updateActiveInput();
     });
   },
 
   init() {
     addEventListener("focusin", this);
     addEventListener("DOMFormBeforeSubmit", this);
+    addEventListener("unload", this, { once: true });
     addMessageListener("FormAutofill:PreviewProfile", this);
     addMessageListener("FormAutofill:ClearForm", this);
-    addMessageListener("FormAutoComplete:PopupClosed", this);
-    addMessageListener("FormAutoComplete:PopupOpened", this);
+
+    AutoCompleteChild.addPopupStateListener(this.popupStateListener);
   },
 
   handleEvent(evt) {
-    if (!evt.isTrusted || !FormAutofill.isAutofillEnabled) {
+    if (!evt.isTrusted) {
       return;
     }
 
     switch (evt.type) {
       case "focusin": {
-        this.onFocusIn(evt);
+        if (FormAutofill.isAutofillEnabled) {
+          this.onFocusIn(evt);
+        }
         break;
       }
       case "DOMFormBeforeSubmit": {
-        this.onDOMFormBeforeSubmit(evt);
+        if (FormAutofill.isAutofillEnabled) {
+          this.onDOMFormBeforeSubmit(evt);
+        }
         break;
       }
+      case "unload": {
+        AutoCompleteChild.removePopupStateListener(this.popupStateListener);
+        break;
+      }
+
       default: {
         throw new Error("Unexpected event type");
       }
     }
   },
 
   onFocusIn(evt) {
     FormAutofillContent.updateActiveInput();
@@ -130,44 +177,23 @@ var FormAutofillFrameScript = {
   },
 
   receiveMessage(message) {
     if (!FormAutofill.isAutofillEnabled) {
       return;
     }
 
     const doc = content.document;
-    const { chromeEventHandler } = doc.ownerGlobal.docShell;
 
     switch (message.name) {
       case "FormAutofill:PreviewProfile": {
         FormAutofillContent.previewProfile(doc);
         break;
       }
       case "FormAutofill:ClearForm": {
         FormAutofillContent.clearForm();
         break;
       }
-      case "FormAutoComplete:PopupClosed": {
-        FormAutofillContent.onPopupClosed(message.data.selectedRowStyle);
-        Services.tm.dispatchToMainThread(() => {
-          chromeEventHandler.removeEventListener(
-            "keydown",
-            FormAutofillContent._onKeyDown,
-            true
-          );
-        });
-
-        break;
-      }
-      case "FormAutoComplete:PopupOpened": {
-        chromeEventHandler.addEventListener(
-          "keydown",
-          FormAutofillContent._onKeyDown,
-          true
-        );
-        break;
-      }
     }
   },
 };
 
 FormAutofillFrameScript.init();
--- a/browser/extensions/formautofill/content/customElements.js
+++ b/browser/extensions/formautofill/content/customElements.js
@@ -9,16 +9,35 @@
 "use strict";
 
 // Wrap in a block to prevent leaking to window scope.
 (() => {
   const { Services } = ChromeUtils.import(
     "resource://gre/modules/Services.jsm"
   );
 
+  function sendMessageToBrowser(msgName, data) {
+    let { AutoCompleteParent } = ChromeUtils.import(
+      "resource://gre/actors/AutoCompleteParent.jsm"
+    );
+
+    let browser = AutoCompleteParent.getCurrentBrowser();
+    if (!browser) {
+      return;
+    }
+
+    if (browser.messageManager) {
+      browser.messageManager.sendAsyncMessage(msgName, data);
+    } else {
+      Cu.reportError(
+        `customElements.js: No messageManager for message "${msgName}"`
+      );
+    }
+  }
+
   class MozAutocompleteProfileListitemBase extends MozElements.MozRichlistitem {
     constructor() {
       super();
 
       /**
        * For form autofill, we want to unify the selection no matter by
        * keyboard navigation or mouseover in order not to confuse user which
        * profile preview is being shown. This field is set to true to indicate
@@ -106,20 +125,17 @@
 
     set selected(val) {
       if (val) {
         this.setAttribute("selected", "true");
       } else {
         this.removeAttribute("selected");
       }
 
-      let { AutoCompletePopup } = ChromeUtils.import(
-        "resource://gre/modules/AutoCompletePopup.jsm"
-      );
-      AutoCompletePopup.sendMessageToBrowser("FormAutofill:PreviewProfile");
+      sendMessageToBrowser("FormAutofill:PreviewProfile");
 
       return val;
     }
 
     get selected() {
       return this.getAttribute("selected") == "true";
     }
 
@@ -345,20 +361,17 @@
     constructor() {
       super();
 
       this.addEventListener("click", event => {
         if (event.button != 0) {
           return;
         }
 
-        let { AutoCompletePopup } = ChromeUtils.import(
-          "resource://gre/modules/AutoCompletePopup.jsm"
-        );
-        AutoCompletePopup.sendMessageToBrowser("FormAutofill:ClearForm");
+        sendMessageToBrowser("FormAutofill:ClearForm");
       });
     }
 
     connectedCallback() {
       if (this.delayConnectedCallback()) {
         return;
       }
 
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 2.3.194
+Current extension version is: 2.4.15
 
-Taken from upstream commit: cd909c53
+Taken from upstream commit: cead77ef
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.3.194';
-var pdfjsBuild = 'cd909c53';
+var pdfjsVersion = '2.4.15';
+var pdfjsBuild = 'cead77ef';
 
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 
 var pdfjsDisplayAPI = __w_pdfjs_require__(5);
 
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(17);
 
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(18);
@@ -221,17 +221,17 @@ exports.utf8StringToString = utf8StringT
 exports.warn = warn;
 exports.unreachable = unreachable;
 Object.defineProperty(exports, "ReadableStream", {
   enumerable: true,
   get: function () {
     return _streams_polyfill.ReadableStream;
   }
 });
-exports.createObjectURL = exports.FormatError = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = void 0;
+exports.createObjectURL = exports.FormatError = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = exports.BaseException = void 0;
 
 __w_pdfjs_require__(2);
 
 var _streams_polyfill = __w_pdfjs_require__(4);
 
 const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
 const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
@@ -604,107 +604,76 @@ function shadow(obj, prop, value) {
     value,
     enumerable: true,
     configurable: true,
     writable: false
   });
   return value;
 }
 
-const PasswordException = function PasswordExceptionClosure() {
-  function PasswordException(msg, code) {
-    this.name = 'PasswordException';
-    this.message = msg;
+const BaseException = function BaseExceptionClosure() {
+  function BaseException(message) {
+    if (this.constructor === BaseException) {
+      unreachable('Cannot initialize BaseException.');
+    }
+
+    this.message = message;
+    this.name = this.constructor.name;
+  }
+
+  BaseException.prototype = new Error();
+  BaseException.constructor = BaseException;
+  return BaseException;
+}();
+
+exports.BaseException = BaseException;
+
+class PasswordException extends BaseException {
+  constructor(msg, code) {
+    super(msg);
     this.code = code;
   }
 
-  PasswordException.prototype = new Error();
-  PasswordException.constructor = PasswordException;
-  return PasswordException;
-}();
+}
 
 exports.PasswordException = PasswordException;
 
-const UnknownErrorException = function UnknownErrorExceptionClosure() {
-  function UnknownErrorException(msg, details) {
-    this.name = 'UnknownErrorException';
-    this.message = msg;
+class UnknownErrorException extends BaseException {
+  constructor(msg, details) {
+    super(msg);
     this.details = details;
   }
 
-  UnknownErrorException.prototype = new Error();
-  UnknownErrorException.constructor = UnknownErrorException;
-  return UnknownErrorException;
-}();
+}
 
 exports.UnknownErrorException = UnknownErrorException;
 
-const InvalidPDFException = function InvalidPDFExceptionClosure() {
-  function InvalidPDFException(msg) {
-    this.name = 'InvalidPDFException';
-    this.message = msg;
-  }
-
-  InvalidPDFException.prototype = new Error();
-  InvalidPDFException.constructor = InvalidPDFException;
-  return InvalidPDFException;
-}();
+class InvalidPDFException extends BaseException {}
 
 exports.InvalidPDFException = InvalidPDFException;
 
-const MissingPDFException = function MissingPDFExceptionClosure() {
-  function MissingPDFException(msg) {
-    this.name = 'MissingPDFException';
-    this.message = msg;
-  }
-
-  MissingPDFException.prototype = new Error();
-  MissingPDFException.constructor = MissingPDFException;
-  return MissingPDFException;
-}();
+class MissingPDFException extends BaseException {}
 
 exports.MissingPDFException = MissingPDFException;
 
-const UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
-  function UnexpectedResponseException(msg, status) {
-    this.name = 'UnexpectedResponseException';
-    this.message = msg;
+class UnexpectedResponseException extends BaseException {
+  constructor(msg, status) {
+    super(msg);
     this.status = status;
   }
 
-  UnexpectedResponseException.prototype = new Error();
-  UnexpectedResponseException.constructor = UnexpectedResponseException;
-  return UnexpectedResponseException;
-}();
+}
 
 exports.UnexpectedResponseException = UnexpectedResponseException;
 
-const FormatError = function FormatErrorClosure() {
-  function FormatError(msg) {
-    this.message = msg;
-  }
-
-  FormatError.prototype = new Error();
-  FormatError.prototype.name = 'FormatError';
-  FormatError.constructor = FormatError;
-  return FormatError;
-}();
+class FormatError extends BaseException {}
 
 exports.FormatError = FormatError;
 
-const AbortException = function AbortExceptionClosure() {
-  function AbortException(msg) {
-    this.name = 'AbortException';
-    this.message = msg;
-  }
-
-  AbortException.prototype = new Error();
-  AbortException.constructor = AbortException;
-  return AbortException;
-}();
+class AbortException extends BaseException {}
 
 exports.AbortException = AbortException;
 const NullCharactersRegExp = /\x00/g;
 
 function removeNullCharacters(str) {
   if (typeof str !== 'string') {
     warn('The argument for removeNullCharacters must be a string.');
     return str;
@@ -1297,17 +1266,17 @@ function _fetchDocument(worker, source, 
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
     source.progressiveDone = pdfDataRangeTransport.progressiveDone;
   }
 
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.3.194',
+    apiVersion: '2.4.15',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -2048,17 +2017,25 @@ class LoopbackPort {
       for (const i in value) {
         let desc,
             p = value;
 
         while (!(desc = Object.getOwnPropertyDescriptor(p, i))) {
           p = Object.getPrototypeOf(p);
         }
 
-        if (typeof desc.value === 'undefined' || typeof desc.value === 'function') {
+        if (typeof desc.value === 'undefined') {
+          continue;
+        }
+
+        if (typeof desc.value === 'function') {
+          if (value.hasOwnProperty && value.hasOwnProperty(i)) {
+            throw new Error(`LoopbackPort.postMessage - cannot clone: ${value[i]}`);
+          }
+
           continue;
         }
 
         result[i] = cloneValue(desc.value);
       }
 
       return result;
     }
@@ -3194,19 +3171,19 @@ const InternalRenderTask = function Inte
       }
     }
 
   }
 
   return InternalRenderTask;
 }();
 
-const version = '2.3.194';
+const version = '2.4.15';
 exports.version = version;
-const build = 'cd909c53';
+const build = 'cead77ef';
 exports.build = build;
 
 /***/ }),
 /* 6 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
@@ -3447,27 +3424,23 @@ class PageViewport {
   convertToPdfPoint(x, y) {
     return _util.Util.applyInverseTransform([x, y], this.transform);
   }
 
 }
 
 exports.PageViewport = PageViewport;
 
-const RenderingCancelledException = function RenderingCancelledException() {
-  function RenderingCancelledException(msg, type) {
-    this.message = msg;
+class RenderingCancelledException extends _util.BaseException {
+  constructor(msg, type) {
+    super(msg);
     this.type = type;
   }
 
-  RenderingCancelledException.prototype = new Error();
-  RenderingCancelledException.prototype.name = 'RenderingCancelledException';
-  RenderingCancelledException.constructor = RenderingCancelledException;
-  return RenderingCancelledException;
-}();
+}
 
 exports.RenderingCancelledException = RenderingCancelledException;
 const LinkTarget = {
   NONE: 0,
   SELF: 1,
   BLANK: 2,
   PARENT: 3,
   TOP: 4
@@ -6496,17 +6469,17 @@ const StreamKind = {
   ENQUEUE: 4,
   ERROR: 5,
   PULL: 6,
   PULL_COMPLETE: 7,
   START_COMPLETE: 8
 };
 
 function wrapReason(reason) {
-  if (typeof reason !== 'object') {
+  if (typeof reason !== 'object' || reason === null) {
     return reason;
   }
 
   switch (reason.name) {
     case 'AbortException':
       return new _util.AbortException(reason.message);
 
     case 'MissingPDFException':
@@ -6787,24 +6760,16 @@ MessageHandler.prototype = {
   },
 
   _processStreamMessage(data) {
     let sourceName = this.sourceName;
     let targetName = data.sourceName;
     const streamId = data.streamId;
     const comObj = this.comObj;
 
-    let deleteStreamController = () => {
-      Promise.all([this.streamControllers[streamId].startCall, this.streamControllers[streamId].pullCall, this.streamControllers[streamId].cancelCall].map(function (capability) {
-        return capability && capability.promise.catch(function () {});
-      })).then(() => {
-        delete this.streamControllers[streamId];
-      });
-    };
-
     switch (data.stream) {
       case StreamKind.START_COMPLETE:
         if (data.success) {
           this.streamControllers[streamId].startCall.resolve();
         } else {
           this.streamControllers[streamId].startCall.reject(wrapReason(data.reason));
         }
 
@@ -6874,33 +6839,38 @@ MessageHandler.prototype = {
         (0, _util.assert)(this.streamControllers[streamId], 'close should have stream controller');
 
         if (this.streamControllers[streamId].isClosed) {
           break;
         }
 
         this.streamControllers[streamId].isClosed = true;
         this.streamControllers[streamId].controller.close();
-        deleteStreamController();
+
+        this._deleteStreamController(streamId);
+
         break;
 
       case StreamKind.ERROR:
         (0, _util.assert)(this.streamControllers[streamId], 'error should have stream controller');
         this.streamControllers[streamId].controller.error(wrapReason(data.reason));
-        deleteStreamController();
+
+        this._deleteStreamController(streamId);
+
         break;
 
       case StreamKind.CANCEL_COMPLETE:
         if (data.success) {
           this.streamControllers[streamId].cancelCall.resolve();
         } else {
           this.streamControllers[streamId].cancelCall.reject(wrapReason(data.reason));
         }
 
-        deleteStreamController();
+        this._deleteStreamController(streamId);
+
         break;
 
       case StreamKind.CANCEL:
         if (!this.streamSinks[streamId]) {
           break;
         }
 
         const {
@@ -6930,16 +6900,23 @@ MessageHandler.prototype = {
         delete this.streamSinks[streamId];
         break;
 
       default:
         throw new Error('Unexpected stream case');
     }
   },
 
+  async _deleteStreamController(streamId) {
+    await Promise.all([this.streamControllers[streamId].startCall, this.streamControllers[streamId].pullCall, this.streamControllers[streamId].cancelCall].map(function (capability) {
+      return capability && capability.promise.catch(function () {});
+    }));
+    delete this.streamControllers[streamId];
+  },
+
   postMessage(message, transfers) {
     if (transfers && this.postMessageTransfers) {
       this.comObj.postMessage(message, transfers);
     } else {
       this.comObj.postMessage(message);
     }
   },
 
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-const pdfjsVersion = '2.3.194';
-const pdfjsBuild = 'cd909c53';
+const pdfjsVersion = '2.4.15';
+const pdfjsBuild = 'cead77ef';
 
 const pdfjsCoreWorker = __w_pdfjs_require__(1);
 
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
@@ -220,17 +220,17 @@ var WorkerMessageHandler = {
 
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     const verbosity = (0, _util.getVerbosityLevel)();
     const apiVersion = docParams.apiVersion;
-    const workerVersion = '2.3.194';
+    const workerVersion = '2.4.15';
 
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
 
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + '_worker';
@@ -702,17 +702,17 @@ exports.utf8StringToString = utf8StringT
 exports.warn = warn;
 exports.unreachable = unreachable;
 Object.defineProperty(exports, "ReadableStream", {
   enumerable: true,
   get: function () {
     return _streams_polyfill.ReadableStream;
   }
 });
-exports.createObjectURL = exports.FormatError = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = void 0;
+exports.createObjectURL = exports.FormatError = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = exports.BaseException = void 0;
 
 __w_pdfjs_require__(3);
 
 var _streams_polyfill = __w_pdfjs_require__(5);
 
 const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
 const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
@@ -1085,107 +1085,76 @@ function shadow(obj, prop, value) {
     value,
     enumerable: true,
     configurable: true,
     writable: false
   });
   return value;
 }
 
-const PasswordException = function PasswordExceptionClosure() {
-  function PasswordException(msg, code) {
-    this.name = 'PasswordException';
-    this.message = msg;
+const BaseException = function BaseExceptionClosure() {
+  function BaseException(message) {
+    if (this.constructor === BaseException) {
+      unreachable('Cannot initialize BaseException.');
+    }
+
+    this.message = message;
+    this.name = this.constructor.name;
+  }
+
+  BaseException.prototype = new Error();
+  BaseException.constructor = BaseException;
+  return BaseException;
+}();
+
+exports.BaseException = BaseException;
+
+class PasswordException extends BaseException {
+  constructor(msg, code) {
+    super(msg);
     this.code = code;
   }
 
-  PasswordException.prototype = new Error();
-  PasswordException.constructor = PasswordException;
-  return PasswordException;
-}();
+}
 
 exports.PasswordException = PasswordException;
 
-const UnknownErrorException = function UnknownErrorExceptionClosure() {
-  function UnknownErrorException(msg, details) {
-    this.name = 'UnknownErrorException';
-    this.message = msg;
+class UnknownErrorException extends BaseException {
+  constructor(msg, details) {
+    super(msg);
     this.details = details;
   }
 
-  UnknownErrorException.prototype = new Error();
-  UnknownErrorException.constructor = UnknownErrorException;
-  return UnknownErrorException;
-}();
+}
 
 exports.UnknownErrorException = UnknownErrorException;
 
-const InvalidPDFException = function InvalidPDFExceptionClosure() {
-  function InvalidPDFException(msg) {
-    this.name = 'InvalidPDFException';
-    this.message = msg;
-  }
-
-  InvalidPDFException.prototype = new Error();
-  InvalidPDFException.constructor = InvalidPDFException;
-  return InvalidPDFException;
-}();
+class InvalidPDFException extends BaseException {}
 
 exports.InvalidPDFException = InvalidPDFException;
 
-const MissingPDFException = function MissingPDFExceptionClosure() {
-  function MissingPDFException(msg) {
-    this.name = 'MissingPDFException';
-    this.message = msg;
-  }
-
-  MissingPDFException.prototype = new Error();
-  MissingPDFException.constructor = MissingPDFException;
-  return MissingPDFException;
-}();
+class MissingPDFException extends BaseException {}
 
 exports.MissingPDFException = MissingPDFException;
 
-const UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
-  function UnexpectedResponseException(msg, status) {
-    this.name = 'UnexpectedResponseException';
-    this.message = msg;
+class UnexpectedResponseException extends BaseException {
+  constructor(msg, status) {
+    super(msg);
     this.status = status;
   }
 
-  UnexpectedResponseException.prototype = new Error();
-  UnexpectedResponseException.constructor = UnexpectedResponseException;
-  return UnexpectedResponseException;
-}();
+}
 
 exports.UnexpectedResponseException = UnexpectedResponseException;
 
-const FormatError = function FormatErrorClosure() {
-  function FormatError(msg) {
-    this.message = msg;
-  }
-
-  FormatError.prototype = new Error();
-  FormatError.prototype.name = 'FormatError';
-  FormatError.constructor = FormatError;
-  return FormatError;
-}();
+class FormatError extends BaseException {}
 
 exports.FormatError = FormatError;
 
-const AbortException = function AbortExceptionClosure() {
-  function AbortException(msg) {
-    this.name = 'AbortException';
-    this.message = msg;
-  }
-
-  AbortException.prototype = new Error();
-  AbortException.constructor = AbortException;
-  return AbortException;
-}();
+class AbortException extends BaseException {}
 
 exports.AbortException = AbortException;
 const NullCharactersRegExp = /\x00/g;
 
 function removeNullCharacters(str) {
   if (typeof str !== 'string') {
     warn('The argument for removeNullCharacters must be a string.');
     return str;
@@ -2714,54 +2683,32 @@ function getLookupTableFactory(initializ
       initializer(lookup);
       initializer = null;
     }
 
     return lookup;
   };
 }
 
-const MissingDataException = function MissingDataExceptionClosure() {
-  function MissingDataException(begin, end) {
+class MissingDataException extends _util.BaseException {
+  constructor(begin, end) {
+    super(`Missing data [${begin}, ${end})`);
     this.begin = begin;
     this.end = end;
-    this.message = `Missing data [${begin}, ${end})`;
-  }
-
-  MissingDataException.prototype = new Error();
-  MissingDataException.prototype.name = 'MissingDataException';
-  MissingDataException.constructor = MissingDataException;
-  return MissingDataException;
-}();
+  }
+
+}
 
 exports.MissingDataException = MissingDataException;
 
-const XRefEntryException = function XRefEntryExceptionClosure() {
-  function XRefEntryException(msg) {
-    this.message = msg;
-  }
-
-  XRefEntryException.prototype = new Error();
-  XRefEntryException.prototype.name = 'XRefEntryException';
-  XRefEntryException.constructor = XRefEntryException;
-  return XRefEntryException;
-}();
+class XRefEntryException extends _util.BaseException {}
 
 exports.XRefEntryException = XRefEntryException;
 
-const XRefParseException = function XRefParseExceptionClosure() {
-  function XRefParseException(msg) {
-    this.message = msg;
-  }
-
-  XRefParseException.prototype = new Error();
-  XRefParseException.prototype.name = 'XRefParseException';
-  XRefParseException.constructor = XRefParseException;
-  return XRefParseException;
-}();
+class XRefParseException extends _util.BaseException {}
 
 exports.XRefParseException = XRefParseException;
 
 function getInheritableProperty({
   dict,
   key,
   getArray = false,
   stopWhenFound = true
@@ -9212,26 +9159,22 @@ Object.defineProperty(exports, "__esModu
 exports.Jbig2Image = void 0;
 
 var _util = __w_pdfjs_require__(2);
 
 var _arithmetic_decoder = __w_pdfjs_require__(18);
 
 var _ccitt = __w_pdfjs_require__(15);
 
-let Jbig2Error = function Jbig2ErrorClosure() {
-  function Jbig2Error(msg) {
-    this.message = 'JBIG2 error: ' + msg;
-  }
-
-  Jbig2Error.prototype = new Error();
-  Jbig2Error.prototype.name = 'Jbig2Error';
-  Jbig2Error.constructor = Jbig2Error;
-  return Jbig2Error;
-}();
+class Jbig2Error extends _util.BaseException {
+  constructor(msg) {
+    super(`JBIG2 error: ${msg}`);
+  }
+
+}
 
 var Jbig2Image = function Jbig2ImageClosure() {
   function ContextCache() {}
 
   ContextCache.prototype = {
     getContexts(id) {
       if (id in this) {
         return this[id];
@@ -11886,49 +11829,32 @@ exports.JpegStream = JpegStream;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.JpegImage = void 0;
 
 var _util = __w_pdfjs_require__(2);
 
-let JpegError = function JpegErrorClosure() {
-  function JpegError(msg) {
-    this.message = 'JPEG error: ' + msg;
-  }
-
-  JpegError.prototype = new Error();
-  JpegError.prototype.name = 'JpegError';
-  JpegError.constructor = JpegError;
-  return JpegError;
-}();
-
-let DNLMarkerError = function DNLMarkerErrorClosure() {
-  function DNLMarkerError(message, scanLines) {
-    this.message = message;
+class JpegError extends _util.BaseException {
+  constructor(msg) {
+    super(`JPEG error: ${msg}`);
+  }
+
+}
+
+class DNLMarkerError extends _util.BaseException {
+  constructor(message, scanLines) {
+    super(message);
     this.scanLines = scanLines;
   }
 
-  DNLMarkerError.prototype = new Error();
-  DNLMarkerError.prototype.name = 'DNLMarkerError';
-  DNLMarkerError.constructor = DNLMarkerError;
-  return DNLMarkerError;
-}();
-
-let EOIMarkerError = function EOIMarkerErrorClosure() {
-  function EOIMarkerError(message) {
-    this.message = message;
-  }
-
-  EOIMarkerError.prototype = new Error();
-  EOIMarkerError.prototype.name = 'EOIMarkerError';
-  EOIMarkerError.constructor = EOIMarkerError;
-  return EOIMarkerError;
-}();
+}
+
+class EOIMarkerError extends _util.BaseException {}
 
 var JpegImage = function JpegImageClosure() {
   var dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]);
   var dctCos1 = 4017;
   var dctSin1 = 799;
   var dctCos3 = 3406;
   var dctSin3 = 2276;
   var dctCos6 = 1567;
@@ -13162,26 +13088,22 @@ Object.defineProperty(exports, "__esModu
   value: true
 });
 exports.JpxImage = void 0;
 
 var _util = __w_pdfjs_require__(2);
 
 var _arithmetic_decoder = __w_pdfjs_require__(18);
 
-let JpxError = function JpxErrorClosure() {
-  function JpxError(msg) {
-    this.message = 'JPX error: ' + msg;
-  }
-
-  JpxError.prototype = new Error();
-  JpxError.prototype.name = 'JpxError';
-  JpxError.constructor = JpxError;
-  return JpxError;
-}();
+class JpxError extends _util.BaseException {
+  constructor(msg) {
+    super(`JPX error: ${msg}`);
+  }
+
+}
 
 var JpxImage = function JpxImageClosure() {
   var SubbandsGainLog2 = {
     'LL': 0,
     'LH': 1,
     'HL': 1,
     'HH': 2
   };
@@ -21801,17 +21723,17 @@ var PartialEvaluator = function PartialE
         if (cidToGidBytes) {
           properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, toUnicode);
         }
 
         return properties;
       });
     },
 
-    _buildSimpleFontToUnicode(properties) {
+    _buildSimpleFontToUnicode(properties, forceGlyphs = false) {
       (0, _util.assert)(!properties.composite, 'Must be a simple font.');
       let toUnicode = [],
           charcode,
           glyphName;
       let encoding = properties.defaultEncoding.slice();
       let baseEncodingName = properties.baseEncodingName;
       let differences = properties.differences;
 
@@ -21847,18 +21769,29 @@ var PartialEvaluator = function PartialE
               if (glyphName.length === 5) {
                 code = parseInt(glyphName.substring(1), 16);
               }
 
               break;
 
             case 'C':
             case 'c':
-              if (glyphName.length >= 3) {
-                code = +glyphName.substring(1);
+              if (glyphName.length >= 3 && glyphName.length <= 4) {
+                const codeStr = glyphName.substring(1);
+
+                if (forceGlyphs) {
+                  code = parseInt(codeStr, 16);
+                  break;
+                }
+
+                code = +codeStr;
+
+                if (Number.isNaN(code) && Number.isInteger(parseInt(codeStr, 16))) {
+                  return this._buildSimpleFontToUnicode(properties, true);
+                }
               }
 
               break;
 
             default:
               let unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
 
               if (unicode !== -1) {
@@ -44718,17 +44651,17 @@ const StreamKind = {
   ENQUEUE: 4,
   ERROR: 5,
   PULL: 6,
   PULL_COMPLETE: 7,
   START_COMPLETE: 8
 };
 
 function wrapReason(reason) {
-  if (typeof reason !== 'object') {
+  if (typeof reason !== 'object' || reason === null) {
     return reason;
   }
 
   switch (reason.name) {
     case 'AbortException':
       return new _util.AbortException(reason.message);
 
     case 'MissingPDFException':
@@ -45009,24 +44942,16 @@ MessageHandler.prototype = {
   },
 
   _processStreamMessage(data) {
     let sourceName = this.sourceName;
     let targetName = data.sourceName;
     const streamId = data.streamId;
     const comObj = this.comObj;
 
-    let deleteStreamController = () => {
-      Promise.all([this.streamControllers[streamId].startCall, this.streamControllers[streamId].pullCall, this.streamControllers[streamId].cancelCall].map(function (capability) {
-        return capability && capability.promise.catch(function () {});
-      })).then(() => {
-        delete this.streamControllers[streamId];
-      });
-    };
-
     switch (data.stream) {
       case StreamKind.START_COMPLETE:
         if (data.success) {
           this.streamControllers[streamId].startCall.resolve();
         } else {
           this.streamControllers[streamId].startCall.reject(wrapReason(data.reason));
         }
 
@@ -45096,33 +45021,38 @@ MessageHandler.prototype = {
         (0, _util.assert)(this.streamControllers[streamId], 'close should have stream controller');
 
         if (this.streamControllers[streamId].isClosed) {
           break;
         }
 
         this.streamControllers[streamId].isClosed = true;
         this.streamControllers[streamId].controller.close();
-        deleteStreamController();
+
+        this._deleteStreamController(streamId);
+
         break;
 
       case StreamKind.ERROR:
         (0, _util.assert)(this.streamControllers[streamId], 'error should have stream controller');
         this.streamControllers[streamId].controller.error(wrapReason(data.reason));
-        deleteStreamController();
+
+        this._deleteStreamController(streamId);
+
         break;
 
       case StreamKind.CANCEL_COMPLETE:
         if (data.success) {
           this.streamControllers[streamId].cancelCall.resolve();
         } else {
           this.streamControllers[streamId].cancelCall.reject(wrapReason(data.reason));
         }
 
-        deleteStreamController();
+        this._deleteStreamController(streamId);
+
         break;
 
       case StreamKind.CANCEL:
         if (!this.streamSinks[streamId]) {
           break;
         }
 
         const {
@@ -45152,16 +45082,23 @@ MessageHandler.prototype = {
         delete this.streamSinks[streamId];
         break;
 
       default:
         throw new Error('Unexpected stream case');
     }
   },
 
+  async _deleteStreamController(streamId) {
+    await Promise.all([this.streamControllers[streamId].startCall, this.streamControllers[streamId].pullCall, this.streamControllers[streamId].cancelCall].map(function (capability) {
+      return capability && capability.promise.catch(function () {});
+    }));
+    delete this.streamControllers[streamId];
+  },
+
   postMessage(message, transfers) {
     if (transfers && this.postMessageTransfers) {
       this.comObj.postMessage(message, transfers);
     } else {
       this.comObj.postMessage(message);
     }
   },
 
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -2420,16 +2420,17 @@ exports.PDFPrintServiceFactory = PDFPrin
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.isValidRotation = isValidRotation;
 exports.isValidScrollMode = isValidScrollMode;
 exports.isValidSpreadMode = isValidSpreadMode;
 exports.isPortraitOrientation = isPortraitOrientation;
 exports.getGlobalEventBus = getGlobalEventBus;
+exports.clamp = clamp;
 exports.getPDFFileNameFromURL = getPDFFileNameFromURL;
 exports.noContextMenuHandler = noContextMenuHandler;
 exports.parseQueryString = parseQueryString;
 exports.backtrackBeforeAllVisibleElements = backtrackBeforeAllVisibleElements;
 exports.getVisibleElements = getVisibleElements;
 exports.roundToDivide = roundToDivide;
 exports.getPageSizeInches = getPageSizeInches;
 exports.approximateFraction = approximateFraction;
@@ -7455,22 +7456,16 @@ class PDFSidebarResizer {
     this.doc = document.documentElement;
     this._width = null;
     this._outerContainerWidth = null;
     this._boundEvents = Object.create(null);
     this.outerContainer = options.outerContainer;
     this.resizer = options.resizer;
     this.eventBus = eventBus;
     this.l10n = l10n;
-
-    if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function' || !CSS.supports(SIDEBAR_WIDTH_VAR, `calc(-1 * ${SIDEBAR_MIN_WIDTH}px)`)) {
-      console.warn('PDFSidebarResizer: ' + 'The browser does not support resizing of the sidebar.');
-      return;
-    }
-
     this.enabled = true;
     this.resizer.classList.remove('hidden');
     this.l10n.getDirection().then(dir => {
       this.isRTL = dir === 'rtl';
     });
 
     this._addEventListeners();
   }
@@ -7483,32 +7478,24 @@ class PDFSidebarResizer {
     return this._outerContainerWidth;
   }
 
   _updateWidth(width = 0) {
     if (!this.enabled) {
       return false;
     }
 
-    const maxWidth = Math.floor(this.outerContainerWidth / 2);
-
-    if (width > maxWidth) {
-      width = maxWidth;
-    }
-
-    if (width < SIDEBAR_MIN_WIDTH) {
-      width = SIDEBAR_MIN_WIDTH;
-    }
-
-    if (width === this._width) {
+    const newWidth = (0, _ui_utils.clamp)(width, SIDEBAR_MIN_WIDTH, Math.floor(this.outerContainerWidth / 2));
+
+    if (newWidth === this._width) {
       return false;
     }
 
-    this._width = width;
-    this.doc.style.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`);
+    this._width = newWidth;
+    this.doc.style.setProperty(SIDEBAR_WIDTH_VAR, `${newWidth}px`);
     return true;
   }
 
   _mouseMove(evt) {
     let width = evt.clientX;
 
     if (this.isRTL) {
       width = this.outerContainerWidth - width;
@@ -7543,39 +7530,45 @@ class PDFSidebarResizer {
       this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
       window.addEventListener('mousemove', _boundEvents.mouseMove);
       window.addEventListener('mouseup', _boundEvents.mouseUp);
     });
     this.eventBus.on('sidebarviewchanged', evt => {
       this.sidebarOpen = !!(evt && evt.view);
     });
     this.eventBus.on('resize', evt => {
-      if (evt && evt.source === window) {
-        this._outerContainerWidth = null;
-
-        if (this._width) {
-          if (this.sidebarOpen) {
-            this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
-
-            let updated = this._updateWidth(this._width);
-
-            Promise.resolve().then(() => {
-              this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
-
-              if (updated) {
-                this.eventBus.dispatch('resize', {
-                  source: this
-                });
-              }
-            });
-          } else {
-            this._updateWidth(this._width);
-          }
-        }
-      }
+      if (!evt || evt.source !== window) {
+        return;
+      }
+
+      this._outerContainerWidth = null;
+
+      if (!this._width) {
+        return;
+      }
+
+      if (!this.sidebarOpen) {
+        this._updateWidth(this._width);
+
+        return;
+      }
+
+      this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
+
+      let updated = this._updateWidth(this._width);
+
+      Promise.resolve().then(() => {
+        this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
+
+        if (updated) {
+          this.eventBus.dispatch('resize', {
+            source: this
+          });
+        }
+      });
     });
   }
 
 }
 
 exports.PDFSidebarResizer = PDFSidebarResizer;
 
 /***/ }),
--- a/browser/extensions/pdfjs/moz.yaml
+++ b/browser/extensions/pdfjs/moz.yaml
@@ -15,15 +15,15 @@ origin:
   description: Portable Document Format (PDF) viewer that is built with HTML5
 
   # Full URL for the package's homepage/etc
   # Usually different from repository url
   url: https://github.com/mozilla/pdf.js
 
   # Human-readable identifier for this version/release
   # Generally "version NNN", "tag SSS", "bookmark SSS"
-  release: version 2.3.194
+  release: version 2.4.15
 
   # The package's license, where possible using the mnemonic from
   # https://spdx.org/licenses/
   # Multiple licenses can be specified (as a YAML list)
   # A "LICENSE" file must exist containing the full license text
   license: Apache-2.0
--- a/browser/locales/en-US/browser/policies/policies-descriptions.ftl
+++ b/browser/locales/en-US/browser/policies/policies-descriptions.ftl
@@ -49,16 +49,18 @@ policy-DisableFirefoxScreenshots = Disab
 policy-DisableFirefoxStudies = Prevent { -brand-short-name } from running studies.
 
 policy-DisableForgetButton = Prevent access to the Forget button.
 
 policy-DisableFormHistory = Don’t remember search and form history.
 
 policy-DisableMasterPasswordCreation = If true, a master password can’t be created.
 
+policy-DisablePasswordReveal = Do not allow passwords to be revealed in saved logins.
+
 policy-DisablePocket = Disable the feature to save webpages to Pocket.
 
 policy-DisablePrivateBrowsing = Disable Private Browsing.
 
 policy-DisableProfileImport = Disable the menu command to Import data from another browser.
 
 policy-DisableProfileRefresh = Disable the Refresh { -brand-short-name } button in the about:support page.
 
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -349,16 +349,21 @@ applications-type-pdf = Portable Documen
 applications-type-pdf-with-type = { applications-type-pdf } ({ $type })
 
 # Variables:
 #   $type-description (String) - Description of the type (e.g "Portable Document Format")
 #   $type (String) - the MIME type (e.g application/binary)
 applications-type-description-with-type = { $type-description } ({ $type })
 
 # Variables:
+#   $extension (String) - file extension (e.g .TXT)
+#   $type (String) - the MIME type (e.g application/binary)
+applications-file-ending-with-type = { applications-file-ending } ({ $type })
+
+# Variables:
 #   $plugin-name (String) - Name of a plugin (e.g Adobe Flash)
 applications-use-plugin-in =
     .label = Use { $plugin-name } (in { -brand-short-name })
 applications-preview-inapp =
     .label = Preview in { -brand-short-name }
 
 ## The strings in this group are used to populate
 ## selected label element based on the string from
--- a/devtools/client/debugger/test/mochitest/helpers.js
+++ b/devtools/client/debugger/test/mochitest/helpers.js
@@ -547,16 +547,17 @@ function isSelectedFrameSelected(dbg, st
 
 /**
  * Clear all the debugger related preferences.
  */
 async function clearDebuggerPreferences(prefs = []) {
   resetSchemaVersion();
   asyncStorage.clear();
   Services.prefs.clearUserPref("devtools.recordreplay.enabled");
+  Services.prefs.clearUserPref("devtools.debugger.alphabetize-outline");
   Services.prefs.clearUserPref("devtools.debugger.pause-on-exceptions");
   Services.prefs.clearUserPref("devtools.debugger.pause-on-caught-exceptions");
   Services.prefs.clearUserPref("devtools.debugger.ignore-caught-exceptions");
   Services.prefs.clearUserPref("devtools.debugger.pending-selected-location");
   Services.prefs.clearUserPref("devtools.debugger.expressions");
   Services.prefs.clearUserPref("devtools.debugger.call-stack-visible");
   Services.prefs.clearUserPref("devtools.debugger.scopes-visible");
   Services.prefs.clearUserPref("devtools.debugger.skip-pausing");
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -406,17 +406,17 @@ var gDevToolsBrowser = (exports.gDevTool
   openContentProcessToolbox(gBrowser) {
     const { childCount } = Services.ppmm;
     // Get the process message manager for the current tab
     const mm = gBrowser.selectedBrowser.messageManager.processMessageManager;
     let processId = null;
     for (let i = 1; i < childCount; i++) {
       const child = Services.ppmm.getChildAt(i);
       if (child == mm) {
-        processId = i;
+        processId = mm.osPid;
         break;
       }
     }
     if (processId) {
       return this._getContentProcessTarget(processId)
         .then(target => {
           // Display a new toolbox in a new window
           return gDevTools.showToolbox(target, null, Toolbox.HostType.WINDOW);
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -1099,17 +1099,18 @@ class HighlightersOverlay {
    *         The function that will hide the highlighter of the highlighted node.
    */
   async _hideHighlighterIfDeadNode(node, hideHighlighter) {
     if (!node) {
       return;
     }
 
     try {
-      const isInTree = await this.walker.isInDOMTree(node);
+      const isInTree =
+        node.walkerFront && (await node.walkerFront.isInDOMTree(node));
       if (!isInTree) {
         hideHighlighter(node);
       }
     } catch (e) {
       this._handleRejection(e);
     }
   }
 
--- a/devtools/client/jsonview/test/doc_frame_script.js
+++ b/devtools/client/jsonview/test/doc_frame_script.js
@@ -1,35 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-/* globals Services, sendAsyncMessage, addMessageListener */
+/* globals sendAsyncMessage, addMessageListener */
 
 // XXX Some helper API could go to:
 // testing/mochitest/tests/SimpleTest/AsyncContentUtils.js
 // (or at least to share test API in devtools)
 
-// Set up a dummy environment so that EventUtils works. We need to be careful to
-// pass a window object into each EventUtils method we call rather than having
-// it rely on the |window| global.
-const EventUtils = {};
-EventUtils.window = content;
-EventUtils.parent = EventUtils.window;
-EventUtils._EU_Ci = Ci; // eslint-disable-line
-EventUtils._EU_Cc = Cc; // eslint-disable-line
-EventUtils.navigator = content.navigator;
-EventUtils.KeyboardEvent = content.KeyboardEvent;
-
-Services.scriptloader.loadSubScript(
-  "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
-  EventUtils
-);
-
 /**
  * When the ready state of the JSON View app changes, it triggers custom event
  * "AppReadyStateChange", then the "Test:JsonView:AppReadyStateChange" message
  * will be sent to the parent process for tests to wait for this event if needed.
  */
 content.addEventListener("AppReadyStateChange", () => {
   sendAsyncMessage("Test:JsonView:AppReadyStateChange");
 });
--- a/devtools/client/responsive/test/browser/browser_tooltip.js
+++ b/devtools/client/responsive/test/browser/browser_tooltip.js
@@ -4,18 +4,16 @@
 "use strict";
 
 const TEST_CONTENT = `<h1 title="test title">test h1</h1>`;
 const TEST_URL = `data:text/html;charset=utf-8,${TEST_CONTENT}`;
 
 // Test for the tooltip coordinate on the browsing document in RDM.
 
 addRDMTask(TEST_URL, async ({ ui }) => {
-  await injectEventUtilsInContentTask(ui.getViewportBrowser());
-
   info("Show a tooltip");
   await spawnViewportTask(ui, {}, async () => {
     const target = content.document.querySelector("h1");
     await EventUtils.synthesizeMouse(
       target,
       1,
       1,
       { type: "mouseover", isSynthesized: false },
--- a/devtools/client/responsive/test/browser/browser_touch_does_not_trigger_hover_states.js
+++ b/devtools/client/responsive/test/browser/browser_touch_does_not_trigger_hover_states.js
@@ -5,17 +5,16 @@
 
 // Test that element hover states are not triggered when touch is enabled.
 
 const TEST_URL = `${URL_ROOT}hover.html`;
 
 addRDMTask(TEST_URL, async function({ ui }) {
   reloadOnTouchChange(true);
 
-  await injectEventUtilsInContentTask(ui.getViewportBrowser());
   await toggleTouchSimulation(ui);
 
   info("Test element hover states when touch is enabled.");
   await testButtonHoverState(ui, "rgb(255, 0, 0)");
   await testDropDownHoverState(ui, "none");
 
   await toggleTouchSimulation(ui);
 
--- a/devtools/client/responsive/test/browser/browser_touch_simulation.js
+++ b/devtools/client/responsive/test/browser/browser_touch_simulation.js
@@ -6,18 +6,16 @@
 // Test global touch simulation button
 
 const TEST_URL = `${URL_ROOT}touch.html`;
 const PREF_DOM_META_VIEWPORT_ENABLED = "dom.meta-viewport.enabled";
 
 addRDMTask(TEST_URL, async function({ ui }) {
   reloadOnTouchChange(true);
 
-  await injectEventUtilsInContentTask(ui.getViewportBrowser());
-
   await waitBootstrap(ui);
   await testWithNoTouch(ui);
   await toggleTouchSimulation(ui);
   await testWithTouch(ui);
   await testWithMetaViewportEnabled(ui);
   await testWithMetaViewportDisabled(ui);
   testTouchButton(ui);
 
--- a/devtools/client/responsive/ui.js
+++ b/devtools/client/responsive/ui.js
@@ -303,16 +303,18 @@ class ResponsiveUI {
     if (!this.isBrowserUIEnabled) {
       this.tab.linkedBrowser.removeEventListener("FullZoomChange", this);
       this.toolWindow.removeEventListener("message", this);
     } else {
       this.rdmFrame.contentWindow.removeEventListener("message", this);
       this.rdmFrame.remove();
 
       this.browserContainerEl.classList.remove("responsive-mode");
+      this.browserStackEl.style.maxWidth = this.browserStackEl.style.minWidth = null;
+      this.browserStackEl.style.maxHeight = this.browserStackEl.style.minHeight = null;
     }
 
     if (!this.isBrowserUIEnabled && !isTabContentDestroying) {
       // Notify the inner browser to stop the frame script
       await message.request(this.toolWindow, "stop-frame-script");
     }
 
     // Ensure the tab is reloaded if required when exiting RDM so that no emulated
--- a/devtools/client/shared/test/shared-head.js
+++ b/devtools/client/shared/test/shared-head.js
@@ -748,73 +748,16 @@ function createTestHTTPServer() {
   registerCleanupFunction(async function cleanup() {
     await new Promise(resolve => server.stop(resolve));
   });
 
   server.start(-1);
   return server;
 }
 
-/**
- * Inject `EventUtils` helpers into ContentTask scope.
- *
- * This helper is automatically exposed to mochitest browser tests,
- * but is missing from content task scope.
- * You should call this method only once per <browser> tag
- *
- * @param {xul:browser} browser
- *        Reference to the browser in which we load content task
- */
-async function injectEventUtilsInContentTask(browser) {
-  await ContentTask.spawn(browser, {}, async function() {
-    if ("EventUtils" in this) {
-      return;
-    }
-
-    const EventUtils = (this.EventUtils = {});
-
-    EventUtils.window = {};
-    EventUtils.parent = EventUtils.window;
-    /* eslint-disable camelcase */
-    EventUtils._EU_Ci = Ci;
-    EventUtils._EU_Cc = Cc;
-    /* eslint-enable camelcase */
-    // EventUtils' `sendChar` function relies on the navigator to synthetize events.
-    EventUtils.navigator = content.navigator;
-    EventUtils.KeyboardEvent = content.KeyboardEvent;
-
-    EventUtils.synthesizeClick = element =>
-      new Promise(resolve => {
-        element.addEventListener(
-          "click",
-          function() {
-            resolve();
-          },
-          { once: true }
-        );
-
-        EventUtils.synthesizeMouseAtCenter(
-          element,
-          { type: "mousedown", isSynthesized: false },
-          content
-        );
-        EventUtils.synthesizeMouseAtCenter(
-          element,
-          { type: "mouseup", isSynthesized: false },
-          content
-        );
-      });
-
-    Services.scriptloader.loadSubScript(
-      "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
-      EventUtils
-    );
-  });
-}
-
 /*
  * Register an actor in the content process of the current tab.
  *
  * Calling ActorRegistry.registerModule only registers the actor in the current process.
  * As all test scripts are ran in the parent process, it is only registered here.
  * This function helps register them in the content process used for the current tab.
  *
  * @param {string} url
--- a/devtools/docs/contributing/performance.md
+++ b/devtools/docs/contributing/performance.md
@@ -130,18 +130,18 @@ It highlights that:
 
 ### Run performance tests
 
 See if any subtest reports a improvement. Ensure that the improvement makes any sense.
 For example, if the test is 50% faster, maybe you broke the performance test.
 This might happen if the test no longer waits for all the operations to finish executing before completing.
 
 To push your current patch to try, execute:
-```
-./mach try -b o -p linux64 -u none -t damp --rebuild-talos 5 --artifact
+```bash
+./mach try fuzzy --query "'linux64/ 'damp" --rebuild 5 --artifact
 ```
 It will print in your Terminal a link to perfherder like this one:
 [https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=9bef6cb13c43bbce21d40ffaea595e082a4c28db](https://treeherder.mozilla.org/perf.html#/comparechooser?newProject=try&newRevision=9bef6cb13c43bbce21d40ffaea595e082a4c28db)
 Running performance tests takes time, so you should open it 30 minutes up to 2 hours later to see your results.
 See [Performance tests (DAMP)](../tests/performance-tests.md) for more information about PerfHerder/try.
 
 Let's look at how to interpret an actual real-life [set of perfherder results](https://treeherder.mozilla.org/perf.html#/comparesubtest?originalProject=mozilla-central&newProject=try&newRevision=9bef6cb13c43bbce21d40ffaea595e082a4c28db&originalSignature=edaec66500db21d37602c99daa61ac983f21a6ac&newSignature=edaec66500db21d37602c99daa61ac983f21a6ac&showOnlyImportant=1&framework=1&selectedTimeRange=172800):
 
--- a/devtools/docs/tests/performance-tests.md
+++ b/devtools/docs/tests/performance-tests.md
@@ -43,17 +43,17 @@ This will automatically record the tests
 to focus on just one subtest run:
 ```bash
 ./mach talos-test --activeTests damp --subtests custom.webconsole --cycles 1 --tppagecycles 1 --geckoProfile --geckoProfileEntries 100000000
 ```
 
 ## How to run it on try?
 
 ```bash
-./mach try -b o -p linux64 -u none -t damp --rebuild-talos 6
+./mach try fuzzy --query "'linux64/ 'damp" --rebuild 6 --artifact
 ```
 * Linux appears to build and run quickly, and offers quite stable results over the other OSes.
 The vast majority of performance issues for DevTools are OS agnostic, so it doesn't really matter which one you run them on.
 * "damp" is the talos bucket in which we run DAMP.
 * And 6 is the number of times we run DAMP tests. That's to do averages between all the 6 runs and helps filtering out the noise.
 
 ## How to get performance profiles on try?
 
--- a/devtools/server/actors/descriptors/process.js
+++ b/devtools/server/actors/descriptors/process.js
@@ -80,31 +80,43 @@ const ProcessDescriptorActor = ActorClas
     return targetActor.form();
   },
 
   /**
    * Connect to a remote process actor, always a ContentProcess target.
    */
   async _childProcessConnect() {
     const { id } = this;
-    const mm = Services.ppmm.getChildAt(id);
+    const mm = this._lookupMessageManager(id);
     if (!mm) {
       return {
         error: "noProcess",
         message: "There is no process with id '" + id + "'.",
       };
     }
     const childTargetForm = await connectToContentProcess(
       this.conn,
       mm,
       this.destroy
     );
     return childTargetForm;
   },
 
+  _lookupMessageManager(id) {
+    for (let i = 0; i < Services.ppmm.childCount; i++) {
+      const mm = Services.ppmm.getChildAt(i);
+
+      // A zero id is used for the parent process, instead of its actual pid.
+      if (id ? mm.osPid == id : mm.isInProcess) {
+        return mm;
+      }
+    }
+    return null;
+  },
+
   /**
    * Connect the a process actor.
    */
   async getTarget() {
     if (!DebuggerServer.allowChromeProcess) {
       return {
         error: "forbidden",
         message: "You are not allowed to debug processes.",
--- a/devtools/server/actors/object.js
+++ b/devtools/server/actors/object.js
@@ -134,27 +134,39 @@ const proto = {
     if (watchpointType === "get") {
       this.obj.defineProperty(property, {
         configurable: desc.configurable,
         enumerable: desc.enumerable,
         set: this.obj.makeDebuggeeValue(v => {
           desc.value = v;
         }),
         get: this.obj.makeDebuggeeValue(() => {
+          const frame = this.thread.dbg.getNewestFrame();
+
+          if (!this.thread.hasMoved(frame, "getWatchpoint")) {
+            return false;
+          }
+
           pauseAndRespond("getWatchpoint");
           return desc.value;
         }),
       });
     }
 
     if (watchpointType === "set") {
       this.obj.defineProperty(property, {
         configurable: desc.configurable,
         enumerable: desc.enumerable,
         set: this.obj.makeDebuggeeValue(v => {
+          const frame = this.thread.dbg.getNewestFrame();
+
+          if (!this.thread.hasMoved(frame, "setWatchpoint")) {
+            return;
+          }
+
           pauseAndRespond("setWatchpoint");
           desc.value = v;
         }),
         get: this.obj.makeDebuggeeValue(() => {
           return desc.value;
         }),
       });
     }
--- a/devtools/server/actors/process.js
+++ b/devtools/server/actors/process.js
@@ -1,40 +1,38 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-var { Cc } = require("chrome");
+const { Cc } = require("chrome");
+const Services = require("Services");
 
 loader.lazyGetter(this, "ppmm", () => {
   return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
 });
 
 function ProcessActorList() {
   this._actors = new Map();
   this._onListChanged = null;
   this._mustNotify = false;
-
-  this._onMessage = this._onMessage.bind(this);
-  this._processScript =
-    "resource://devtools/server/startup/debug-new-process.js";
+  this._hasObserver = false;
 }
 
 ProcessActorList.prototype = {
   getList: function() {
     const processes = [];
     for (let i = 0; i < ppmm.childCount; i++) {
+      const mm = ppmm.getChildAt(i);
       processes.push({
-        // XXX: may not be a perfect id, but process message manager doesn't
-        // expose anything...
-        id: i,
-        // XXX Weak, but appear to be stable
-        parent: i == 0,
+        // An ID of zero is always used for the parent. It would be nice to fix
+        // this so that the pid is also used for the parent, see bug 1587443.
+        id: mm.isInProcess ? 0 : mm.osPid,
+        parent: mm.isInProcess,
         // TODO: exposes process message manager on frameloaders in order to compute this
         tabCount: undefined,
       });
     }
     this._mustNotify = true;
     this._checkListening();
 
     return processes;
@@ -53,36 +51,29 @@ ProcessActorList.prototype = {
     }
 
     this._onListChanged = onListChanged;
     this._checkListening();
   },
 
   _checkListening: function() {
     if (this._onListChanged !== null && this._mustNotify) {
-      this._knownProcesses = [];
-      for (let i = 0; i < ppmm.childCount; i++) {
-        this._knownProcesses.push(ppmm.getChildAt(i));
+      if (!this._hasObserver) {
+        Services.obs.addObserver(this, "ipc:content-created");
+        Services.obs.addObserver(this, "ipc:content-shutdown");
+        this._hasObserver = true;
       }
-      ppmm.addMessageListener("debug:new-process", this._onMessage);
-      ppmm.loadProcessScript(this._processScript, true);
-    } else {
-      ppmm.removeMessageListener("debug:new-process", this._onMessage);
-      ppmm.removeDelayedProcessScript(this._processScript);
+    } else if (this._hasObserver) {
+      Services.obs.removeObserver(this, "ipc:content-created");
+      Services.obs.removeObserver(this, "ipc:content-shutdown");
+      this._hasObserver = false;
     }
   },
 
-  _notifyListChanged: function() {
+  observe() {
     if (this._mustNotify) {
       this._onListChanged();
       this._mustNotify = false;
     }
   },
-
-  _onMessage: function({ target }) {
-    if (this._knownProcesses.includes(target)) {
-      return;
-    }
-    this._notifyListChanged();
-  },
 };
 
 exports.ProcessActorList = ProcessActorList;
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -601,23 +601,16 @@ RootActor.prototype = {
         error: "wrongParameter",
         message: "getProcess requires a valid `id` attribute.",
       };
     }
     // If the request doesn't contains id parameter or id is 0
     // (id == 0, based on onListProcesses implementation)
     const id = request.id || 0;
 
-    const mm = Services.ppmm.getChildAt(id);
-    if (!mm) {
-      return {
-        error: "noProcess",
-        message: "There is no process with id '" + id + "'.",
-      };
-    }
     this._processDescriptorActorPool =
       this._processDescriptorActorPool || new Pool(this.conn);
 
     let processDescriptor = this._getKnownDescriptor(
       id,
       this._processDescriptorActorPool
     );
     if (!processDescriptor) {
deleted file mode 100644
--- a/devtools/server/startup/debug-new-process.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/* global sendAsyncMessage */
-
-sendAsyncMessage("debug:new-process");
--- a/devtools/server/startup/moz.build
+++ b/devtools/server/startup/moz.build
@@ -2,12 +2,11 @@
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
     'content-process.js',
     'content-process.jsm',
-    'debug-new-process.js',
     'frame.js',
     'worker.js',
 )
--- a/devtools/server/tests/browser/browser_canvasframe_helper_03.js
+++ b/devtools/server/tests/browser/browser_canvasframe_helper_03.js
@@ -115,25 +115,14 @@ add_task(async function() {
       "The mousedown event hasn't been handled after the helper was destroyed"
     );
 
     function synthesizeMouseDown(x, y, win) {
       // We need to make sure the inserted anonymous content can be targeted by the
       // event right after having been inserted, and so we need to force a sync
       // reflow.
       win.document.documentElement.offsetWidth;
-      // Minimal environment for EventUtils to work.
-      const EventUtils = {
-        window: content,
-        parent: content,
-        _EU_Ci: Ci,
-        _EU_Cc: Cc,
-      };
-      Services.scriptloader.loadSubScript(
-        "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
-        EventUtils
-      );
       EventUtils.synthesizeMouseAtPoint(x, y, { type: "mousedown" }, win);
     }
   });
 
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_canvasframe_helper_04.js
+++ b/devtools/server/tests/browser/browser_canvasframe_helper_04.js
@@ -8,17 +8,16 @@
 
 const TEST_URL_1 =
   "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test 1";
 const TEST_URL_2 =
   "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test 2";
 
 add_task(async function() {
   const browser = await addTab(TEST_URL_1);
-  await injectEventUtilsInContentTask(browser);
   await ContentTask.spawn(browser, TEST_URL_2, async function(url2) {
     const { require } = ChromeUtils.import(
       "resource://devtools/shared/Loader.jsm"
     );
     const {
       HighlighterEnvironment,
     } = require("devtools/server/actors/highlighters");
     const {
--- a/devtools/server/tests/browser/browser_canvasframe_helper_05.js
+++ b/devtools/server/tests/browser/browser_canvasframe_helper_05.js
@@ -120,25 +120,14 @@ add_task(async function() {
     env.destroy();
     helper.destroy();
 
     function synthesizeMouseDown(x, y, win) {
       // We need to make sure the inserted anonymous content can be targeted by the
       // event right after having been inserted, and so we need to force a sync
       // reflow.
       win.document.documentElement.offsetWidth;
-      // Minimal environment for EventUtils to work.
-      const EventUtils = {
-        window: content,
-        parent: content,
-        _EU_Ci: Ci,
-        _EU_Cc: Cc,
-      };
-      Services.scriptloader.loadSubScript(
-        "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
-        EventUtils
-      );
       EventUtils.synthesizeMouseAtPoint(x, y, { type: "mousedown" }, win);
     }
   });
 
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_canvasframe_helper_06.js
+++ b/devtools/server/tests/browser/browser_canvasframe_helper_06.js
@@ -102,25 +102,14 @@ add_task(async function() {
     env.destroy();
     helper.destroy();
 
     function synthesizeMouseDown(x, y, win) {
       // We need to make sure the inserted anonymous content can be targeted by the
       // event right after having been inserted, and so we need to force a sync
       // reflow.
       win.document.documentElement.offsetWidth;
-      // Minimal environment for EventUtils to work.
-      const EventUtils = {
-        window: content,
-        parent: content,
-        _EU_Ci: Ci,
-        _EU_Cc: Cc,
-      };
-      Services.scriptloader.loadSubScript(
-        "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
-        EventUtils
-      );
       EventUtils.synthesizeMouseAtPoint(x, y, { type: "mousedown" }, win);
     }
   });
 
   gBrowser.removeCurrentTab();
 });
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_watchpoint-02.js
@@ -0,0 +1,223 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable no-shadow */
+
+"use strict";
+
+/*
+Test that debugger advances instead of pausing twice on the
+same line when encountering both a watchpoint and a breakpoint.
+*/
+
+add_task(
+  threadFrontTest(async args => {
+    await testBreakpointAndSetWatchpoint(args);
+    await testBreakpointAndGetWatchpoint(args);
+    await testLoops(args);
+  })
+);
+
+// Test that we advance to the next line when a location
+// has both a breakpoint and set watchpoint.
+async function testBreakpointAndSetWatchpoint({ threadFront, debuggee }) {
+  function evaluateTestCode(debuggee) {
+    /* eslint-disable */
+    Cu.evalInSandbox(
+      `                                   // 1
+      function stopMe(obj) {              // 2
+        debugger;                         // 3
+        obj.a = 2;                        // 4
+        debugger;                         // 5
+      }                                   //
+      stopMe({a: 1})`,
+      debuggee,
+      "1.8",
+      "test_watchpoint-02.js",
+    );
+    /* eslint-disable */
+  }
+
+  const packet = await executeOnNextTickAndWaitForPause(
+    () => evaluateTestCode(debuggee),
+    threadFront
+  );
+
+  info("Test that we pause on the debugger statement.");
+  Assert.equal(packet.frame.where.line, 3);
+  Assert.equal(packet.why.type, "debuggerStatement");
+
+  info("Add set watchpoint.");
+  const args = packet.frame.arguments;
+  const obj = args[0];
+  const objClient = threadFront.pauseGrip(obj);
+  await objClient.addWatchpoint("a", "obj.a", "set");
+
+  info("Add breakpoint.");
+  const source = await getSourceById(threadFront, packet.frame.where.actor);
+
+  const location = {
+    sourceUrl: source.url,
+    line: 4,
+  };
+
+  threadFront.setBreakpoint(
+    location,
+    {},
+  );
+
+  info("Test that pause occurs on breakpoint.");
+  const packet2 = await resumeAndWaitForPause(threadFront);
+  Assert.equal(packet2.frame.where.line, 4);
+  Assert.equal(packet2.why.type, "breakpoint");
+
+  const packet3 = await resumeAndWaitForPause(threadFront);
+
+  info("Test that we pause on the second debugger statement.");
+  Assert.equal(packet3.frame.where.line, 5);
+  Assert.equal(packet3.why.type, "debuggerStatement");
+
+  info("Remove breakpoint and finish.");
+   threadFront.removeBreakpoint(
+    location,
+    {}
+  );
+
+  await resume(threadFront);
+}
+
+// Test that we advance to the next line when a location 
+// has both a breakpoint and get watchpoint.
+async function testBreakpointAndGetWatchpoint({ threadFront, debuggee }) {
+  function evaluateTestCode(debuggee) {
+    /* eslint-disable */
+    Cu.evalInSandbox(
+      `                                   // 1
+      function stopMe(obj) {              // 2
+        debugger;                         // 3
+        obj.a + 4;                        // 4
+        debugger;                         // 5
+      }                                   // 
+      stopMe({a: 1})`,
+      debuggee,
+      "1.8",
+      "test_watchpoint-02.js",
+    );
+    /* eslint-disable */
+  }
+
+  const packet = await executeOnNextTickAndWaitForPause(
+    () => evaluateTestCode(debuggee),
+    threadFront
+  );
+
+  info("Test that we pause on the debugger statement.");
+  Assert.equal(packet.frame.where.line, 3);
+
+  info("Add get watchpoint.");
+  const args = packet.frame.arguments;
+  const obj = args[0];
+  const objClient = threadFront.pauseGrip(obj);
+  await objClient.addWatchpoint("a", "obj.a", "get");
+
+  info("Add breakpoint.");
+  const source = await getSourceById(threadFront, packet.frame.where.actor);
+
+  const location = {
+    sourceUrl: source.url,
+    line: 4,
+  };
+
+  threadFront.setBreakpoint(
+    location,
+    {},
+  );
+
+  info("Test that pause occurs on breakpoint.");
+  const packet2 = await resumeAndWaitForPause(threadFront);
+  Assert.equal(packet2.frame.where.line, 4);
+  Assert.equal(packet2.why.type, "breakpoint");
+
+  const packet3 = await resumeAndWaitForPause(threadFront);
+
+  info("Test that we pause on the second debugger statement.");
+  Assert.equal(packet3.frame.where.line, 5);
+  Assert.equal(packet3.why.type, "debuggerStatement");
+
+  info("Remove breakpoint and finish.");
+  threadFront.removeBreakpoint(
+    location,
+    {}
+  );
+
+  await resume(threadFront);
+}
+
+// Test that we can pause multiple times 
+// on the same line for a watchpoint.
+async function testLoops({ threadFront, debuggee, targetFront }) {
+  async function evaluateJS(input) {
+    const consoleFront = await targetFront.getFront("console");
+    const { result } = await consoleFront.evaluateJSAsync(input, {
+      thread: threadFront.actor,
+      frameActor: packet.frame.actor,
+    });
+    return result;
+  }
+
+  function evaluateTestCode(debuggee) {
+    /* eslint-disable */
+    Cu.evalInSandbox(
+      `                                   // 1
+      function stopMe(obj) {              // 2
+        let i = 0;                        // 3  
+        debugger;                         // 4
+        while (i++ < 2) {                 // 5
+          obj.a = 2;                      // 6
+        }                                 // 7
+        debugger;                         // 8
+      }                                   // 
+      stopMe({a: 1})`,
+      debuggee,
+      "1.8",
+      "test_watchpoint-02.js",
+    );
+    /* eslint-disable */
+  }
+
+  const packet = await executeOnNextTickAndWaitForPause(
+    () => evaluateTestCode(debuggee),
+    threadFront
+  );
+
+  info("Test that we pause on the debugger statement.");
+  Assert.equal(packet.frame.where.line, 4);
+  Assert.equal(packet.why.type, "debuggerStatement");
+
+  info("Add set watchpoint.");
+  const args = packet.frame.arguments;
+  const obj = args[0];
+  const objClient = threadFront.pauseGrip(obj);
+  await objClient.addWatchpoint("a", "obj.a", "set");
+
+  info("Test that watchpoint triggers pause on set.");
+  const packet2 = await resumeAndWaitForPause(threadFront);
+  Assert.equal(packet2.frame.where.line, 6);
+  Assert.equal(packet2.why.type, "setWatchpoint");
+  let result =  await evaluateJS("obj.a");
+  Assert.equal(result, 1);
+
+  info("Test that watchpoint triggers pause on set (2nd time).");
+  const packet3 = await resumeAndWaitForPause(threadFront);
+  Assert.equal(packet3.frame.where.line, 6);
+  Assert.equal(packet3.why.type, "setWatchpoint");
+  let result2 =  await evaluateJS("obj.a");
+  Assert.equal(result2, 2);
+
+  info("Test that we pause on second debugger statement.");
+  const packet4 = await resumeAndWaitForPause(threadFront);
+  Assert.equal(packet4.frame.where.line, 8);
+  Assert.equal(packet4.why.type, "debuggerStatement");
+
+  await resume(threadFront);
+}
+
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -212,16 +212,17 @@ skip-if = true # breakpoint sliding is n
 [test_longstringactor.js]
 [test_longstringgrips-01.js]
 [test_source-01.js]
 [test_source-02.js]
 [test_source-03.js]
 [test_source-04.js]
 [test_wasm_source-01.js]
 [test_watchpoint-01.js]
+[test_watchpoint-02.js]
 [test_breakpoint-actor-map.js]
 skip-if = true # tests for breakpoint actors are obsolete bug 1524374
 [test_unsafeDereference.js]
 [test_add_actors.js]
 [test_ignore_caught_exceptions.js]
 [test_ignore_no_interface_exceptions.js]
 [test_requestTypes.js]
 reason = bug 937197
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -426,20 +426,16 @@ nsDocShell::nsDocShell(BrowsingContext* 
 }
 
 nsDocShell::~nsDocShell() {
   MOZ_ASSERT(!mObserved);
 
   // Avoid notifying observers while we're in the dtor.
   mIsBeingDestroyed = true;
 
-#ifdef MOZ_GECKO_PROFILER
-  profiler_unregister_pages(mHistoryID);
-#endif
-
   Destroy();
 
   if (mSessionHistory) {
     mSessionHistory->LegacySHistory()->ClearRootDocShell();
   }
 
   if (--gDocShellCount == 0) {
     NS_IF_RELEASE(sURIFixup);
@@ -8254,17 +8250,17 @@ nsresult nsDocShell::CreateContentViewer
 #ifdef MOZ_GECKO_PROFILER
         nsCOMPtr<nsIURI> prinURI;
         thisPrincipal->GetURI(getter_AddRefs(prinURI));
         nsPrintfCString marker("Iframe loaded in background: %s",
                                prinURI->GetSpecOrDefault().get());
         TimeStamp now = TimeStamp::Now();
         profiler_add_text_marker("Background Iframe", marker,
                                  JS::ProfilingCategoryPair::DOM, now, now,
-                                 Nothing(), Nothing());
+                                 Nothing());
 #endif
         SetBackgroundLoadIframe();
       }
     }
   }
 
   NS_ENSURE_SUCCESS(Embed(viewer), NS_ERROR_FAILURE);
 
@@ -11080,32 +11076,16 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, 
     nsCOMPtr<nsISHEntry> currentSH;
     mSessionHistory->LegacySHistory()->GetEntryAtIndex(
         index, getter_AddRefs(currentSH));
     if (currentSH != mLSHE) {
       mSessionHistory->LegacySHistory()->ReplaceEntry(index, mLSHE);
     }
   }
 
-#ifdef MOZ_GECKO_PROFILER
-  // We register the page load only if the load updates the history and it's
-  // not a refresh. This also registers the iframes in shift-reload case, but
-  // it's reasonable to register since we are updating the historyId in that
-  // case.
-  if (updateSHistory) {
-    uint32_t id = 0;
-    nsAutoCString spec;
-    if (mLSHE) {
-      mLSHE->GetID(&id);
-    }
-    aURI->GetSpec(spec);
-    profiler_register_page(mHistoryID, id, spec, IsFrame());
-  }
-#endif
-
   // If this is a POST request, we do not want to include this in global
   // history.
   if (updateGHistory && aAddToGlobalHistory && !ChannelIsPost(aChannel)) {
     nsCOMPtr<nsIURI> previousURI;
     uint32_t previousFlags = 0;
 
     if (aLoadType & LOAD_CMD_RELOAD) {
       // On a reload request, we don't set redirecting flags.
@@ -11416,24 +11396,16 @@ nsresult nsDocShell::UpdateURLAndHistory
     // Set the new SHEntry's title (bug 655273).
     nsString title;
     mOSHE->GetTitle(title);
     newSHEntry->SetTitle(title);
 
     // AddToSessionHistory may not modify mOSHE.  In case it doesn't,
     // we'll just set mOSHE here.
     mOSHE = newSHEntry;
-
-#ifdef MOZ_GECKO_PROFILER
-    uint32_t id = 0;
-    GetOSHEId(&id);
-    profiler_register_page(mHistoryID, id, aNewURI->GetSpecOrDefault(),
-                           IsFrame());
-#endif
-
   } else {
     // Step 3.
     newSHEntry = mOSHE;
 
     // Since we're not changing which page we have loaded, pass
     if (!newSHEntry) {
       nsresult rv = AddToSessionHistory(
           aNewURI, nullptr,
--- a/dom/base/ProcessMessageManager.cpp
+++ b/dom/base/ProcessMessageManager.cpp
@@ -12,17 +12,20 @@
 namespace mozilla {
 namespace dom {
 
 ProcessMessageManager::ProcessMessageManager(
     ipc::MessageManagerCallback* aCallback,
     ParentProcessMessageManager* aParentManager, MessageManagerFlags aFlags)
     : MessageSender(aCallback, aParentManager,
                     aFlags | MessageManagerFlags::MM_CHROME |
-                        MessageManagerFlags::MM_PROCESSMANAGER) {
+                        MessageManagerFlags::MM_PROCESSMANAGER),
+      mPid(-1),
+      // aCallback is only specified if this is the in-process manager.
+      mInProcess(!!aCallback) {
   MOZ_ASSERT(!(aFlags & ~(MessageManagerFlags::MM_GLOBAL |
                           MessageManagerFlags::MM_OWNSCALLBACK)));
 
   // This is a bit hackish. We attach to the parent manager, but only if we have
   // a callback (which is only for the in-process message manager). For other
   // cases we wait until the child process is running (see
   // MessageSender::InitWithCallback).
   if (aParentManager && mCallback) {
--- a/dom/base/ProcessMessageManager.h
+++ b/dom/base/ProcessMessageManager.h
@@ -36,14 +36,23 @@ class ProcessMessageManager final : publ
   void RemoveDelayedProcessScript(const nsAString& aURL) {
     RemoveDelayedScript(aURL);
   }
   void GetDelayedProcessScripts(JSContext* aCx,
                                 nsTArray<nsTArray<JS::Value>>& aScripts,
                                 mozilla::ErrorResult& aError) {
     GetDelayedScripts(aCx, aScripts, aError);
   }
+
+  void SetOsPid(int32_t aPid) { mPid = aPid; }
+  int32_t OsPid() const { return mPid; }
+
+  bool IsInProcess() const { return mInProcess; }
+
+ private:
+  int32_t mPid;
+  bool mInProcess;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_ProcessMessageManager_h
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -158,21 +158,21 @@ void nsDOMNavigationTiming::NotifyLoadEv
       TimeDuration duration = mLoadEventEnd - mLoadEventStart;
       nsAutoCString spec;
       if (mLoadedURI) {
         mLoadedURI->GetSpec(spec);
       }
       nsPrintfCString marker(
           "Document %s loaded after %dms, load event duration %dms", spec.get(),
           int(elapsed.ToMilliseconds()), int(duration.ToMilliseconds()));
-      DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
       PAGELOAD_LOG(("%s", marker.get()));
-      PROFILER_ADD_MARKER_WITH_PAYLOAD("DocumentLoad", DOM, TextMarkerPayload,
-                                       (marker, mNavigationStart, mLoadEventEnd,
-                                        docShellId, docShellHistoryId));
+      PROFILER_ADD_MARKER_WITH_PAYLOAD(
+          "DocumentLoad", DOM, TextMarkerPayload,
+          (marker, mNavigationStart, mLoadEventEnd,
+           profiler_get_inner_window_id_from_docshell(mDocShell)));
     }
 #endif
     Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_END_MS,
                                    mNavigationStart);
   }
 }
 
 void nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI,
@@ -353,20 +353,20 @@ void nsDOMNavigationTiming::TTITimeout(n
     nsAutoCString spec;
     if (mLoadedURI) {
       mLoadedURI->GetSpec(spec);
     }
     nsPrintfCString marker("TTFI after %dms (LongTask was at %dms) for URL %s",
                            int(elapsed.ToMilliseconds()),
                            int(elapsedLongTask.ToMilliseconds()), spec.get());
 
-    DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
     PROFILER_ADD_MARKER_WITH_PAYLOAD(
         "TTFI", DOM, TextMarkerPayload,
-        (marker, mNavigationStart, mTTFI, docShellId, docShellHistoryId));
+        (marker, mNavigationStart, mTTFI,
+         profiler_get_inner_window_id_from_docshell(mDocShell)));
   }
 #endif
   return;
 }
 
 void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mNavigationStart.IsNull());
@@ -387,21 +387,20 @@ void nsDOMNavigationTiming::NotifyNonBla
     nsPrintfCString marker(
         "Non-blank paint after %dms for URL %s, %s",
         int(elapsed.ToMilliseconds()), spec.get(),
         mDocShellHasBeenActiveSinceNavigationStart
             ? "foreground tab"
             : "this tab was inactive some of the time between navigation start "
               "and first non-blank paint");
     PAGELOAD_LOG(("%s", marker.get()));
-    DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
-    PROFILER_ADD_MARKER_WITH_PAYLOAD("FirstNonBlankPaint", DOM,
-                                     TextMarkerPayload,
-                                     (marker, mNavigationStart, mNonBlankPaint,
-                                      docShellId, docShellHistoryId));
+    PROFILER_ADD_MARKER_WITH_PAYLOAD(
+        "FirstNonBlankPaint", DOM, TextMarkerPayload,
+        (marker, mNavigationStart, mNonBlankPaint,
+         profiler_get_inner_window_id_from_docshell(mDocShell)));
   }
 #endif
 
   if (mDocShellHasBeenActiveSinceNavigationStart) {
     if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(mNavigationStart)) {
       Telemetry::AccumulateTimeDelta(
           Telemetry::TIME_TO_NON_BLANK_PAINT_NETOPT_MS, mNavigationStart,
           mNonBlankPaint);
@@ -436,22 +435,21 @@ void nsDOMNavigationTiming::NotifyConten
     }
     nsPrintfCString marker(
         "Contentful paint after %dms for URL %s, %s",
         int(elapsed.ToMilliseconds()), spec.get(),
         mDocShellHasBeenActiveSinceNavigationStart
             ? "foreground tab"
             : "this tab was inactive some of the time between navigation start "
               "and first non-blank paint");
-    DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
     PAGELOAD_LOG(("%s", marker.get()));
     PROFILER_ADD_MARKER_WITH_PAYLOAD(
         "FirstContentfulPaint", DOM, TextMarkerPayload,
-        (marker, mNavigationStart, mContentfulPaint, docShellId,
-         docShellHistoryId));
+        (marker, mNavigationStart, mContentfulPaint,
+         profiler_get_inner_window_id_from_docshell(mDocShell)));
   }
 #endif
 
   if (!mTTITimer) {
     mTTITimer = NS_NewTimer();
   }
 
   // TTI is first checked 5 seconds after the FCP (non-blank-paint is very close
@@ -486,22 +484,21 @@ void nsDOMNavigationTiming::NotifyDOMCon
     }
     nsPrintfCString marker(
         "DOMContentFlushed after %dms for URL %s, %s",
         int(elapsed.ToMilliseconds()), spec.get(),
         mDocShellHasBeenActiveSinceNavigationStart
             ? "foreground tab"
             : "this tab was inactive some of the time between navigation start "
               "and DOMContentFlushed");
-    DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
     PAGELOAD_LOG(("%s", marker.get()));
     PROFILER_ADD_MARKER_WITH_PAYLOAD(
         "DOMContentFlushed", DOM, TextMarkerPayload,
-        (marker, mNavigationStart, mDOMContentFlushed, docShellId,
-         docShellHistoryId));
+        (marker, mNavigationStart, mDOMContentFlushed,
+         profiler_get_inner_window_id_from_docshell(mDocShell)));
   }
 #endif
 }
 
 void nsDOMNavigationTiming::NotifyDocShellStateChanged(
     DocShellState aDocShellState) {
   mDocShellHasBeenActiveSinceNavigationStart &=
       (aDocShellState == DocShellState::eActive);
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1587,16 +1587,17 @@ ProcessMessageManager* nsFrameMessageMan
     // already started when we send pending scripts.
     mm = new ProcessMessageManager(
         nullptr, nsFrameMessageManager::sParentProcessManager);
   } else {
     mm =
         new ProcessMessageManager(new SameParentProcessMessageManagerCallback(),
                                   nsFrameMessageManager::sParentProcessManager,
                                   MessageManagerFlags::MM_OWNSCALLBACK);
+    mm->SetOsPid(base::GetCurrentProcId());
     sSameProcessParentManager = mm;
   }
   return mm;
 }
 
 nsresult NS_NewChildProcessMessageManager(nsISupports** aResult) {
   NS_ASSERTION(!nsFrameMessageManager::GetChildProcessManager(),
                "Re-creating sChildProcessManager");
--- a/dom/chrome-webidl/MessageManager.webidl
+++ b/dom/chrome-webidl/MessageManager.webidl
@@ -606,10 +606,15 @@ ChromeMessageSender includes FrameScript
 
 /**
  * ProcessMessageManager is used in a parent process to communicate with a child process
  * (or with the process itself in a single-process scenario).
  */
 [ChromeOnly, Exposed=Window]
 interface ProcessMessageManager : MessageSender
 {
+  // PID of the process being communicated with.
+  readonly attribute long osPid;
+
+  // Whether this is message manager for the current process.
+  readonly attribute boolean isInProcess;
 };
 ProcessMessageManager includes ProcessScriptLoader;
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -1021,29 +1021,33 @@ nsresult EventDispatcher::Dispatch(nsISu
           }
           nsAutoString typeStr;
           postVisitor.mDOMEvent->GetType(typeStr);
           AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
               "EventDispatcher::Dispatch", OTHER, typeStr);
 
           nsCOMPtr<nsIDocShell> docShell;
           docShell = nsContentUtils::GetDocShellForEventTarget(aEvent->mTarget);
-          DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
+          Maybe<uint64_t> innerWindowID;
+          if (nsCOMPtr<nsPIDOMWindowInner> inner =
+                  do_QueryInterface(aEvent->mTarget->GetOwnerGlobal())) {
+            innerWindowID = Some(inner->WindowID());
+          }
           PROFILER_ADD_MARKER_WITH_PAYLOAD(
               "DOMEvent", DOM, DOMEventMarkerPayload,
               (typeStr, aEvent->mTimeStamp, "DOMEvent", TRACING_INTERVAL_START,
-               docShellId, docShellHistoryId));
+               innerWindowID));
 
           EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
                                                        aCallback, cd);
 
           PROFILER_ADD_MARKER_WITH_PAYLOAD(
               "DOMEvent", DOM, DOMEventMarkerPayload,
               (typeStr, aEvent->mTimeStamp, "DOMEvent", TRACING_INTERVAL_END,
-               docShellId, docShellHistoryId));
+               innerWindowID));
         } else
 #endif
         {
           EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
                                                        aCallback, cd);
         }
         aEvent->mPath = nullptr;
 
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -1076,16 +1076,18 @@ void IDBDatabase::DisconnectFromOwner() 
   DOMEventTargetHelper::DisconnectFromOwner();
 }
 
 void IDBDatabase::LastRelease() {
   AssertIsOnOwningThread();
 
   CloseInternal();
 
+  ExpireFileActors(/* aExpireAll */ true);
+
   if (mBackgroundActor) {
     mBackgroundActor->SendDeleteMeInternal();
     MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
   }
 }
 
 nsresult IDBDatabase::PostHandleEvent(EventChainPostVisitor& aVisitor) {
   nsresult rv =
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1509,16 +1509,17 @@ void ContentParent::ShutDownMessageManag
   if (!mMessageManager) {
     return;
   }
 
   mMessageManager->ReceiveMessage(
       mMessageManager, nullptr, CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr,
       nullptr, nullptr, nullptr, IgnoreErrors());
 
+  mMessageManager->SetOsPid(-1);
   mMessageManager->Disconnect();
   mMessageManager = nullptr;
 }
 
 void ContentParent::RemoveFromList() {
   if (IsForJSPlugin()) {
     if (sJSPluginContentParents) {
       sJSPluginContentParents->Remove(mJSPluginID);
@@ -2551,16 +2552,17 @@ bool ContentParent::InitInternal(Process
   // because different remote types require different sandbox privileges.
   Unused << SendRemoteType(mRemoteType);
 
   ScriptPreloader::InitContentChild(*this);
 
   // Initialize the message manager (and load delayed scripts) now that we
   // have established communications with the child.
   mMessageManager->InitWithCallback(this);
+  mMessageManager->SetOsPid(Pid());
 
   // Set the subprocess's priority.  We do this early on because we're likely
   // /lowering/ the process's CPU and memory priority, which it has inherited
   // from this process.
   //
   // This call can cause us to send IPC messages to the child process, so it
   // must come after the Open() call above.
   ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
--- a/dom/ipc/WindowGlobalChild.cpp
+++ b/dom/ipc/WindowGlobalChild.cpp
@@ -379,16 +379,29 @@ void WindowGlobalChild::ReceiveRawMessag
   RefPtr<JSWindowActorChild> actor =
       GetActor(aMeta.actorName(), IgnoreErrors());
   if (actor) {
     actor->ReceiveRawMessage(aMeta, std::move(aData));
   }
 }
 
 void WindowGlobalChild::SetDocumentURI(nsIURI* aDocumentURI) {
+#ifdef MOZ_GECKO_PROFILER
+  // Registers a DOM Window with the profiler. It re-registers the same Inner
+  // Window ID with different URIs because when a Browsing context is first
+  // loaded, the first url loaded in it will be about:blank. This call keeps the
+  // first non-about:blank registration of window and discards the previous one.
+  uint64_t embedderInnerWindowID = 0;
+  if (mBrowsingContext->GetParent()) {
+    embedderInnerWindowID = mBrowsingContext->GetEmbedderInnerWindowId();
+  }
+  profiler_register_page(mBrowsingContext->Id(), mInnerWindowId,
+                         aDocumentURI->GetSpecOrDefault(),
+                         embedderInnerWindowID);
+#endif
   mDocumentURI = aDocumentURI;
   SendUpdateDocumentURI(aDocumentURI);
 }
 
 const nsAString& WindowGlobalChild::GetRemoteType() {
   if (XRE_IsContentProcess()) {
     return ContentChild::GetSingleton()->GetRemoteType();
   }
@@ -426,16 +439,20 @@ already_AddRefed<JSWindowActorChild> Win
   actor->Init(aName, this);
   mWindowActors.Put(aName, actor);
   return actor.forget();
 }
 
 void WindowGlobalChild::ActorDestroy(ActorDestroyReason aWhy) {
   gWindowGlobalChildById->Remove(mInnerWindowId);
 
+#ifdef MOZ_GECKO_PROFILER
+  profiler_unregister_page(mInnerWindowId);
+#endif
+
   // Destroy our JSWindowActors, and reject any pending queries.
   nsRefPtrHashtable<nsStringHashKey, JSWindowActorChild> windowActors;
   mWindowActors.SwapElements(windowActors);
   for (auto iter = windowActors.Iter(); !iter.Done(); iter.Next()) {
     iter.Data()->RejectPendingQueries();
     iter.Data()->AfterDestroy();
   }
   windowActors.Clear();
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -219,35 +219,16 @@ VideoData::VideoData(int64_t aOffset, co
       mNextKeyFrameTime(TimeUnit::Invalid()) {
   MOZ_ASSERT(!mDuration.IsNegative(), "Frame must have non-negative duration.");
   mKeyframe = aKeyframe;
   mTimecode = aTimecode;
 }
 
 VideoData::~VideoData() {}
 
-void VideoData::SetListener(UniquePtr<Listener> aListener) {
-  MOZ_ASSERT(!mSentToCompositor,
-             "Listener should be registered before sending data");
-
-  mListener = std::move(aListener);
-}
-
-void VideoData::MarkSentToCompositor() {
-  if (mSentToCompositor) {
-    return;
-  }
-
-  mSentToCompositor = true;
-  if (mListener != nullptr) {
-    mListener->OnSentToCompositor();
-    mListener = nullptr;
-  }
-}
-
 size_t VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
   size_t size = aMallocSizeOf(this);
 
   // Currently only PLANAR_YCBCR has a well defined function for determining
   // it's size, so reporting is limited to that type.
   if (mImage && mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     const mozilla::layers::PlanarYCbCrImage* img =
         static_cast<const mozilla::layers::PlanarYCbCrImage*>(mImage.get());
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -446,22 +446,16 @@ class VideoData : public MediaData {
     };
 
     Plane mPlanes[3];
     YUVColorSpace mYUVColorSpace = YUVColorSpace::UNKNOWN;
     ColorDepth mColorDepth = ColorDepth::COLOR_8;
     ColorRange mColorRange = ColorRange::LIMITED;
   };
 
-  class Listener {
-   public:
-    virtual void OnSentToCompositor() = 0;
-    virtual ~Listener() {}
-  };
-
   // Constructs a VideoData object. If aImage is nullptr, creates a new Image
   // holding a copy of the YCbCr data passed in aBuffer. If aImage is not
   // nullptr, it's stored as the underlying video image and aBuffer is assumed
   // to point to memory within aImage so no copy is made. aTimecode is a codec
   // specific number representing the timestamp of the frame of video data.
   // Returns nsnull if an error occurs. This may indicate that memory couldn't
   // be allocated to create the VideoData object, or it may indicate some
   // problem with the input data (e.g. negative stride).
@@ -506,34 +500,32 @@ class VideoData : public MediaData {
 
   int32_t mFrameID;
 
   VideoData(int64_t aOffset, const media::TimeUnit& aTime,
             const media::TimeUnit& aDuration, bool aKeyframe,
             const media::TimeUnit& aTimecode, IntSize aDisplay,
             uint32_t aFrameID);
 
-  void SetListener(UniquePtr<Listener> aListener);
-  void MarkSentToCompositor();
+  void MarkSentToCompositor() { mSentToCompositor = true; }
   bool IsSentToCompositor() { return mSentToCompositor; }
 
   void UpdateDuration(const media::TimeUnit& aDuration);
   void UpdateTimestamp(const media::TimeUnit& aTimestamp);
 
   void SetNextKeyFrameTime(const media::TimeUnit& aTime) {
     mNextKeyFrameTime = aTime;
   }
 
   const media::TimeUnit& NextKeyFrameTime() const { return mNextKeyFrameTime; }
 
  protected:
   ~VideoData();
 
   bool mSentToCompositor;
-  UniquePtr<Listener> mListener;
   media::TimeUnit mNextKeyFrameTime;
 };
 
 enum class CryptoScheme : uint8_t {
   None,
   Cenc,
   Cbcs,
 };
--- a/dom/media/VideoFrameContainer.cpp
+++ b/dom/media/VideoFrameContainer.cpp
@@ -1,17 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "VideoFrameContainer.h"
+
+#ifdef MOZ_WIDGET_ANDROID
+#include "GLImages.h"  // for SurfaceTextureImage
+#endif
+#include "MediaDecoderOwner.h"
 #include "mozilla/Telemetry.h"
-#include "MediaDecoderOwner.h"
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 static LazyLogModule gVideoFrameContainerLog("VideoFrameContainer");
 #define CONTAINER_LOG(type, msg) MOZ_LOG(gVideoFrameContainerLog, type, msg)
 
 #define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead
@@ -73,33 +77,60 @@ void VideoFrameContainer::UpdatePrincipa
     const ImageContainer::FrameID& aFrameID) {
   if (mPendingPrincipalHandle == aPrincipalHandle) {
     return;
   }
   mPendingPrincipalHandle = aPrincipalHandle;
   mFrameIDForPendingPrincipalHandle = aFrameID;
 }
 
+#ifdef MOZ_WIDGET_ANDROID
+static void NotifySetCurrent(Image* aImage) {
+  if (aImage == nullptr) {
+    return;
+  }
+
+  SurfaceTextureImage* image = aImage->AsSurfaceTextureImage();
+  if (image == nullptr) {
+    return;
+  }
+
+  image->OnSetCurrent();
+}
+#endif
+
 void VideoFrameContainer::SetCurrentFrame(const gfx::IntSize& aIntrinsicSize,
                                           Image* aImage,
                                           const TimeStamp& aTargetTime) {
+#ifdef MOZ_WIDGET_ANDROID
+    NotifySetCurrent(aImage);
+#endif
   if (aImage) {
     MutexAutoLock lock(mMutex);
     AutoTArray<ImageContainer::NonOwningImage, 1> imageList;
     imageList.AppendElement(
         ImageContainer::NonOwningImage(aImage, aTargetTime, ++mFrameID));
     SetCurrentFramesLocked(aIntrinsicSize, imageList);
   } else {
     ClearCurrentFrame(aIntrinsicSize);
   }
 }
 
 void VideoFrameContainer::SetCurrentFrames(
     const gfx::IntSize& aIntrinsicSize,
     const nsTArray<ImageContainer::NonOwningImage>& aImages) {
+#ifdef MOZ_WIDGET_ANDROID
+  // When there are multiple frames, only the last one is effective
+  // (see bug 1299068 comment 4). Here I just count on VideoSink and VideoOutput
+  // to send one frame at a time and warn if not.
+  Unused << NS_WARN_IF(aImages.Length() > 1);
+  for (auto& image : aImages) {
+    NotifySetCurrent(image.mImage);
+  }
+#endif
   MutexAutoLock lock(mMutex);
   SetCurrentFramesLocked(aIntrinsicSize, aImages);
 }
 
 void VideoFrameContainer::SetCurrentFramesLocked(
     const gfx::IntSize& aIntrinsicSize,
     const nsTArray<ImageContainer::NonOwningImage>& aImages) {
   mMutex.AssertCurrentThreadOwns();
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -57,23 +57,24 @@ class RenderOrReleaseOutput {
   CodecProxy::GlobalRef mCodec;
   Sample::GlobalRef mSample;
 };
 
 class RemoteVideoDecoder : public RemoteDataDecoder {
  public:
   // Render the output to the surface when the frame is sent
   // to compositor, or release it if not presented.
-  class CompositeListener : private RenderOrReleaseOutput,
-                            public VideoData::Listener {
+  class CompositeListener
+      : private RenderOrReleaseOutput,
+        public layers::SurfaceTextureImage::SetCurrentCallback {
    public:
     CompositeListener(CodecProxy::Param aCodec, Sample::Param aSample)
         : RenderOrReleaseOutput(aCodec, aSample) {}
 
-    void OnSentToCompositor() override { ReleaseOutput(true); }
+    void operator()(void) override { ReleaseOutput(true); }
   };
 
   class InputInfo {
    public:
     InputInfo() {}
 
     InputInfo(const int64_t aDurationUs, const gfx::IntSize& aImageSize,
               const gfx::IntSize& aDisplaySize)
@@ -250,17 +251,17 @@ class RemoteVideoDecoder : public Remote
     }
 
     AssertOnTaskQueue();
     if (GetState() == State::SHUTDOWN) {
       aSample->Dispose();
       return;
     }
 
-    UniquePtr<VideoData::Listener> releaseSample(
+    UniquePtr<layers::SurfaceTextureImage::SetCurrentCallback> releaseSample(
         new CompositeListener(mJavaDecoder, aSample));
 
     BufferInfo::LocalRef info = aSample->Info();
     MOZ_ASSERT(info);
 
     int32_t flags;
     bool ok = NS_SUCCEEDED(info->Flags(&flags));
 
@@ -286,25 +287,26 @@ class RemoteVideoDecoder : public Remote
       // Ignore output with no corresponding input.
       return;
     }
 
     if (ok && (size > 0 || presentationTimeUs >= 0)) {
       RefPtr<layers::Image> img = new layers::SurfaceTextureImage(
           mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */,
           gl::OriginPos::BottomLeft, mConfig.HasAlpha());
+      img->AsSurfaceTextureImage()->RegisterSetCurrentCallback(
+          std::move(releaseSample));
 
       RefPtr<VideoData> v = VideoData::CreateFromImage(
           inputInfo.mDisplaySize, offset,
           TimeUnit::FromMicroseconds(presentationTimeUs),
-          TimeUnit::FromMicroseconds(inputInfo.mDurationUs), img,
+          TimeUnit::FromMicroseconds(inputInfo.mDurationUs), img.forget(),
           !!(flags & MediaCodec::BUFFER_FLAG_SYNC_FRAME),
           TimeUnit::FromMicroseconds(presentationTimeUs));
 
-      v->SetListener(std::move(releaseSample));
       RemoteDataDecoder::UpdateOutputStatus(std::move(v));
     }
 
     if (isEOS) {
       DrainComplete();
     }
   }
 
--- a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html
@@ -13,16 +13,20 @@
   });
 
   runNetworkTest(async function (options) {
     // Use fake video here since the native fake device on linux doesn't
     // change color as needed by checkVideoPlaying() below.
     await pushPrefs(
       ['media.video_loopback_dev', ''],
       ['media.navigator.streams.fake', true]);
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
 
     const test = new PeerConnectionTest(options);
     addRenegotiation(test.chain,
       [
         function PC_LOCAL_ADD_SECOND_STREAM(test) {
           test.setMediaConstraints([{video: true}, {video: true}],
                                    [{video: true}]);
           return test.pcLocal.getAllUserMediaAndAddStreams([{video: true}]);
--- a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html
@@ -13,16 +13,20 @@
   });
 
   runNetworkTest(async function (options = {}) {
     // Use fake video here since the native fake device on linux doesn't
     // change color as needed by checkVideoPlaying() below.
     await pushPrefs(
       ['media.video_loopback_dev', ''],
       ['media.navigator.streams.fake', true]);
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
 
     options.bundle = false;
     const test = new PeerConnectionTest(options);
     addRenegotiation(test.chain,
       [
         function PC_LOCAL_ADD_SECOND_STREAM(test) {
           test.setMediaConstraints([{video: true}, {video: true}],
                                    [{video: true}]);
--- a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html
+++ b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html
@@ -8,17 +8,22 @@
 <pre id="test">
 <script type="application/javascript">
 createHTML({
   bug: "1032848",
   title: "Canvas(2D)::CaptureStream as video-only input to peerconnection",
   visible: true
 });
 
-runNetworkTest(() => {
+runNetworkTest(async () => {
+  // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+  if (navigator.userAgent.includes("Android")) {
+    await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+  }
+
   var test = new PeerConnectionTest();
   var mediaElement;
   var h = new CaptureStreamTestHelper2D();
   var canvas = document.createElement('canvas');
   var stream;
   canvas.id = 'source_canvas';
   canvas.width = canvas.height = 10;
   document.getElementById('content').appendChild(canvas);
--- a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d_noSSRC.html
+++ b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d_noSSRC.html
@@ -8,17 +8,22 @@
 <pre id="test">
 <script type="application/javascript">
 createHTML({
   title: "Canvas(2D)::CaptureStream as video-only input to peerconnection with no a=ssrc",
   visible: true
 });
 
 var test;
-runNetworkTest((options) => {
+runNetworkTest(async (options) => {
+  // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+  if (navigator.userAgent.includes("Android")) {
+    await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+  }
+
   options = options || { };
   options.ssrc = false;
   test = new PeerConnectionTest(options);
   var mediaElement;
   var h = new CaptureStreamTestHelper2D();
   var canvas = document.createElement('canvas');
   var stream;
   canvas.id = 'source_canvas';
--- a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html
+++ b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html
@@ -19,17 +19,22 @@
   void main() { gl_FragColor = uColor; }
 </script>
 <script type="application/javascript">
 createHTML({
   bug: "1032848",
   title: "Canvas(WebGL)::CaptureStream as video-only input to peerconnection"
 });
 
-runNetworkTest(() => {
+runNetworkTest(async () => {
+  // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+  if (navigator.userAgent.includes("Android")) {
+    await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+  }
+
   var test = new PeerConnectionTest();
   var vremote;
   var h = new CaptureStreamTestHelperWebGL();
   var canvas = document.createElement('canvas');
   canvas.id = 'source_canvas';
   canvas.width = canvas.height = 10;
   canvas.style.display = 'none';
   document.getElementById('content').appendChild(canvas);
--- a/dom/media/tests/mochitest/test_peerConnection_disabledVideoPreNegotiation.html
+++ b/dom/media/tests/mochitest/test_peerConnection_disabledVideoPreNegotiation.html
@@ -9,17 +9,22 @@
 <script type="application/javascript">
   createHTML({
     bug: "1570673",
     title: "Sending an initially disabled video track should be playable remotely",
     visible: true,
   });
 
   var test;
-  runNetworkTest(function (options) {
+  runNetworkTest(async (options) => {
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
+
     test = new PeerConnectionTest(options);
     test.setMediaConstraints([{video: true}], []);
     test.chain.insertAfter("PC_LOCAL_GUM", function PC_LOCAL_DISABLE_VIDEO() {
       for (const {track} of test.pcLocal._pc.getSenders()) {
         if (track.kind == "video") {
           track.enabled = false;
         }
       }
--- a/dom/media/tests/mochitest/test_peerConnection_multiple_captureStream_canvas_2d.html
+++ b/dom/media/tests/mochitest/test_peerConnection_multiple_captureStream_canvas_2d.html
@@ -11,17 +11,22 @@ createHTML({
   bug: "1166832",
   title: "Canvas(2D)::Multiple CaptureStream as video-only input to peerconnection",
   visible: true
 });
 
 /**
  * Test to verify using multiple capture streams concurrently.
  */
-runNetworkTest(() => {
+runNetworkTest(async () => {
+  // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+  if (navigator.userAgent.includes("Android")) {
+    await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+  }
+
   var test = new PeerConnectionTest();
   var h = new CaptureStreamTestHelper2D(50, 50);
 
   var vremote1;
   var stream1;
   var canvas1 = h.createAndAppendElement('canvas', 'source_canvas1');
 
   var vremote2;
--- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html
@@ -13,16 +13,20 @@
   });
 
   runNetworkTest(async function (options) {
     // Use fake video here since the native fake device on linux doesn't
     // change color as needed by checkVideoPlaying() below.
     await pushPrefs(
       ['media.video_loopback_dev', ''],
       ['media.navigator.streams.fake', true]);
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
 
     const test = new PeerConnectionTest(options);
     const helper = new VideoStreamHelper();
     var originalTrack;
     let haveMuteEvent = new Promise(() => {});
     let haveUnmuteEvent = new Promise(() => {});
     addRenegotiation(test.chain,
       [
--- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html
@@ -13,16 +13,20 @@
   });
 
   runNetworkTest(async function (options) {
     // Use fake video here since the native fake device on linux doesn't
     // change color as needed by checkVideoPlaying() below.
     await pushPrefs(
       ['media.video_loopback_dev', ''],
       ['media.navigator.streams.fake', true]);
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
 
     options = options || { };
     options.bundle = false;
     const test = new PeerConnectionTest(options);
     const helper = new VideoStreamHelper();
     var originalTrack;
     addRenegotiation(test.chain,
       [
--- a/dom/media/tests/mochitest/test_peerConnection_removeVideoTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeVideoTrack.html
@@ -7,17 +7,22 @@
 <body>
 <pre id="test">
 <script type="application/javascript">
   createHTML({
     bug: "1017888",
     title: "Renegotiation: remove video track"
   });
 
-  runNetworkTest(function (options) {
+  runNetworkTest(async (options) => {
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
+
     const test = new PeerConnectionTest(options);
     let receivedTrack, element;
     addRenegotiation(test.chain,
       [
         function PC_REMOTE_SETUP_HELPER(test) {
           is(test.pcRemote._pc.getReceivers().length, 1,
              "pcRemote should have one receiver before renegotiation");
 
--- a/dom/media/tests/mochitest/test_peerConnection_renderAfterRenegotiation.html
+++ b/dom/media/tests/mochitest/test_peerConnection_renderAfterRenegotiation.html
@@ -30,17 +30,22 @@
       // Test RTCTrackEvent required args here.
       mustThrowWith("RTCTrackEvent wo/required args",
                     "TypeError", () => new RTCTrackEvent("track", {}));
       v2.srcObject = e.streams[0];
       resolve();
     }
   });
 
-  runNetworkTest(function() {
+  runNetworkTest(async () => {
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
+
     v2 = createMediaElement('video', 'v2');
     is(v2.currentTime, 0, "v2.currentTime is zero at outset");
 
     const emitter = new VideoFrameEmitter(CaptureStreamTestHelper.prototype.blue,
                                           CaptureStreamTestHelper.prototype.green,
                                           10, 10);
     emitter.start();
     emitter.stream().getTracks().forEach(t => pc1.addTrack(t, emitter.stream()));
--- a/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
+++ b/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
@@ -7,18 +7,23 @@
 <body>
 <pre id="test">
 <script type="application/javascript">
   createHTML({
     bug: "1017888",
     title: "Renegotiation: replaceTrack followed by adding a second video stream"
   });
 
-  runNetworkTest(function (options) {
-   pushPrefs(['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => {
+  runNetworkTest(async (options) => {
+    await pushPrefs(['media.peerconnection.video.min_bitrate_estimate', 180*1000]);
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
+
     const test = new PeerConnectionTest(options);
     test.setMediaConstraints([{video:true}], [{video:true}]);
     const helper = new VideoStreamHelper();
     const emitter1 = new VideoFrameEmitter(CaptureStreamTestHelper.prototype.red,
                                            CaptureStreamTestHelper.prototype.green);
     const emitter2 = new VideoFrameEmitter(CaptureStreamTestHelper.prototype.blue,
                                            CaptureStreamTestHelper.prototype.grey);
     test.chain.replace("PC_LOCAL_GUM", [
@@ -55,15 +60,14 @@
           }
           ok(!vremote.ended, "Original track should not have ended after renegotiation (replaceTrack is not signalled!)");
           return helper.checkVideoPlaying(vremote);
         }
       ]
     );
 
     test.run();
-   });
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_peerConnection_setParameters_scaleResolutionDownBy.html
+++ b/dom/media/tests/mochitest/test_peerConnection_setParameters_scaleResolutionDownBy.html
@@ -27,16 +27,20 @@ async function checkScaleDownBy(scale) {
   is(remoteElem.videoWidth, expectedWidth,
     `Width should have scaled down by ${scale}`);
   is(remoteElem.videoHeight, expectedWidth / originalAspectRatio,
     `Height should have scaled down by ${scale}`);
 }
 
 runNetworkTest(async function (options) {
   await pushPrefs(['media.peerconnection.video.lock_scaling', true]);
+  // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+  if (navigator.userAgent.includes("Android")) {
+    await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+  }
 
   let test = new PeerConnectionTest(options);
   test.setMediaConstraints([{video: true}], []);
   test.chain.append([
     function CHECK_PRECONDITIONS() {
       is(test.pcLocal._pc.getSenders().length, 1,
           "Should have 1 local sender");
       is(test.pcLocal.localMediaElements.length, 1,
--- a/dom/media/tests/mochitest/test_peerConnection_trackDisabling_clones.html
+++ b/dom/media/tests/mochitest/test_peerConnection_trackDisabling_clones.html
@@ -19,16 +19,20 @@ runNetworkTest(async () => {
     ["media.getusermedia.camera.stop_on_disable.enabled", true],
     ["media.getusermedia.camera.stop_on_disable.delay_ms", 0],
     ["media.getusermedia.microphone.stop_on_disable.enabled", true],
     ["media.getusermedia.microphone.stop_on_disable.delay_ms", 0],
     // Always use fake tracks since we depend on audio to have a large 1000Hz
     // component.
     ['media.audio_loopback_dev', ''],
     ['media.navigator.streams.fake', true]);
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
 
   var originalStream;
   var localVideoOriginal;
 
   test.setMediaConstraints([{audio: true, video: true}], []);
   test.chain.replace("PC_LOCAL_GUM", [
     function PC_LOCAL_GUM_CLONE() {
       return getUserMedia(test.pcLocal.constraints[0]).then(stream => {
--- a/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html
+++ b/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html
@@ -7,17 +7,22 @@
 <body>
 <pre id="test">
 <script type="application/javascript">
   createHTML({
     bug: "1166832",
     title: "Renegotiation: verify video after renegotiation"
   });
 
-runNetworkTest(() => {
+runNetworkTest(async () => {
+  // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+  if (navigator.userAgent.includes("Android")) {
+    await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+  }
+
   var test = new PeerConnectionTest();
 
   var h1 = new CaptureStreamTestHelper2D(50, 50);
   var canvas1 = h1.createAndAppendElement('canvas', 'source_canvas1');
   var stream1;
   var vremote1;
 
   var h2 = new CaptureStreamTestHelper2D(50, 50);
--- a/dom/media/tests/mochitest/test_peerConnection_videoRenegotiationInactiveAnswer.html
+++ b/dom/media/tests/mochitest/test_peerConnection_videoRenegotiationInactiveAnswer.html
@@ -9,17 +9,22 @@
 <pre id="test">
 <script type="application/javascript">
   createHTML({
     bug: "1213773",
     title: "Renegotiation: answerer uses a=inactive for video"
   });
 
   var test;
-  runNetworkTest(function (options) {
+  runNetworkTest(async (options) => {
+    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
+    if (navigator.userAgent.includes("Android")) {
+      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
+    }
+
     const emitter = new VideoFrameEmitter();
     const helper = new VideoStreamHelper();
 
     test = new PeerConnectionTest(options);
 
     test.chain.replace("PC_LOCAL_GUM", [
       function PC_LOCAL_CANVAS_CAPTURESTREAM(test) {
         test.pcLocal.attachLocalStream(emitter.stream());
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -217,23 +217,22 @@ void Performance::Mark(const nsAString& 
   }
 
   RefPtr<PerformanceMark> performanceMark =
       new PerformanceMark(GetParentObject(), aName, Now());
   InsertUserEntry(performanceMark);
 
 #ifdef MOZ_GECKO_PROFILER
   if (profiler_can_accept_markers()) {
-    nsCOMPtr<EventTarget> et = do_QueryInterface(GetOwner());
-    nsCOMPtr<nsIDocShell> docShell =
-        nsContentUtils::GetDocShellForEventTarget(et);
-    DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
-    PROFILER_ADD_MARKER_WITH_PAYLOAD(
-        "UserTiming", DOM, UserTimingMarkerPayload,
-        (aName, TimeStamp::Now(), docShellId, docShellHistoryId));
+    Maybe<uint64_t> innerWindowId;
+    if (GetOwner()) {
+      innerWindowId = Some(GetOwner()->WindowID());
+    }
+    PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTiming", DOM, UserTimingMarkerPayload,
+                                     (aName, TimeStamp::Now(), innerWindowId));
   }
 #endif
 }
 
 void Performance::ClearMarks(const Optional<nsAString>& aName) {
   ClearUserEntries(aName, NS_LITERAL_STRING("mark"));
 }
 
@@ -321,24 +320,23 @@ void Performance::Measure(const nsAStrin
     if (aStartMark.WasPassed()) {
       startMark.emplace(aStartMark.Value());
     }
     Maybe<nsString> endMark;
     if (aEndMark.WasPassed()) {
       endMark.emplace(aEndMark.Value());
     }
 
-    nsCOMPtr<EventTarget> et = do_QueryInterface(GetOwner());
-    nsCOMPtr<nsIDocShell> docShell =
-        nsContentUtils::GetDocShellForEventTarget(et);
-    DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
-    PROFILER_ADD_MARKER_WITH_PAYLOAD(
-        "UserTiming", DOM, UserTimingMarkerPayload,
-        (aName, startMark, endMark, startTimeStamp, endTimeStamp, docShellId,
-         docShellHistoryId));
+    Maybe<uint64_t> innerWindowId;
+    if (GetOwner()) {
+      innerWindowId = Some(GetOwner()->WindowID());
+    }
+    PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTiming", DOM, UserTimingMarkerPayload,
+                                     (aName, startMark, endMark, startTimeStamp,
+                                      endTimeStamp, innerWindowId));
   }
 #endif
 }
 
 void Performance::ClearMeasures(const Optional<nsAString>& aName) {
   ClearUserEntries(aName, NS_LITERAL_STRING("measure"));
 }
 
--- a/gfx/2d/FilterNodeD2D1.cpp
+++ b/gfx/2d/FilterNodeD2D1.cpp
@@ -643,16 +643,19 @@ already_AddRefed<FilterNode> FilterNodeD
     filter = new FilterNodePremultiplyAdapterD2D1(aDC, filter, aType);
   }
 
   return filter.forget();
 }
 
 void FilterNodeD2D1::InitUnmappedProperties() {
   switch (mType) {
+    case FilterType::COLOR_MATRIX:
+      mEffect->SetValue(D2D1_COLORMATRIX_PROP_CLAMP_OUTPUT, TRUE);
+      break;
     case FilterType::TRANSFORM:
       mEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_BORDER_MODE,
                         D2D1_BORDER_MODE_HARD);
       break;
     default:
       break;
   }
 }
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -26,16 +26,22 @@ class GLImage : public Image {
 
   GLImage* AsGLImage() override { return this; }
 };
 
 #ifdef MOZ_WIDGET_ANDROID
 
 class SurfaceTextureImage : public GLImage {
  public:
+  class SetCurrentCallback {
+   public:
+    virtual void operator()(void) = 0;
+    virtual ~SetCurrentCallback() {}
+  };
+
   SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
                       const gfx::IntSize& aSize, bool aContinuous,
                       gl::OriginPos aOriginPos, bool aHasAlpha = true);
 
   gfx::IntSize GetSize() const override { return mSize; }
   AndroidSurfaceTextureHandle GetHandle() const { return mHandle; }
   bool GetContinuous() const { return mContinuous; }
   gl::OriginPos GetOriginPos() const { return mOriginPos; }
@@ -45,22 +51,34 @@ class SurfaceTextureImage : public GLIma
     // We can implement this, but currently don't want to because it will cause
     // the SurfaceTexture to be permanently bound to the snapshot readback
     // context.
     return nullptr;
   }
 
   SurfaceTextureImage* AsSurfaceTextureImage() override { return this; }
 
+  void RegisterSetCurrentCallback(UniquePtr<SetCurrentCallback> aCallback) {
+    mSetCurrentCallback = std::move(aCallback);
+  }
+
+  void OnSetCurrent() {
+    if (mSetCurrentCallback) {
+      (*mSetCurrentCallback)();
+      mSetCurrentCallback.reset();
+    }
+  }
+
  private:
   AndroidSurfaceTextureHandle mHandle;
   gfx::IntSize mSize;
   bool mContinuous;
   gl::OriginPos mOriginPos;
   const bool mHasAlpha;
+  UniquePtr<SetCurrentCallback> mSetCurrentCallback;
 };
 
 #endif  // MOZ_WIDGET_ANDROID
 
 }  // namespace layers
 }  // namespace mozilla
 
 #endif  // GFX_GLIMAGES_H
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -726,17 +726,16 @@ struct DIGroup {
               mKey.value().second(), descriptor, bytes,
               ViewAs<ImagePixel>(mVisibleRect,
                                  PixelCastJustification::LayerIsImage),
               dirtyRect)) {
         return;
       }
     }
     mFonts = std::move(fonts);
-    mInvalidRect.SetEmpty();
     aResources.SetBlobImageVisibleArea(
         mKey.value().second(),
         ViewAs<ImagePixel>(mVisibleRect, PixelCastJustification::LayerIsImage));
     mLastVisibleRect = mVisibleRect;
     PushImage(aBuilder, itemBounds);
     GP("End EndGroup\n\n");
   }
 
@@ -1212,16 +1211,18 @@ void Grouper::ConstructGroups(nsDisplayL
   nsDisplayItem* startOfCurrentGroup = item;
   while (item) {
     if (IsItemProbablyActive(item, mDisplayListBuilder)) {
       // We're going to be starting a new group.
       RefPtr<WebRenderGroupData> groupData =
           aCommandBuilder->CreateOrRecycleWebRenderUserData<WebRenderGroupData>(
               item, aBuilder.GetRenderRoot());
 
+      groupData->mFollowingGroup.mInvalidRect.SetEmpty();
+
       // Initialize groupData->mFollowingGroup with data from currentGroup.
       // We want to copy out this information before calling EndGroup because
       // EndGroup will set mLastVisibleRect depending on whether
       // we send something to WebRender.
 
       // TODO: compute the group bounds post-grouping, so that they can be
       // tighter for just the sublist that made it into this group.
       // We want to ensure the tight bounds are still clipped by area
@@ -1476,16 +1477,18 @@ void WebRenderCommandBuilder::DoGrouping
   GP("LayerBounds: %d %d %d %d\n", layerBounds.x, layerBounds.y,
      layerBounds.width, layerBounds.height);
   GP("VisibleRect: %d %d %d %d\n", visibleRect.x, visibleRect.y,
      visibleRect.width, visibleRect.height);
 
   GP("Inherrited scale %f %f\n", scale.width, scale.height);
   GP("Bounds: %d %d %d %d vs %d %d %d %d\n", p.x, p.y, p.width, p.height, q.x,
      q.y, q.width, q.height);
+
+  group.mInvalidRect.SetEmpty();
   if (group.mAppUnitsPerDevPixel != appUnitsPerDevPixel ||
       group.mScale != scale || group.mResidualOffset != residualOffset) {
     GP("Property change. Deleting blob\n");
 
     if (group.mAppUnitsPerDevPixel != appUnitsPerDevPixel) {
       GP(" App unit change %d -> %d\n", group.mAppUnitsPerDevPixel,
          appUnitsPerDevPixel);
     }
@@ -2176,18 +2179,24 @@ WebRenderCommandBuilder::GenerateFallbac
                              aItem->GetBuildingRect(), scale.width,
                              scale.height, appUnitsPerDevPixel, residualOffset))
                          .Intersect(dtRect);
 
   auto visibleSize = visibleRect.Size();
   if (visibleSize.IsEmpty()) {
     return nullptr;
   }
-  // Display item bounds should be unscaled
-  aImageRect = visibleRect / layerScale;
+
+  if (useBlobImage) {
+    // Display item bounds should be unscaled
+    aImageRect = visibleRect / layerScale;
+  } else {
+    // Display item bounds should be unscaled
+    aImageRect = dtRect / layerScale;
+  }
 
   // We always paint items at 0,0 so the visibleRect that we use inside the blob
   // is needs to be adjusted by the display item bounds top left.
   visibleRect -= dtRect.TopLeft();
 
   nsDisplayItemGeometry* geometry = fallbackData->mGeometry;
 
   bool needPaint = true;
@@ -2320,17 +2329,17 @@ WebRenderCommandBuilder::GenerateFallbac
       imageData->CreateImageClientIfNeeded();
       RefPtr<ImageClient> imageClient = imageData->GetImageClient();
       RefPtr<ImageContainer> imageContainer =
           LayerManager::CreateImageContainer();
       bool isInvalidated = false;
 
       {
         UpdateImageHelper helper(imageContainer, imageClient,
-                                 visibleSize.ToUnknownSize(), format);
+                                 dtRect.Size().ToUnknownSize(), format);
         {
           RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
           if (!dt) {
             return nullptr;
           }
           if (!fallbackData->mBasicLayerManager) {
             fallbackData->mBasicLayerManager =
                 new BasicLayerManager(mManager->GetWidget());
--- a/gfx/wr/Cargo.lock
+++ b/gfx/wr/Cargo.lock
@@ -1055,20 +1055,20 @@ dependencies = [
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke-derive 0.2.0",
 ]
 
 [[package]]
 name = "peek-poke-derive"
 version = "0.2.0"
 dependencies = [
- "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "percent-encoding"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -1108,16 +1108,24 @@ dependencies = [
 name = "proc-macro2"
 version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "proc-macro2"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "procedural-masquerade"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quick-error"
 version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1126,16 +1134,24 @@ source = "registry+https://github.com/ru
 name = "quote"
 version = "0.6.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "rand"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1518,27 +1534,48 @@ version = "0.15.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "syn"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "synstructure"
 version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "synstructure"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "tempfile"
 version = "3.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1628,16 +1665,21 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "unreachable"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2128,19 +2170,21 @@ dependencies = [
 "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
 "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
 "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
 "checksum plane-split 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe16a646a08f4b4dd74035b9ff8e378eb1a4012a74f14f5889e7001cdbece33"
 "checksum png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8422b27bb2c013dd97b9aef69e161ce262236f49aaf46a0489011c8ff0264602"
 "checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
+"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"
 "checksum procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1574a51c3fd37b26d2c0032b649d08a7d51d4cca9c41bbc5bf7118fa4509d0"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
 "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
 "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
@@ -2176,30 +2220,33 @@ dependencies = [
 "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
 "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
 "checksum smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa"
 "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
 "checksum stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "69b7df505db8e81d54ff8be4693421e5b543e08214bd8d99eb761fcb4d5668ba"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum svg_fmt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c666f0fed8e1e20e057af770af9077d72f3d5a33157b8537c1475dd8ffd6d32b"
 "checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"
+"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
+"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203"
 "checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5920e77802b177479ab5795767fa48e68f61b2f516c2ac0041e2978dd8efe483"
 "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
 "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
 "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
 "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7904a7e2bb3cdf0cf5e783f44204a85a37a93151738fa349f06680f59a98b45"
--- a/gfx/wr/peek-poke/peek-poke-derive/Cargo.toml
+++ b/gfx/wr/peek-poke/peek-poke-derive/Cargo.toml
@@ -5,13 +5,13 @@ authors = ["Dan Glastonbury <dan.glaston
 license = "MIT/Apache-2.0"
 edition = "2018"
 
 [lib]
 doctest = false
 proc-macro = true
 
 [dependencies]
-proc-macro2 = "0.4"
-quote = "0.6"
-syn = "0.15"
-synstructure = "0.10"
+proc-macro2 = "1"
+quote = "1"
+syn = "1"
+synstructure = "0.12"
 unicode-xid = "0.1"
--- a/gfx/wr/servo-tidy.toml
+++ b/gfx/wr/servo-tidy.toml
@@ -11,16 +11,23 @@ packages = [
     "lazy_static",
     "percent-encoding",
     "rand",
     "rand_core",
     "winapi",
     "core-graphics",
     "core-text",
     "yaml-rust",
+
+    # These are tracked in bug 1587468, see there for pending work.
+    "syn",
+    "quote",
+    "unicode-xid",
+    "synstructure",
+    "proc-macro2",
 ]
 
 # Files that are ignored for all tidy and lint checks.
 files = [
     "./wrench/src/egl.rs",  # Copied from glutin
     "./ci-scripts/wrupdater/converter.py",  # servo-tidy doesn't like python3
     "./ci-scripts/wrupdater/read-json.py",  # servo-tidy doesn't like python3
 ]
--- a/intl/l10n/L10nRegistry.jsm
+++ b/intl/l10n/L10nRegistry.jsm
@@ -1,15 +1,20 @@
 const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 // eslint-disable-next-line mozilla/use-services
 const appinfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
 const { FluentBundle, FluentResource } = ChromeUtils.import("resource://gre/modules/Fluent.jsm");
 const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
+ChromeUtils.defineModuleGetter(
+  this,
+  "NetUtil",
+  "resource://gre/modules/NetUtil.jsm"
+);
 
 const isParentProcess = appinfo.processType === appinfo.PROCESS_TYPE_DEFAULT;
 /**
  * L10nRegistry is a localization resource management system for Gecko.
  *
  * It manages the list of resource sources provided with the app and allows
  * for additional sources to be added and updated.
  *
@@ -749,16 +754,38 @@ this.L10nRegistry.load = function(url) {
  * @returns {string}
  */
 this.L10nRegistry.loadSync = function(uri) {
   try {
     let url = Services.io.newURI(uri);
     let data = Cu.readUTF8URI(url);
     return data;
   } catch (e) {
-    return false;
+    if (
+      e.result == Cr.NS_ERROR_INVALID_ARG ||
+      e.result == Cr.NS_ERROR_NOT_INITIALIZED
+    ) {
+      try {
+        // The preloader doesn't support this url or isn't initialized
+        // (xpcshell test). Try a synchronous channel load.
+        let stream = NetUtil.newChannel({
+          uri,
+          loadUsingSystemPrincipal: true,
+        }).open();
+
+        return NetUtil.readInputStreamToString(stream, stream.available(), {
+          charset: "UTF-8",
+        });
+      } catch (e) {
+        Cu.reportError(e);
+      }
+    } else {
+      Cu.reportError(e);
+    }
   }
+
+  return false;
 };
 
 this.FileSource = FileSource;
 this.IndexedFileSource = IndexedFileSource;
 
 var EXPORTED_SYMBOLS = ["L10nRegistry", "FileSource", "IndexedFileSource"];
--- a/js/src/jit/JitScript.cpp
+++ b/js/src/jit/JitScript.cpp
@@ -8,24 +8,28 @@
 
 #include "mozilla/BinarySearch.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Move.h"
 #include "mozilla/ScopeExit.h"
 
 #include "jit/BaselineIC.h"
 #include "jit/BytecodeAnalysis.h"
+#include "vm/BytecodeIterator.h"
+#include "vm/BytecodeLocation.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/JSScript.h"
 #include "vm/Stack.h"
 #include "vm/TypeInference.h"
 #include "wasm/WasmInstance.h"
 
 #include "gc/FreeOp-inl.h"
 #include "jit/JSJitFrameIter-inl.h"
+#include "vm/BytecodeIterator-inl.h"
+#include "vm/BytecodeLocation-inl.h"
 #include "vm/JSScript-inl.h"
 #include "vm/TypeInference-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 /* static */
 size_t JitScript::NumTypeSets(JSScript* script) {
@@ -274,39 +278,39 @@ void JitScript::printTypes(JSContext* cx
     if (JSAtom* name = script->functionNonDelazifying()->explicitName()) {
       name->dumpCharsNoNewline(out);
     }
   }
 
   fprintf(stderr, "\n    this:");
   thisTypes(sweep, script)->print();
 
-  for (unsigned i = 0; script->functionNonDelazifying() &&
+  for (uint32_t i = 0; script->functionNonDelazifying() &&
                        i < script->functionNonDelazifying()->nargs();
        i++) {
     fprintf(stderr, "\n    arg%u:", i);
     argTypes(sweep, script, i)->print();
   }
   fprintf(stderr, "\n");
 
-  for (jsbytecode* pc = script->code(); pc < script->codeEnd();
-       pc += GetBytecodeLength(pc)) {
+  for (BytecodeLocation it : AllBytecodesIterable(script)) {
     {
       fprintf(stderr, "%p:", script.get());
       Sprinter sprinter(cx);
       if (!sprinter.init()) {
         return;
       }
-      Disassemble1(cx, script, pc, script->pcToOffset(pc), true, &sprinter);
+      Disassemble1(cx, script, it.toRawBytecode(), it.bytecodeToOffset(script),
+                   true, &sprinter);
       fprintf(stderr, "%s", sprinter.string());
     }
 
-    if (BytecodeOpHasTypeSet(JSOp(*pc))) {
-      StackTypeSet* types = bytecodeTypes(sweep, script, pc);
-      fprintf(stderr, "  typeset %u:", unsigned(types - typeArray(sweep)));
+    if (it.opHasTypeSet()) {
+      StackTypeSet* types = bytecodeTypes(sweep, script, it.toRawBytecode());
+      fprintf(stderr, "  typeset %u:", uint32_t(types - typeArray(sweep)));
       types->print();
       fprintf(stderr, "\n");
     }
   }
 
   fprintf(stderr, "\n");
 }
 #endif /* DEBUG */
--- a/js/src/vm/BytecodeLocation-inl.h
+++ b/js/src/vm/BytecodeLocation-inl.h
@@ -17,17 +17,18 @@ inline bool BytecodeLocation::isValid(co
   // Note: Don't create a new BytecodeLocation during the implementation of
   // this, as it is used in the constructor, and will recurse forever.
   return script->contains(*this) || toRawBytecode() == script->codeEnd();
 }
 
 inline bool BytecodeLocation::isInBounds(const JSScript* script) const {
   return script->contains(*this);
 }
-inline uint32_t BytecodeLocation::bytecodeToOffset(JSScript* script) {
+inline uint32_t BytecodeLocation::bytecodeToOffset(
+    const JSScript* script) const {
   return script->pcToOffset(this->rawBytecode_);
 }
 
 inline PropertyName* BytecodeLocation::getPropertyName(
     const JSScript* script) const {
   MOZ_ASSERT(this->isValid());
   return script->getName(this->rawBytecode_);
 }
--- a/js/src/vm/BytecodeLocation.h
+++ b/js/src/vm/BytecodeLocation.h
@@ -64,17 +64,17 @@ class BytecodeLocation {
   // Return true if this bytecode location is valid for the given script.
   // This includes the location 1-past the end of the bytecode.
   bool isValid(const JSScript* script) const;
 
   // Return true if this bytecode location is within the bounds of the
   // bytecode for a given script.
   bool isInBounds(const JSScript* script) const;
 
-  uint32_t bytecodeToOffset(JSScript* script);
+  uint32_t bytecodeToOffset(const JSScript* script) const;
 
   PropertyName* getPropertyName(const JSScript* script) const;
 
   bool operator==(const BytecodeLocation& other) const {
     MOZ_ASSERT(this->debugOnlyScript_ == other.debugOnlyScript_);
     return rawBytecode_ == other.rawBytecode_;
   }
 
@@ -115,16 +115,18 @@ class BytecodeLocation {
     MOZ_ASSERT(isInBounds());
     return getOp() == op;
   }
 
   bool isJumpTarget() const { return BytecodeIsJumpTarget(getOp()); }
 
   bool isJump() const { return IsJumpOpcode(getOp()); }
 
+  bool opHasTypeSet() const { return BytecodeOpHasTypeSet(getOp()); }
+
   bool fallsThrough() const { return BytecodeFallsThrough(getOp()); }
 
   uint32_t icIndex() const { return GET_ICINDEX(rawBytecode_); }
 
   bool isEqualityOp() const { return IsEqualityOp(getOp()); }
 
   bool isStrictEqualityOp() const {
     return is(JSOP_STRICTEQ) || is(JSOP_STRICTNE);
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -327,16 +327,23 @@ interface nsIXPCComponents_Utils : nsISu
      * In an NS_FREE_PERMANENT_DATA build, intentionally leak a C++ object. This
      * is needed to test leak checking.
      */
     void intentionallyLeak();
 
     [implicit_jscontext]
     jsval getJSTestingFunctions();
 
+    /**
+     * Returns an object containing `filename` and `lineNumber` properties
+     * describing the source location of the given function.
+     */
+    [implicit_jscontext]
+    jsval getFunctionSourceLocation(in jsval func);
+
     /*
      * To be called from JS only.
      *
      * Call 'function', using the provided stack as the async stack responsible
      * for the call, and propagate its return value or the exception it throws.
      * The function is called with no arguments, and 'this' is 'undefined'.
      *
      * The code in the function will see the given stack frame as the
@@ -673,16 +680,17 @@ interface nsIXPCComponents_Utils : nsISu
      * The file must be a text file encoded in UTF-8. Otherwise the result is
      * undefined.
      */
     AUTF8String readUTF8File(in nsIFile file);
 
     /*
      * Reads the given local file URL and returns its contents. This has the
      * same semantics of readUTF8File.
+     * Only supports file URLs or URLs that point into one of the omnijars.
      */
     AUTF8String readUTF8URI(in nsIURI url);
 
     /* Create a spellchecker object. */
     nsIEditorSpellCheck createSpellChecker();
 
     /* Create a commandline object. */
     nsISupports createCommandLine();
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -876,30 +876,30 @@ struct MOZ_STACK_CLASS ExceptionArgParse
   bool parseStack(HandleValue v) {
     if (!v.isObject()) {
       // eStack has already been initialized to null, which is what we want
       // for any non-object values (including null).
       return true;
     }
 
     RootedObject stackObj(cx, &v.toObject());
-    return NS_SUCCEEDED(xpc->WrapJS(
-        cx, stackObj, NS_GET_IID(nsIStackFrame), getter_AddRefs(eStack)));
+    return NS_SUCCEEDED(xpc->WrapJS(cx, stackObj, NS_GET_IID(nsIStackFrame),
+                                    getter_AddRefs(eStack)));
   }
 
   bool parseData(HandleValue v) {
     if (!v.isObject()) {
       // eData has already been initialized to null, which is what we want
       // for any non-object values (including null).
       return true;
     }
 
     RootedObject obj(cx, &v.toObject());
-    return NS_SUCCEEDED(xpc->WrapJS(cx, obj, NS_GET_IID(nsISupports),
-                                    getter_AddRefs(eData)));
+    return NS_SUCCEEDED(
+        xpc->WrapJS(cx, obj, NS_GET_IID(nsISupports), getter_AddRefs(eData)));
   }
 
   bool parseOptionsObject(HandleObject obj) {
     RootedValue v(cx);
 
     if (!getOption(obj, "result", &v) || (!v.isUndefined() && !parseResult(v)))
       return false;
 
@@ -1745,16 +1745,56 @@ nsXPCComponents_Utils::GetJSTestingFunct
   if (!obj) {
     return NS_ERROR_XPC_JAVASCRIPT_ERROR;
   }
   retval.setObject(*obj);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXPCComponents_Utils::GetFunctionSourceLocation(HandleValue funcValue,
+                                                 JSContext* cx,
+                                                 MutableHandleValue retval) {
+  NS_ENSURE_TRUE(funcValue.isObject(), NS_ERROR_INVALID_ARG);
+
+  nsAutoString filename;
+  uint32_t lineNumber;
+  {
+    RootedObject funcObj(cx, UncheckedUnwrap(&funcValue.toObject()));
+    JSAutoRealm ar(cx, funcObj);
+
+    Rooted<JSFunction*> func(cx, JS_GetObjectFunction(funcObj));
+    NS_ENSURE_TRUE(func, NS_ERROR_INVALID_ARG);
+
+    RootedScript script(cx, JS_GetFunctionScript(cx, func));
+    NS_ENSURE_TRUE(func, NS_ERROR_FAILURE);
+
+    AppendUTF8toUTF16(nsDependentCString(JS_GetScriptFilename(script)),
+                      filename);
+    lineNumber = JS_GetScriptBaseLineNumber(cx, script) + 1;
+  }
+
+  RootedObject res(cx, JS_NewPlainObject(cx));
+  NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
+
+  RootedValue filenameVal(cx);
+  if (!xpc::NonVoidStringToJsval(cx, filename, &filenameVal) ||
+      !JS_DefineProperty(cx, res, "filename", filenameVal, JSPROP_ENUMERATE)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!JS_DefineProperty(cx, res, "lineNumber", lineNumber, JSPROP_ENUMERATE)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  retval.setObject(*res);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXPCComponents_Utils::CallFunctionWithAsyncStack(HandleValue function,
                                                   nsIStackFrame* stack,
                                                   const nsAString& asyncCause,
                                                   JSContext* cx,
                                                   MutableHandleValue retval) {
   nsresult rv;
 
   if (!stack || asyncCause.IsEmpty()) {
--- a/layout/base/AutoProfilerStyleMarker.h
+++ b/layout/base/AutoProfilerStyleMarker.h
@@ -13,23 +13,21 @@
 #include "GeckoProfiler.h"
 #include "ProfilerMarkerPayload.h"
 
 namespace mozilla {
 
 class MOZ_RAII AutoProfilerStyleMarker {
  public:
   explicit AutoProfilerStyleMarker(UniqueProfilerBacktrace aCause,
-                                   const Maybe<nsID>& aDocShellId,
-                                   const Maybe<uint32_t>& aDocShellHistoryId)
+                                   const Maybe<uint64_t>& aInnerWindowID)
       : mActive(profiler_can_accept_markers()),
         mStartTime(TimeStamp::Now()),
         mCause(std::move(aCause)),
-        mDocShellId(aDocShellId),
-        mDocShellHistoryId(aDocShellHistoryId) {
+        mInnerWindowID(aInnerWindowID) {
     if (!mActive) {
       return;
     }
     MOZ_ASSERT(!ServoTraversalStatistics::sActive,
                "Nested AutoProfilerStyleMarker");
     ServoTraversalStatistics::sSingleton = ServoTraversalStatistics();
     ServoTraversalStatistics::sActive = true;
   }
@@ -37,23 +35,21 @@ class MOZ_RAII AutoProfilerStyleMarker {
   ~AutoProfilerStyleMarker() {
     if (!mActive) {
       return;
     }
     ServoTraversalStatistics::sActive = false;
     PROFILER_ADD_MARKER_WITH_PAYLOAD(
         "Styles", LAYOUT, StyleMarkerPayload,
         (mStartTime, TimeStamp::Now(), std::move(mCause),
-         ServoTraversalStatistics::sSingleton, mDocShellId,
-         mDocShellHistoryId));
+         ServoTraversalStatistics::sSingleton, mInnerWindowID));
   }
 
  private:
   bool mActive;
   TimeStamp mStartTime;
   UniqueProfilerBacktrace mCause;
-  Maybe<nsID> mDocShellId;
-  Maybe<uint32_t> mDocShellHistoryId;
+  Maybe<uint64_t> mInnerWindowID;
 };
 
 }  // namespace mozilla
 
 #endif  // mozilla_AutoProfilerStyleMarker_h
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4104,20 +4104,22 @@ void PresShell::DoFlushPendingNotificati
         mPresContext->EffectCompositor()->PostRestyleForThrottledAnimations();
       }
     }
 
     // The FlushResampleRequests() above flushed style changes.
     if (MOZ_LIKELY(!mIsDestroying)) {
       nsAutoScriptBlocker scriptBlocker;
 #ifdef MOZ_GECKO_PROFILER
-      nsCOMPtr<nsIDocShell> docShell = mPresContext->GetDocShell();
-      DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
+      Maybe<uint64_t> innerWindowID;
+      if (auto* window = mDocument->GetInnerWindow()) {
+        innerWindowID = Some(window->WindowID());
+      }
       AutoProfilerStyleMarker tracingStyleFlush(std::move(mStyleCause),
-                                                docShellId, docShellHistoryId);
+                                                innerWindowID);
 #endif
       PerfStats::AutoMetricRecording<PerfStats::Metric::Styling> autoRecording;
 
       mPresContext->RestyleManager()->ProcessPendingRestyles();
     }
 
 #ifdef MOZ_XBL
     // Process whatever XBL constructors those restyles queued up.  This
@@ -4133,20 +4135,22 @@ void PresShell::DoFlushPendingNotificati
     // In particular, reflow depends on style being completely up to
     // date.  If it's not, then style reparenting, which can
     // happen during reflow, might suddenly pick up the new rules and
     // we'll end up with frames whose style doesn't match the frame
     // type.
     if (MOZ_LIKELY(!mIsDestroying)) {
       nsAutoScriptBlocker scriptBlocker;
 #ifdef MOZ_GECKO_PROFILER
-      nsCOMPtr<nsIDocShell> docShell = mPresContext->GetDocShell();
-      DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
+      Maybe<uint64_t> innerWindowID;
+      if (auto* window = mDocument->GetInnerWindow()) {
+        innerWindowID = Some(window->WindowID());
+      }
       AutoProfilerStyleMarker tracingStyleFlush(std::move(mStyleCause),
-                                                docShellId, docShellHistoryId);
+                                                innerWindowID);
 #endif
       PerfStats::AutoMetricRecording<PerfStats::Metric::Styling> autoRecording;
 
       mPresContext->RestyleManager()->ProcessPendingRestyles();
       // Clear mNeedStyleFlush here agagin to make this flag work properly for
       // optimization since the flag might have set in ProcessPendingRestyles().
       mNeedStyleFlush = false;
     }
@@ -9122,20 +9126,23 @@ bool PresShell::DoReflow(nsIFrame* targe
   bool isTimelineRecording = timelines && timelines->HasConsumer(docShell);
 
   if (isTimelineRecording) {
     timelines->AddMarkerForDocShell(docShell, "Reflow",
                                     MarkerTracingType::START);
   }
 
 #ifdef MOZ_GECKO_PROFILER
-  DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
+  Maybe<uint64_t> innerWindowID;
+  if (auto* window = mDocument->GetInnerWindow()) {
+    innerWindowID = Some(window->WindowID());
+  }
   AutoProfilerTracing tracingLayoutFlush(
       "Paint", "Reflow", JS::ProfilingCategoryPair::LAYOUT,
-      std::move(mReflowCause), docShellId, docShellHistoryId);
+      std::move(mReflowCause), innerWindowID);
   mReflowCause = nullptr;
 #endif
 
   FlushPendingScrollAnchorSelections();
 
   if (mReflowContinueTimer) {
     mReflowContinueTimer->Cancel();
     mReflowContinueTimer = nullptr;
--- a/layout/generic/StickyScrollContainer.cpp
+++ b/layout/generic/StickyScrollContainer.cpp
@@ -260,16 +260,21 @@ nsPoint StickyScrollContainer::ComputePo
   position.y = std::max(position.y, std::min(stick.y, contain.YMost()));
   position.y = std::min(position.y, std::max(stick.YMost(), contain.y));
   position.x = std::max(position.x, std::min(stick.x, contain.XMost()));
   position.x = std::min(position.x, std::max(stick.XMost(), contain.x));
 
   return position;
 }
 
+bool StickyScrollContainer::IsStuckInYDirection(nsIFrame* aFrame) const {
+  nsPoint position = ComputePosition(aFrame);
+  return position.y != aFrame->GetNormalPosition().y;
+}
+
 void StickyScrollContainer::GetScrollRanges(nsIFrame* aFrame,
                                             nsRectAbsolute* aOuter,
                                             nsRectAbsolute* aInner) const {
   // We need to use the first in flow; continuation frames should not move
   // relative to each other and should get identical scroll ranges.
   // Also, ComputeStickyLimits requires this.
   nsIFrame* firstCont =
       nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
--- a/layout/generic/StickyScrollContainer.h
+++ b/layout/generic/StickyScrollContainer.h
@@ -80,16 +80,24 @@ class StickyScrollContainer final : publ
   void UpdatePositions(nsPoint aScrollPosition, nsIFrame* aSubtreeRoot);
 
   // nsIScrollPositionListener
   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override;
   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) override;
 
   ~StickyScrollContainer();
 
+  const nsTArray<nsIFrame*>& GetFrames() const { return mFrames; }
+
+  /**
+   * Returns true if the frame is "stuck" in the y direction, ie it's acting
+   * like fixed position. aFrame should be in GetFrames().
+   */
+  bool IsStuckInYDirection(nsIFrame* aFrame) const;
+
  private:
   explicit StickyScrollContainer(nsIScrollableFrame* aScrollFrame);
 
   /**
    * Compute two rectangles that determine sticky positioning: |aStick|, based
    * on the scroll container, and |aContain|, based on the containing block.
    * Sticky positioning keeps the frame position (its upper-left corner) always
    * within |aContain| and secondarily within |aStick|.
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -4429,26 +4429,29 @@ nsSize ScrollFrameHelper::GetLineScrollA
       std::max(1, sMinLineScrollAmountInPixels) * appUnitsPerDevPixel;
   nscoord horizontalAmount = fm ? fm->AveCharWidth() : 0;
   nscoord verticalAmount = fm ? fm->MaxHeight() : 0;
   return nsSize(std::max(horizontalAmount, minScrollAmountInAppUnits),
                 std::max(verticalAmount, minScrollAmountInAppUnits));
 }
 
 /**
- * Compute the scrollport size excluding any fixed-pos headers and
- * footers. A header or footer is an box that spans that entire width
- * of the viewport and touches the top (or bottom, respectively) of the
- * viewport. We also want to consider fixed elements that stack or overlap
- * to effectively create a larger header or footer. Headers and footers that
- * cover more than a third of the the viewport are ignored since they
+ * Compute the scrollport size excluding any fixed-pos and sticky-pos (that are
+ * stuck) headers and footers. A header or footer is an box that spans that
+ * entire width of the viewport and touches the top (or bottom, respectively) of
+ * the viewport. We also want to consider fixed/sticky elements that stack or
+ * overlap to effectively create a larger header or footer. Headers and footers
+ * that cover more than a third of the the viewport are ignored since they
  * probably aren't true headers and footers and we don't want to restrict
  * scrolling too much in such cases. This is a bit conservative --- some
  * pages use elements as headers or footers that don't span the entire width
  * of the viewport --- but it should be a good start.
+ *
+ * If aViewportFrame is non-null then the scroll frame is the root scroll
+ * frame and we should consider fixed-pos items.
  */
 struct TopAndBottom {
   TopAndBottom(nscoord aTop, nscoord aBottom) : top(aTop), bottom(aBottom) {}
 
   nscoord top, bottom;
 };
 struct TopComparator {
   bool Equals(const TopAndBottom& A, const TopAndBottom& B) const {
@@ -4461,30 +4464,56 @@ struct TopComparator {
 struct ReverseBottomComparator {
   bool Equals(const TopAndBottom& A, const TopAndBottom& B) const {
     return A.bottom == B.bottom;
   }
   bool LessThan(const TopAndBottom& A, const TopAndBottom& B) const {
     return A.bottom > B.bottom;
   }
 };
+
+static void AddToListIfHeaderFooter(nsIFrame* aFrame,
+                                    nsIFrame* aScrollPortFrame,
+                                    const nsRect& aScrollPort,
+                                    nsTArray<TopAndBottom>& aList) {
+  nsRect r = aFrame->GetRectRelativeToSelf();
+  r = nsLayoutUtils::TransformFrameRectToAncestor(aFrame, r, aScrollPortFrame);
+  r = r.Intersect(aScrollPort);
+  if ((r.width >= aScrollPort.width / 2 ||
+       r.width >= NSIntPixelsToAppUnits(800, AppUnitsPerCSSPixel())) &&
+      r.height <= aScrollPort.height / 3) {
+    aList.AppendElement(TopAndBottom(r.y, r.YMost()));
+  }
+}
+
 static nsSize GetScrollPortSizeExcludingHeadersAndFooters(
-    nsIFrame* aViewportFrame, const nsRect& aScrollPort) {
-  AutoTArray<TopAndBottom, 50> list;
-  nsFrameList fixedFrames = aViewportFrame->GetChildList(nsIFrame::kFixedList);
-  for (nsFrameList::Enumerator iterator(fixedFrames); !iterator.AtEnd();
-       iterator.Next()) {
-    nsIFrame* f = iterator.get();
-    nsRect r = f->GetRectRelativeToSelf();
-    r = nsLayoutUtils::TransformFrameRectToAncestor(f, r, aViewportFrame);
-    r = r.Intersect(aScrollPort);
-    if ((r.width >= aScrollPort.width / 2 ||
-         r.width >= NSIntPixelsToAppUnits(800, AppUnitsPerCSSPixel())) &&
-        r.height <= aScrollPort.height / 3) {
-      list.AppendElement(TopAndBottom(r.y, r.YMost()));
+    nsIFrame* aScrollFrame, nsIFrame* aViewportFrame,
+    const nsRect& aScrollPort) {
+  AutoTArray<TopAndBottom, 10> list;
+  if (aViewportFrame) {
+    nsFrameList fixedFrames =
+        aViewportFrame->GetChildList(nsIFrame::kFixedList);
+    for (nsFrameList::Enumerator iterator(fixedFrames); !iterator.AtEnd();
+         iterator.Next()) {
+      AddToListIfHeaderFooter(iterator.get(), aViewportFrame, aScrollPort,
+                              list);
+    }
+  }
+
+  // Add sticky frames that are currently in "fixed" positions
+  StickyScrollContainer* ssc =
+      StickyScrollContainer::GetStickyScrollContainerForScrollFrame(
+          aScrollFrame);
+  if (ssc) {
+    const nsTArray<nsIFrame*>& stickyFrames = ssc->GetFrames();
+    for (nsIFrame* f : stickyFrames) {
+      // If it's acting like fixed position.
+      if (ssc->IsStuckInYDirection(f)) {
+        AddToListIfHeaderFooter(f, aScrollFrame, aScrollPort, list);
+      }
     }
   }
 
   list.Sort(TopComparator());
   nscoord headerBottom = 0;
   for (uint32_t i = 0; i < list.Length(); ++i) {
     if (list[i].top <= headerBottom) {
       headerBottom = std::max(headerBottom, list[i].bottom);
@@ -4502,26 +4531,23 @@ static nsSize GetScrollPortSizeExcluding
   headerBottom = std::min(aScrollPort.height / 3, headerBottom);
   footerTop = std::max(aScrollPort.height - aScrollPort.height / 3, footerTop);
 
   return nsSize(aScrollPort.width, footerTop - headerBottom);
 }
 
 nsSize ScrollFrameHelper::GetPageScrollAmount() const {
   nsSize lineScrollAmount = GetLineScrollAmount();
-  nsSize effectiveScrollPortSize;
-  if (mIsRoot) {
-    // Reduce effective scrollport height by the height of any fixed-pos
-    // headers or footers
-    nsIFrame* root = mOuter->PresShell()->GetRootFrame();
-    effectiveScrollPortSize =
-        GetScrollPortSizeExcludingHeadersAndFooters(root, mScrollPort);
-  } else {
-    effectiveScrollPortSize = mScrollPort.Size();
-  }
+
+  // Reduce effective scrollport height by the height of any
+  // fixed-pos/sticky-pos headers or footers
+  nsSize effectiveScrollPortSize = GetScrollPortSizeExcludingHeadersAndFooters(
+      mOuter, mIsRoot ? mOuter->PresShell()->GetRootFrame() : nullptr,
+      mScrollPort);
+
   // The page increment is the size of the page, minus the smaller of
   // 10% of the size or 2 lines.
   return nsSize(effectiveScrollPortSize.width -
                     std::min(effectiveScrollPortSize.width / 10,
                              2 * lineScrollAmount.width),
                 effectiveScrollPortSize.height -
                     std::min(effectiveScrollPortSize.height / 10,
                              2 * lineScrollAmount.height));
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1577566-1-ref.html
@@ -0,0 +1,20 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Bug 1577566, reference: The alpha channel should be clamped at the right time so that it doesn't bright colors.</title>
+
+<style>
+
+#box {
+  width: 100px;
+  height: 100px;
+  background-color: rgb(0, 204, 0); /* 0, 0.8, 0 */
+}
+
+</style>
+
+<div id="box"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1577566-1.html
@@ -0,0 +1,33 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Bug 1577566: The alpha channel should be clamped at the right time so that it doesn't bright colors.</title>
+
+<style>
+
+#box {
+  width: 100px;
+  height: 100px;
+  background-color: black;
+  filter: url(#filter);
+}
+
+</style>
+
+<div id="box"></div>
+
+<svg height="0">
+  <defs>
+    <filter id="filter" color-interpolation-filters="sRGB">
+      <feColorMatrix type="matrix"
+                     values="0 0 0 0 0
+                             0 0 0 0 0.8
+                             0 0 0 0 0
+                             0 0 0 2 0"/>
+    </filter>
+  </defs>
+</svg>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -2106,9 +2106,10 @@ skip-if(!asyncPan) == 1544895.html 15448
 pref(image.downscale-during-decode.enabled,true) == 1553571-1.html 1553571-1-ref.html
 == 1558937-1.html 1558937-1-ref.html
 != 1563484.html 1563484-notref.html
 == 1563484.html 1563484-ref.html
 fuzzy-if(!webrender||!winWidget,251-255,464-1613) fuzzy-if(geckoview&&webrender,251-253,1392-1401) == 1562733-rotated-nastaliq-1.html 1562733-rotated-nastaliq-1-ref.html
 fuzzy-if(winWidget&&webrender,0-31,0-3) fuzzy-if(geckoview&&webrender,0-93,0-87) == 1562733-rotated-nastaliq-2.html 1562733-rotated-nastaliq-2-ref.html
 test-pref(plain_text.wrap_long_lines,false) != 1565129.txt 1565129.txt
 fuzzy(0-32,0-8) fuzzy-if(Android&&webrender,0-32,0-1458) == 1576553-1.html 1576553-1-ref.html
+fuzzy(0-1,0-10000) == 1577566-1.html 1577566-1-ref.html
 == 1579953-2.html 1579953-2-ref.html
--- a/layout/reftests/forms/textbox/reftest.list
+++ b/layout/reftests/forms/textbox/reftest.list
@@ -1,11 +1,11 @@
 # access-key tests are no use on OS X because access keys are not indicated visually
 # no real XUL theme on Android so we just skip
 skip-if(cocoaWidget||Android) != chrome://reftest/content/forms/textbox/accesskey-1.xul chrome://reftest/content/forms/textbox/accesskey-1-notref.xul
 fuzzy-if(winWidget,0-1,0-3) skip-if(cocoaWidget||Android) fails-if(webrender) == chrome://reftest/content/forms/textbox/accesskey-2.xul chrome://reftest/content/forms/textbox/accesskey-2-ref.xul
 # accesskey-3 fails because of defects in XUL bidi support
 fails-if(!cocoaWidget) skip-if(cocoaWidget||Android) == chrome://reftest/content/forms/textbox/accesskey-3.xul chrome://reftest/content/forms/textbox/accesskey-3-ref.xul
 skip-if(cocoaWidget||Android) != chrome://reftest/content/forms/textbox/accesskey-3.xul chrome://reftest/content/forms/textbox/accesskey-3-notref.xul
-fuzzy-if(winWidget,0-1,0-3) skip-if(cocoaWidget||Android) fails-if(webrender) == chrome://reftest/content/forms/textbox/accesskey-4.xul chrome://reftest/content/forms/textbox/accesskey-4-ref.xul
+fuzzy-if(winWidget,0-1,0-3) skip-if(cocoaWidget||Android) fails-if(webrender&&!Android) == chrome://reftest/content/forms/textbox/accesskey-4.xul chrome://reftest/content/forms/textbox/accesskey-4-ref.xul
 skip-if(cocoaWidget||Android) != chrome://reftest/content/forms/textbox/accesskey-4.xul chrome://reftest/content/forms/textbox/accesskey-4-notref.xul
 skip-if(Android) == chrome://reftest/content/forms/textbox/align-baseline-1.xul chrome://reftest/content/forms/textbox/align-baseline-1-ref.xul # test for bug 494901
 skip-if(Android) == chrome://reftest/content/forms/textbox/setsize.xul chrome://reftest/content/forms/textbox/setsize-ref.xul
--- a/memory/mozalloc/mozalloc_abort.cpp
+++ b/memory/mozalloc/mozalloc_abort.cpp
@@ -50,29 +50,32 @@ void fillAbortMessage(char (&msg)[N], ui
       reinterpret_cast<void*>(retAddress - uintptr_t(info.dli_fbase));
   const char* const sym = info.dli_sname ? info.dli_sname : "";
 
   SprintfLiteral(msg, "abort() called from %s:%p (%s)",
                  base_module ? base_module + 1 : module, module_offset, sym);
 }
 #endif
 
-#if defined(XP_UNIX) && !defined(MOZ_ASAN)
+#if defined(XP_UNIX) && !defined(MOZ_ASAN) && !defined(MOZ_TSAN)
 // Define abort() here, so that it is used instead of the system abort(). This
 // lets us control the behavior when aborting, in order to get better results
 // on *NIX platforms. See mozalloc_abort for details.
 //
 // For AddressSanitizer, we must not redefine system abort because the ASan
 // option "abort_on_error=1" calls abort() and therefore causes the following
 // call chain with our redefined abort:
 //
 // ASan -> abort() -> moz_abort() -> MOZ_CRASH() -> Segmentation fault
 //
 // That segmentation fault will be interpreted as another bug by ASan and as a
 // result, ASan will just exit(1) instead of aborting.
+//
+// The same applies to ThreadSanitizer when run with "halt_on_error=1" in
+// combination with "abort_on_error=1".
 extern "C" void abort(void) {
 #  ifdef MOZ_WIDGET_ANDROID
   char msg[64] = {};
   fillAbortMessage(msg, uintptr_t(__builtin_return_address(0)));
 #  else
   const char* const msg = "Redirecting call to abort() to mozalloc_abort\n";
 #  endif
 
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -6137,33 +6137,30 @@
 -     name: media.navigator.hardware.vp8_decode.acceleration_enabled
       type: bool
       value: false
       mirror: never
   #endif  # ANDROID
 
   # Use MediaDataDecoder API for VP8/VP9 in WebRTC. This includes hardware
   # acceleration for decoding.
-  # disable on android bug 1509316
 -   name: media.navigator.mediadatadecoder_vpx_enabled
     type: RelaxedAtomicBool
-  #if defined(NIGHTLY_BUILD) && !defined(ANDROID)
+  #if defined(NIGHTLY_BUILD)
     value: true
   #else
     value: false
   #endif
     mirror: always
 
   # Use MediaDataDecoder API for H264 in WebRTC. This includes hardware
-  # acceleration for decoding. False on Android due to bug 1509316.
+  # acceleration for decoding.
 -   name: media.navigator.mediadatadecoder_h264_enabled
     type: RelaxedAtomicBool
-  #if defined(ANDROID)
-    value: false
-  #elif defined(_ARM64_) && defined(XP_WIN)
+  #if defined(_ARM64_) && defined(XP_WIN)
     value: false
   #else
     value: true
   #endif
     mirror: always
 
 #endif  # MOZ_WEBRTC
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1261,16 +1261,23 @@ pref("network.http.version", "1.1");    
 // pref("network.http.version", "0.9");   // it'll work too if you're crazy
 // keep-alive option is effectively obsolete. Nevertheless it'll work with
 // some older 1.0 servers:
 
 pref("network.http.proxy.version", "1.1");    // default
 // pref("network.http.proxy.version", "1.0"); // uncomment this out in case of problems
                                               // (required if using junkbuster proxy)
 
+// Whether we should respect the BE_CONSERVATIVE (aka nsIHttpChannelInternal.beConservative)
+// flag when connecting to a proxy.  If the configured proxy accepts only TLS 1.3, system
+// requests like updates will not pass through.  Setting this pref to false will fix that
+// problem.
+// Default at true to preserve the behavior we had before for backward compat.
+pref("network.http.proxy.respect-be-conservative", true);
+
 // this preference can be set to override the socket type used for normal
 // HTTP traffic.  an empty value indicates the normal TCP/IP socket type.
 pref("network.http.default-socket-type", "");
 
 // There is a problem with some IIS7 servers that don't close the connection
 // properly after it times out (bug #491541). Default timeout on IIS7 is
 // 120 seconds. We need to reuse or drop the connection within this time.
 // We set the timeout a little shorter to keep a reserve for cases when
--- a/mozglue/baseprofiler/core/PageInformation.cpp
+++ b/mozglue/baseprofiler/core/PageInformation.cpp
@@ -10,37 +10,42 @@
 
 #  include "PageInformation.h"
 
 #  include "BaseProfileJSONWriter.h"
 
 namespace mozilla {
 namespace baseprofiler {
 
-PageInformation::PageInformation(const std::string& aDocShellId,
-                                 uint32_t aDocShellHistoryId,
-                                 const std::string& aUrl, bool aIsSubFrame)
-    : mDocShellId(aDocShellId),
-      mDocShellHistoryId(aDocShellHistoryId),
+PageInformation::PageInformation(uint64_t aBrowsingContextID,
+                                 uint64_t aInnerWindowID,
+                                 const std::string& aUrl,
+                                 uint64_t aEmbedderInnerWindowID)
+    : mBrowsingContextID(aBrowsingContextID),
+      mInnerWindowID(aInnerWindowID),
       mUrl(aUrl),
-      mIsSubFrame(aIsSubFrame),
+      mEmbedderInnerWindowID(aEmbedderInnerWindowID),
       mRefCnt(0) {}
 
-bool PageInformation::Equals(PageInformation* aOtherPageInfo) {
-  return DocShellHistoryId() == aOtherPageInfo->DocShellHistoryId() &&
-         DocShellId() == aOtherPageInfo->DocShellId() &&
-         IsSubFrame() == aOtherPageInfo->IsSubFrame();
+bool PageInformation::Equals(PageInformation* aOtherPageInfo) const {
+  // It's enough to check inner window IDs because they are unique for each
+  // page. Therefore, we don't have to check browsing context ID or url.
+  return InnerWindowID() == aOtherPageInfo->InnerWindowID();
 }
 
-void PageInformation::StreamJSON(SpliceableJSONWriter& aWriter) {
+void PageInformation::StreamJSON(SpliceableJSONWriter& aWriter) const {
   aWriter.StartObjectElement();
-  aWriter.StringProperty("docshellId", DocShellId().c_str());
-  aWriter.DoubleProperty("historyId", DocShellHistoryId());
+  // Here, we are converting uint64_t to double. Both Browsing Context and Inner
+  // Window IDs are creating using `nsContentUtils::GenerateProcessSpecificId`,
+  // which is specifically designed to only use 53 of the 64 bits to be lossless
+  // when passed into and out of JS as a double.
+  aWriter.DoubleProperty("browsingContextID", BrowsingContextID());
+  aWriter.DoubleProperty("innerWindowID", InnerWindowID());
   aWriter.StringProperty("url", Url().c_str());
-  aWriter.BoolProperty("isSubFrame", IsSubFrame());
+  aWriter.DoubleProperty("embedderInnerWindowID", EmbedderInnerWindowID());
   aWriter.EndObject();
 }
 
 size_t PageInformation::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
   return aMallocSizeOf(this);
 }
 
 }  // namespace baseprofiler
--- a/mozglue/baseprofiler/core/PageInformation.h
+++ b/mozglue/baseprofiler/core/PageInformation.h
@@ -22,54 +22,54 @@ class SpliceableJSONWriter;
 // while the page information is important and registered with the profiler,
 // but regardless of whether the profiler is running. All accesses to it are
 // protected by the profiler state lock.
 // When the page gets unregistered, we keep the profiler buffer position
 // to determine if we are still using this page. If not, we unregister
 // it in the next page registration.
 class PageInformation final {
  public:
-  PageInformation(const std::string& aDocShellId, uint32_t aDocShellHistoryId,
-                  const std::string& aUrl, bool aIsSubFrame);
+  PageInformation(uint64_t aBrowsingContextID, uint64_t aInnerWindowID,
+                  const std::string& aUrl, uint64_t aEmbedderInnerWindowID);
 
   // Using hand-rolled ref-counting, because RefCounted.h macros don't produce
   // the same code between mozglue and libxul, see bug 1536656.
   MFBT_API void AddRef() const { ++mRefCnt; }
   MFBT_API void Release() const {
     MOZ_ASSERT(int32_t(mRefCnt) > 0);
     if (--mRefCnt) {
       delete this;
     }
   }
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
-  bool Equals(PageInformation* aOtherDocShellInfo);
-  void StreamJSON(SpliceableJSONWriter& aWriter);
+  bool Equals(PageInformation* aOtherPageInfo) const;
+  void StreamJSON(SpliceableJSONWriter& aWriter) const;
 
-  uint32_t DocShellHistoryId() { return mDocShellHistoryId; }
-  const std::string& DocShellId() { return mDocShellId; }
-  const std::string& Url() { return mUrl; }
-  bool IsSubFrame() { return mIsSubFrame; }
+  uint64_t InnerWindowID() const { return mInnerWindowID; }
+  uint64_t BrowsingContextID() const { return mBrowsingContextID; }
+  const std::string& Url() const { return mUrl; }
+  uint64_t EmbedderInnerWindowID() const { return mEmbedderInnerWindowID; }
 
-  Maybe<uint64_t> BufferPositionWhenUnregistered() {
+  Maybe<uint64_t> BufferPositionWhenUnregistered() const {
     return mBufferPositionWhenUnregistered;
   }
 
   void NotifyUnregistered(uint64_t aBufferPosition) {
     mBufferPositionWhenUnregistered = Some(aBufferPosition);
   }
 
  private:
-  const std::string mDocShellId;
-  const uint32_t mDocShellHistoryId;
+  const uint64_t mBrowsingContextID;
+  const uint64_t mInnerWindowID;
   const std::string mUrl;
-  const bool mIsSubFrame;
+  const uint64_t mEmbedderInnerWindowID;
 
-  // Holds the buffer position when DocShell is unregistered.
-  // It's used to determine if we still use this DocShell in the profiler or
+  // Holds the buffer position when page is unregistered.
+  // It's used to determine if we still use this page in the profiler or
   // not.
   Maybe<uint64_t> mBufferPositionWhenUnregistered;
 
   mutable Atomic<int32_t, MemoryOrdering::ReleaseAcquire,
                  recordreplay::Behavior::DontPreserve>
       mRefCnt;
 };
 
--- a/mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
+++ b/mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
@@ -107,72 +107,69 @@ void ProfilerMarkerPayload::StreamType(c
   aWriter.StringProperty("type", aMarkerType);
 }
 
 BlocksRingBuffer::Length
 ProfilerMarkerPayload::CommonPropsTagAndSerializationBytes() const {
   return sizeof(DeserializerTag) +
          BlocksRingBuffer::SumBytes(mCommonProps.mStartTime,
                                     mCommonProps.mEndTime, mCommonProps.mStack,
-                                    mCommonProps.mDocShellId,
-                                    mCommonProps.mDocShellHistoryId);
+                                    mCommonProps.mInnerWindowID);
 }
 
 void ProfilerMarkerPayload::SerializeTagAndCommonProps(
     DeserializerTag aDeserializerTag,
     BlocksRingBuffer::EntryWriter& aEntryWriter) const {
   aEntryWriter.WriteObject(aDeserializerTag);
   aEntryWriter.WriteObject(mCommonProps.mStartTime);
   aEntryWriter.WriteObject(mCommonProps.mEndTime);
   aEntryWriter.WriteObject(mCommonProps.mStack);
-  aEntryWriter.WriteObject(mCommonProps.mDocShellId);
-  aEntryWriter.WriteObject(mCommonProps.mDocShellHistoryId);
+  aEntryWriter.WriteObject(mCommonProps.mInnerWindowID);
 }
 
 // static
 ProfilerMarkerPayload::CommonProps
 ProfilerMarkerPayload::DeserializeCommonProps(
     BlocksRingBuffer::EntryReader& aEntryReader) {
   CommonProps props;
   aEntryReader.ReadIntoObject(props.mStartTime);
   aEntryReader.ReadIntoObject(props.mEndTime);
   aEntryReader.ReadIntoObject(props.mStack);
-  aEntryReader.ReadIntoObject(props.mDocShellId);
-  aEntryReader.ReadIntoObject(props.mDocShellHistoryId);
+  aEntryReader.ReadIntoObject(props.mInnerWindowID);
   return props;
 }
 
 void ProfilerMarkerPayload::StreamCommonProps(
     const char* aMarkerType, SpliceableJSONWriter& aWriter,
     const TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks) const {
   StreamType(aMarkerType, aWriter);
   WriteTime(aWriter, aProcessStartTime, mCommonProps.mStartTime, "startTime");
   WriteTime(aWriter, aProcessStartTime, mCommonProps.mEndTime, "endTime");
-  if (mCommonProps.mDocShellId) {
-    aWriter.StringProperty("docShellId", mCommonProps.mDocShellId->c_str());
-  }
-  if (mCommonProps.mDocShellHistoryId) {
-    aWriter.DoubleProperty("docshellHistoryId",
-                           mCommonProps.mDocShellHistoryId.ref());
+  if (mCommonProps.mInnerWindowID) {
+    // Here, we are converting uint64_t to double. Both Browsing Context and
+    // Inner Window IDs are creating using
+    // `nsContentUtils::GenerateProcessSpecificId`, which is specifically
+    // designed to only use 53 of the 64 bits to be lossless when passed into
+    // and out of JS as a double.
+    aWriter.DoubleProperty("innerWindowID", mCommonProps.mInnerWindowID.ref());
   }
   if (mCommonProps.mStack) {
     aWriter.StartObjectProperty("stack");
     {
       mCommonProps.mStack->StreamJSON(aWriter, aProcessStartTime,
                                       aUniqueStacks);
     }
     aWriter.EndObject();
   }
 }
 
 TracingMarkerPayload::TracingMarkerPayload(
     const char* aCategory, TracingKind aKind,
-    const Maybe<std::string>& aDocShellId,
-    const Maybe<uint32_t>& aDocShellHistoryId, UniqueProfilerBacktrace aCause)
-    : ProfilerMarkerPayload(aDocShellId, aDocShellHistoryId, std::move(aCause)),
+    const Maybe<uint64_t>& aInnerWindowID, UniqueProfilerBacktrace aCause)
+    : ProfilerMarkerPayload(aInnerWindowID, std::move(aCause)),
       mCategory(aCategory),
       mKind(aKind) {}
 
 TracingMarkerPayload::TracingMarkerPayload(CommonProps&& aCommonProps,
                                            const char* aCategory,
                                            TracingKind aKind)
     : ProfilerMarkerPayload(std::move(aCommonProps)),
       mCategory(aCategory),
@@ -223,18 +220,17 @@ void TracingMarkerPayload::StreamPayload
 }
 
 FileIOMarkerPayload::FileIOMarkerPayload(const char* aOperation,
                                          const char* aSource,
                                          const char* aFilename,
                                          const TimeStamp& aStartTime,
                                          const TimeStamp& aEndTime,
                                          UniqueProfilerBacktrace aStack)
-    : ProfilerMarkerPayload(aStartTime, aEndTime, Nothing(), Nothing(),
-                            std::move(aStack)),
+    : ProfilerMarkerPayload(aStartTime, aEndTime, Nothing(), std::move(aStack)),
       mSource(aSource),
       mOperation(aOperation ? strdup(aOperation) : nullptr),
       mFilename(aFilename ? strdup(aFilename) : nullptr) {
   MOZ_ASSERT(aSource);
 }
 
 FileIOMarkerPayload::FileIOMarkerPayload(CommonProps&& aCommonProps,
                                          const char* aSource,
@@ -282,30 +278,26 @@ void FileIOMarkerPayload::StreamPayload(
   aWriter.StringProperty("source", mSource);
   if (mFilename && *mFilename) {
     aWriter.StringProperty("filename", mFilename.get());
   }
 }
 
 UserTimingMarkerPayload::UserTimingMarkerPayload(
     const std::string& aName, const TimeStamp& aStartTime,
-    const Maybe<std::string>& aDocShellId,
-    const Maybe<uint32_t>& aDocShellHistoryId)
-    : ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
-                            aDocShellHistoryId),
+    const Maybe<uint64_t>& aInnerWindowID)
+    : ProfilerMarkerPayload(aStartTime, aStartTime, aInnerWindowID),
       mEntryType("mark"),
       mName(aName) {}
 
 UserTimingMarkerPayload::UserTimingMarkerPayload(
     const std::string& aName, const Maybe<std::string>& aStartMark,
     const Maybe<std::string>& aEndMark, const TimeStamp& aStartTime,
-    const TimeStamp& aEndTime, const Maybe<std::string>& aDocShellId,
-    const Maybe<uint32_t>& aDocShellHistoryId)
-    : ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
-                            aDocShellHistoryId),
+    const TimeStamp& aEndTime, const Maybe<uint64_t>& aInnerWindowID)
+    : ProfilerMarkerPayload(aStartTime, aEndTime, aInnerWindowID),
       mEntryType("measure"),
       mName(aName),
       mStartMark(aStartMark),
       mEndMark(aEndMark) {}
 
 UserTimingMarkerPayload::UserTimingMarkerPayload(
     CommonProps&& aCommonProps, const char* aEntryType, std::string&& aName,
     Maybe<std::string>&& aStartMark, Maybe<std::string>&& aEndMark)
@@ -373,30 +365,27 @@ TextMarkerPayload::TextMarkerPayload(con
 
 TextMarkerPayload::TextMarkerPayload(const std::string& aText,
                                      const TimeStamp& aStartTime,
                                      const TimeStamp& aEndTime)
     : ProfilerMarkerPayload(aStartTime, aEndTime), mText(aText) {}
 
 TextMarkerPayload::TextMarkerPayload(const std::string& aText,
                                      const TimeStamp& aStartTime,
-                                     const Maybe<std::string>& aDocShellId,
-                                     const Maybe<uint32_t>& aDocShellHistoryId)
-    : ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
-                            aDocShellHistoryId),
+                                     const Maybe<uint64_t>& aInnerWindowID)
+    : ProfilerMarkerPayload(aStartTime, aStartTime, aInnerWindowID),
       mText(aText) {}
 
 TextMarkerPayload::TextMarkerPayload(const std::string& aText,
                                      const TimeStamp& aStartTime,
                                      const TimeStamp& aEndTime,
-                                     const Maybe<std::string>& aDocShellId,
-                                     const Maybe<uint32_t>& aDocShellHistoryId,
+                                     const Maybe<uint64_t>& aInnerWindowID,
                                      UniqueProfilerBacktrace aCause)
-    : ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
-                            aDocShellHistoryId, std::move(aCause)),
+    : ProfilerMarkerPayload(aStartTime, aEndTime, aInnerWindowID,
+                            std::move(aCause)),
       mText(aText) {}
 
 TextMarkerPayload::TextMarkerPayload(CommonProps&& aCommonProps,
                                      std::string&& aText)
     : ProfilerMarkerPayload(std::move(aCommonProps)), mText(std::move(aText)) {}
 
 TextMarkerPayload::~TextMarkerPayload() = default;
 
--- a/mozglue/baseprofiler/core/platform.cpp
+++ b/mozglue/baseprofiler/core/platform.cpp
@@ -345,36 +345,46 @@ class CorePS {
       }
     }
   }
 
   PS_GET(Vector<RefPtr<PageInformation>>&, RegisteredPages)
 
   static void AppendRegisteredPage(PSLockRef,
                                    RefPtr<PageInformation>&& aRegisteredPage) {
-    // Disabling this assertion for now until we fix the same page registration
-    // issue. See Bug 1542918.
-#  if 0
     struct RegisteredPageComparator {
       PageInformation* aA;
       bool operator()(PageInformation* aB) const { return aA->Equals(aB); }
     };
-    MOZ_RELEASE_ASSERT(std::none_of(
+
+    auto foundPageIter = std::find_if(
         sInstance->mRegisteredPages.begin(), sInstance->mRegisteredPages.end(),
-        RegisteredPageComparator{aRegisteredPage.get()}));
-#  endif
+        RegisteredPageComparator{aRegisteredPage.get()});
+
+    if (foundPageIter != sInstance->mRegisteredPages.end()) {
+      if ((*foundPageIter)->Url() == "about:blank") {
+        // When a BrowsingContext is loaded, the first url loaded in it will be
+        // about:blank, and if the principal matches, the first document loaded
+        // in it will share an inner window. That's why we should delete the
+        // intermittent about:blank if they share the inner window.
+        sInstance->mRegisteredPages.erase(foundPageIter);
+      } else {
+        // Do not register the same page again.
+        return;
+      }
+    }
     MOZ_RELEASE_ASSERT(
         sInstance->mRegisteredPages.append(std::move(aRegisteredPage)));
   }
 
-  static void RemoveRegisteredPages(PSLockRef,
-                                    const std::string& aRegisteredDocShellId) {
-    // Remove RegisteredPage from mRegisteredPages by given DocShell Id.
+  static void RemoveRegisteredPage(PSLockRef,
+                                   uint64_t aRegisteredInnerWindowID) {
+    // Remove RegisteredPage from mRegisteredPages by given inner window ID.
     sInstance->mRegisteredPages.eraseIf([&](const RefPtr<PageInformation>& rd) {
-      return rd->DocShellId() == aRegisteredDocShellId;
+      return rd->InnerWindowID() == aRegisteredInnerWindowID;
     });
   }
 
   static void ClearRegisteredPages(PSLockRef) {
     sInstance->mRegisteredPages.clear();
   }
 
   PS_GET(const Vector<BaseProfilerCount*>&, Counters)
@@ -425,17 +435,17 @@ class CorePS {
   // the underlying buffer in memory.
   BlocksRingBuffer mCoreBlocksRingBuffer;
 
   // Info on all the registered threads.
   // ThreadIds in mRegisteredThreads are unique.
   Vector<UniquePtr<RegisteredThread>> mRegisteredThreads;
 
   // Info on all the registered pages.
-  // DocShellId and DocShellHistoryId pairs in mRegisteredPages are unique.
+  // InnerWindowIDs in mRegisteredPages are unique.
   Vector<RefPtr<PageInformation>> mRegisteredPages;
 
   // Non-owning pointers to all active counters
   Vector<BaseProfilerCount*> mCounters;
 
 #  ifdef USE_LUL_STACKWALK
   // LUL's state. Null prior to the first activation, non-null thereafter.
   UniquePtr<lul::LUL> mLul;
@@ -665,17 +675,17 @@ class ActivePS {
   static Vector<RefPtr<PageInformation>> ProfiledPages(PSLockRef aLock) {
     Vector<RefPtr<PageInformation>> array;
     for (auto& d : CorePS::RegisteredPages(aLock)) {
       MOZ_RELEASE_ASSERT(array.append(d));
     }
     for (auto& d : sInstance->mDeadProfiledPages) {
       MOZ_RELEASE_ASSERT(array.append(d));
     }
-    // We don't need to sort the DocShells like threads since we won't show them
+    // We don't need to sort the pages like threads since we won't show them
     // as a list.
     return array;
   }
 
   // Do a linear search through mLiveProfiledThreads to find the
   // ProfiledThreadData object for a RegisteredThread.
   static ProfiledThreadData* GetProfiledThreadData(
       PSLockRef, RegisteredThread* aRegisteredThread) {
@@ -736,22 +746,22 @@ class ActivePS {
           Maybe<uint64_t> bufferPosition =
               aProfiledThreadData->BufferPositionWhenUnregistered();
           MOZ_RELEASE_ASSERT(bufferPosition,
                              "should have unregistered this thread");
           return *bufferPosition < bufferRangeStart;
         });
   }
 
-  static void UnregisterPages(PSLockRef aLock,
-                              const std::string& aRegisteredDocShellId) {
+  static void UnregisterPage(PSLockRef aLock,
+                             uint64_t aRegisteredInnerWindowID) {
     auto& registeredPages = CorePS::RegisteredPages(aLock);
     for (size_t i = 0; i < registeredPages.length(); i++) {
       RefPtr<PageInformation>& page = registeredPages[i];
-      if (page->DocShellId() == aRegisteredDocShellId) {
+      if (page->InnerWindowID() == aRegisteredInnerWindowID) {
         page->NotifyUnregistered(sInstance->mProfileBuffer->BufferRangeEnd());
         MOZ_RELEASE_ASSERT(
             sInstance->mDeadProfiledPages.append(std::move(page)));
         registeredPages.erase(&registeredPages[i--]);
       }
     }
   }
 
@@ -1564,17 +1574,17 @@ static void StreamCategories(SpliceableJ
 
 static int64_t MicrosecondsSince1970();
 
 static void StreamMetaJSCustomObject(PSLockRef aLock,
                                      SpliceableJSONWriter& aWriter,
                                      bool aIsShuttingDown) {
   MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
 
-  aWriter.IntProperty("version", 16);
+  aWriter.IntProperty("version", 17);
 
   // The "startTime" field holds the number of milliseconds since midnight
   // January 1, 1970 GMT. This grotty code computes (Now - (Now -
   // ProcessStartTime)) to convert CorePS::ProcessStartTime() into that form.
   TimeDuration delta = TimeStamp::NowUnfuzzed() - CorePS::ProcessStartTime();
   aWriter.DoubleProperty(
       "startTime", MicrosecondsSince1970() / 1000.0 - delta.ToMilliseconds());
 
@@ -3054,58 +3064,57 @@ void profiler_unregister_thread() {
     // - We've already called profiler_unregister_thread() for this thread.
     //   (Whether or not it should, this does happen in practice.)
     //
     // Either way, TLSRegisteredThread should be empty.
     MOZ_RELEASE_ASSERT(!TLSRegisteredThread::RegisteredThread(lock));
   }
 }
 
-void profiler_register_page(const std::string& aDocShellId, uint32_t aHistoryId,
-                            const std::string& aUrl, bool aIsSubFrame) {
-  DEBUG_LOG("profiler_register_page(%s, %u, %s, %d)", aDocShellId.c_str(),
-            aHistoryId, aUrl.c_str(), aIsSubFrame);
+void profiler_register_page(uint64_t aBrowsingContextID,
+                            uint64_t aInnerWindowID, const std::string& aUrl,
+                            uint64_t aEmbedderInnerWindowID) {
+  DEBUG_LOG("profiler_register_page(%" PRIu64 ", %" PRIu64 ", %s, %" PRIu64 ")",
+            aBrowsingContextID, aInnerWindowID, aUrl.c_str(),
+            aEmbedderInnerWindowID);
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   PSAutoLock lock;
 
-  // If profiler is not active, delete all the previous page entries of the
-  // given DocShell since we won't need those.
-  if (!ActivePS::Exists(lock)) {
-    CorePS::RemoveRegisteredPages(lock, aDocShellId);
-  }
-
-  RefPtr<PageInformation> pageInfo =
-      new PageInformation(aDocShellId, aHistoryId, aUrl, aIsSubFrame);
+  // When a Browsing context is first loaded, the first url loaded in it will be
+  // about:blank. Because of that, this call keeps the first non-about:blank
+  // registration of window and discards the previous one.
+  RefPtr<PageInformation> pageInfo = new PageInformation(
+      aBrowsingContextID, aInnerWindowID, aUrl, aEmbedderInnerWindowID);
   CorePS::AppendRegisteredPage(lock, std::move(pageInfo));
 
   // After appending the given page to CorePS, look for the expired
   // pages and remove them if there are any.
   if (ActivePS::Exists(lock)) {
     ActivePS::DiscardExpiredPages(lock);
   }
 }
 
-void profiler_unregister_pages(const std::string& aRegisteredDocShellId) {
+void profiler_unregister_page(uint64_t aRegisteredInnerWindowID) {
   if (!CorePS::Exists()) {
     // This function can be called after the main thread has already shut down.
     return;
   }
 
   PSAutoLock lock;
 
   // During unregistration, if the profiler is active, we have to keep the
   // page information since there may be some markers associated with the given
   // page. But if profiler is not active. we have no reason to keep the
   // page information here because there can't be any marker associated with it.
   if (ActivePS::Exists(lock)) {
-    ActivePS::UnregisterPages(lock, aRegisteredDocShellId);
+    ActivePS::UnregisterPage(lock, aRegisteredInnerWindowID);
   } else {
-    CorePS::RemoveRegisteredPages(lock, aRegisteredDocShellId);
+    CorePS::RemoveRegisteredPage(lock, aRegisteredInnerWindowID);
   }
 }
 
 void profiler_clear_all_pages() {
   if (!CorePS::Exists()) {
     // This function can be called after the main thread has already shut down.
     return;
   }
@@ -3307,66 +3316,61 @@ void profiler_add_marker_for_thread(int 
   CorePS::CoreBlocksRingBuffer().PutObjects(
       ProfileBufferEntry::Kind::MarkerData, aThreadId,
       WrapBlocksRingBufferUnownedCString(aMarkerName),
       static_cast<uint32_t>(aCategoryPair), aPayload, delta.ToMilliseconds());
 }
 
 void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
                       ProfilingCategoryPair aCategoryPair, TracingKind aKind,
-                      const Maybe<std::string>& aDocShellId,
-                      const Maybe<uint32_t>& aDocShellHistoryId) {
-  MOZ_RELEASE_ASSERT(CorePS::Exists());
-
-  VTUNE_TRACING(aMarkerName, aKind);
-
-  // This function is hot enough that we use RacyFeatures, notActivePS.
-  if (!profiler_can_accept_markers()) {
-    return;
-  }
-
-  AUTO_PROFILER_STATS(base_add_marker_with_TracingMarkerPayload);
-  profiler_add_marker(aMarkerName, aCategoryPair,
-                      TracingMarkerPayload(aCategoryString, aKind, aDocShellId,
-                                           aDocShellHistoryId));
-}
-
-void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
-                      ProfilingCategoryPair aCategoryPair, TracingKind aKind,
-                      UniqueProfilerBacktrace aCause,
-                      const Maybe<std::string>& aDocShellId,
-                      const Maybe<uint32_t>& aDocShellHistoryId) {
+                      const Maybe<uint64_t>& aInnerWindowID) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   VTUNE_TRACING(aMarkerName, aKind);
 
   // This function is hot enough that we use RacyFeatures, notActivePS.
   if (!profiler_can_accept_markers()) {
     return;
   }
 
   AUTO_PROFILER_STATS(base_add_marker_with_TracingMarkerPayload);
   profiler_add_marker(
       aMarkerName, aCategoryPair,
-      TracingMarkerPayload(aCategoryString, aKind, aDocShellId,
-                           aDocShellHistoryId, std::move(aCause)));
+      TracingMarkerPayload(aCategoryString, aKind, aInnerWindowID));
+}
+
+void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
+                      ProfilingCategoryPair aCategoryPair, TracingKind aKind,
+                      UniqueProfilerBacktrace aCause,
+                      const Maybe<uint64_t>& aInnerWindowID) {
+  MOZ_RELEASE_ASSERT(CorePS::Exists());
+
+  VTUNE_TRACING(aMarkerName, aKind);
+
+  // This function is hot enough that we use RacyFeatures, notActivePS.
+  if (!profiler_can_accept_markers()) {
+    return;
+  }
+
+  AUTO_PROFILER_STATS(base_add_marker_with_TracingMarkerPayload);
+  profiler_add_marker(aMarkerName, aCategoryPair,
+                      TracingMarkerPayload(aCategoryString, aKind,
+                                           aInnerWindowID, std::move(aCause)));
 }
 
 void profiler_add_text_marker(const char* aMarkerName, const std::string& aText,
                               ProfilingCategoryPair aCategoryPair,
                               const TimeStamp& aStartTime,
                               const TimeStamp& aEndTime,
-                              const Maybe<std::string>& aDocShellId,
-                              const Maybe<uint32_t>& aDocShellHistoryId,
+                              const Maybe<uint64_t>& aInnerWindowID,
                               UniqueProfilerBacktrace aCause) {
   AUTO_PROFILER_STATS(base_add_marker_with_TextMarkerPayload);
-  profiler_add_marker(
-      aMarkerName, aCategoryPair,
-      TextMarkerPayload(aText, aStartTime, aEndTime, aDocShellId,
-                        aDocShellHistoryId, std::move(aCause)));
+  profiler_add_marker(aMarkerName, aCategoryPair,
+                      TextMarkerPayload(aText, aStartTime, aEndTime,
+                                        aInnerWindowID, std::move(aCause)));
 }
 
 // NOTE: aCollector's methods will be called while the target thread is paused.
 // Doing things in those methods like allocating -- which may try to claim
 // locks -- is a surefire way to deadlock.
 void profiler_suspend_and_sample_thread(int aThreadId, uint32_t aFeatures,
                                         ProfilerStackCollector& aCollector,
                                         bool aSampleNative /* = true */) {
--- a/mozglue/baseprofiler/public/BaseProfiler.h
+++ b/mozglue/baseprofiler/public/BaseProfiler.h
@@ -63,29 +63,20 @@
 #  define AUTO_BASE_PROFILER_LABEL_FAST(label, categoryPair, ctx)
 #  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, \
                                                 categoryPair, ctx, flags)
 
 #  define BASE_PROFILER_ADD_MARKER(markerName, categoryPair)
 #  define BASE_PROFILER_ADD_MARKER_WITH_PAYLOAD( \
       markerName, categoryPair, PayloadType, parenthesizedPayloadArgs)
 
-#  define MOZDECLARE_DOCSHELL_AND_HISTORY_ID(docShell)
 #  define BASE_PROFILER_TRACING(categoryString, markerName, categoryPair, kind)
-#  define BASE_PROFILER_TRACING_DOCSHELL(categoryString, markerName, \
-                                         categoryPair, kind, docshell)
 #  define AUTO_BASE_PROFILER_TRACING(categoryString, markerName, categoryPair)
-#  define AUTO_BASE_PROFILER_TRACING_DOCSHELL(categoryString, markerName, \
-                                              categoryPair, docShell)
 #  define AUTO_BASE_PROFILER_TEXT_MARKER_CAUSE(markerName, text, categoryPair, \
                                                cause)
-#  define AUTO_BASE_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text, \
-                                                  categoryPair, docShell)
-#  define AUTO_BASE_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE( \
-      markerName, text, categoryPair, docShell, cause)
 
 #  define AUTO_PROFILER_STATS(name)
 
 #else  // !MOZ_BASE_PROFILER
 
 #  include "BaseProfilingStack.h"
 
 #  include "mozilla/Assertions.h"
@@ -325,42 +316,44 @@ MFBT_API void profiler_ensure_started(
       ::mozilla::baseprofiler::profiler_register_thread(name, &stackTop); \
     } while (0)
 #  define BASE_PROFILER_UNREGISTER_THREAD() \
     ::mozilla::baseprofiler::profiler_unregister_thread()
 MFBT_API ProfilingStack* profiler_register_thread(const char* name,
                                                   void* guessStackTop);
 MFBT_API void profiler_unregister_thread();
 
-// Register pages with the profiler.
+// Registers a DOM Window (the JS global `window`) with the profiler. Each
+// Window _roughly_ corresponds to a single document loaded within a
+// BrowsingContext. The unique IDs for both the Window and BrowsingContext are
+// recorded to allow correlating different Windows loaded within the same tab or
+// frame element.
+//
+// We register pages for each navigations but we do not register
+// history.pushState or history.replaceState since they correspond to the same
+// Inner Window ID. When a Browsing context is first loaded, the first url
+// loaded in it will be about:blank. Because of that, this call keeps the first
+// non-about:blank registration of window and discards the previous one.
 //
-// The `page` means every new history entry for docShells.
-// DocShellId + HistoryID is a unique pair to identify these pages.
-// We also keep these pairs inside markers to associate with the pages.
-// That allows us to see which markers belong to a specific page and filter the
-// markers by a page.
-// We register pages in these cases:
-// - If there is a navigation through a link or URL bar.
-// - If there is a navigation through `location.replace` or `history.pushState`.
-// We do not register pages in these cases:
-// - If there is a history navigation through the back and forward buttons.
-// - If there is a navigation through `history.replaceState` or anchor scrolls.
+//   "aBrowsingContextID"     is the ID of the browsing context that document
+//                            belongs to. That's used to determine the tab of
+//                            that page.
+//   "aInnerWindowID"         is the ID of the `window` global object of that
+//                            document.
+//   "aUrl"                   is the URL of the page.
+//   "aEmbedderInnerWindowID" is the inner window id of embedder. It's used to
+//                            determine sub documents of a page.
+MFBT_API void profiler_register_page(uint64_t aBrowsingContextID,
+                                     uint64_t aInnerWindowID,
+                                     const std::string& aUrl,
+                                     uint64_t aEmbedderInnerWindowID);
+// Unregister page with the profiler.
 //
-//   "aDocShellId" is the ID of the docShell that page belongs to.
-//   "aHistoryId"  is the ID of the history entry on the given docShell.
-//   "aUrl"        is the URL of the page.
-//   "aIsSubFrame" is true if the page is a sub frame.
-MFBT_API void profiler_register_page(const std::string& aDocShellId,
-                                     uint32_t aHistoryId,
-                                     const std::string& aUrl, bool aIsSubFrame);
-// Unregister pages with the profiler.
-//
-// Take a docShellId and unregister all the page entries that have the given ID.
-MFBT_API void profiler_unregister_pages(
-    const std::string& aRegisteredDocShellId);
+// Take a Inner Window ID and unregister the page entry that has the same ID.
+MFBT_API void profiler_unregister_page(uint64_t aRegisteredInnerWindowID);
 
 // Remove all registered and unregistered pages in the profiler.
 void profiler_clear_all_pages();
 
 class BaseProfilerCount;
 MFBT_API void profiler_add_sampled_counter(BaseProfilerCount* aCounter);
 MFBT_API void profiler_remove_sampled_counter(BaseProfilerCount* aCounter);
 
@@ -751,147 +744,93 @@ MFBT_API void profiler_add_marker_for_th
     UniquePtr<ProfilerMarkerPayload> aPayload);
 
 enum TracingKind {
   TRACING_EVENT,
   TRACING_INTERVAL_START,
   TRACING_INTERVAL_END,
 };
 
-// Helper macro to retrieve DocShellId and DocShellHistoryId from docShell
-#  define MOZDECLARE_DOCSHELL_AND_HISTORY_ID(docShell)   \
-    Maybe<std::string> docShellId;                       \
-    Maybe<uint32_t> docShellHistoryId;                   \
-    if (docShell) {                                      \
-      docShellId = mozilla::Some(docShell->HistoryID()); \
-      uint32_t id;                                       \
-      nsresult rv = docShell->GetOSHEId(&id);            \
-      if (NS_SUCCEEDED(rv)) {                            \
-        docShellHistoryId = mozilla::Some(id);           \
-      } else {                                           \
-        docShellHistoryId = mozilla::Nothing();          \
-      }                                                  \
-    } else {                                             \
-      docShellId = mozilla::Nothing();                   \
-      docShellHistoryId = mozilla::Nothing();            \
-    }
-
 // Adds a tracing marker to the profile. A no-op if the profiler is inactive or
 // in privacy mode.
 
 #  define BASE_PROFILER_TRACING(categoryString, markerName, categoryPair, \
                                 kind)                                     \
     ::mozilla::baseprofiler::profiler_tracing(                            \
         categoryString, markerName,                                       \
         ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair, kind)
-#  define BASE_PROFILER_TRACING_DOCSHELL(categoryString, markerName,        \
-                                         categoryPair, kind, docShell)      \
-    MOZDECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                           \
-    ::mozilla::baseprofiler::profiler_tracing(                              \
-        categoryString, markerName,                                         \
-        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair, kind, \
-        docShellId, docShellHistoryId)
 
 MFBT_API void profiler_tracing(
     const char* aCategoryString, const char* aMarkerName,
     ProfilingCategoryPair aCategoryPair, TracingKind aKind,
-    const Maybe<std::string>& aDocShellId = Nothing(),
-    const Maybe<uint32_t>& aDocShellHistoryId = Nothing());
+    const Maybe<uint64_t>& aInnerWindowID = Nothing());
 MFBT_API void profiler_tracing(
     const char* aCategoryString, const char* aMarkerName,
     ProfilingCategoryPair aCategoryPair, TracingKind aKind,
     UniqueProfilerBacktrace aCause,
-    const Maybe<std::string>& aDocShellId = Nothing(),
-    const Maybe<uint32_t>& aDocShellHistoryId = Nothing());
+    const Maybe<uint64_t>& aInnerWindowID = Nothing());
 
 // Adds a START/END pair of tracing markers.
 #  define AUTO_BASE_PROFILER_TRACING(categoryString, markerName, categoryPair) \
     ::mozilla::baseprofiler::AutoProfilerTracing BASE_PROFILER_RAII(           \
         categoryString, markerName,                                            \
         ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair,          \
-        Nothing(), Nothing())
-#  define AUTO_BASE_PROFILER_TRACING_DOCSHELL(categoryString, markerName, \
-                                              categoryPair, docShell)     \
-    MOZDECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                         \
-    ::mozilla::baseprofiler::AutoProfilerTracing BASE_PROFILER_RAII(      \
-        categoryString, markerName,                                       \
-        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair,     \
-        docShellId, docShellHistoryId)
+        Nothing())
 
 // Add a text marker. Text markers are similar to tracing markers, with the
 // difference that text markers have their "text" separate from the marker name;
 // multiple text markers with the same name can have different text, and these
 // markers will still be displayed in the same "row" in the UI.
 // Another difference is that text markers combine the start and end markers
 // into one marker.
 MFBT_API void profiler_add_text_marker(
     const char* aMarkerName, const std::string& aText,
     ProfilingCategoryPair aCategoryPair, const TimeStamp& aStartTime,
     const TimeStamp& aEndTime,
-    const Maybe<std::string>& aDocShellId = Nothing(),
-    const Maybe<uint32_t>& aDocShellHistoryId = Nothing(),
+    const Maybe<uint64_t>& aInnerWindowID = Nothing(),
     UniqueProfilerBacktrace aCause = nullptr);
 
 class MOZ_RAII AutoProfilerTextMarker {
  public:
   AutoProfilerTextMarker(const char* aMarkerName, const std::string& aText,
                          ProfilingCategoryPair aCategoryPair,
-                         const Maybe<std::string>& aDocShellId,
-                         const Maybe<uint32_t>& aDocShellHistoryId,
+                         const Maybe<uint64_t>& aInnerWindowID,
                          UniqueProfilerBacktrace&& aCause =
                              nullptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mMarkerName(aMarkerName),
         mText(aText),
         mCategoryPair(aCategoryPair),
         mStartTime(TimeStamp::NowUnfuzzed()),
         mCause(std::move(aCause)),
-        mDocShellId(aDocShellId),
-        mDocShellHistoryId(aDocShellHistoryId) {
+        mInnerWindowID(aInnerWindowID) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   }
 
   ~AutoProfilerTextMarker() {
     profiler_add_text_marker(mMarkerName, mText, mCategoryPair, mStartTime,
-                             TimeStamp::NowUnfuzzed(), mDocShellId,
-                             mDocShellHistoryId, std::move(mCause));
+                             TimeStamp::NowUnfuzzed(), mInnerWindowID,
+                             std::move(mCause));
   }
 
  protected:
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   const char* mMarkerName;
   std::string mText;
   const ProfilingCategoryPair mCategoryPair;
   TimeStamp mStartTime;
   UniqueProfilerBacktrace mCause;
-  const Maybe<std::string> mDocShellId;
-  const Maybe<uint32_t> mDocShellHistoryId;
+  const Maybe<uint64_t> mInnerWindowID;
 };
 
 #  define AUTO_BASE_PROFILER_TEXT_MARKER_CAUSE(markerName, text, categoryPair, \
                                                cause)                          \
     ::mozilla::baseprofiler::AutoProfilerTextMarker BASE_PROFILER_RAII(        \
         markerName, text,                                                      \
         ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair,          \
-        mozilla::Nothing(), mozilla::Nothing(), cause)
-
-#  define AUTO_BASE_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text,       \
-                                                  categoryPair, docShell) \
-    MOZDECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                         \
-    ::mozilla::baseprofiler::AutoProfilerTextMarker BASE_PROFILER_RAII(   \
-        markerName, text,                                                 \
-        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair,     \
-        docShellId, docShellHistoryId)
-
-#  define AUTO_BASE_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE(                \
-      markerName, text, categoryPair, docShell, cause)                  \
-    MOZDECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                       \
-    ::mozilla::baseprofiler::AutoProfilerTextMarker BASE_PROFILER_RAII( \
-        markerName, text,                                               \
-        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair,   \
-        docShellId, docShellHistoryId, cause)
+        mozilla::Nothing(), cause)
 
 //---------------------------------------------------------------------------
 // Output profiles
 //---------------------------------------------------------------------------
 
 // Set a user-friendly process name, used in JSON stream.
 MFBT_API void profiler_set_process_name(const std::string& aProcessName);
 
@@ -1036,57 +975,52 @@ class MOZ_RAII AutoProfilerLabel {
   // See the comment on the definition in platform.cpp for details about this.
   static MOZ_THREAD_LOCAL(ProfilingStack*) sProfilingStack;
 };
 
 class MOZ_RAII AutoProfilerTracing {
  public:
   AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
                       ProfilingCategoryPair aCategoryPair,
-                      const Maybe<std::string>& aDocShellId,
-                      const Maybe<uint32_t>& aDocShellHistoryId
+                      const Maybe<uint64_t>& aInnerWindowID
                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mCategoryString(aCategoryString),
         mMarkerName(aMarkerName),
         mCategoryPair(aCategoryPair),
-        mDocShellId(aDocShellId),
-        mDocShellHistoryId(aDocShellHistoryId) {
+        mInnerWindowID(aInnerWindowID) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     profiler_tracing(mCategoryString, mMarkerName, aCategoryPair,
-                     TRACING_INTERVAL_START, mDocShellId, mDocShellHistoryId);
+                     TRACING_INTERVAL_START, mInnerWindowID);
   }
 
   AutoProfilerTracing(
       const char* aCategoryString, const char* aMarkerName,
       ProfilingCategoryPair aCategoryPair, UniqueProfilerBacktrace aBacktrace,
-      const Maybe<std::string>& aDocShellId,
-      const Maybe<uint32_t>& aDocShellHistoryId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+      const Maybe<uint64_t>& aInnerWindowID MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mCategoryString(aCategoryString),
         mMarkerName(aMarkerName),
         mCategoryPair(aCategoryPair),
-        mDocShellId(aDocShellId),
-        mDocShellHistoryId(aDocShellHistoryId) {
+        mInnerWindowID(aInnerWindowID) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     profiler_tracing(mCategoryString, mMarkerName, aCategoryPair,
-                     TRACING_INTERVAL_START, std::move(aBacktrace), mDocShellId,
-                     mDocShellHistoryId);
+                     TRACING_INTERVAL_START, std::move(aBacktrace),
+                     mInnerWindowID);
   }
 
   ~AutoProfilerTracing() {
     profiler_tracing(mCategoryString, mMarkerName, mCategoryPair,
-                     TRACING_INTERVAL_END, mDocShellId, mDocShellHistoryId);
+                     TRACING_INTERVAL_END, mInnerWindowID);
   }
 
  protected:
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   const char* mCategoryString;
   const char* mMarkerName;
   const ProfilingCategoryPair mCategoryPair;
-  const Maybe<std::string> mDocShellId;
-  const Maybe<uint32_t> mDocShellHistoryId;
+  const Maybe<uint64_t> mInnerWindowID;
 };
 
 // Get the MOZ_BASE_PROFILER_STARTUP* environment variables that should be
 // supplied to a child process that is about to be launched, in order
 // to make that child process start with the same profiler settings as
 // in the current process.  The given function is invoked once for
 // each variable to be set.
 MFBT_API void GetProfilerEnvVarsForChildProcess(
--- a/mozglue/baseprofiler/public/BaseProfilerMarkerPayload.h
+++ b/mozglue/baseprofiler/public/BaseProfilerMarkerPayload.h
@@ -31,28 +31,25 @@ class UniqueStacks;
 // This is an abstract class that can be implemented to supply data to be
 // attached with a profiler marker.
 //
 // When subclassing this, note that the destructor can be called on any thread,
 // i.e. not necessarily on the thread that created the object.
 class ProfilerMarkerPayload {
  public:
   explicit ProfilerMarkerPayload(
-      const Maybe<std::string>& aDocShellId = Nothing(),
-      const Maybe<uint32_t>& aDocShellHistoryId = Nothing(),
+      const Maybe<uint64_t>& aInnerWindowID = Nothing(),
       UniqueProfilerBacktrace aStack = nullptr)
       : mCommonProps{TimeStamp{}, TimeStamp{}, std::move(aStack),
-                     std::move(aDocShellId), std::move(aDocShellHistoryId)} {}
+                     aInnerWindowID} {}
 
   ProfilerMarkerPayload(const TimeStamp& aStartTime, const TimeStamp& aEndTime,
-                        const Maybe<std::string>& aDocShellId = Nothing(),
-                        const Maybe<uint32_t>& aDocShellHistoryId = Nothing(),
+                        const Maybe<uint64_t>& aInnerWindowID = Nothing(),
                         UniqueProfilerBacktrace aStack = nullptr)
-      : mCommonProps{aStartTime, aEndTime, std::move(aStack),
-                     std::move(aDocShellId), std::move(aDocShellHistoryId)} {}
+      : mCommonProps{aStartTime, aEndTime, std::move(aStack), aInnerWindowID} {}
 
   virtual ~ProfilerMarkerPayload() {}
 
   // Compute the number of bytes needed to serialize the `DeserializerTag` and
   // payload, including in the no-payload (nullptr) case.
   static BlocksRingBuffer::Length TagAndSerializationBytes(
       const ProfilerMarkerPayload* aPayload) {
     if (!aPayload) {
@@ -125,18 +122,17 @@ class ProfilerMarkerPayload {
   // Get the `Deserializer` for a given `DeserializerTag`.
   // Tag 0 is reserved as no-payload deserializer (which returns nullptr).
   MFBT_API static Deserializer DeserializerForTag(DeserializerTag aTag);
 
   struct CommonProps {
     TimeStamp mStartTime;
     TimeStamp mEndTime;
     UniqueProfilerBacktrace mStack;
-    Maybe<std::string> mDocShellId;
-    Maybe<uint32_t> mDocShellHistoryId;
+    Maybe<uint64_t> mInnerWindowID;
   };
 
   // Deserializers can use this base constructor.
   explicit ProfilerMarkerPayload(CommonProps&& aCommonProps)
       : mCommonProps(std::move(aCommonProps)) {}
 
   // Serialization/deserialization of common props in ProfilerMarkerPayload.
   MFBT_API BlocksRingBuffer::Length CommonPropsTagAndSerializationBytes() const;
@@ -173,24 +169,23 @@ class ProfilerMarkerPayload {
       const ::mozilla::TimeStamp& aProcessStartTime,                           \
       ::mozilla::baseprofiler::UniqueStacks& aUniqueStacks) const override;    \
   static UniquePtr<ProfilerMarkerPayload> Deserialize(                         \
       BlocksRingBuffer::EntryReader& aEntryReader);                            \
   MFBT_API BlocksRingBuffer::Length TagAndSerializationBytes() const override; \
   MFBT_API void SerializeTagAndPayload(                                        \
       BlocksRingBuffer::EntryWriter& aEntryWriter) const override;
 
-// TODO: Increase the coverage of tracing markers that include DocShell
+// TODO: Increase the coverage of tracing markers that include InnerWindowID
 // information
 class TracingMarkerPayload : public ProfilerMarkerPayload {
  public:
   MFBT_API TracingMarkerPayload(
       const char* aCategory, TracingKind aKind,
-      const Maybe<std::string>& aDocShellId = Nothing(),
-      const Maybe<uint32_t>& aDocShellHistoryId = Nothing(),
+      const Maybe<uint64_t>& aInnerWindowID = Nothing(),
       UniqueProfilerBacktrace aCause = nullptr);
 
   MFBT_API ~TracingMarkerPayload() override;
 
   DECL_BASE_STREAM_PAYLOAD
 
  private:
   MFBT_API TracingMarkerPayload(CommonProps&& aCommonProps,
@@ -221,26 +216,24 @@ class FileIOMarkerPayload : public Profi
   UniqueFreePtr<char> mOperation;
   UniqueFreePtr<char> mFilename;
 };
 
 class UserTimingMarkerPayload : public ProfilerMarkerPayload {
  public:
   MFBT_API UserTimingMarkerPayload(const std::string& aName,
                                    const TimeStamp& aStartTime,
-                                   const Maybe<std::string>& aDocShellId,
-                                   const Maybe<uint32_t>& aDocShellHistoryId);
+                                   const Maybe<uint64_t>& aInnerWindowID);
 
   MFBT_API UserTimingMarkerPayload(const std::string& aName,
                                    const Maybe<std::string>& aStartMark,
                                    const Maybe<std::string>& aEndMark,
                                    const TimeStamp& aStartTime,
                                    const TimeStamp& aEndTime,
-                                   const Maybe<std::string>& aDocShellId,
-                                   const Maybe<uint32_t>& aDocShellHistoryId);
+                                   const Maybe<uint64_t>& aInnerWindowID);
 
   MFBT_API ~UserTimingMarkerPayload() override;
 
   DECL_BASE_STREAM_PAYLOAD
 
  private:
   MFBT_API UserTimingMarkerPayload(CommonProps&& aCommonProps,
                                    const char* aEntryType, std::string&& aName,
@@ -286,24 +279,22 @@ class TextMarkerPayload : public Profile
                              const TimeStamp& aStartTime);
 
   MFBT_API TextMarkerPayload(const std::string& aText,
                              const TimeStamp& aStartTime,
                              const TimeStamp& aEndTime);
 
   MFBT_API TextMarkerPayload(const std::string& aText,
                              const TimeStamp& aStartTime,
-                             const Maybe<std::string>& aDocShellId,
-                             const Maybe<uint32_t>& aDocShellHistoryId);
+                             const Maybe<uint64_t>& aInnerWindowID);
 
   MFBT_API TextMarkerPayload(const std::string& aText,
                              const TimeStamp& aStartTime,
                              const TimeStamp& aEndTime,
-                             const Maybe<std::string>& aDocShellId,
-                             const Maybe<uint32_t>& aDocShellHistoryId,
+                             const Maybe<uint64_t>& aInnerWindowID,
                              UniqueProfilerBacktrace aCause = nullptr);
 
   MFBT_API ~TextMarkerPayload() override;
 
   DECL_BASE_STREAM_PAYLOAD
 
  private:
   MFBT_API TextMarkerPayload(CommonProps&& aCommonProps, std::string&& aText);
--- a/mozglue/tests/TestBaseProfiler.cpp
+++ b/mozglue/tests/TestBaseProfiler.cpp
@@ -1707,17 +1707,17 @@ void TestProfiler() {
         "FileIOMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
         baseprofiler::FileIOMarkerPayload(
             "operation", "source", "filename", TimeStamp::NowUnfuzzed(),
             TimeStamp::NowUnfuzzed(), std::move(cause)));
 
     baseprofiler::profiler_add_marker(
         "UserTimingMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
         baseprofiler::UserTimingMarkerPayload("name", TimeStamp::NowUnfuzzed(),
-                                              Nothing{}, Nothing{}));
+                                              Nothing{}));
 
     baseprofiler::profiler_add_marker(
         "HangMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
         baseprofiler::HangMarkerPayload(TimeStamp::NowUnfuzzed(),
                                         TimeStamp::NowUnfuzzed()));
 
     baseprofiler::profiler_add_marker(
         "LongTaskMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -121,16 +121,17 @@ nsHttpConnectionMgr::nsHttpConnectionMgr
       mThrottleEnabled(false),
       mThrottleVersion(2),
       mThrottleSuspendFor(0),
       mThrottleResumeFor(0),
       mThrottleReadLimit(0),
       mThrottleReadInterval(0),
       mThrottleHoldTime(0),
       mThrottleMaxTime(0),
+      mBeConservativeForProxy(true),
       mIsShuttingDown(false),
       mNumActiveConns(0),
       mNumIdleConns(0),
       mNumSpdyActiveConns(0),
       mNumHalfOpenConns(0),
       mTimeOfNextWakeUp(UINT64_MAX),
       mPruningNoTraffic(false),
       mTimeoutTickArmed(false),
@@ -2998,16 +2999,19 @@ void nsHttpConnectionMgr::OnMsgUpdatePar
       mThrottleReadInterval = value;
       break;
     case THROTTLING_HOLD_TIME:
       mThrottleHoldTime = value;
       break;
     case THROTTLING_MAX_TIME:
       mThrottleMaxTime = TimeDuration::FromMilliseconds(value);
       break;
+    case PROXY_BE_CONSERVATIVE:
+      mBeConservativeForProxy = !!value;
+      break;
     default:
       MOZ_ASSERT_UNREACHABLE("unexpected parameter name");
   }
 }
 
 // nsHttpConnectionMgr::nsConnectionEntry
 nsHttpConnectionMgr::nsConnectionEntry::~nsConnectionEntry() {
   LOG(("nsConnectionEntry::~nsConnectionEntry this=%p", this));
@@ -4008,16 +4012,34 @@ nsHttpConnectionMgr::nsHalfOpenSocket::n
 nsHttpConnectionMgr::nsHalfOpenSocket::~nsHalfOpenSocket() {
   MOZ_ASSERT(!mStreamOut);
   MOZ_ASSERT(!mBackupStreamOut);
   LOG(("Destroying nsHalfOpenSocket [this=%p]\n", this));
 
   if (mEnt) mEnt->RemoveHalfOpen(this);
 }
 
+bool nsHttpConnectionMgr::BeConservativeIfProxied(nsIProxyInfo* proxy) {
+  if (mBeConservativeForProxy) {
+    // The pref says to be conservative for proxies.
+    return true;
+  }
+
+  if (!proxy) {
+    // There is no proxy, so be conservative by default.
+    return true;
+  }
+
+  // Be conservative only if there is no proxy host set either.
+  // This logic was copied from nsSSLIOLayerAddToSocket.
+  nsAutoCString proxyHost;
+  proxy->GetHost(proxyHost);
+  return proxyHost.IsEmpty();
+}
+
 nsresult nsHttpConnectionMgr::nsHalfOpenSocket::SetupStreams(
     nsISocketTransport** transport, nsIAsyncInputStream** instream,
     nsIAsyncOutputStream** outstream, bool isBackup) {
   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
   MOZ_ASSERT(mEnt);
   nsresult rv;
   nsTArray<nsCString> socketTypes;
@@ -4080,17 +4102,18 @@ nsresult nsHttpConnectionMgr::nsHalfOpen
   if (ci->GetPrivate() || ci->GetIsolated()) {
     tmpFlags |= nsISocketTransport::NO_PERMANENT_STORAGE;
   }
 
   if (ci->GetLessThanTls13()) {
     tmpFlags |= nsISocketTransport::DONT_TRY_ESNI;
   }
 
-  if ((mCaps & NS_HTTP_BE_CONSERVATIVE) || ci->GetBeConservative()) {
+  if (((mCaps & NS_HTTP_BE_CONSERVATIVE) || ci->GetBeConservative()) &&
+      gHttpHandler->ConnMgr()->BeConservativeIfProxied(ci->ProxyInfo())) {
     LOG(("Setting Socket to BE_CONSERVATIVE"));
     tmpFlags |= nsISocketTransport::BE_CONSERVATIVE;
   }
 
   if (mCaps & NS_HTTP_DISABLE_IPV4) {
     tmpFlags |= nsISocketTransport::DISABLE_IPV4;
   } else if (mCaps & NS_HTTP_DISABLE_IPV6) {
     tmpFlags |= nsISocketTransport::DISABLE_IPV6;
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -60,17 +60,18 @@ class nsHttpConnectionMgr final : public
     MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
     MAX_REQUEST_DELAY,
     THROTTLING_ENABLED,
     THROTTLING_SUSPEND_FOR,
     THROTTLING_RESUME_FOR,
     THROTTLING_READ_LIMIT,
     THROTTLING_READ_INTERVAL,
     THROTTLING_HOLD_TIME,
-    THROTTLING_MAX_TIME
+    THROTTLING_MAX_TIME,
+    PROXY_BE_CONSERVATIVE
   };
 
   //-------------------------------------------------------------------------
   // NOTE: functions below may only be called on the main thread.
   //-------------------------------------------------------------------------
 
   nsHttpConnectionMgr();
 
@@ -560,16 +561,17 @@ class nsHttpConnectionMgr final : public
   bool mThrottleEnabled;
   uint32_t mThrottleVersion;
   uint32_t mThrottleSuspendFor;
   uint32_t mThrottleResumeFor;
   uint32_t mThrottleReadLimit;
   uint32_t mThrottleReadInterval;
   uint32_t mThrottleHoldTime;
   TimeDuration mThrottleMaxTime;
+  bool mBeConservativeForProxy;
   Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
 
   //-------------------------------------------------------------------------
   // NOTE: these members are only accessed on the socket transport thread
   //-------------------------------------------------------------------------
 
   MOZ_MUST_USE bool ProcessPendingQForEntry(nsConnectionEntry*,
                                             bool considerAll);
@@ -813,16 +815,20 @@ class nsHttpConnectionMgr final : public
       nsConnectionEntry* ent, nsAHttpTransaction* trans);
 
   // When current active tab is changed, this function uses
   // |previousWindowId| to select background transactions and
   // mCurrentTopLevelOuterContentWindowId| to select foreground transactions.
   // Then, it notifies selected transactions' connection of the new active tab
   // id.
   void NotifyConnectionOfWindowIdChange(uint64_t previousWindowId);
+
+  // A test if be-conservative should be used when proxy is setup for the
+  // connection
+  bool BeConservativeIfProxied(nsIProxyInfo* proxy);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket,
                               NS_HALFOPENSOCKET_IID)
 
 }  // namespace net
 }  // namespace mozilla
 
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -1314,16 +1314,26 @@ void nsHttpHandler::PrefsChanged(const c
       if (httpVersion.EqualsLiteral("1.1"))
         mProxyHttpVersion = HttpVersion::v1_1;
       else
         mProxyHttpVersion = HttpVersion::v1_0;
       // it does not make sense to issue a HTTP/0.9 request to a proxy server
     }
   }
 
+  if (PREF_CHANGED(HTTP_PREF("proxy.respect-be-conservative"))) {
+    rv =
+        Preferences::GetBool(HTTP_PREF("proxy.respect-be-conservative"), &cVar);
+    if (NS_SUCCEEDED(rv) && mConnMgr) {
+      Unused << mConnMgr->UpdateParam(
+          nsHttpConnectionMgr::PROXY_BE_CONSERVATIVE,
+          static_cast<int32_t>(cVar));
+    }
+  }
+
   if (PREF_CHANGED(HTTP_PREF("qos"))) {
     rv = Preferences::GetInt(HTTP_PREF("qos"), &val);
     if (NS_SUCCEEDED(rv)) mQoSBits = (uint8_t)clamped(val, 0, 0xff);
   }
 
   if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
     nsAutoCString acceptEncodings;
     rv = Preferences::GetCString(HTTP_PREF("accept-encoding"), acceptEncodings);
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -50,17 +50,17 @@ lazy_static = "1"
 log = "0.4"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = "0.1"
 matches = "0.1"
 nsstring = {path = "../../../xpcom/rust/nsstring/", optional = true}
 num_cpus = {version = "1.1.0"}
 num-integer = "0.1"
 num-traits = "0.2"
-num-derive = "0.2"
+num-derive = "0.3"
 ordered-float = "1.0"
 owning_ref = "0.4"
 parking_lot = "0.9"
 precomputed-hash = "0.1.1"
 rayon = "1"
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true, features = ["derive"]}
 servo_arc = { path = "../servo_arc" }
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -722,33 +722,34 @@ linux64-fuzzing-ccov/opt:
     run-on-projects: ['mozilla-central', 'try']
     worker-type: b-linux
     worker:
         max-run-time: 5400
         env:
             PERFHERDER_EXTRA_OPTIONS: fuzzing-ccov
             FORCE_GCC: '1'
             ASAN_OPTIONS: "detect_leaks=0"
+            RUSTC_BOOTSTRAP: '1'
     run:
         using: mozharness
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: fuzzing-ccov
         tooltool-downloads: public
         need-xvfb: true
     fetches:
         toolchain:
             - linux64-clang
             - linux64-gcc
             - linux64-cbindgen
-            - linux64-rust-nightly
+            - linux64-rust
             - linux64-rust-size
             - linux64-sccache
             - linux64-nasm
             - linux64-node
 
 linux64-asan-reporter-nightly/opt:
     description: "Linux64 Opt ASAN Reporter Nightly"
     attributes:
@@ -996,16 +997,17 @@ linux64-tup/opt:
         platform: linux64/opt
         symbol: Btup
         tier: 3
     worker-type: b-linux
     worker:
         max-run-time: 3600
         env:
             PERFHERDER_EXTRA_OPTIONS: tup
+            RUSTC_BOOTSTRAP: '1'
     run:
         using: mozharness
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
@@ -1013,17 +1015,17 @@ linux64-tup/opt:
         mozconfig-variant: tup
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: []
     fetches:
         toolchain:
             - linux64-binutils
             - linux64-clang
-            - linux64-rust-nightly
+            - linux64-rust
             - linux64-cbindgen
             - linux64-sccache
             - linux64-tup
             - linux64-nasm
             - linux64-node
 
 linux64-ccov/debug:
     description: "Linux64-CCov Debug"
@@ -1039,32 +1041,33 @@ linux64-ccov/debug:
     worker:
         artifacts:
             - name: public/code-coverage-grcov.zip
               path: /builds/worker/workspace/build/src/obj-firefox/code-coverage-grcov.zip
               type: file
         max-run-time: 7200
         env:
             FORCE_GCC: '1'
+            RUSTC_BOOTSTRAP: '1'
     run:
         using: mozharness
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-debug
         mozconfig-variant: code-coverage-debug
         tooltool-downloads: public
         need-xvfb: true
     fetches:
         toolchain:
             - linux64-clang-8
-            - linux64-rust-nightly
+            - linux64-rust
             - linux64-gcc
             - linux64-grcov
             - linux64-cbindgen
             - linux64-sccache
             - linux64-nasm
             - linux64-node
 
 linux64-ccov/opt:
@@ -1077,32 +1080,33 @@ linux64-ccov/opt:
         symbol: B
         tier: 2
     run-on-projects: ['mozilla-central', 'try']
     worker-type: b-linux
     worker:
         max-run-time: 7200
         env:
             FORCE_GCC: '1'
+            RUSTC_BOOTSTRAP: '1'
     run:
         using: mozharness
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-opt
         mozconfig-variant: code-coverage-opt
         tooltool-downloads: public
         need-xvfb: true
     fetches:
         toolchain:
             - linux64-clang-8
-            - linux64-rust-nightly
+            - linux64-rust
             - linux64-gcc
             - linux64-cbindgen
             - linux64-sccache
             - linux64-nasm
             - linux64-node
 
 linux64-add-on-devel/opt:
     description: "Linux64 add-on-devel"
--- a/taskcluster/ci/build/macosx.yml
+++ b/taskcluster/ci/build/macosx.yml
@@ -351,16 +351,17 @@ macosx64-ccov/debug:
         platform: osx-cross-ccov/debug
         symbol: B
         tier: 1
     worker-type: b-linux
     worker:
         max-run-time: 7200
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
+            RUSTC_BOOTSTRAP: '1'
     run:
         using: mozharness
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
@@ -371,17 +372,17 @@ macosx64-ccov/debug:
     fetches:
         toolchain:
             - linux64-binutils
             - linux64-cctools-port
             - linux64-clang-macosx-cross
             - linux64-hfsplus
             - linux64-libdmg
             - linux64-llvm-dsymutil
-            - linux64-rust-nightly-macos
+            - linux64-rust-macos
             - linux64-rust-size
             - linux64-cbindgen
             - linux64-sccache
             - linux64-nasm
             - linux64-node
 
 macosx64-gcp/debug:
     description: "MacOS X x64 Cross-compile - built on GCP"
--- a/taskcluster/ci/build/windows.yml
+++ b/taskcluster/ci/build/windows.yml
@@ -661,31 +661,32 @@ win64-ccov/debug:
     worker:
         artifacts:
             - name: public/code-coverage-grcov.zip
               path: build\src\obj-firefox\code-coverage-grcov.zip
               type: file
         max-run-time: 7200
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win64/releng.manifest"
+            RUSTC_BOOTSTRAP: '1'
     run:
         options: [append-env-variables-from-configs]
         script: mozharness/scripts/fx_desktop_build.py
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/ccov_debug.py
         mozconfig-variant: code-coverage
     run-on-projects: ['mozilla-central', 'try']
     fetches:
         toolchain:
             - win64-clang-cl
-            - win64-rust-nightly
+            - win64-rust
             - win64-rust-size
             - win64-cbindgen
             - win64-grcov
             - win64-sccache
             - win64-nasm
             - win64-node
 
 win64-asan/debug:
--- a/taskcluster/ci/fetch/toolchains.yml
+++ b/taskcluster/ci/fetch/toolchains.yml
@@ -114,17 +114,17 @@ gmp-6.1.0:
         strip-components: 1
         add-prefix: gmp-source/
 
 iris-2.0:
     description: Iris_Firefox source code
     fetch:
         type: git
         repo: https://github.com/mozilla/iris_firefox
-        revision: db45d30941a6f0a81ba369b89cf66ebd9a6ba393
+        revision: 614bf07e14769552a533798fb3ccf8a7c1e7f23d
 
 isl-0.15:
     description: ISL 0.15 source code
     fetch:
         type: static-url
         url: ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.15.tar.bz2
         sha256: 8ceebbf4d9a81afa2b4449113cee4b7cb14a687d7a549a963deb5e2a41458b6b
         size: 1574964
--- a/taskcluster/ci/toolchain/rust.yml
+++ b/taskcluster/ci/toolchain/rust.yml
@@ -89,28 +89,16 @@ linux64-rust-1.37:
             '--channel', '1.37.0',
             '--host', 'x86_64-unknown-linux-gnu',
             '--target', 'x86_64-unknown-linux-gnu',
             '--target', 'i686-unknown-linux-gnu',
             '--target', 'aarch64-unknown-linux-gnu',
         ]
         toolchain-alias: linux64-rust
 
-linux64-rust-nightly:
-    description: "rust nightly repack"
-    treeherder:
-        symbol: TL(rust-nightly)
-    run:
-        arguments: [
-            '--channel', 'nightly-2019-06-28',
-            '--host', 'x86_64-unknown-linux-gnu',
-            '--target', 'x86_64-unknown-linux-gnu',
-            '--target', 'i686-unknown-linux-gnu',
-        ]
-
 linux64-rust-macos-1.31:
     description: "rust repack with macos-cross support"
     treeherder:
         symbol: TL(rust-macos-1.31)
     run:
         arguments: [
             '--channel', '1.31.0',
             '--host', 'x86_64-unknown-linux-gnu',
@@ -189,28 +177,16 @@ linux64-rust-macos-1.37:
         arguments: [
             '--channel', '1.37.0',
             '--host', 'x86_64-unknown-linux-gnu',
             '--target', 'x86_64-unknown-linux-gnu',
             '--target', 'x86_64-apple-darwin',
         ]
         toolchain-alias: linux64-rust-macos
 
-linux64-rust-nightly-macos:
-    description: "rust nightly repack with macos-cross support"
-    treeherder:
-        symbol: TL(rust-nightly-macos)
-    run:
-        arguments: [
-            '--channel', 'nightly-2019-06-28',
-            '--host', 'x86_64-unknown-linux-gnu',
-            '--target', 'x86_64-unknown-linux-gnu',
-            '--target', 'x86_64-apple-darwin',
-        ]
-
 linux64-rust-android-1.37:
     description: "rust repack with android-cross support"
     treeherder:
         symbol: TL(rust-android)
     run:
         arguments: [
             '--channel', '1.37.0',
             '--host', 'x86_64-unknown-linux-gnu',
@@ -268,28 +244,16 @@ win64-rust-1.37:
             '--channel', '1.37.0',
             '--host', 'x86_64-pc-windows-msvc',
             '--target', 'x86_64-pc-windows-msvc',
             '--target', 'i686-pc-windows-msvc',
             '--target', 'aarch64-pc-windows-msvc',
         ]
         toolchain-alias: win64-rust
 
-win64-rust-nightly:
-    description: "rust nightly repack"
-    treeherder:
-        symbol: TW64(rust-nightly)
-    run:
-        arguments: [
-            '--channel', 'nightly-2019-06-28',
-            '--host', 'x86_64-pc-windows-msvc',
-            '--target', 'x86_64-pc-windows-msvc',
-            '--target', 'i686-pc-windows-msvc',
-        ]
-
 mingw32-rust-1.31:
     treeherder:
         symbol: TMW(rust-1.31)
     run:
         arguments: [
             '--channel', '1.31.0',
             '--host', 'x86_64-unknown-linux-gnu',
             '--target', 'i686-unknown-linux-gnu',
--- a/testing/marionette/capabilities.js
+++ b/testing/marionette/capabilities.js
@@ -430,17 +430,17 @@ const UnhandledPromptBehavior = {
 };
 
 /** WebDriver session capabilities representation. */
 class Capabilities extends Map {
   /** @class */
   constructor() {
     super([
       // webdriver
-      ["browserName", appinfo.name],
+      ["browserName", getWebDriverBrowserName()],
       ["browserVersion", appinfo.version],
       ["platformName", getWebDriverPlatformName()],
       ["platformVersion", Services.sysinfo.getProperty("version")],
       ["acceptInsecureCerts", false],
       ["pageLoadStrategy", PageLoadStrategy.Normal],
       ["proxy", new Proxy()],
       ["setWindowRect", appinfo.name == "firefox"],
       ["timeouts", new Timeouts()],
--- a/testing/mochitest/BrowserTestUtils/content/content-task.js
+++ b/testing/mochitest/BrowserTestUtils/content/content-task.js
@@ -3,21 +3,69 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* eslint-env mozilla/frame-script */
 
 "use strict";
 
 ChromeUtils.import("resource://testing-common/Task.jsm", this);
 ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm", this);
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const AssertCls = ChromeUtils.import(
   "resource://testing-common/Assert.jsm",
   null
 ).Assert;
 
+// Injects EventUtils into ContentTask scope. To avoid leaks, this does not hold on
+// to the window global. This means you **need** to pass the window as an argument to
+// the individual EventUtils functions.
+// See SimpleTest/EventUtils.js for documentation.
+var EventUtils = {};
+
+EventUtils.window = {};
+EventUtils.parent = EventUtils.window;
+EventUtils._EU_Ci = Ci;
+EventUtils._EU_Cc = Cc;
+EventUtils.KeyboardEvent = content.KeyboardEvent;
+EventUtils.navigator = content.navigator;
+
+EventUtils.synthesizeClick = element =>
+  new Promise(resolve => {
+    element.addEventListener(
+      "click",
+      function() {
+        resolve();
+      },
+      { once: true }
+    );
+
+    EventUtils.synthesizeMouseAtCenter(
+      element,
+      { type: "mousedown", isSynthesized: false },
+      content
+    );
+    EventUtils.synthesizeMouseAtCenter(
+      element,
+      { type: "mouseup", isSynthesized: false },
+      content
+    );
+  });
+
+try {
+  Services.scriptloader.loadSubScript(
+    "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
+    EventUtils
+  );
+} catch (e) {
+  // There are some xpcshell tests which may use ContentTask.
+  // Just ignore if loading EventUtils fails. Tests that need it
+  // will fail anyway.
+  EventUtils = null;
+}
+
 addMessageListener("content-task:spawn", function(msg) {
   let id = msg.data.id;
   let source = msg.data.runnable || "()=>{}";
 
   function getStack(aStack) {
     let frames = [];
     for (let frame = aStack; frame; frame = frame.caller) {
       frames.push(frame.filename + ":" + frame.name + ":" + frame.lineNumber);
--- a/testing/mochitest/tests/Harness_sanity/test_SpecialPowersSpawn.html
+++ b/testing/mochitest/tests/Harness_sanity/test_SpecialPowersSpawn.html
@@ -48,12 +48,22 @@
 
     result = await SpecialPowers.spawn(SpecialPowers.getPrivilegedProps(frame, "browsingContext"),
                                        ["#span"], selector => {
       let elem = content.document.querySelector(selector);
       return elem.textContent;
     });
 
     is(result, "Hello there.", "Got correct element text from browsing context");
+
+    let line = 58; // Keep this in sync with the line number where the callback function starts.
+    let callback = () => {
+      let e = new Error("Hello.");
+      return { filename: e.fileName, lineNumber: e.lineNumber };
+    };
+
+    let loc = await SpecialPowers.spawn(frame, [], callback);
+    is(loc.filename, location.href, "Error should have correct script filename");
+    is(loc.lineNumber, line + 2, "Error should have correct script line number");
   });
 </script>
 </body>
 </html>
--- a/testing/specialpowers/content/SpecialPowersChild.jsm
+++ b/testing/specialpowers/content/SpecialPowersChild.jsm
@@ -1246,23 +1246,23 @@ class SpecialPowersChild extends JSWindo
     return WrapPrivileged.wrap(tmp.FormHistory);
   }
   getFormFillController(window) {
     return Cc["@mozilla.org/satchel/form-fill-controller;1"].getService(
       Ci.nsIFormFillController
     );
   }
   attachFormFillControllerTo(window) {
-    this.getFormFillController().attachPopupElementToBrowser(
-      window.docShell,
+    this.getFormFillController().attachPopupElementToDocument(
+      window.document,
       this._getAutoCompletePopup(window)
     );
   }
   detachFormFillControllerFrom(window) {
-    this.getFormFillController().detachFromBrowser(window.docShell);
+    this.getFormFillController().detachFromDocument(window.document);
   }
   isBackButtonEnabled(window) {
     return !this._getTopChromeWindow(window)
       .document.getElementById("Browser:Back")
       .hasAttribute("disabled");
   }
   // XXX end of problematic APIs
 
@@ -1663,17 +1663,17 @@ class SpecialPowersChild extends JSWindo
    */
   spawn(target, args, task) {
     let browsingContext = this._browsingContextForTarget(target);
 
     return this.sendQuery("Spawn", {
       browsingContext,
       args,
       task: String(task),
-      caller: SpecialPowersSandbox.getCallerInfo(Components.stack.caller),
+      caller: Cu.getFunctionSourceLocation(task),
       hasHarness: typeof this.SimpleTest === "object",
     });
   }
 
   snapshotContext(target, rect, background) {
     let browsingContext = this._browsingContextForTarget(target);
 
     return this.sendQuery("Snapshot", {
--- a/testing/specialpowers/content/SpecialPowersSandbox.jsm
+++ b/testing/specialpowers/content/SpecialPowersSandbox.jsm
@@ -39,23 +39,16 @@ class SpecialPowersSandbox {
           return this.Assert;
         },
         enumerable: true,
         configurable: true,
       });
     }
   }
 
-  static getCallerInfo(frame) {
-    return {
-      filename: frame.filename,
-      lineNumber: frame.lineNumber,
-    };
-  }
-
   get Assert() {
     if (!this._Assert) {
       this._Assert = new Assert((err, message, stack) => {
         this.report(err, message, stack);
       });
     }
     return this._Assert;
   }
--- a/testing/web-platform/meta/websockets/binary/__dir__.ini
+++ b/testing/web-platform/meta/websockets/binary/__dir__.ini
@@ -1,3 +1,3 @@
-lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
+lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::ContentPrincipal::AddonPolicy, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
 lsan-max-stack-depth: 7
 leak-threshold: [tab:51200]
--- a/testing/web-platform/meta/websockets/constructor/__dir__.ini
+++ b/testing/web-platform/meta/websockets/constructor/__dir__.ini
@@ -1,3 +1,3 @@
 lsan-max-stack-depth: 7
-lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::detail::UniqueSelector, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
+lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::ContentPrincipal::AddonPolicy, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::detail::UniqueSelector, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
 leak-threshold: [tab:51200]
--- a/third_party/rust/autocfg/.cargo-checksum.json
+++ b/third_party/rust/autocfg/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"59b541962c15f51087a11d7296e3b69ec6d9b8a8e9e8db949e7629ea28183564","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"d0e320dccace525a2cbcf3bc5d43ac9b7b61ee86b9c9713bf68993c3ad789d0a","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"7392068683dc86107bcf8073c81ff8fb7026f5fb98a355a4d47301c5946eeccb","src/tests.rs":"34bdceeffdbdd7f2535a6ed8272482b17325dba044c91bb96f3f8caeec58a83d","src/version.rs":"165324950f2195aaf068c47a4f2f0992b2bf18d8b7f4f17b6b264767523c0e5d"},"package":"a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"}
\ No newline at end of file
+{"files":{"Cargo.lock":"461e5e87b13d7faf25813b08b5003060c39d8af0953f30d5b80ae0926c888022","Cargo.toml":"1eded5c9954b3bb92bb2c7403e026198e66a2a42199db06fc9cafddc8d1fd677","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"ba9a1621483e0b9f017f07c282d00d5cf3a2d8660cca6df6b14941319d748953","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"411d8dbc48ab0f67cb10243f1e16b235407818c96556c838182e4004da995dff","src/tests.rs":"0b1353344e832553d328c47f1639ced877b5dff70fd2024d84130bd1c33eee07","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3"},"package":"b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "autocfg"
+version = "0.1.6"
+
--- a/third_party/rust/autocfg/Cargo.toml
+++ b/third_party/rust/autocfg/Cargo.toml
@@ -1,23 +1,23 @@
 # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
 #
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "autocfg"
-version = "0.1.2"
+version = "0.1.6"
 authors = ["Josh Stone <cuviper@gmail.com>"]
 description = "Automatic cfg for Rust compiler features"
 readme = "README.md"
 keywords = ["rustc", "build", "autoconf"]
 categories = ["development-tools::build-utils"]
 license = "Apache-2.0/MIT"
 repository = "https://github.com/cuviper/autocfg"
 
--- a/third_party/rust/autocfg/README.md
+++ b/third_party/rust/autocfg/README.md
@@ -38,17 +38,30 @@ fn main() {
 If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
 for Cargo, which translates to Rust arguments `--cfg has_i128`.  Then in the
 rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
 should only be used when the compiler supports it.
 
 
 ## Release Notes
 
-- 0.1.2 (2018-01-16)
+- 0.1.6 (2019-08-19)
+  - Add `probe`/`emit_sysroot_crate`, by @leo60228
+
+- 0.1.5 (2019-07-16)
+  - Mask some warnings from newer rustc.
+
+- 0.1.4 (2019-05-22)
+  - Relax `std`/`no_std` probing to a warning instead of an error.
+  - Improve `rustc` bootstrap compatibility.
+
+- 0.1.3 (2019-05-21)
+  - Auto-detects if `#![no_std]` is needed for the `$TARGET`
+
+- 0.1.2 (2019-01-16)
   - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`
   - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`
 
 
 ## Minimum Rust version policy
 
 This crate's minimum supported `rustc` version is `1.0.0`.  Compatibility is
 its entire reason for existence, so this crate will be extremely conservative
--- a/third_party/rust/autocfg/src/lib.rs
+++ b/third_party/rust/autocfg/src/lib.rs
@@ -31,23 +31,30 @@
 //!
 //! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
 //! for Cargo, which translates to Rust arguments `--cfg has_i128`.  Then in the
 //! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
 //! should only be used when the compiler supports it.
 
 #![deny(missing_debug_implementations)]
 #![deny(missing_docs)]
+// allow future warnings that can't be fixed while keeping 1.0 compatibility
+#![allow(unknown_lints)]
+#![allow(bare_trait_objects)]
+#![allow(ellipsis_inclusive_range_patterns)]
 
 use std::env;
 use std::ffi::OsString;
 use std::fs;
-use std::io::Write;
+use std::io::{stderr, Write};
 use std::path::PathBuf;
 use std::process::{Command, Stdio};
+#[allow(deprecated)]
+use std::sync::atomic::ATOMIC_USIZE_INIT;
+use std::sync::atomic::{AtomicUsize, Ordering};
 
 mod error;
 pub use error::Error;
 
 mod version;
 use version::Version;
 
 #[cfg(test)]
@@ -55,16 +62,17 @@ mod tests;
 
 /// Helper to detect compiler features for `cfg` output in build scripts.
 #[derive(Clone, Debug)]
 pub struct AutoCfg {
     out_dir: PathBuf,
     rustc: PathBuf,
     rustc_version: Version,
     target: Option<OsString>,
+    no_std: bool,
 }
 
 /// Writes a config flag for rustc on standard out.
 ///
 /// This looks like: `cargo:rustc-cfg=CFG`
 ///
 /// Cargo will use this in arguments to rustc, like `--cfg CFG`.
 pub fn emit(cfg: &str) {
@@ -132,22 +140,35 @@ impl AutoCfg {
 
         // Sanity check the output directory
         let dir = dir.into();
         let meta = try!(fs::metadata(&dir).map_err(error::from_io));
         if !meta.is_dir() || meta.permissions().readonly() {
             return Err(error::from_str("output path is not a writable directory"));
         }
 
-        Ok(AutoCfg {
+        let mut ac = AutoCfg {
             out_dir: dir,
             rustc: rustc,
             rustc_version: rustc_version,
             target: env::var_os("TARGET"),
-        })
+            no_std: false,
+        };
+
+        // Sanity check with and without `std`.
+        if !ac.probe("").unwrap_or(false) {
+            ac.no_std = true;
+            if !ac.probe("").unwrap_or(false) {
+                // Neither worked, so assume nothing...
+                ac.no_std = false;
+                let warning = b"warning: autocfg could not probe for `std`\n";
+                stderr().write_all(warning).ok();
+            }
+        }
+        Ok(ac)
     }
 
     /// Test whether the current `rustc` reports a version greater than
     /// or equal to "`major`.`minor`".
     pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool {
         self.rustc_version >= Version::new(major, minor, 0)
     }
 
@@ -155,48 +176,66 @@ impl AutoCfg {
     /// if the current `rustc` is at least that version.
     pub fn emit_rustc_version(&self, major: usize, minor: usize) {
         if self.probe_rustc_version(major, minor) {
             emit(&format!("rustc_{}_{}", major, minor));
         }
     }
 
     fn probe<T: AsRef<[u8]>>(&self, code: T) -> Result<bool, Error> {
-        use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
-
+        #[allow(deprecated)]
         static ID: AtomicUsize = ATOMIC_USIZE_INIT;
 
         let id = ID.fetch_add(1, Ordering::Relaxed);
         let mut command = Command::new(&self.rustc);
         command
-            .arg(format!("--crate-name=probe{}", id))
+            .arg("--crate-name")
+            .arg(format!("probe{}", id))
             .arg("--crate-type=lib")
             .arg("--out-dir")
             .arg(&self.out_dir)
             .arg("--emit=llvm-ir");
 
         if let Some(target) = self.target.as_ref() {
             command.arg("--target").arg(target);
         }
 
         command.arg("-").stdin(Stdio::piped());
         let mut child = try!(command.spawn().map_err(error::from_io));
-        try!(
-            child
-                .stdin
-                .take()
-                .expect("rustc stdin")
-                .write_all(code.as_ref())
-                .map_err(error::from_io)
-        );
+        let mut stdin = child.stdin.take().expect("rustc stdin");
+
+        if self.no_std {
+            try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io));
+        }
+        try!(stdin.write_all(code.as_ref()).map_err(error::from_io));
+        drop(stdin);
 
         let status = try!(child.wait().map_err(error::from_io));
         Ok(status.success())
     }
 
+    /// Tests whether the given sysroot crate can be used.
+    ///
+    /// The test code is subject to change, but currently looks like:
+    ///
+    /// ```ignore
+    /// extern crate CRATE as probe;
+    /// ```
+    pub fn probe_sysroot_crate(&self, name: &str) -> bool {
+        self.probe(format!("extern crate {} as probe;", name)) // `as _` wasn't stabilized until Rust 1.33
+            .unwrap_or(false)
+    }
+
+    /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true.
+    pub fn emit_sysroot_crate(&self, name: &str) {
+        if self.probe_sysroot_crate(name) {
+            emit(&format!("has_{}", mangle(name)));
+        }
+    }
+
     /// Tests whether the given path can be used.
     ///
     /// The test code is subject to change, but currently looks like:
     ///
     /// ```ignore
     /// pub use PATH;
     /// ```
     pub fn probe_path(&self, path: &str) -> bool {
@@ -279,10 +318,11 @@ impl AutoCfg {
     }
 }
 
 fn mangle(s: &str) -> String {
     s.chars()
         .map(|c| match c {
             'A'...'Z' | 'a'...'z' | '0'...'9' => c,
             _ => '_',
-        }).collect()
+        })
+        .collect()
 }
--- a/third_party/rust/autocfg/src/tests.rs
+++ b/third_party/rust/autocfg/src/tests.rs
@@ -1,10 +1,17 @@
 use super::AutoCfg;
 
+impl AutoCfg {
+    fn core_std(&self, path: &str) -> String {
+        let krate = if self.no_std { "core" } else { "std" };
+        format!("{}::{}", krate, path)
+    }
+}
+
 #[test]
 fn autocfg_version() {
     let ac = AutoCfg::with_dir("target").unwrap();
     println!("version: {:?}", ac.rustc_version);
     assert!(ac.probe_rustc_version(1, 0));
 }
 
 #[test]
@@ -18,40 +25,75 @@ fn version_cmp() {
     assert!(Version::new(1, 2, 4) > v123);
     assert!(Version::new(1, 10, 0) > v123);
     assert!(Version::new(2, 0, 0) > v123);
 }
 
 #[test]
 fn probe_add() {
     let ac = AutoCfg::with_dir("target").unwrap();
-    assert!(ac.probe_path("std::ops::Add"));
-    assert!(ac.probe_trait("std::ops::Add"));
-    assert!(ac.probe_trait("std::ops::Add<i32>"));
-    assert!(ac.probe_trait("std::ops::Add<i32, Output = i32>"));
-    assert!(ac.probe_type("std::ops::Add<i32, Output = i32>"));
+    let add = ac.core_std("ops::Add");
+    let add_rhs = ac.core_std("ops::Add<i32>");
+    let add_rhs_output = ac.core_std("ops::Add<i32, Output = i32>");
+    assert!(ac.probe_path(&add));
+    assert!(ac.probe_trait(&add));
+    assert!(ac.probe_trait(&add_rhs));
+    assert!(ac.probe_trait(&add_rhs_output));
+    assert!(ac.probe_type(&add_rhs_output));
 }
 
 #[test]
 fn probe_as_ref() {
     let ac = AutoCfg::with_dir("target").unwrap();
-    assert!(ac.probe_path("std::convert::AsRef"));
-    assert!(ac.probe_trait("std::convert::AsRef<str>"));
-    assert!(ac.probe_type("std::convert::AsRef<str>"));
+    let as_ref = ac.core_std("convert::AsRef");
+    let as_ref_str = ac.core_std("convert::AsRef<str>");
+    assert!(ac.probe_path(&as_ref));
+    assert!(ac.probe_trait(&as_ref_str));
+    assert!(ac.probe_type(&as_ref_str));
 }
 
 #[test]
 fn probe_i128() {
     let ac = AutoCfg::with_dir("target").unwrap();
     let missing = !ac.probe_rustc_version(1, 26);
-    assert!(missing ^ ac.probe_path("std::i128"));
+    let i128_path = ac.core_std("i128");
+    assert!(missing ^ ac.probe_path(&i128_path));
     assert!(missing ^ ac.probe_type("i128"));
 }
 
 #[test]
 fn probe_sum() {
     let ac = AutoCfg::with_dir("target").unwrap();
     let missing = !ac.probe_rustc_version(1, 12);
-    assert!(missing ^ ac.probe_path("std::iter::Sum"));
-    assert!(missing ^ ac.probe_trait("std::iter::Sum"));
-    assert!(missing ^ ac.probe_trait("std::iter::Sum<i32>"));
-    assert!(missing ^ ac.probe_type("std::iter::Sum<i32>"));
+    let sum = ac.core_std("iter::Sum");
+    let sum_i32 = ac.core_std("iter::Sum<i32>");
+    assert!(missing ^ ac.probe_path(&sum));
+    assert!(missing ^ ac.probe_trait(&sum));
+    assert!(missing ^ ac.probe_trait(&sum_i32));
+    assert!(missing ^ ac.probe_type(&sum_i32));
+}
+
+#[test]
+fn probe_std() {
+    let ac = AutoCfg::with_dir("target").unwrap();
+    assert_eq!(ac.probe_sysroot_crate("std"), !ac.no_std);
 }
+
+#[test]
+fn probe_alloc() {
+    let ac = AutoCfg::with_dir("target").unwrap();
+    let missing = !ac.probe_rustc_version(1, 36);
+    assert!(missing ^ ac.probe_sysroot_crate("alloc"));
+}
+
+#[test]
+fn probe_bad_sysroot_crate() {
+    let ac = AutoCfg::with_dir("target").unwrap();
+    assert!(!ac.probe_sysroot_crate("doesnt_exist"));
+}
+
+#[test]
+fn probe_no_std() {
+    let ac = AutoCfg::with_dir("target").unwrap();
+    assert!(ac.probe_type("i32"));
+    assert!(ac.probe_type("[i32]"));
+    assert_eq!(ac.probe_type("Vec<i32>"), !ac.no_std);
+}
--- a/third_party/rust/autocfg/src/version.rs
+++ b/third_party/rust/autocfg/src/version.rs
@@ -19,22 +19,20 @@ impl Version {
             major: major,
             minor: minor,
             patch: patch,
         }
     }
 
     pub fn from_rustc(rustc: &Path) -> Result<Self, Error> {
         // Get rustc's verbose version
-        let output = try!(
-            Command::new(rustc)
-                .args(&["--version", "--verbose"])
-                .output()
-                .map_err(error::from_io)
-        );
+        let output = try!(Command::new(rustc)
+            .args(&["--version", "--verbose"])
+            .output()
+            .map_err(error::from_io));
         if !output.status.success() {
             return Err(error::from_str("could not execute rustc"));
         }
         let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8));
 
         // Find the release line in the verbose version output.
         let release = match output.lines().find(|line| line.starts_with("release: ")) {
             Some(line) => &line["release: ".len()..],
--- a/third_party/rust/cssparser-macros/.cargo-checksum.json
+++ b/third_party/rust/cssparser-macros/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"865ab5a711a4fea88adf215f7c0207f1ad2ee80c310229f6d2a5770d2ff36486","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","lib.rs":"66c99e9dd05190f31f59ccfd3f9558540f94a501e88849bcaf09191f9f3323da"},"package":"b16e382d9b983fdb9ac6a36b37fdeb84ce3ea81f749febfee3463cfa7f24275e"}
\ No newline at end of file
+{"files":{"Cargo.toml":"2933f8de8e313cbee4a5643b10242657dc6e7d06baac22d2c17b390b6c844419","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","lib.rs":"d3f200eeedd4e0dfe88562449368b01d07754fed677359e1e92d3293e1c8d8c6"},"package":"5bb1c84e87c717666564ec056105052331431803d606bd45529b28547b611eef"}
\ No newline at end of file
--- a/third_party/rust/cssparser-macros/Cargo.toml
+++ b/third_party/rust/cssparser-macros/Cargo.toml
@@ -1,39 +1,39 @@
 # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
 #
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cssparser-macros"
-version = "0.3.5"
+version = "0.3.6"
 authors = ["Simon Sapin <simon.sapin@exyr.org>"]
 description = "Procedural macros for cssparser"
 documentation = "https://docs.rs/cssparser-macros/"
 license = "MPL-2.0"
 repository = "https://github.com/servo/rust-cssparser"
 
 [lib]
 path = "lib.rs"
 proc-macro = true
 [dependencies.phf_codegen]
 version = "0.7"
 
 [dependencies.proc-macro2]
-version = "0.4"
+version = "1"
 
 [dependencies.procedural-masquerade]
 version = "0.1"
 
 [dependencies.quote]
-version = "0.6"
+version = "1"
 
 [dependencies.syn]
-version = "0.15.12"
+version = "1"
 features = ["full", "extra-traits"]
--- a/third_party/rust/cssparser-macros/lib.rs
+++ b/third_party/rust/cssparser-macros/lib.rs
@@ -1,39 +1,45 @@
 /* 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/. */
 
-#[macro_use] extern crate procedural_masquerade;
+#[macro_use]
+extern crate procedural_masquerade;
 extern crate phf_codegen;
 extern crate proc_macro;
 extern crate proc_macro2;
-#[macro_use] extern crate quote;
+#[macro_use]
+extern crate quote;
 extern crate syn;
 
-#[allow(unused_imports)] use std::ascii::AsciiExt;
+use proc_macro2::{TokenStream, TokenTree};
 use quote::TokenStreamExt;
 use std::iter;
-use proc_macro2::{TokenStream, TokenTree};
 
 define_proc_macros! {
     /// Input: the arms of a `match` expression.
     ///
     /// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
     ///
     /// Panic if the arms contain non-string patterns,
     /// or string patterns that contains ASCII uppercase letters.
     #[allow(non_snake_case)]
     pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
         let expr = syn::parse_str(&format!("match x {{ {} }}", input)).unwrap();
         let arms = match expr {
             syn::Expr::Match(syn::ExprMatch { arms, .. }) => arms,
             _ => panic!("expected a match expression, got {:?}", expr)
         };
-        max_len(arms.into_iter().flat_map(|arm| arm.pats).filter_map(|pattern| {
+        max_len(arms.into_iter().flat_map(|ref arm| {
+            match arm.pat {
+                syn::Pat::Or(ref p) => p.cases.iter().cloned().collect(),
+                ref p => vec![p.clone()]
+            }
+        }).filter_map(|pattern| {
             let expr = match pattern {
                 syn::Pat::Lit(expr) => expr,
                 syn::Pat::Wild(_) => return None,
                 _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
             };
             match *expr.expr {
                 syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref lit), .. }) => {
                     assert_eq!(lit.value(), lit.value().to_ascii_lowercase(),
@@ -83,17 +89,18 @@ define_proc_macros! {
         let mut initializer_bytes = Vec::new();
         map.build(&mut initializer_bytes).unwrap();
         tokens.append_all(syn::parse_str::<syn::Expr>(::std::str::from_utf8(&initializer_bytes).unwrap()));
         tokens.append_all(quote!(;));
         tokens.to_string()
     }
 }
 
-fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
+fn max_len<I: Iterator<Item = usize>>(lengths: I) -> String {
     let max_length = lengths.max().expect("expected at least one string");
     quote!( const MAX_LENGTH: usize = #max_length; ).to_string()
 }
 
 fn string_literal(token: &TokenTree) -> String {
-    let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect()).expect(&format!("expected string literal, got {:?}", token));
+    let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect())
+        .expect(&format!("expected string literal, got {:?}", token));
     lit.value()
 }
--- a/third_party/rust/cssparser/.cargo-checksum.json
+++ b/third_party/rust/cssparser/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"435243ec516989de48ba8715497f53c86efdd24b776e64d3667c3c9630f74695","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"a533b45a9c43083c6a6000a9c99a1acfed123d6430b232352ae02f1144a09f12","build.rs":"08e4a99d5184b2f22ab93bc0a024fec18dbd8fd38b9db638f19d4defede858ee","build/match_byte.rs":"e8537833ff1599a1bdbd0167f6295af7bd21e42024f32b982af32d58c156685c","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"8d3017ba8d644172908bd80d35e9be1081db477d2e0b0ea13971e29a466d451f","src/cow_rc_str.rs":"89b5dff5cf80eef3fcff0c11799e54a978d02d8b8963a621fbb999d35e7c03a3","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"98b28ca7c72b8d20b3d76ae5b841be87bcadfc89e433ecc95fcf37aa15731442","src/macros.rs":"a50a0a7afa43e099dc008e54956e4c1fdfba2e9795d006b22e9eb45065fed61e","src/nth.rs":"a9d5fa0bd2c3ae7c48c851b9f5508ebdb07affdf5d0737bb8d85a7befab2ef9c","src/parser.rs":"fe2eb2be084923bf362de4b95c029beb21f172ad972a6452c400f640b43a583e","src/rules_and_declarations.rs":"b0288def4392faad529296ea7850895470dce8322a712056c5232699688df67a","src/serializer.rs":"4f47d46d0d056baa1dbbef3168c5d400645062eaff5dd637b0172bd2af784ed4","src/size_of_tests.rs":"a628cacc876f240ac1bb9e287cdae293bffc4b86d45d9307e4fc2f822e8f3e84","src/tests.rs":"bf97071b691c0b0c932af5813e876142ce707ba57774742dbe60889b1dc54069","src/tokenizer.rs":"483c6629a4b057d56be6aada97689aa03a914702d4e78618fb095b4ee5b6f90d","src/unicode_range.rs":"c4655c817db0dabb1d55669ac61a56ecf7f6a6c4353cf5b539b13bea6511c3dd"},"package":"a921abc45ea75c2c817d951caeda31b94539d09a6b5e8d58a857b3b35c9c3894"}
\ No newline at end of file
+{"files":{"Cargo.toml":"9b63e0b5efaef0d3eaf50854bb45a8dd559f6eae4f69640943b27de4e4597023","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"a533b45a9c43083c6a6000a9c99a1acfed123d6430b232352ae02f1144a09f12","build.rs":"a41191c5917b37c911d4c191305ad975ad6d4c6cc778c38cfdf5c63c161aaffb","build/match_byte.rs":"190fa542a4a69ac197f9768320b03750cce2f61b3d99d84491d3c3116dafb461","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"af1c53f333cabde0736cc3e43e9045b0727eee6220eda7041af894abed1f0baa","src/cow_rc_str.rs":"89b5dff5cf80eef3fcff0c11799e54a978d02d8b8963a621fbb999d35e7c03a3","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"980f4d339e77926eeb2c556f2716f6ed42b7aa38c3ce4ede7079ab67ca70a843","src/macros.rs":"a67ee23aace36d9f407c544b8b522b8180be04e239d1afdc9d849c5ca8022d51","src/nth.rs":"6896c997742af6f014b37ad57a5450c979054fd9c311fed29ec1ac42b2b256d6","src/parser.rs":"fe2eb2be084923bf362de4b95c029beb21f172ad972a6452c400f640b43a583e","src/rules_and_declarations.rs":"b0288def4392faad529296ea7850895470dce8322a712056c5232699688df67a","src/serializer.rs":"18c6e1533a2d84cf080444f034d3690c1a87c354609c5d336bb46d8b63448911","src/size_of_tests.rs":"a628cacc876f240ac1bb9e287cdae293bffc4b86d45d9307e4fc2f822e8f3e84","src/tests.rs":"b7391de644691e1a2d5af6c8c6f7575fa5895010a65c5ba5eae65376bd2c35af","src/tokenizer.rs":"7967940ff2970d6eef9a97feecf3c09f30c19b6d8a1f3e68594305a2dc59e85d","src/unicode_range.rs":"c4655c817db0dabb1d55669ac61a56ecf7f6a6c4353cf5b539b13bea6511c3dd"},"package":"fbe18ca4efb9ba3716c6da66cc3d7e673bf59fa576353011f48c4cfddbdd740e"}
\ No newline at end of file
--- a/third_party/rust/cssparser/Cargo.toml
+++ b/third_party/rust/cssparser/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cssparser"
-version = "0.25.7"
+version = "0.25.9"
 authors = ["Simon Sapin <simon.sapin@exyr.org>"]
 build = "build.rs"
 exclude = ["src/css-parsing-tests/**", "src/big-data-url.css"]
 description = "Rust implementation of CSS Syntax Level 3"
 documentation = "https://docs.rs/cssparser/"
 readme = "README.md"
 keywords = ["css", "syntax", "parser"]
 license = "MPL-2.0"
@@ -51,23 +51,26 @@ optional = true
 [dependencies.smallvec]
 version = "0.6"
 [dev-dependencies.difference]
 version = "2.0"
 
 [dev-dependencies.encoding_rs]
 version = "0.8"
 
-[dev-dependencies.rustc-serialize]
-version = "0.3"
+[dev-dependencies.serde_json]
+version = "1.0"
+[build-dependencies.autocfg]
+version = "0.1.4"
+
 [build-dependencies.proc-macro2]
-version = "0.4"
+version = "1"
 
 [build-dependencies.quote]
-version = "0.6"
+version = "1"
 
 [build-dependencies.syn]
-version = "0.15.12"
+version = "1"
 features = ["extra-traits", "fold", "full"]
 
 [features]
 bench = []
 dummy_match_byte = []
--- a/third_party/rust/cssparser/build.rs
+++ b/third_party/rust/cssparser/build.rs
@@ -1,21 +1,21 @@
 /* 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/. */
 
+extern crate autocfg;
 #[macro_use]
 extern crate quote;
 #[macro_use]
 extern crate syn;
 extern crate proc_macro2;
 
 #[cfg(feature = "dummy_match_byte")]
 mod codegen {
-    use std::path::Path;
     pub fn main() {}
 }
 
 #[cfg(not(feature = "dummy_match_byte"))]
 #[path = "build/match_byte.rs"]
 mod match_byte;
 
 #[cfg(not(feature = "dummy_match_byte"))]
@@ -45,10 +45,12 @@ mod codegen {
 }
 
 fn main() {
     if std::mem::size_of::<Option<bool>>() == 1 {
         // https://github.com/rust-lang/rust/pull/45225
         println!("cargo:rustc-cfg=rustc_has_pr45225")
     }
 
+    autocfg::new().emit_has_path("std::mem::MaybeUninit");
+
     codegen::main();
 }
--- a/third_party/rust/cssparser/build/match_byte.rs
+++ b/third_party/rust/cssparser/build/match_byte.rs
@@ -67,16 +67,64 @@ fn get_byte_from_expr_lit(expr: &Box<syn
             } else {
                 panic!("Found a pattern that wasn't a byte")
             }
         }
         _ => unreachable!(),
     }
 }
 
+/// Parse a pattern and fill the table accordingly
+fn parse_pat_to_table<'a>(pat: &'a syn::Pat, case_id: u8, wildcard: &mut Option<&'a syn::Ident>, table: &mut [u8; 256]) {
+    match pat {
+        &syn::Pat::Lit(syn::PatLit { ref expr, .. }) => {
+            let value = get_byte_from_expr_lit(expr);
+            if table[value as usize] == 0 {
+                table[value as usize] = case_id;
+            }
+        }
+        &syn::Pat::Range(syn::PatRange { ref lo, ref hi, .. }) => {
+            let lo = get_byte_from_expr_lit(lo);
+            let hi = get_byte_from_expr_lit(hi);
+            for value in lo..hi {
+                if table[value as usize] == 0 {
+                    table[value as usize] = case_id;
+                }
+            }
+            if table[hi as usize] == 0 {
+                table[hi as usize] = case_id;
+            }
+        }
+        &syn::Pat::Wild(_) => {
+            for byte in table.iter_mut() {
+                if *byte == 0 {
+                    *byte = case_id;
+                }
+            }
+        }
+        &syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
+            assert_eq!(*wildcard, None);
+            *wildcard = Some(ident);
+            for byte in table.iter_mut() {
+                if *byte == 0 {
+                    *byte = case_id;
+                }
+            }
+        },
+        &syn::Pat::Or(syn::PatOr { ref cases, .. }) => {
+            for case in cases {
+                parse_pat_to_table(case, case_id, wildcard, table);
+            }
+        }
+        _ => {
+            panic!("Unexpected pattern: {:?}. Buggy code ?", pat);
+        }
+    }
+}
+
 /// Expand a TokenStream corresponding to the `match_byte` macro.
 ///
 /// ## Example
 ///
 /// ```rust
 /// match_byte! { tokenizer.next_byte_unchecked(),
 ///     b'a'..b'z' => { ... }
 ///     b'0'..b'9' => { ... }
@@ -92,58 +140,18 @@ fn expand_match_byte(body: &TokenStream)
     let mut table = [0u8; 256];
     let mut match_body = Vec::new();
     let mut wildcard = None;
 
     for (i, ref arm) in match_byte.arms.iter().enumerate() {
         let case_id = i + 1;
         let index = case_id as isize;
         let name = syn::Ident::new(&format!("Case{}", case_id), Span::call_site());
+        parse_pat_to_table(&arm.pat, case_id as u8, &mut wildcard, &mut table);
 
-        for pat in &arm.pats {
-            match pat {
-                &syn::Pat::Lit(syn::PatLit { ref expr }) => {
-                    let value = get_byte_from_expr_lit(expr);
-                    if table[value as usize] == 0 {
-                        table[value as usize] = case_id as u8;
-                    }
-                }
-                &syn::Pat::Range(syn::PatRange { ref lo, ref hi, .. }) => {
-                    let lo = get_byte_from_expr_lit(lo);
-                    let hi = get_byte_from_expr_lit(hi);
-                    for value in lo..hi {
-                        if table[value as usize] == 0 {
-                            table[value as usize] = case_id as u8;
-                        }
-                    }
-                    if table[hi as usize] == 0 {
-                        table[hi as usize] = case_id as u8;
-                    }
-                }
-                &syn::Pat::Wild(_) => {
-                    for byte in table.iter_mut() {
-                        if *byte == 0 {
-                            *byte = case_id as u8;
-                        }
-                    }
-                }
-                &syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
-                    assert_eq!(wildcard, None);
-                    wildcard = Some(ident);
-                    for byte in table.iter_mut() {
-                        if *byte == 0 {
-                            *byte = case_id as u8;
-                        }
-                    }
-                }
-                _ => {
-                    panic!("Unexpected pattern: {:?}. Buggy code ?", pat);
-                }
-            }
-        }
         cases.push(quote!(#name = #index));
         let body = &arm.body;
         match_body.push(quote!(Case::#name => { #body }))
     }
     let en = quote!(enum Case {
         #(#cases),*
     });
 
@@ -165,31 +173,31 @@ fn expand_match_byte(body: &TokenStream)
 
 impl Fold for MatchByteParser {
     fn fold_stmt(&mut self, stmt: syn::Stmt) -> syn::Stmt {
         match stmt {
             syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro { ref mac, .. })) => {
                 if mac.path == parse_quote!(match_byte) {
                     return syn::fold::fold_stmt(
                         self,
-                        syn::Stmt::Expr(expand_match_byte(&mac.tts)),
+                        syn::Stmt::Expr(expand_match_byte(&mac.tokens)),
                     );
                 }
             }
             _ => {}
         }
 
         syn::fold::fold_stmt(self, stmt)
     }
 
     fn fold_expr(&mut self, expr: syn::Expr) -> syn::Expr {
         match expr {
             syn::Expr::Macro(syn::ExprMacro { ref mac, .. }) => {
                 if mac.path == parse_quote!(match_byte) {
-                    return syn::fold::fold_expr(self, expand_match_byte(&mac.tts));
+                    return syn::fold::fold_expr(self, expand_match_byte(&mac.tokens));
                 }
             }
             _ => {}
         }
 
         syn::fold::fold_expr(self, expr)
     }
 }
--- a/third_party/rust/cssparser/src/color.rs
+++ b/third_party/rust/cssparser/src/color.rs
@@ -525,19 +525,19 @@ pub fn parse_color_keyword(ident: &str) 
         }
     }
     keyword(ident).cloned().ok_or(())
 }
 
 #[inline]
 fn from_hex(c: u8) -> Result<u8, ()> {
     match c {
-        b'0'...b'9' => Ok(c - b'0'),
-        b'a'...b'f' => Ok(c - b'a' + 10),
-        b'A'...b'F' => Ok(c - b'A' + 10),
+        b'0'..=b'9' => Ok(c - b'0'),
+        b'a'..=b'f' => Ok(c - b'a' + 10),
+        b'A'..=b'F' => Ok(c - b'A' + 10),
         _ => Err(()),
     }
 }
 
 fn clamp_unit_f32(val: f32) -> u8 {
     // Whilst scaling by 256 and flooring would provide
     // an equal distribution of integers to percentage inputs,
     // this is not what Gecko does so we instead multiply by 255
--- a/third_party/rust/cssparser/src/lib.rs
+++ b/third_party/rust/cssparser/src/lib.rs
@@ -77,17 +77,17 @@ extern crate matches;
 extern crate procedural_masquerade;
 #[cfg(test)]
 extern crate difference;
 #[cfg(test)]
 extern crate encoding_rs;
 #[doc(hidden)]
 pub extern crate phf as _internal__phf;
 #[cfg(test)]
-extern crate rustc_serialize;
+extern crate serde_json;
 #[cfg(feature = "serde")]
 extern crate serde;
 #[cfg(feature = "heapsize")]
 #[macro_use]
 extern crate heapsize;
 extern crate smallvec;
 
 pub use cssparser_macros::*;
--- a/third_party/rust/cssparser/src/macros.rs
+++ b/third_party/rust/cssparser/src/macros.rs
@@ -105,37 +105,63 @@ macro_rules! ascii_case_insensitive_phf_
 ///
 /// Define a local variable named `$output`
 /// and assign it the result of calling `_internal__to_lowercase`
 /// with a stack-allocated buffer of length `$BUFFER_SIZE`.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! cssparser_internal__to_lowercase {
     ($input: expr, $BUFFER_SIZE: expr => $output: ident) => {
-        // mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
+        let mut buffer;
+        // Safety: `buffer` is only used in `_internal__to_lowercase`,
         // which initializes with `copy_from_slice` the part of the buffer it uses,
         // before it uses it.
         #[allow(unsafe_code)]
-        let mut buffer: [u8; $BUFFER_SIZE] = unsafe { ::std::mem::uninitialized() };
+        let buffer = unsafe { cssparser_internal__uninit!(buffer, $BUFFER_SIZE) };
         let input: &str = $input;
-        let $output = $crate::_internal__to_lowercase(&mut buffer, input);
+        let $output = $crate::_internal__to_lowercase(buffer, input);
     };
 }
 
+#[cfg(has_std__mem__MaybeUninit)]
+#[macro_export]
+#[doc(hidden)]
+macro_rules! cssparser_internal__uninit {
+    ($buffer: ident, $BUFFER_SIZE: expr) => {
+        {
+            $buffer = ::std::mem::MaybeUninit::<[u8; $BUFFER_SIZE]>::uninit();
+            &mut *($buffer.as_mut_ptr())
+        }
+    }
+}
+
+// FIXME: remove this when we require Rust 1.36
+#[cfg(not(has_std__mem__MaybeUninit))]
+#[macro_export]
+#[doc(hidden)]
+macro_rules! cssparser_internal__uninit {
+    ($buffer: ident, $BUFFER_SIZE: expr) => {
+        {
+            $buffer = ::std::mem::uninitialized::<[u8; $BUFFER_SIZE]>();
+            &mut $buffer
+        }
+    }
+}
+
 /// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
 ///
 /// **This function is not part of the public API. It can change or be removed between any verisons.**
 ///
 /// If `input` is larger than buffer, return `None`.
 /// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
 #[doc(hidden)]
 #[allow(non_snake_case)]
 pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
     if let Some(buffer) = buffer.get_mut(..input.len()) {
-        if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
+        if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'..=b'Z')) {
             buffer.copy_from_slice(input.as_bytes());
             buffer[first_uppercase..].make_ascii_lowercase();
             // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
             // then lowercased (which preserves UTF-8 well-formedness)
             unsafe { Some(::std::str::from_utf8_unchecked(buffer)) }
         } else {
             // Input is already lower-case
             Some(input)
--- a/third_party/rust/cssparser/src/nth.rs
+++ b/third_party/rust/cssparser/src/nth.rs
@@ -100,17 +100,17 @@ fn parse_signless_b<'i, 't>(
         token => Err(input.new_basic_unexpected_token_error(token)),
     }
 }
 
 fn parse_n_dash_digits(string: &str) -> Result<i32, ()> {
     let bytes = string.as_bytes();
     if bytes.len() >= 3
         && bytes[..2].eq_ignore_ascii_case(b"n-")
-        && bytes[2..].iter().all(|&c| matches!(c, b'0'...b'9'))
+        && bytes[2..].iter().all(|&c| matches!(c, b'0'..=b'9'))
     {
         Ok(parse_number_saturate(&string[1..]).unwrap()) // Include the minus sign
     } else {
         Err(())
     }
 }
 
 fn parse_number_saturate(string: &str) -> Result<i32, ()> {
--- a/third_party/rust/cssparser/src/serializer.rs
+++ b/third_party/rust/cssparser/src/serializer.rs
@@ -202,17 +202,17 @@ where
         serialize_name(&value[2..], dest)
     } else if value == "-" {
         dest.write_str("\\-")
     } else {
         if value.as_bytes()[0] == b'-' {
             dest.write_str("-")?;
             value = &value[1..];
         }
-        if let digit @ b'0'...b'9' = value.as_bytes()[0] {
+        if let digit @ b'0'..=b'9' = value.as_bytes()[0] {
             hex_escape(digit, dest)?;
             value = &value[1..];
         }
         serialize_name(value, dest)
     }
 }
 
 /// Write a CSS name, like a custom property name.
@@ -221,17 +221,17 @@ where
 /// consider using `serialize_identifier`.
 pub fn serialize_name<W>(value: &str, dest: &mut W) -> fmt::Result
 where
     W: fmt::Write,
 {
     let mut chunk_start = 0;
     for (i, b) in value.bytes().enumerate() {
         let escaped = match b {
-            b'0'...b'9' | b'A'...b'Z' | b'a'...b'z' | b'_' | b'-' => continue,
+            b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'_' | b'-' => continue,
             _ if !b.is_ascii() => continue,
             b'\0' => Some("\u{FFFD}"),
             _ => None,
         };
         dest.write_str(&value[chunk_start..i])?;
         if let Some(escaped) = escaped {
             dest.write_str(escaped)?;
         } else if (b >= b'\x01' && b <= b'\x1F') || b == b'\x7F' {
@@ -246,17 +246,17 @@ where
 
 fn serialize_unquoted_url<W>(value: &str, dest: &mut W) -> fmt::Result
 where
     W: fmt::Write,
 {
     let mut chunk_start = 0;
     for (i, b) in value.bytes().enumerate() {
         let hex = match b {
-            b'\0'...b' ' | b'\x7F' => true,
+            b'\0'..=b' ' | b'\x7F' => true,
             b'(' | b')' | b'"' | b'\'' | b'\\' => false,
             _ => continue,
         };
         dest.write_str(&value[chunk_start..i])?;
         if hex {
             hex_escape(b, dest)?;
         } else {
             char_escape(b, dest)?;
@@ -313,17 +313,17 @@ where
 {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         let mut chunk_start = 0;
         for (i, b) in s.bytes().enumerate() {
             let escaped = match b {
                 b'"' => Some("\\\""),
                 b'\\' => Some("\\\\"),
                 b'\0' => Some("\u{FFFD}"),
-                b'\x01'...b'\x1F' | b'\x7F' => None,
+                b'\x01'..=b'\x1F' | b'\x7F' => None,
                 _ => continue,
             };
             self.inner.write_str(&s[chunk_start..i])?;
             match escaped {
                 Some(x) => self.inner.write_str(x)?,
                 None => hex_escape(b, self.inner)?,
             };
             chunk_start = i + 1;
--- a/third_party/rust/cssparser/src/tests.rs
+++ b/third_party/rust/cssparser/src/tests.rs
@@ -1,144 +1,143 @@
 /* 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/. */
 
 #[cfg(feature = "bench")]
 extern crate test;
 
 use encoding_rs;
-use rustc_serialize::json::{self, Json, ToJson};
+use serde_json::{self, Value, json, Map};
 
 #[cfg(feature = "bench")]
 use self::test::Bencher;
 
 use super::{
     parse_important, parse_nth, parse_one_declaration, parse_one_rule, stylesheet_encoding,
     AtRuleParser, AtRuleType, BasicParseError, BasicParseErrorKind, Color, CowRcStr,
     DeclarationListParser, DeclarationParser, Delimiter, EncodingSupport, ParseError,
     ParseErrorKind, Parser, ParserInput, QualifiedRuleParser, RuleListParser, SourceLocation,
     ToCss, Token, TokenSerializationType, UnicodeRange, RGBA,
 };
 
 macro_rules! JArray {
     ($($e: expr,)*) => { JArray![ $( $e ),* ] };
-    ($($e: expr),*) => { Json::Array(vec!( $( $e.to_json() ),* )) }
+    ($($e: expr),*) => { Value::Array(vec!( $( $e.to_json() ),* )) }
 }
 
-fn almost_equals(a: &Json, b: &Json) -> bool {
+fn almost_equals(a: &Value, b: &Value) -> bool {
     match (a, b) {
-        (&Json::I64(a), _) => almost_equals(&Json::F64(a as f64), b),
-        (&Json::U64(a), _) => almost_equals(&Json::F64(a as f64), b),
-        (_, &Json::I64(b)) => almost_equals(a, &Json::F64(b as f64)),
-        (_, &Json::U64(b)) => almost_equals(a, &Json::F64(b as f64)),
+        (&Value::Number(ref a), &Value::Number(ref b)) => {
+            let a = a.as_f64().unwrap();
+            let b = b.as_f64().unwrap();
+            (a - b).abs() <= a.abs() * 1e-6
+        },
 
-        (&Json::F64(a), &Json::F64(b)) => (a - b).abs() <= a.abs() * 1e-6,
-
-        (&Json::Boolean(a), &Json::Boolean(b)) => a == b,
-        (&Json::String(ref a), &Json::String(ref b)) => a == b,
-        (&Json::Array(ref a), &Json::Array(ref b)) => {
+        (&Value::Bool(a), &Value::Bool(b)) => a == b,
+        (&Value::String(ref a), &Value::String(ref b)) => a == b,
+        (&Value::Array(ref a), &Value::Array(ref b)) => {
             a.len() == b.len()
                 && a.iter()
                     .zip(b.iter())
                     .all(|(ref a, ref b)| almost_equals(*a, *b))
         }
-        (&Json::Object(_), &Json::Object(_)) => panic!("Not implemented"),
-        (&Json::Null, &Json::Null) => true,
+        (&Value::Object(_), &Value::Object(_)) => panic!("Not implemented"),
+        (&Value::Null, &Value::Null) => true,
         _ => false,
     }
 }
 
-fn normalize(json: &mut Json) {
+fn normalize(json: &mut Value) {
     match *json {
-        Json::Array(ref mut list) => {
+        Value::Array(ref mut list) => {
             for item in list.iter_mut() {
                 normalize(item)