Merge mozilla-central to mozilla-beta. a=same-version-merge l10n=same-version-merge CLOSED TREE DEVEDITION_70_0b2_BUILD1
authorRazvan Maries <rmaries@mozilla.com>
Thu, 29 Aug 2019 18:21:14 +0300
changeset 554326 e9268d2f323358d07eaf690515108508d6d7588e
parent 553609 2be1512798c3b5624558765eb5b4b2943431328e (current diff)
parent 554325 23824765c6aa026ccc3e3aea1c851c07ab8937ee (diff)
child 554327 e6aac3ce7a0b45db418f3aa9cddb278461e23ed8
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssame-version-merge
milestone70.0
Merge mozilla-central to mozilla-beta. a=same-version-merge l10n=same-version-merge CLOSED TREE
.cargo/.gitignore
browser/actors/SubframeCrashChild.jsm
browser/actors/SubframeCrashParent.jsm
browser/components/aboutlogins/content/icons/delete.svg
browser/components/aboutlogins/tests/unit/test_getBreachesForLogins.js
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser-remote.ini
browser/components/extensions/test/xpcshell/head_remote.js
browser/components/extensions/test/xpcshell/xpcshell-common.ini
browser/components/extensions/test/xpcshell/xpcshell-remote.ini
build/build-clang/r355141-arm64-cfg.patch
devtools/client/application/src/components/manifest/ManifestItemIcon.js
devtools/client/application/src/components/manifest/ManifestItemText.js
devtools/client/application/src/components/manifest/ManifestItemWarning.js
devtools/client/application/src/components/manifest/ManifestView.css
devtools/client/application/src/components/manifest/ManifestView.js
devtools/client/application/src/components/manifest/ManifestViewEmpty.js
devtools/client/application/test/components/manifest/__snapshots__/components_application_panel-ManifestView.test.js.snap
devtools/client/application/test/components/manifest/__snapshots__/components_application_panel-ManifestViewEmpty.test.js.snap
devtools/client/application/test/components/manifest/components_application_panel-ManifestView.test.js
devtools/client/application/test/components/manifest/components_application_panel-ManifestViewEmpty.test.js
devtools/server/actors/addon/addons.js
devtools/server/actors/addon/webextension.js
devtools/server/actors/targets/webextension-proxy.js
devtools/server/tests/unit/test_addons_actor.js
devtools/shared/specs/addon/webextension.js
netwerk/system/linux/nsNotifyAddrListener_Linux.cpp
netwerk/system/linux/nsNotifyAddrListener_Linux.h
taskcluster/scripts/misc/build-geckodriver.sh
taskcluster/scripts/misc/osx-cross-linker
testing/awsy/awsy/alternate-server-replay.py
testing/web-platform/meta/bluetooth/characteristic/getDescriptor/gen-characteristic-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptor/gen-descriptor-get-same-object.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptor/gen-service-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptors/gen-descriptor-get-same-object.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptors/gen-service-is-removed-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/getDescriptors/gen-service-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/readValue/gen-characteristic-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/startNotifications/gen-characteristic-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/characteristic/writeValue/gen-characteristic-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/descriptor/readValue/gen-service-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/descriptor/readValue/read-succeeds.https.html.ini
testing/web-platform/meta/bluetooth/descriptor/writeValue/buffer-is-detached.https.html.ini
testing/web-platform/meta/bluetooth/descriptor/writeValue/gen-service-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/device/gattserverdisconnected-event/disconnected.https.html.ini
testing/web-platform/meta/bluetooth/device/gattserverdisconnected-event/disconnected_gc.https.html.ini
testing/web-platform/meta/bluetooth/device/gattserverdisconnected-event/one-event-per-disconnection.https.html.ini
testing/web-platform/meta/bluetooth/device/gattserverdisconnected-event/reconnect-during-disconnected-event.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-disconnect-called-before.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-disconnected-device.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-get-same-object.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-invalid-service-name.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-no-permission-present-service.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryService/gen-service-not-found.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-disconnected-device.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-get-same-object.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-invalid-service-name.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-blocklisted-characteristic.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-characteristic-not-found.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-error.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-get-same-object.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-invalid-characteristic-name.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-reconnect-during.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristic/gen-service-is-removed.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-blocklisted-characteristic-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-characteristic-not-found-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-get-same-object-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-get-same-object.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-invalid-characteristic-name.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-reconnect-during-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-reconnect-during.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-service-is-removed-with-uuid.https.html.ini
testing/web-platform/meta/bluetooth/service/getCharacteristics/gen-service-is-removed.https.html.ini
testing/web-platform/meta/css/css-box/parsing/padding-invalid.html.ini
testing/web-platform/meta/css/css-flexbox/auto-margins-001.html.ini
testing/web-platform/meta/css/css-layout-api/auto-block-size-absolute.https.html.ini
testing/web-platform/meta/css/css-layout-api/auto-block-size-flex.https.html.ini
testing/web-platform/meta/css/css-layout-api/auto-block-size-floats.https.html.ini
testing/web-platform/meta/css/css-layout-api/auto-block-size-inflow.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-absolute-left-right-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-absolute-none.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-absolute-top-bottom.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-block-none-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-block-none.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-fixed-max.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-fixed-min.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-fixed-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-fixed.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-basis-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-column-basis.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-column-grow.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-column-none.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-column-stretch-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-grow-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-none.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-percentage-indefinite.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-stretch-max.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-flex-stretch.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-grid-none.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-grid-stretch-max.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-grid-stretch.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-grid-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-percentage-indefinite.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-percentage-quirks-mode.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-percentage-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-percentage.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-block-size-quirky-body.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-absolute-left-right.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-absolute-top-bottom-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-block-auto-avoid-floats-vlr.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-block-auto-avoid-floats.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-block-auto-vlr.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-block-auto.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-fixed-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-fixed.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-flex-grow-column-vrl.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-flex-grow.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-grid.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-percentage-vlr.https.html.ini
testing/web-platform/meta/css/css-layout-api/constraints-fixed-inline-size-percentage.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-constructor-error.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-error.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-invalid-child.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-invalid-fragment.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-no-promise.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-return.https.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-unresolved-promise.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-absolute.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-before-after.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-fixed.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-float.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-inflow.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-inlines-dynamic.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-inlines.https.html.ini
testing/web-platform/meta/css/css-layout-api/layout-child-text.https.html.ini
testing/web-platform/meta/css/css-layout-api/position-fragment-htb-ltr.https.html.ini
testing/web-platform/meta/css/css-layout-api/position-fragment-htb-rtl.https.html.ini
testing/web-platform/meta/css/css-layout-api/position-fragment-vlr-ltr.https.html.ini
testing/web-platform/meta/css/css-layout-api/position-fragment-vlr-rtl.https.html.ini
testing/web-platform/meta/css/css-layout-api/position-fragment-vrl-ltr.https.html.ini
testing/web-platform/meta/css/css-layout-api/position-fragment-vrl-rtl.https.html.ini
testing/web-platform/meta/css/css-tables/html5-table-formatting-3.html.ini
testing/web-platform/meta/css/css-transitions/transitions-animatable-properties-01.html.ini
testing/web-platform/meta/css/css-writing-modes/relpos-inline-overflowing-block-vrl.html.ini
testing/web-platform/meta/html/semantics/forms/autofocus/no-cross-origin-autofocus.sub.html.ini
testing/web-platform/meta/mathml/relations/css-styling/writing-mode/writing-mode-001.html.ini
testing/web-platform/meta/speech-api/SpeechSynthesis-speak-twice.html.ini
testing/web-platform/meta/trusted-types/TrustedTypePolicy-exposed.tentative.html.ini
testing/web-platform/meta/trusted-types/TrustedTypePolicyFactory-createPolicy-defaultTests.tentative.html.ini
testing/web-platform/meta/trusted-types/TrustedTypePolicyFactory-createPolicy-exposedTests.tentative.html.ini
testing/web-platform/tests/bluetooth/characteristic/getDescriptor/gen-characteristic-is-removed.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptor/gen-descriptor-get-same-object.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptor/gen-service-is-removed.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed-with-uuid.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptors/gen-descriptor-get-same-object.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptors/gen-service-is-removed-with-uuid.https.html
testing/web-platform/tests/bluetooth/characteristic/getDescriptors/gen-service-is-removed.https.html
testing/web-platform/tests/bluetooth/characteristic/readValue/gen-characteristic-is-removed.https.html
testing/web-platform/tests/bluetooth/characteristic/startNotifications/gen-characteristic-is-removed.https.html
testing/web-platform/tests/bluetooth/characteristic/writeValue/gen-characteristic-is-removed.https.html
testing/web-platform/tests/bluetooth/descriptor/readValue/gen-service-is-removed.https.html
testing/web-platform/tests/bluetooth/descriptor/readValue/read-succeeds.https.html
testing/web-platform/tests/bluetooth/descriptor/writeValue/buffer-is-detached.https.html
testing/web-platform/tests/bluetooth/descriptor/writeValue/gen-service-is-removed.https.html
testing/web-platform/tests/bluetooth/device/gattserverdisconnected-event/disconnected.https.html
testing/web-platform/tests/bluetooth/device/gattserverdisconnected-event/disconnected_gc.https.html
testing/web-platform/tests/bluetooth/device/gattserverdisconnected-event/one-event-per-disconnection.https.html
testing/web-platform/tests/bluetooth/device/gattserverdisconnected-event/reconnect-during-disconnected-event.https.html
testing/web-platform/tests/bluetooth/script-tests/base_test_html.template
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnected-device.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-same-object.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-invalid-service-name.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-service-not-found.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.https.html
testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-blocklisted-characteristic.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-characteristic-not-found.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-error.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-get-same-object.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-invalid-characteristic-name.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-reconnect-during.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristic/gen-service-is-removed.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-blocklisted-characteristic-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-characteristic-not-found-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-get-same-object-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-get-same-object.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-invalid-characteristic-name.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-reconnect-during-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-reconnect-during.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-service-is-removed-with-uuid.https.html
testing/web-platform/tests/bluetooth/service/getCharacteristics/gen-service-is-removed.https.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-absolute-ref.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-absolute.https.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-flex-ref.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-flex.https.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-floats-ref.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-floats.https.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-inflow-ref.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-inflow.https.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-negative-ref.html
testing/web-platform/tests/css/css-layout-api/auto-block-size-negative.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-absolute-left-right-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-absolute-none.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-absolute-top-bottom.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-block-none-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-block-none.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-fixed-max.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-fixed-min.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-fixed-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-fixed.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-basis-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-column-basis.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-column-grow.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-column-none.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-column-stretch-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-grow-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-none.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-percentage-indefinite.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-stretch-max.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-flex-stretch.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-grid-none.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-grid-stretch-max.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-grid-stretch.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-grid-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-percentage-indefinite.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-percentage-quirks-mode.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-percentage-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-percentage.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-block-size-quirky-body.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-absolute-left-right.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-absolute-top-bottom-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-block-auto-avoid-floats-vlr.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-block-auto-avoid-floats.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-block-auto-vlr.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-block-auto.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-fixed-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-fixed.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-flex-grow-column-vrl.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-flex-grow.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-grid.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-percentage-vlr.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-percentage.https.html
testing/web-platform/tests/css/css-layout-api/constraints-fixed-inline-size-ref.html
testing/web-platform/tests/css/css-layout-api/fallback-constructor-error.https.html
testing/web-platform/tests/css/css-layout-api/fallback-layout-error.https.html
testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-child.https.html
testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-fragment.https.html
testing/web-platform/tests/css/css-layout-api/fallback-layout-no-promise.https.html
testing/web-platform/tests/css/css-layout-api/fallback-layout-return.https.html
testing/web-platform/tests/css/css-layout-api/fallback-layout-unresolved-promise.https.html
testing/web-platform/tests/css/css-layout-api/fallback-ref.html
testing/web-platform/tests/css/css-layout-api/layout-child-absolute.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-before-after.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-fixed.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-float.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-inflow.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-inlines-dynamic.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-inlines.https.html
testing/web-platform/tests/css/css-layout-api/layout-child-text.https.html
testing/web-platform/tests/css/css-layout-api/position-fragment-htb-ltr.https.html
testing/web-platform/tests/css/css-layout-api/position-fragment-htb-rtl.https.html
testing/web-platform/tests/css/css-layout-api/position-fragment-ref.html
testing/web-platform/tests/css/css-layout-api/position-fragment-vlr-ltr.https.html
testing/web-platform/tests/css/css-layout-api/position-fragment-vlr-rtl.https.html
testing/web-platform/tests/css/css-layout-api/position-fragment-vrl-ltr.https.html
testing/web-platform/tests/css/css-layout-api/position-fragment-vrl-rtl.https.html
testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-block-size-quirky-body-iframe.html
testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-block-size.js
testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-inline-size.js
testing/web-platform/tests/css/css-layout-api/support/layout-child-sizes-worklet.js
testing/web-platform/tests/css/css-layout-api/support/layout-child-worklet.js
testing/web-platform/tests/css/css-layout-api/support/layout-position-child-worklet.js
testing/web-platform/tests/css/css-transforms/animation/resources/interpolation-testcommon.js
testing/web-platform/tests/css/css-transitions/transitions-animatable-properties-01.html
testing/web-platform/tests/html/interaction/focus/document-level-focus-apis/test.html
testing/web-platform/tests/html/semantics/forms/autofocus/no-cross-origin-autofocus.sub.html
testing/web-platform/tests/intersection-observer/cross-origin-iframe.html
testing/web-platform/tests/trusted-types/TrustedTypePolicy-exposed.tentative.html
testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-defaultTests.tentative.html
testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-exposedTests.tentative.html
testing/web-platform/tests/websockets/handlers/delayed-passive-close_wsh.py
third_party/rust/bzip2-sys/.cargo-checksum.json
third_party/rust/bzip2-sys/Cargo.toml
third_party/rust/bzip2-sys/build.rs
third_party/rust/bzip2-sys/bzip2-1.0.6/CHANGES
third_party/rust/bzip2-sys/bzip2-1.0.6/LICENSE
third_party/rust/bzip2-sys/bzip2-1.0.6/Makefile
third_party/rust/bzip2-sys/bzip2-1.0.6/Makefile-libbz2_so
third_party/rust/bzip2-sys/bzip2-1.0.6/README
third_party/rust/bzip2-sys/bzip2-1.0.6/README.COMPILATION.PROBLEMS
third_party/rust/bzip2-sys/bzip2-1.0.6/README.XML.STUFF
third_party/rust/bzip2-sys/bzip2-1.0.6/blocksort.c
third_party/rust/bzip2-sys/bzip2-1.0.6/bz-common.xsl
third_party/rust/bzip2-sys/bzip2-1.0.6/bz-fo.xsl
third_party/rust/bzip2-sys/bzip2-1.0.6/bz-html.xsl
third_party/rust/bzip2-sys/bzip2-1.0.6/bzdiff
third_party/rust/bzip2-sys/bzip2-1.0.6/bzdiff.1
third_party/rust/bzip2-sys/bzip2-1.0.6/bzgrep
third_party/rust/bzip2-sys/bzip2-1.0.6/bzgrep.1
third_party/rust/bzip2-sys/bzip2-1.0.6/bzip.css
third_party/rust/bzip2-sys/bzip2-1.0.6/bzip2.1
third_party/rust/bzip2-sys/bzip2-1.0.6/bzip2.1.preformatted
third_party/rust/bzip2-sys/bzip2-1.0.6/bzip2.c
third_party/rust/bzip2-sys/bzip2-1.0.6/bzip2.txt
third_party/rust/bzip2-sys/bzip2-1.0.6/bzip2recover.c
third_party/rust/bzip2-sys/bzip2-1.0.6/bzlib.c
third_party/rust/bzip2-sys/bzip2-1.0.6/bzlib.h
third_party/rust/bzip2-sys/bzip2-1.0.6/bzlib_private.h
third_party/rust/bzip2-sys/bzip2-1.0.6/bzmore
third_party/rust/bzip2-sys/bzip2-1.0.6/bzmore.1
third_party/rust/bzip2-sys/bzip2-1.0.6/compress.c
third_party/rust/bzip2-sys/bzip2-1.0.6/crctable.c
third_party/rust/bzip2-sys/bzip2-1.0.6/decompress.c
third_party/rust/bzip2-sys/bzip2-1.0.6/dlltest.c
third_party/rust/bzip2-sys/bzip2-1.0.6/dlltest.dsp
third_party/rust/bzip2-sys/bzip2-1.0.6/entities.xml
third_party/rust/bzip2-sys/bzip2-1.0.6/format.pl
third_party/rust/bzip2-sys/bzip2-1.0.6/huffman.c
third_party/rust/bzip2-sys/bzip2-1.0.6/libbz2.def
third_party/rust/bzip2-sys/bzip2-1.0.6/libbz2.dsp
third_party/rust/bzip2-sys/bzip2-1.0.6/makefile.msc
third_party/rust/bzip2-sys/bzip2-1.0.6/manual.html
third_party/rust/bzip2-sys/bzip2-1.0.6/manual.ps
third_party/rust/bzip2-sys/bzip2-1.0.6/manual.xml
third_party/rust/bzip2-sys/bzip2-1.0.6/mk251.c
third_party/rust/bzip2-sys/bzip2-1.0.6/randtable.c
third_party/rust/bzip2-sys/bzip2-1.0.6/sample1.bz2
third_party/rust/bzip2-sys/bzip2-1.0.6/sample1.ref
third_party/rust/bzip2-sys/bzip2-1.0.6/sample2.bz2
third_party/rust/bzip2-sys/bzip2-1.0.6/sample2.ref
third_party/rust/bzip2-sys/bzip2-1.0.6/sample3.bz2
third_party/rust/bzip2-sys/bzip2-1.0.6/sample3.ref
third_party/rust/bzip2-sys/bzip2-1.0.6/spewG.c
third_party/rust/bzip2-sys/bzip2-1.0.6/unzcrash.c
third_party/rust/bzip2-sys/bzip2-1.0.6/words0
third_party/rust/bzip2-sys/bzip2-1.0.6/words1
third_party/rust/bzip2-sys/bzip2-1.0.6/words2
third_party/rust/bzip2-sys/bzip2-1.0.6/words3
third_party/rust/bzip2-sys/bzip2-1.0.6/xmlproc.sh
third_party/rust/bzip2-sys/lib.rs
third_party/rust/bzip2/.cargo-checksum.json
third_party/rust/bzip2/Cargo.toml
third_party/rust/bzip2/LICENSE-APACHE
third_party/rust/bzip2/LICENSE-MIT
third_party/rust/bzip2/README.md
third_party/rust/bzip2/appveyor.yml
third_party/rust/bzip2/src/bufread.rs
third_party/rust/bzip2/src/lib.rs
third_party/rust/bzip2/src/mem.rs
third_party/rust/bzip2/src/read.rs
third_party/rust/bzip2/src/write.rs
third_party/rust/bzip2/tests/tokio.rs
toolkit/components/antitracking/test/browser/browser_storageAccessPrivateWindow.js
toolkit/modules/WebProgressChild.jsm
deleted file mode 100644
--- a/.cargo/.gitignore
+++ /dev/null
@@ -1,1 +0,0 @@
-config
copy from .cargo/config.in
copy to .cargo/config
--- a/.cargo/config.in
+++ b/.cargo/config
@@ -1,45 +1,41 @@
-# Note: if you add more configure substitutions here with required values
-# you will also need to fix the sed commands in:
-# taskcluster/scripts/builder/build-sm-mozjs-crate.sh
-# taskcluster/scripts/builder/build-sm-rust-bindings.sh
+# This file contains vendoring instructions for cargo.
+# It was generated by `mach vendor rust`.
+# Please do not edit.
 
-[source.crates-io]
-registry = 'https://github.com/rust-lang/crates.io-index'
-replace-with = 'vendored-sources'
-
-[source."https://github.com/servo/serde"]
-git = "https://github.com/servo/serde"
-branch = "deserialize_from_enums10"
+[source."https://github.com/hsivonen/packed_simd"]
+branch = "rust_1_32"
+git = "https://github.com/hsivonen/packed_simd"
 replace-with = "vendored-sources"
 
-[source."https://github.com/retep998/winapi-rs"]
+[source."https://github.com/froydnj/winapi-rs"]
+branch = "aarch64"
 git = "https://github.com/froydnj/winapi-rs"
-branch = "aarch64"
 replace-with = "vendored-sources"
 
-[source."https://github.com/rust-lang-nursery/packed_simd"]
-git = "https://github.com/hsivonen/packed_simd"
-branch = "rust_1_32"
+[source."https://github.com/alexcrichton/mio-named-pipes"]
+branch = "master"
+git = "https://github.com/alexcrichton/mio-named-pipes"
+replace-with = "vendored-sources"
+
+[source."https://github.com/NikVolf/tokio-named-pipes"]
+branch = "stable"
+git = "https://github.com/NikVolf/tokio-named-pipes"
 replace-with = "vendored-sources"
 
 [source."https://github.com/CraneStation/Cranelift"]
 git = "https://github.com/CraneStation/Cranelift"
-rev = "72b97fcb398537c6bb3ab73c45c428652321cbb6"
 replace-with = "vendored-sources"
+rev = "164f91a1f473e582e18e48d056c51787d9a1c24d"
 
-[source."https://github.com/ChunMinChang/coreaudio-sys"]
-git = "https://github.com/ChunMinChang/coreaudio-sys"
-branch = "gecko-build"
+[source.crates-io]
 replace-with = "vendored-sources"
 
-[source."https://github.com/alexcrichton/mio-named-pipes"]
-git = "https://github.com/alexcrichton/mio-named-pipes"
-replace-with = "vendored-sources"
-
-[source."https://github.com/NikVolf/tokio-named-pipes"]
-git = "https://github.com/NikVolf/tokio-named-pipes"
-branch = "stable"
-replace-with = "vendored-sources"
-
+# Take advantage of the fact that cargo will treat lines starting with #
+# as comments to add preprocessing directives for when this file is included
+# from .cargo/config.in.
+#define REPLACE_NAME vendored-sources
+#define VENDORED_DIRECTORY third_party/rust
+#ifndef top_srcdir
 [source.vendored-sources]
-directory = '@top_srcdir@/third_party/rust'
+directory = "third_party/rust"
+#endif
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -1,45 +1,10 @@
-# Note: if you add more configure substitutions here with required values
-# you will also need to fix the sed commands in:
-# taskcluster/scripts/builder/build-sm-mozjs-crate.sh
-# taskcluster/scripts/builder/build-sm-rust-bindings.sh
-
-[source.crates-io]
-registry = 'https://github.com/rust-lang/crates.io-index'
-replace-with = 'vendored-sources'
+# Please do not edit this file.
 
-[source."https://github.com/servo/serde"]
-git = "https://github.com/servo/serde"
-branch = "deserialize_from_enums10"
-replace-with = "vendored-sources"
-
-[source."https://github.com/retep998/winapi-rs"]
-git = "https://github.com/froydnj/winapi-rs"
-branch = "aarch64"
-replace-with = "vendored-sources"
+# Note: this file is only really needed when objdir is not a subdirectory of
+# the top source directory.
 
-[source."https://github.com/rust-lang-nursery/packed_simd"]
-git = "https://github.com/hsivonen/packed_simd"
-branch = "rust_1_32"
-replace-with = "vendored-sources"
-
-[source."https://github.com/CraneStation/Cranelift"]
-git = "https://github.com/CraneStation/Cranelift"
-rev = "72b97fcb398537c6bb3ab73c45c428652321cbb6"
-replace-with = "vendored-sources"
+#include config
+#filter substitution
 
-[source."https://github.com/ChunMinChang/coreaudio-sys"]
-git = "https://github.com/ChunMinChang/coreaudio-sys"
-branch = "gecko-build"
-replace-with = "vendored-sources"
-
-[source."https://github.com/alexcrichton/mio-named-pipes"]
-git = "https://github.com/alexcrichton/mio-named-pipes"
-replace-with = "vendored-sources"
-
-[source."https://github.com/NikVolf/tokio-named-pipes"]
-git = "https://github.com/NikVolf/tokio-named-pipes"
-branch = "stable"
-replace-with = "vendored-sources"
-
-[source.vendored-sources]
-directory = '@top_srcdir@/third_party/rust'
+[source.@REPLACE_NAME@]
+directory = "@top_srcdir@/@VENDORED_DIRECTORY@"
--- a/.cron.yml
+++ b/.cron.yml
@@ -73,17 +73,16 @@ jobs:
       job:
           type: decision-task
           treeherder-symbol: ship_geckoview
           target-tasks-method: ship_geckoview
           include-push-tasks: true
       run-on-projects:
           - mozilla-central
           - mozilla-beta
-          - mozilla-release
       when:
           by-project:
               mozilla-central: [{hour: 10, minute: 0}]
               mozilla-beta:
                   - {weekday: 'Monday', hour: 10, minute: 0}
                   - {weekday: 'Thursday', hour: 10, minute: 0}
 
     - name: tp6m-fennec-v64
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -78,17 +78,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "audio_thread_priority"
-version = "0.18.0"
+version = "0.19.1"
 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)",
  "dbus 0.6.4 (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)",
  "mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
@@ -120,31 +120,31 @@ dependencies = [
  "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "audioipc-client"
 version = "0.4.0"
 dependencies = [
- "audio_thread_priority 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc 0.2.4",
  "cubeb-backend 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures-cpupool 0.1.8 (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)",
  "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "audioipc-server"
 version = "0.2.3"
 dependencies = [
- "audio_thread_priority 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc 0.2.4",
  "cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.23 (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)",
  "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -193,18 +193,18 @@ dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "baldrdash"
 version = "0.1.0"
 dependencies = [
  "bindgen 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-codegen 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
- "cranelift-wasm 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
+ "cranelift-codegen 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
+ "cranelift-wasm 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "base64"
 version = "0.9.3"
@@ -380,17 +380,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "bookmark_sync"
 version = "0.1.0"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "dogear 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dogear 0.3.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)",
  "moz_task 0.1.0",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "storage 0.1.0",
  "storage_variant 0.1.0",
  "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -422,34 +422,16 @@ name = "bytes"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "bzip2"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bzip2-sys 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)",
-]
-
-[[package]]
-name = "bzip2-sys"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "cc"
 version = "1.0.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cert_storage"
 version = "0.0.1"
 dependencies = [
@@ -623,71 +605,71 @@ name = "cose-c"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.38.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6#72b97fcb398537c6bb3ab73c45c428652321cbb6"
-dependencies = [
- "cranelift-entity 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
+version = "0.40.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d#164f91a1f473e582e18e48d056c51787d9a1c24d"
+dependencies = [
+ "cranelift-entity 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.38.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6#72b97fcb398537c6bb3ab73c45c428652321cbb6"
-dependencies = [
- "cranelift-bforest 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
- "cranelift-codegen-meta 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
- "cranelift-entity 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
+version = "0.40.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d#164f91a1f473e582e18e48d056c51787d9a1c24d"
+dependencies = [
+ "cranelift-bforest 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
+ "cranelift-codegen-meta 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
+ "cranelift-entity 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
  "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)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.38.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6#72b97fcb398537c6bb3ab73c45c428652321cbb6"
-dependencies = [
- "cranelift-entity 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
+version = "0.40.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d#164f91a1f473e582e18e48d056c51787d9a1c24d"
+dependencies = [
+ "cranelift-entity 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.38.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6#72b97fcb398537c6bb3ab73c45c428652321cbb6"
+version = "0.40.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d#164f91a1f473e582e18e48d056c51787d9a1c24d"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.38.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6#72b97fcb398537c6bb3ab73c45c428652321cbb6"
-dependencies = [
- "cranelift-codegen 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
+version = "0.40.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d#164f91a1f473e582e18e48d056c51787d9a1c24d"
+dependencies = [
+ "cranelift-codegen 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.38.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6#72b97fcb398537c6bb3ab73c45c428652321cbb6"
-dependencies = [
- "cranelift-codegen 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
- "cranelift-entity 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
- "cranelift-frontend 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)",
+version = "0.40.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d#164f91a1f473e582e18e48d056c51787d9a1c24d"
+dependencies = [
+ "cranelift-codegen 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
+ "cranelift-entity 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
+ "cranelift-frontend 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)",
  "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)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "wasmparser 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasmparser 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crc"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -951,17 +933,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_users 0.2.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 = "dogear"
-version = "0.3.1"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "dtoa"
@@ -1251,17 +1233,17 @@ dependencies = [
  "xpcom-gtest 0.1.0",
 ]
 
 [[package]]
 name = "gkrust-shared"
 version = "0.1.0"
 dependencies = [
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "audio_thread_priority 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc-client 0.4.0",
  "audioipc-server 0.2.3",
  "authenticator 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitsdownload 0.1.0",
  "bookmark_sync 0.1.0",
  "cert_storage 0.0.1",
  "cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb-coreaudio 0.1.0",
@@ -3562,17 +3544,17 @@ dependencies = [
  "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.32.1"
+version = "0.37.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "webdriver"
 version = "0.40.1"
 dependencies = [
  "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3851,17 +3833,16 @@ dependencies = [
  "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "zip"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [metadata]
 "checksum Inflector 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1b33cd9b653730fc539c53c7b3c672d2f47108fa20c6df571fa5817178f5a14c"
@@ -3870,17 +3851,17 @@ dependencies = [
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774"
 "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
 "checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
 "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
 "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.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bf0d279b855523da1d60ea3bf145f797b92ed96190f26975730e517e7bfc7df"
+"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 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.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
 "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
 "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"
@@ -3893,18 +3874,16 @@ dependencies = [
 "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
 "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
 "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"
 "checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
 "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
 "checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
 "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
 "checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
-"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
-"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
 "checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd"
 "checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
 "checksum clang-sys 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4227269cec09f5f83ff160be12a1e9b0262dd1aa305302d5ba296c2ebd291055"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
@@ -3912,22 +3891,22 @@ dependencies = [
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
 "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5"
 "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887"
 "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
 "checksum core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62ceafe1622ffc9a332199096841d0ff9912ec8cf8f9cde01e254a7d5217cd10"
 "checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
 "checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
-"checksum cranelift-bforest 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)" = "<none>"
-"checksum cranelift-codegen 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)" = "<none>"
-"checksum cranelift-codegen-meta 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)" = "<none>"
-"checksum cranelift-entity 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)" = "<none>"
-"checksum cranelift-frontend 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)" = "<none>"
-"checksum cranelift-wasm 0.38.0 (git+https://github.com/CraneStation/Cranelift?rev=72b97fcb398537c6bb3ab73c45c428652321cbb6)" = "<none>"
+"checksum cranelift-bforest 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)" = "<none>"
+"checksum cranelift-codegen 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)" = "<none>"
+"checksum cranelift-codegen-meta 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)" = "<none>"
+"checksum cranelift-entity 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)" = "<none>"
+"checksum cranelift-frontend 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)" = "<none>"
+"checksum cranelift-wasm 0.40.0 (git+https://github.com/CraneStation/Cranelift?rev=164f91a1f473e582e18e48d056c51787d9a1c24d)" = "<none>"
 "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
 "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
 "checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7"
 "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
 "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4"
 "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"
@@ -3942,17 +3921,17 @@ dependencies = [
 "checksum darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6afc018370c3bff3eb51f89256a6bdb18b4fdcda72d577982a14954a7a0b402c"
 "checksum darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d8dac1c6f1d29a41c4712b4400f878cb4fcc4c7628f298dd75038e024998d1"
 "checksum dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e1b39f3f6aa3d4a1522c4f0f9f1e9e9167bd93740a8690874caa7cf8ce47d7"
 "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
 "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871"
 "checksum devd-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d009f166c0d9e9f9909dc751630b3a6411ab7f85a153d32d01deb364ffe52a7"
 "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
 "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
-"checksum dogear 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "251a15c9a597d70eb53cbb0c5473d8d8c6241aef615c092030ebab27fb5b26ef"
+"checksum dogear 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57cd6ee785daa898686f3e2fb4a2b1ce490fcd6d69665c857d16fb61b48f4aae"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
 "checksum encoding_c_mem 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9516d857aa9e070e02890ed3906f678ffca7fac8d82bd53c3567d96337f256"
 "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
 "checksum enum-display-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53f76eb63c4bfc6fce5000f106254701b741fc9a65ee08445fde0ff39e583f1c"
@@ -4182,17 +4161,17 @@ dependencies = [
 "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
 "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
 "checksum warp 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "33857527c63bc514452f885d0a57019f28139c58fef2b3566016ecc0d44e5d24"
-"checksum wasmparser 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22d1801de30f112ddaf665291097694ee33a36d1cb414b53a921d05b3519674a"
+"checksum wasmparser 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82dbea680995dad585289fd47889cf9614133ebfcc3bda95737ef8bdc9e11db6"
 "checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044"
 "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -58,16 +58,16 @@ codegen-units = 1
 
 [patch.crates-io]
 libudev-sys = { path = "dom/webauthn/libudev-sys" }
 winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
 packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }
 
 [patch.crates-io.cranelift-codegen]
 git = "https://github.com/CraneStation/Cranelift"
-rev = "72b97fcb398537c6bb3ab73c45c428652321cbb6"
+rev = "164f91a1f473e582e18e48d056c51787d9a1c24d"
 
 [patch.crates-io.cranelift-wasm]
 git = "https://github.com/CraneStation/Cranelift"
-rev = "72b97fcb398537c6bb3ab73c45c428652321cbb6"
+rev = "164f91a1f473e582e18e48d056c51787d9a1c24d"
 
 [patch.crates-io.coreaudio-sys]
 path = "third_party/rust/coreaudio-sys"
--- a/accessible/base/Logging.cpp
+++ b/accessible/base/Logging.cpp
@@ -353,17 +353,17 @@ static void GetDocLoadEventType(AccEvent
 }
 
 static void DescribeNode(nsINode* aNode, nsAString& aOutDescription) {
   if (!aNode) {
     aOutDescription.AppendLiteral("null");
     return;
   }
 
-  aOutDescription.AppendPrintf("%p, ", (void*)aNode);
+  aOutDescription.AppendPrintf("0x%p, ", (void*)aNode);
   aOutDescription.Append(aNode->NodeInfo()->QualifiedName());
 
   if (!aNode->IsElement()) {
     return;
   }
 
   dom::Element* elm = aNode->AsElement();
 
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -71,16 +71,17 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/StaticPrefs_ui.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/KeyboardEventBinding.h"
 #include "mozilla/dom/TreeWalker.h"
 
 using namespace mozilla;
@@ -244,17 +245,17 @@ KeyBinding Accessible::AccessKey() const
     }
 
     if (label) key = nsCoreUtils::GetAccessKeyFor(label->GetContent());
   }
 
   if (!key) return KeyBinding();
 
   // Get modifier mask. Use ui.key.generalAccessKey (unless it is -1).
-  switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
+  switch (StaticPrefs::ui_key_generalAccessKey()) {
     case -1:
       break;
     case dom::KeyboardEvent_Binding::DOM_VK_SHIFT:
       return KeyBinding(key, KeyBinding::kShift);
     case dom::KeyboardEvent_Binding::DOM_VK_CONTROL:
       return KeyBinding(key, KeyBinding::kControl);
     case dom::KeyboardEvent_Binding::DOM_VK_ALT:
       return KeyBinding(key, KeyBinding::kAlt);
@@ -270,20 +271,22 @@ KeyBinding Accessible::AccessKey() const
 
   nsCOMPtr<nsIDocShellTreeItem> treeItem(document->GetDocShell());
   if (!treeItem) return KeyBinding();
 
   nsresult rv = NS_ERROR_FAILURE;
   int32_t modifierMask = 0;
   switch (treeItem->ItemType()) {
     case nsIDocShellTreeItem::typeChrome:
-      rv = Preferences::GetInt("ui.key.chromeAccess", &modifierMask);
+      modifierMask = StaticPrefs::ui_key_chromeAccess();
+      rv = NS_OK;
       break;
     case nsIDocShellTreeItem::typeContent:
-      rv = Preferences::GetInt("ui.key.contentAccess", &modifierMask);
+      modifierMask = StaticPrefs::ui_key_contentAccess();
+      rv = NS_OK;
       break;
   }
 
   return NS_SUCCEEDED(rv) ? KeyBinding(key, modifierMask) : KeyBinding();
 }
 
 KeyBinding Accessible::KeyboardShortcut() const { return KeyBinding(); }
 
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1996,16 +1996,30 @@ void DocAccessible::ContentRemoved(nsICo
     ContentRemoved(acc);
   }
 
   dom::AllChildrenIterator iter =
       dom::AllChildrenIterator(aContentNode, nsIContent::eAllChildren, true);
   while (nsIContent* childNode = iter.GetNextChild()) {
     ContentRemoved(childNode);
   }
+
+  // If this node has a shadow root, remove its explicit children too.
+  // The host node may be removed after the shadow root was attached, and
+  // before we asynchronously prune the light DOM and construct the shadow DOM.
+  // If this is a case where the node does not have its own accessible, we will
+  // not recurse into its current children, so we need to use an
+  // ExplicitChildIterator in order to get its accessible children in the light
+  // DOM, since they are not accessible anymore via AllChildrenIterator.
+  if (aContentNode->GetShadowRoot()) {
+    dom::ExplicitChildIterator iter = dom::ExplicitChildIterator(aContentNode);
+    while (nsIContent* childNode = iter.GetNextChild()) {
+      ContentRemoved(childNode);
+    }
+  }
 }
 
 bool DocAccessible::RelocateARIAOwnedIfNeeded(nsIContent* aElement) {
   if (!aElement->HasID()) return false;
 
   AttrRelProviders* list = GetRelProviders(
       aElement->AsElement(), nsDependentAtomString(aElement->GetID()));
   if (list) {
new file mode 100644
--- /dev/null
+++ b/accessible/tests/crashtests/1572811.html
@@ -0,0 +1,9 @@
+<script>
+function go() {
+  a.style.overflow = "auto";
+}
+</script>
+<body onload=go()>
+<table id="a" background="3">
+<th>
+<textarea style="position:absolute">A</textarea>
--- a/accessible/tests/crashtests/crashtests.list
+++ b/accessible/tests/crashtests/crashtests.list
@@ -1,11 +1,12 @@
 load 448064.xhtml # This test instantiates a11y, so be careful about adding tests before it
 load chrome://reftest/content/crashtests/accessible/tests/crashtests/471493.xul
 asserts-if(!browserIsRemote,2) load 884202.html
+load 1572811.html
 load 890760.html
 load 893515.html
 load 1072792.xhtml
 load 1380199.html
 load 1402999.html
 load 1463962.html
 load 1484778.html
 load 1494707.html
--- a/accessible/tests/mochitest/treeupdate/test_delayed_removal.html
+++ b/accessible/tests/mochitest/treeupdate/test_delayed_removal.html
@@ -178,16 +178,28 @@
       getNode("c8_owned_container").hidden = true;
       await events;
 
       testAccessibleTree("c8",{ SECTION: [
         { EDITCOMBOBOX: [] }, // c8_owner
       ] });
     }
 
+    // Bug 1572829
+    async function removeShadowRootHost() {
+      info("removeShadowRootHost");
+      document.body.offsetTop; // Flush layout.
+
+      let event = waitForEvent(EVENT_REORDER, "c9", "removeShadowRootHost");
+      getNode("c9").firstElementChild.attachShadow({mode: "open"});
+      getNode("c9").firstElementChild.replaceWith("");
+
+      await event;
+    }
+
     async function doTest() {
       await hideDivFromInsideSpan();
 
       await showDivFromInsideSpan();
 
       await removeDivFromInsideSpan();
 
       await addCSSGeneratedContent();
@@ -195,16 +207,18 @@
       await removeCSSGeneratedContent();
 
       await intermediateNonAccessibleContainers();
 
       await intermediateNonAccessibleContainerBecomesAccessible();
 
       await removeRelocatedWhenDomAncestorHidden();
 
+      await removeShadowRootHost();
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -244,11 +258,15 @@
 
   <div id="c8">
     <div id="c8_owner" role="combobox" aria-owns="c8_owned"></div>
     <div id="c8_owned_container">
       <div id="c8_owned" role="listbox"></div>
     </div>
   </div>
 
+  <div id="c9">
+    <div><dir>a</dir></div>
+  </div>
+
   <div id="eventdump"></div>
 </body>
 </html>
deleted file mode 100644
--- a/browser/actors/SubframeCrashChild.jsm
+++ /dev/null
@@ -1,30 +0,0 @@
-/* vim: set ts=2 sw=2 sts=2 et tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var EXPORTED_SYMBOLS = ["SubframeCrashChild"];
-
-let { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-class SubframeCrashChild extends JSWindowActorChild {
-  receiveMessage(message) {
-    if (message.name == "SubframeCrashed") {
-      this.onSubframeCrashed(message.data.id);
-    }
-  }
-
-  onSubframeCrashed(browsingContextId) {
-    let bc = BrowsingContext.get(browsingContextId);
-    let iframe = bc.embedderElement;
-    let uri = Services.io.newURI(iframe.src);
-    iframe.removeAttribute("fission");
-    iframe.removeAttribute("src");
-    // Passing a null remoteType is currently how we tell the iframe to run
-    // in the same process as the embedder.
-    iframe.changeRemoteness({ remoteType: null });
-    let docShell = iframe.frameLoader.docShell;
-    docShell.displayLoadError(Cr.NS_ERROR_FRAME_CRASHED, uri, null);
-  }
-}
deleted file mode 100644
--- a/browser/actors/SubframeCrashParent.jsm
+++ /dev/null
@@ -1,9 +0,0 @@
-/* vim: set ts=2 sw=2 sts=2 et tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var EXPORTED_SYMBOLS = ["SubframeCrashParent"];
-
-class SubframeCrashParent extends JSWindowActorParent {}
--- a/browser/actors/moz.build
+++ b/browser/actors/moz.build
@@ -41,14 +41,12 @@ FINAL_TARGET_FILES.actors += [
     'OfflineAppsChild.jsm',
     'PageInfoChild.jsm',
     'PageStyleChild.jsm',
     'PluginChild.jsm',
     'PluginParent.jsm',
     'PromptParent.jsm',
     'RFPHelperChild.jsm',
     'SearchTelemetryChild.jsm',
-    'SubframeCrashChild.jsm',
-    'SubframeCrashParent.jsm',
     'SwitchDocumentDirectionChild.jsm',
     'URIFixupChild.jsm',
     'WebRTCChild.jsm',
 ]
--- a/browser/app/profile/channel-prefs.js
+++ b/browser/app/profile/channel-prefs.js
@@ -1,5 +1,9 @@
 /* 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/. */
 
+// This pref is in its own file for complex reasons. See the comment in
+// browser/app/Makefile.in, bug 756325, and bug 1431342 for details. Do not add
+// other prefs to this file.
+
 pref("app.update.channel", "@MOZ_UPDATE_CHANNEL@");
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1,13 +1,17 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+// Non-static prefs that are specific to desktop Firefox belong in this file
+// (unless there is a compelling and documented reason for them to belong in
+// another file).
+//
 // Please indent all prefs defined within #ifdef/#ifndef conditions. This
 // improves readability, particular for conditional blocks that exceed a single
 // screen.
 
 #filter substitution
 
 #ifdef XP_UNIX
   #ifndef XP_MACOSX
@@ -154,17 +158,17 @@ pref("app.update.url", "https://aus5.moz
 // app.update.interval is in branding section
 // app.update.promptWaitTime is in branding section
 
 // Whether or not to attempt using the service for updates.
 #ifdef MOZ_MAINTENANCE_SERVICE
   pref("app.update.service.enabled", true);
 #endif
 
-#ifdef XP_WIN
+#ifdef MOZ_BITS_DOWNLOAD
   // If set to true, the Update Service will attempt to use Windows BITS to
   // download updates and will fallback to downloading internally if that fails.
   pref("app.update.BITS.enabled", true);
 #endif
 
 // Symmetric (can be overridden by individual extensions) update preferences.
 // e.g.
 //  extensions.{GUID}.update.enabled
@@ -1560,22 +1564,20 @@ pref("browser.ping-centre.log", false);
 pref("browser.ping-centre.staging.endpoint", "https://onyx_tiles.stage.mozaws.net/v3/links/ping-centre");
 pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla.com/v3/links/ping-centre");
 
 // Enable GMP support in the addon manager.
 pref("media.gmp-provider.enabled", true);
 
 // Enable blocking access to storage from tracking resources by default.
 pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
-#ifdef EARLY_BETA_OR_EARLIER
-  // Enable fingerprinting blocking by default only in nightly and early beta.
-  pref("privacy.trackingprotection.fingerprinting.enabled", true);
-#endif
 
-// Enable cryptomining blocking by default for all channels, only on desktop.
+// Enable fingerprinting and cryptomining blocking by default for all channels,
+// only on desktop.
+pref("privacy.trackingprotection.fingerprinting.enabled", true);
 pref("privacy.trackingprotection.cryptomining.enabled", true);
 
 pref("browser.contentblocking.database.enabled", true);
 
 pref("dom.storage_access.enabled", true);
 
 pref("browser.contentblocking.control-center.ui.showBlockedLabels", true);
 pref("browser.contentblocking.control-center.ui.showAllowedLabels", false);
@@ -1777,22 +1779,19 @@ pref("signon.showAutoCompleteFooter", tr
 pref("signon.management.page.enabled", true);
 pref("signon.management.page.breach-alerts.enabled", true);
 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
-pref("signon.management.page.faqURL", "https://lockwise.firefox.com/faq.html");
-pref("signon.management.page.feedbackURL",
-     "https://www.surveygizmo.com/s3/5036102/Lockwise-feedback?ver=%VERSION%");
 // 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
-// the utm_creative param be last. 
+// the utm_creative param be last.
 pref("signon.management.page.mobileAndroidURL", "https://app.adjust.com/6tteyjo?redirect=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dmozilla.lockbox&utm_campaign=Desktop&utm_adgroup=InProduct&utm_creative=");
 pref("signon.management.page.mobileAppleURL", "https://app.adjust.com/6tteyjo?redirect=https%3A%2F%2Fitunes.apple.com%2Fapp%2Fid1314000270%3Fmt%3D8&utm_campaign=Desktop&utm_adgroup=InProduct&utm_creative=");
 pref("signon.management.page.breachAlertUrl",
      "https://monitor.firefox.com/breach-details/");
 
 pref("signon.management.page.hideMobileFooter", false);
 
 // Enable the "Simplify Page" feature in Print Preview. This feature
@@ -2038,17 +2037,17 @@ pref("devtools.eyedropper.zoom", 6);
 // Enable to collapse attributes that are too long.
 pref("devtools.markup.collapseAttributes", true);
 // Length to collapse attributes
 pref("devtools.markup.collapseAttributeLength", 120);
 // Whether to auto-beautify the HTML on copy.
 pref("devtools.markup.beautifyOnCopy", false);
 // Whether or not the DOM mutation breakpoints context menu are enabled in the
 // markup view.
-pref("devtools.markup.mutationBreakpoints.enabled", false);
+pref("devtools.markup.mutationBreakpoints.enabled", true);
 
 // DevTools default color unit
 pref("devtools.defaultColorUnit", "authored");
 
 // Enable the Memory tools
 pref("devtools.memory.enabled", true);
 
 pref("devtools.memory.custom-census-displays", "{}");
@@ -2249,20 +2248,23 @@ pref("devtools.webconsole.timestampMessa
   pref("devtools.webconsole.features.editor", true);
 #else
   pref("devtools.webconsole.features.editor", false);
 #endif
 
 // Saved editor mode state in the console.
 pref("devtools.webconsole.input.editor", false);
 
-// Editor width for webconsole and browserconsole
+// Editor width for webconsole and browserconsole.
 pref("devtools.webconsole.input.editorWidth", 0);
 pref("devtools.browserconsole.input.editorWidth", 0);
 
+// Display an onboarding UI for the Editor mode.
+pref("devtools.webconsole.input.editorOnboarding", true);
+
 // Disable the new performance recording panel by default
 pref("devtools.performance.new-panel-enabled", false);
 
 // Enable message grouping in the console, true by default
 pref("devtools.webconsole.groupWarningMessages", true);
 
 // Saved state of the Display content messages checkbox in the browser console.
 pref("devtools.browserconsole.contentMessages", false);
@@ -2372,9 +2374,8 @@ pref("devtools.webide.templatesURL", "ht
 pref("devtools.webide.autoinstallADBExtension", true);
 pref("devtools.webide.autoConnectRuntime", true);
 pref("devtools.webide.restoreLastProject", true);
 pref("devtools.webide.enableLocalRuntime", false);
 pref("devtools.webide.lastConnectedRuntime", "");
 pref("devtools.webide.lastSelectedProject", "");
 pref("devtools.webide.zoom", "1");
 pref("devtools.webide.busyTimeout", 10000);
-
--- a/browser/app/winlauncher/moz.build
+++ b/browser/app/winlauncher/moz.build
@@ -55,13 +55,14 @@ OS_LIBS += [
 
 TEST_DIRS += [
     'test',
 ]
 
 if CONFIG['MOZ_LAUNCHER_PROCESS']:
     UNIFIED_SOURCES += [
         '/toolkit/xre/LauncherRegistryInfo.cpp',
+        '/toolkit/xre/WinTokenUtils.cpp',
     ]
     for var in ('MOZ_APP_BASENAME', 'MOZ_APP_VENDOR'):
         DEFINES[var] = '"%s"' % CONFIG[var]
 
 DisableStlWrapping()
--- a/browser/base/content/browser-siteIdentity.js
+++ b/browser/base/content/browser-siteIdentity.js
@@ -154,16 +154,22 @@ var gIdentityHandler = {
     ));
   },
   get _identityPopupMainViewHeaderLabel() {
     delete this._identityPopupMainViewHeaderLabel;
     return (this._identityPopupMainViewHeaderLabel = document.getElementById(
       "identity-popup-mainView-panel-header-span"
     ));
   },
+  get _identityPopupSecurityView() {
+    delete this._identityPopupSecurityView;
+    return (this._identityPopupSecurityView = document.getElementById(
+      "identity-popup-securityView"
+    ));
+  },
   get _identityPopupSecurityEVContentOwner() {
     delete this._identityPopupSecurityEVContentOwner;
     return (this._identityPopupSecurityEVContentOwner = document.getElementById(
       "identity-popup-security-ev-content-owner"
     ));
   },
   get _identityPopupContentOwner() {
     delete this._identityPopupContentOwner;
@@ -927,24 +933,18 @@ var gIdentityHandler = {
    * based on the specified mode, and the details of the SSL cert, where
    * applicable
    */
   refreshIdentityPopup() {
     // Update cookies and site data information and show the
     // "Clear Site Data" button if the site is storing local data.
     this._clearSiteDataFooter.hidden = true;
     if (this._uriHasHost) {
-      let host = this._uri.host;
-      SiteDataManager.updateSites().then(async () => {
-        let baseDomain = SiteDataManager.getBaseDomainFromHost(host);
-        let siteData = await SiteDataManager.getSites(baseDomain);
-
-        if (siteData && siteData.length) {
-          this._clearSiteDataFooter.hidden = false;
-        }
+      SiteDataManager.hasSiteData(this._uri.asciiHost).then(hasData => {
+        this._clearSiteDataFooter.hidden = !hasData;
       });
     }
 
     // Update "Learn More" for Mixed Content Blocking and Insecure Login Forms.
     let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
     this._identityPopupMixedContentLearnMore.forEach(e =>
       e.setAttribute("href", baseURL + "mixed-content")
     );
@@ -1067,16 +1067,23 @@ var gIdentityHandler = {
     }
 
     // Push the appropriate strings out to the UI.
     this._identityPopupMainViewHeaderLabel.textContent = gNavigatorBundle.getFormattedString(
       "identity.headerMainWithHost",
       [host]
     );
 
+    this._identityPopupSecurityView.setAttribute(
+      "title",
+      gNavigatorBundle.getFormattedString("identity.headerSecurityWithHost", [
+        host,
+      ])
+    );
+
     this._identityPopupSecurityEVContentOwner.textContent = gNavigatorBundle.getFormattedString(
       "identity.ev.contentOwner",
       [owner]
     );
 
     this._identityPopupContentOwner.textContent = owner;
     this._identityPopupContentSupp.textContent = supplemental;
     this._identityPopupContentVerif.textContent = verifier;
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -134,19 +134,19 @@ panelview[mainview] > .panel-header {
     /* Without this, pinned tabs get a bit too tall when the tabstrip overflows. */
     vertical-align: top;
   }
 }
 
 
 #tabbrowser-tabs:not([overflow="true"]):not([hashiddentabs]) ~ #alltabs-button,
 #tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button,
-#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
-#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
-#TabsToolbar[customizing="true"] #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button {
+#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
+#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
+#TabsToolbar[customizing="true"] #tabs-newtab-button {
   visibility: collapse;
 }
 
 #tabbrowser-tabs:not([overflow="true"])[using-closing-tabs-spacer] ~ #alltabs-button {
   visibility: hidden; /* temporary space to keep a tab's close button under the cursor */
 }
 
 .tabbrowser-tab:not([pinned]) {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -63,17 +63,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   ShortcutUtils: "resource://gre/modules/ShortcutUtils.jsm",
   SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm",
   SiteDataManager: "resource:///modules/SiteDataManager.jsm",
   SitePermissions: "resource:///modules/SitePermissions.jsm",
-  SubframeCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   TabModalPrompt: "chrome://global/content/tabprompts.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
   Translation: "resource:///modules/translation/Translation.jsm",
   UITour: "resource:///modules/UITour.jsm",
   UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
   UrlbarInput: "resource:///modules/UrlbarInput.jsm",
   UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
@@ -7961,48 +7960,23 @@ var OfflineApps = {
     // again.
     Services.perms.add(
       uri,
       "offline-app",
       Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN
     );
   },
 
-  // XXX: duplicated in preferences/advanced.js
-  _getOfflineAppUsage(host, groups) {
-    let cacheService = Cc[
-      "@mozilla.org/network/application-cache-service;1"
-    ].getService(Ci.nsIApplicationCacheService);
-    if (!groups) {
-      try {
-        groups = cacheService.getGroups();
-      } catch (ex) {
-        return 0;
-      }
-    }
-
-    let usage = 0;
-    for (let group of groups) {
-      let uri = Services.io.newURI(group);
-      if (uri.asciiHost == host) {
-        let cache = cacheService.getActiveCache(group);
-        usage += cache.usage;
-      }
-    }
-
-    return usage;
-  },
-
   _usedMoreThanWarnQuota(uri) {
     // if the user has already allowed excessive usage, don't bother checking
     if (
       Services.perms.testExactPermission(uri, "offline-app") !=
       Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN
     ) {
-      let usageBytes = this._getOfflineAppUsage(uri.asciiHost);
+      let usageBytes = SiteDataManager.getAppCacheUsageByHost(uri.asciiHost);
       let warnQuotaKB = Services.prefs.getIntPref("offline-apps.quota.warn");
       // The pref is in kb, the usage we get is in bytes, so multiply the quota
       // to compare correctly:
       if (usageBytes >= warnQuotaKB * 1024) {
         return true;
       }
     }
 
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -731,17 +731,17 @@
                   tooltip="tabbrowser-tab-tooltip"
                   stopwatchid="FX_TAB_CLICK_MS">
               <hbox class="tab-drop-indicator-box">
                 <image class="tab-drop-indicator" hidden="true"/>
               </hbox>
               <arrowscrollbox orient="horizontal" flex="1" style="min-width: 1px;" clicktoscroll="true" class="tabbrowser-arrowscrollbox" scrolledtostart="true" scrolledtoend="true">
                 <tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/>
                 <toolbarbutton id="tabs-newtab-button"
-                               class="tabs-newtab-button toolbarbutton-1"
+                               class="toolbarbutton-1"
                                command="cmd_newNavigatorTab"
                                onclick="checkForMiddleClick(this, event);"
                                tooltip="dynamic-shortcut-tooltip"/>
                 <spacer class="closing-tabs-spacer" style="width: 0;"/>
               </arrowscrollbox>
               <html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
             </tabs>
 
--- a/browser/base/content/tabbrowser-tabs.js
+++ b/browser/base/content/tabbrowser-tabs.js
@@ -901,17 +901,17 @@
       event.stopPropagation();
     }
 
     get tabbox() {
       return document.getElementById("tabbrowser-tabbox");
     }
 
     get newTabButton() {
-      return this.querySelector(".tabs-newtab-button");
+      return this.querySelector("#tabs-newtab-button");
     }
 
     // Accessor for tabs.  arrowScrollbox has two non-tab elements at the
     // end, everything else is <tab>s
     get allTabs() {
       let children = Array.from(this.arrowScrollbox.children);
       children.pop();
       children.pop();
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -5261,22 +5261,16 @@
         }
       });
 
       this.addEventListener("oop-browser-crashed", event => {
         if (!event.isTrusted) {
           return;
         }
 
-        if (!event.isTopFrame) {
-          let bc = BrowsingContext.get(event.browsingContextId);
-          SubframeCrashHandler.onSubframeCrash(bc);
-          return;
-        }
-
         let browser = event.originalTarget;
 
         // Preloaded browsers do not actually have any tabs. If one crashes,
         // it should be released and removed.
         if (browser === this.preloadedBrowser) {
           NewTabPagePreloading.removePreloadedBrowser(window);
           return;
         }
--- a/browser/base/content/test/performance/browser_startup_content.js
+++ b/browser/base/content/test/performance/browser_startup_content.js
@@ -44,17 +44,16 @@ const whitelist = {
     "resource:///actors/BrowserTabChild.jsm",
     "resource:///modules/ContentMetaHandler.jsm",
     "resource:///actors/LinkHandlerChild.jsm",
     "resource:///actors/SearchTelemetryChild.jsm",
     "resource://gre/modules/ActorChild.jsm",
     "resource://gre/modules/ActorManagerChild.jsm",
     "resource://gre/modules/E10SUtils.jsm",
     "resource://gre/modules/Readerable.jsm",
-    "resource://gre/modules/WebProgressChild.jsm",
 
     // Telemetry
     "resource://gre/modules/TelemetryController.jsm", // bug 1470339
     "resource://gre/modules/TelemetryUtils.jsm", // bug 1470339
 
     // Extensions
     "resource://gre/modules/ExtensionProcessScript.jsm",
     "resource://gre/modules/ExtensionUtils.jsm",
--- a/browser/base/content/test/performance/browser_windowopen.js
+++ b/browser/base/content/test/performance/browser_windowopen.js
@@ -78,22 +78,17 @@ add_task(async function() {
       },
       exceptions: [
         {
           name: "bug 1421463 - reload toolbar icon shouldn't flicker",
           condition: r =>
             inRange(r.h, 13, 14) &&
             inRange(r.w, 14, 16) && // icon size
             inRange(r.y1, 40, 80) && // in the toolbar
-            // near the left side of the screen
-            // The reload icon is shifted on devedition builds
-            // where there's an additional devtools toolbar icon.
-            AppConstants.MOZ_DEV_EDITION
-              ? inRange(r.x1, 100, 120)
-              : inRange(r.x1, 65, 100),
+            inRange(r.x1, 65, 100), // near the left side of the screen
         },
         {
           name: "bug 1555842 - the urlbar shouldn't flicker",
           condition: r => {
             let inputFieldRect = win.gURLBar.inputField.getBoundingClientRect();
 
             return (
               (!AppConstants.DEBUG ||
--- a/browser/base/content/test/siteIdentity/browser.ini
+++ b/browser/base/content/test/siteIdentity/browser.ini
@@ -107,16 +107,17 @@ tags = mcb
 support-files =
   test_no_mcb_on_http_site_img.html
   test_no_mcb_on_http_site_img.css
   test_no_mcb_on_http_site_font.html
   test_no_mcb_on_http_site_font.css
   test_no_mcb_on_http_site_font2.html
   test_no_mcb_on_http_site_font2.css
 [browser_no_mcb_for_loopback.js]
+skip-if = fission # Timeouts
 tags = mcb
 support-files =
   ../general/moz.png
   test_no_mcb_for_loopback.html
 [browser_no_mcb_for_onions.js]
 tags = mcb
 support-files =
   test_no_mcb_for_onions.html
--- a/browser/base/content/test/siteIdentity/browser_identityPopup_clearSiteData.js
+++ b/browser/base/content/test/siteIdentity/browser_identityPopup_clearSiteData.js
@@ -1,75 +1,86 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const TEST_ORIGIN = "https://example.com";
 const TEST_SUB_ORIGIN = "https://test1.example.com";
 const REMOVE_DIALOG_URL =
   "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
 
+// Greek IDN for 'example.test'.
+const TEST_IDN_ORIGIN =
+  "https://\u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1.\u03B4\u03BF\u03BA\u03B9\u03BC\u03AE";
+const TEST_PUNY_ORIGIN = "https://xn--hxajbheg2az3al.xn--jxalpdlp/";
+const TEST_PUNY_SUB_ORIGIN = "https://sub1.xn--hxajbheg2az3al.xn--jxalpdlp/";
+
 ChromeUtils.defineModuleGetter(
   this,
   "SiteDataTestUtils",
   "resource://testing-common/SiteDataTestUtils.jsm"
 );
 
 add_task(async function setup() {
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
 
   registerCleanupFunction(() => {
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
 });
 
-async function testClearing(testQuota, testCookies) {
+async function testClearing(
+  testQuota,
+  testCookies,
+  testURI,
+  origin,
+  subOrigin
+) {
   // Add some test quota storage.
   if (testQuota) {
-    await SiteDataTestUtils.addToIndexedDB(TEST_ORIGIN);
-    await SiteDataTestUtils.addToIndexedDB(TEST_SUB_ORIGIN);
+    await SiteDataTestUtils.addToIndexedDB(origin);
+    await SiteDataTestUtils.addToIndexedDB(subOrigin);
   }
 
   // Add some test cookies.
   if (testCookies) {
-    SiteDataTestUtils.addToCookies(TEST_ORIGIN, "test1", "1");
-    SiteDataTestUtils.addToCookies(TEST_ORIGIN, "test2", "2");
-    SiteDataTestUtils.addToCookies(TEST_SUB_ORIGIN, "test3", "1");
+    SiteDataTestUtils.addToCookies(origin, "test1", "1");
+    SiteDataTestUtils.addToCookies(origin, "test2", "2");
+    SiteDataTestUtils.addToCookies(subOrigin, "test3", "1");
   }
 
-  await BrowserTestUtils.withNewTab(TEST_ORIGIN, async function(browser) {
+  await BrowserTestUtils.withNewTab(testURI, async function(browser) {
     // Verify we have added quota storage.
     if (testQuota) {
-      let usage = await SiteDataTestUtils.getQuotaUsage(TEST_ORIGIN);
+      let usage = await SiteDataTestUtils.getQuotaUsage(origin);
       Assert.greater(usage, 0, "Should have data for the base origin.");
 
-      usage = await SiteDataTestUtils.getQuotaUsage(TEST_SUB_ORIGIN);
+      usage = await SiteDataTestUtils.getQuotaUsage(subOrigin);
       Assert.greater(usage, 0, "Should have data for the sub origin.");
     }
 
     // Open the identity popup.
     let { gIdentityHandler } = gBrowser.ownerGlobal;
     let promisePanelOpen = BrowserTestUtils.waitForEvent(
       gIdentityHandler._identityPopup,
       "popupshown"
     );
-    let siteDataUpdated = TestUtils.topicObserved(
-      "sitedatamanager:sites-updated"
-    );
     gIdentityHandler._identityBox.click();
     await promisePanelOpen;
-    await siteDataUpdated;
 
     let clearFooter = document.getElementById(
       "identity-popup-clear-sitedata-footer"
     );
     let clearButton = document.getElementById(
       "identity-popup-clear-sitedata-button"
     );
-    ok(!clearFooter.hidden, "The clear data footer is not hidden.");
+    TestUtils.waitForCondition(
+      () => !clearFooter.hidden,
+      "The clear data footer is not hidden."
+    );
 
     let cookiesCleared;
     if (testCookies) {
       cookiesCleared = Promise.all([
         TestUtils.topicObserved(
           "cookie-changed",
           (subj, data) => data == "deleted" && subj.name == "test1"
         ),
@@ -82,17 +93,19 @@ async function testClearing(testQuota, t
           (subj, data) => data == "deleted" && subj.name == "test3"
         ),
       ]);
     }
 
     Services.telemetry.clearEvents();
 
     // Click the "Clear data" button.
-    siteDataUpdated = TestUtils.topicObserved("sitedatamanager:sites-updated");
+    let siteDataUpdated = TestUtils.topicObserved(
+      "sitedatamanager:sites-updated"
+    );
     let hideEvent = BrowserTestUtils.waitForEvent(
       gIdentityHandler._identityPopup,
       "popuphidden"
     );
     let removeDialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
       "accept",
       REMOVE_DIALOG_URL
     );
@@ -111,64 +124,77 @@ async function testClearing(testQuota, t
     );
     is(buttonEvents.length, 1, "recorded telemetry for the button click");
 
     await siteDataUpdated;
 
     // Check that cookies were deleted.
     if (testCookies) {
       await cookiesCleared;
-      let uri = Services.io.newURI(TEST_ORIGIN);
+      let uri = Services.io.newURI(origin);
       is(
         Services.cookies.countCookiesFromHost(uri.host),
         0,
         "Cookies from the base domain should be cleared"
       );
-      uri = Services.io.newURI(TEST_SUB_ORIGIN);
+      uri = Services.io.newURI(subOrigin);
       is(
         Services.cookies.countCookiesFromHost(uri.host),
         0,
         "Cookies from the sub domain should be cleared"
       );
     }
 
     // Check that quota storage was deleted.
     if (testQuota) {
       await TestUtils.waitForCondition(async () => {
-        let usage = await SiteDataTestUtils.getQuotaUsage(TEST_ORIGIN);
+        let usage = await SiteDataTestUtils.getQuotaUsage(origin);
         return usage == 0;
       }, "Should have no data for the base origin.");
 
-      let usage = await SiteDataTestUtils.getQuotaUsage(TEST_SUB_ORIGIN);
+      let usage = await SiteDataTestUtils.getQuotaUsage(subOrigin);
       is(usage, 0, "Should have no data for the sub origin.");
     }
 
     // Open the site identity panel again to check that the button isn't shown anymore.
     promisePanelOpen = BrowserTestUtils.waitForEvent(
       gIdentityHandler._identityPopup,
       "popupshown"
     );
-    siteDataUpdated = TestUtils.topicObserved("sitedatamanager:sites-updated");
     gIdentityHandler._identityBox.click();
     await promisePanelOpen;
-    await siteDataUpdated;
+
+    // Wait for a second to see if the button is shown.
+    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+    await new Promise(c => setTimeout(c, 1000));
 
     ok(
       clearFooter.hidden,
       "The clear data footer is hidden after clearing data."
     );
   });
 }
 
 // Test removing quota managed storage.
 add_task(async function test_ClearSiteData() {
-  await testClearing(true, false);
+  await testClearing(true, false, TEST_ORIGIN, TEST_ORIGIN, TEST_SUB_ORIGIN);
 });
 
 // Test removing cookies.
 add_task(async function test_ClearCookies() {
-  await testClearing(false, true);
+  await testClearing(false, true, TEST_ORIGIN, TEST_ORIGIN, TEST_SUB_ORIGIN);
 });
 
 // Test removing both.
 add_task(async function test_ClearCookiesAndSiteData() {
-  await testClearing(true, true);
+  await testClearing(true, true, TEST_ORIGIN, TEST_ORIGIN, TEST_SUB_ORIGIN);
 });
+
+// Test IDN Domains
+add_task(async function test_IDN_ClearCookiesAndSiteData() {
+  await testClearing(
+    true,
+    true,
+    TEST_IDN_ORIGIN,
+    TEST_PUNY_ORIGIN,
+    TEST_PUNY_SUB_ORIGIN
+  );
+});
--- a/browser/base/content/test/siteProtections/browser_protections_UI.js
+++ b/browser/base/content/test/siteProtections/browser_protections_UI.js
@@ -62,19 +62,21 @@ add_task(async function setup() {
       // when landing on the page.
       ["browser.contentblocking.report.monitor.enabled", false],
       ["browser.contentblocking.report.lockwise.enabled", false],
       ["browser.contentblocking.report.proxy.enabled", false],
     ],
   });
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
+  Services.telemetry.clearEvents();
 
   registerCleanupFunction(() => {
     Services.telemetry.canRecordExtended = oldCanRecord;
+    Services.telemetry.clearEvents();
   });
 });
 
 add_task(async function testToggleSwitch() {
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
     "https://example.com"
   );
@@ -599,24 +601,26 @@ add_task(async function testQuickSwitchT
   gBrowser.selectedTab = tabOne;
 
   // Wait for the second tab to be reloaded.
   await browserLoadedPromise;
 
   // Check that the first tab is still with ETP enabled.
   ok(
     !ContentBlockingAllowList.includes(gBrowser.selectedBrowser),
-    "The tracking protection icon state is still enabled."
+    "The ETP state of the first tab is still enabled."
   );
 
   // Check the ETP is disabled on the second origin.
-  gBrowser.selectedTab = tabTwo;
   ok(
-    ContentBlockingAllowList.includes(gBrowser.selectedBrowser),
-    "The tracking protection icon state has been changed to disabled."
+    ContentBlockingAllowList.includes(tabTwo.linkedBrowser),
+    "The ETP state of the second tab has been changed to disabled."
   );
 
+  // Clean up the state of the allow list for the second tab.
+  ContentBlockingAllowList.remove(tabTwo.linkedBrowser);
+
   BrowserTestUtils.removeTab(tabOne);
   BrowserTestUtils.removeTab(tabTwo);
 
   // Finally, clear the tracking database.
   await TrackingDBService.clearAll();
 });
--- a/browser/branding/aurora/content/horizontal-lockup.svg
+++ b/browser/branding/aurora/content/horizontal-lockup.svg
@@ -56,16 +56,22 @@
       <stop stop-color="#BFF3FF" stop-opacity=".8" offset="0%"/>
       <stop stop-color="#0DF" stop-opacity="0" offset="100%"/>
     </linearGradient>
     <linearGradient x1="-10%" y1="66%" x2="110%" y2="33%" id="u">
       <stop offset="0" stop-color="#0250bb"/>
       <stop offset=".123" stop-color="#024eb6"/>
       <stop offset="1" stop-color="#054096"/>
     </linearGradient>
+    <linearGradient x1="110%" y1="66%" x2="-10%" y2="33%" id="v">
+      <stop offset="0" stop-color="#80ebff"/>
+      <stop offset=".33" stop-color="#0df"/>
+      <stop offset=".66" stop-color="#00b3f4"/>
+      <stop offset="1" stop-color="#00b3f4"/>
+    </linearGradient>
     <radialGradient cx="55%" cy="25%" r="60%" id="a">
       <stop stop-color="#0DF" stop-opacity=".4" offset="10%"/>
       <stop stop-color="#7542E5" stop-opacity=".25" offset="90%"/>
     </radialGradient>
     <radialGradient cx="49.238%" cy="52.7%" fx="49%" fy="52.7%" r="51%" id="b">
       <stop stop-color="#7542E5" stop-opacity="0" offset="91%"/>
       <stop stop-color="#0DF" stop-opacity=".4" offset="100%"/>
     </radialGradient>
@@ -96,16 +102,29 @@
       <stop stop-color="#00B3F4" offset="100%"/>
     </radialGradient>
     <radialGradient cx="15%" cy="-43%" fx="15%" fy="-43%" r="230%" gradientTransform="matrix(.9814 0 0 1 .003 0)" id="j">
       <stop stop-color="#AAF2FF" offset="18%"/>
       <stop stop-color="#0DF" offset="43%"/>
       <stop stop-color="#0060DF" offset="69%"/>
     </radialGradient>
   </defs>
+  <style>
+    .channel-name {
+      fill: url(#u);
+    }
+
+    @supports -moz-bool-pref("browser.in-content.dark-mode") {
+    @media (prefers-color-scheme: dark) {
+      .channel-name {
+        fill: url(#v);
+      }
+    }
+    }
+  </style>
   <path fill="#09204d" d="M22.361 46.629l2.442 6.77 3.669 4.951 8.614 1.644 4.121 0.35 7.036-1.758 3.031-2.905-28.913-9.052z"/>
   <path fill="#09204d" d="M58.818 36.642l-0.863-2.862-2.466-4.654-2.821-2.974-2.995-2.139-2.6-1.02-3.12-1.11-5.137-0.327-3.24 0.584-2.643 0.813-4.69 2.745-2.931 3.271-2.703 4.39-1.063 3.736-0.199 5.669 1.014 3.865 2.236 4.4 1.576 2.125 2.181 2 2.723 1.842 3.358 1.461 5.619 0.659 2.935 0.082 4.342-1.223 3.882-2.131 2.497-2.131 1.937-2.31 2.738-5.36 0.604-3.667-0.171-5.734z"/>
   <path fill="#0e56d7" d="M38.91 24.132l-2.301 2.282 3.753 1.522 2.792-3.463-4.244-0.341z"/>
   <path fill="#1053d1" d="M40.362 27.936l7.266-0.221-4.474-3.242-2.792 3.463z"/>
   <path fill="#0b4fbf" d="M47.088 24.449l-3.934 0.024 4.474 3.242 4.137-0.27-4.677-2.996z"/>
   <path fill="#0b48b0" d="M51.765 27.445l-2.352-3.243 3.255 1.95-0.903 1.293z"/>
   <path fill="#0c45a7" d="M54.879 29.431l-3.114-1.986 0.903-1.293 2.211 3.279z"/>
   <path fill="#0f46af" d="M51.765 27.445l-0.521 2.222 2.848 1.139-2.327-3.361z"/>
@@ -250,10 +269,10 @@
   <path d="M52.08 0.033l0.02-0.022c-8.78 5.137-12.334 14.206-13.174 19.812A28.672 28.672 0 0 1 50.647 1.735a5.436 5.436 0 0 1 1.433-1.702z" fill="url(#n)"/>
   <path d="M61.749 52.456l0.022-0.05c0.343-0.816 4.952-12.268-3.844-20.365a7.876 7.876 0 0 0-0.583-0.476c-0.079-0.059-0.156-0.118-0.241-0.177a13.543 13.543 0 0 0-9-2.325H48.1a8.612 8.612 0 0 0-0.353 0.055C61.546 36.01 58.039 59.55 39.266 59.2l0.153 0.009C58.45 59.957 62.2 36.618 48.977 29.3a14.05 14.05 0 0 1 7.349 2.122 8.183 8.183 0 0 1 0.247 0.169 7.4 7.4 0 0 1 0.6 0.452c9.107 7.747 4.95 19.37 4.638 20.2l-0.02 0.052" fill="url(#o)"/>
   <path d="M25.662 33.61a19.385 19.385 0 0 0 14.029 0.345 19.388 19.388 0 0 1-14.133-0.733 14.743 14.743 0 0 0-14.081 0.45l-0.051 0.033h-0.005l-0.042 0.028-0.032 0.022-0.02 0.014h-0.006l-0.014 0.01h-0.005l0.018 0.043v0.006l0.022 0.05v0.01l0.033 0.072v0.006a8 8 0 0 0 0.255 0.487 9.925 9.925 0 0 0 8.852 5.1c-0.7 6.146 2.438 13.282 10.036 17.242-7.262-4.185-10.313-11.78-9.465-17.821-5.607-0.148-8.114-3.509-8.831-4.934a15.333 15.333 0 0 1 13.44-0.43z" fill="url(#p)"/>
   <path d="M27.049 24.872l-0.19-0.111 0.2 0.132zm-0.04-0.142a17.957 17.957 0 0 1-0.063-9.309 28.285 28.285 0 0 0-8.98 6.811 29.292 29.292 0 0 1 8.189-5.784 18.179 18.179 0 0 0 0.854 8.282z" fill="url(#q)"/>
   <path d="M2.547 46.226l-0.031-0.111a35.886 35.886 0 0 1-0.9-3.951 16.765 16.765 0 0 1 0-5 32.988 32.988 0 0 0-0.355 3.88v0.2a38.774 38.774 0 0 0 26.04 36.608A39.224 39.224 0 0 1 2.547 46.226z" fill="url(#r)"/>
   <path d="M2.236 42.32c-0.679-3.122 0.7-9.141 0.717-9.226A32.689 32.689 0 0 1 8.16 21.352v0.006-0.006a34 34 0 0 1 3.623-4.341 28.275 28.275 0 0 1 3.792-3.245 3.338 3.338 0 0 1 0.164-0.1c-0.014 2.948 0.154 7.923 1.519 9.554h0.018c0.187-0.01 5.835-0.259 8.724 1.5 0.321 0.2 0.585 0.359 0.821 0.51a11.927 11.927 0 0 1 1.029 0.731c0.606 0.486 1.294 1.135 2.743 2.482 2.1 1.951 6.669 3.891 8.644 4.815-1.924-0.969-6.464-3.04-8.511-5.055-1.407-1.385-2.075-2.052-2.666-2.553a11.762 11.762 0 0 0-1-0.758c-0.231-0.157-0.49-0.327-0.8-0.531-2.83-1.838-8.458-1.736-8.644-1.732h-0.018c-1.406-1.779-1.436-7.293-1.364-9.252 0-0.076 0-0.145 0.008-0.21V13.04c0-0.042 0-0.083 0.007-0.118 0 0-0.007-0.007-0.016-0.007h-0.035l-0.022 0.008-0.032 0.012-0.031 0.013-0.037 0.017-0.04 0.019-0.04 0.02-0.049 0.024-0.039 0.021-0.058 0.03-0.033 0.018a19.292 19.292 0 0 0-0.864 0.5 28.275 28.275 0 0 0-3.792 3.245A34 34 0 0 0 7.535 21.2v0.006V21.2a32.689 32.689 0 0 0-5.207 11.738c-0.018 0.084-1.4 6.1-0.717 9.226C4.159 57.2 16.154 69.215 30.892 72.778 16.441 69.031 4.748 57.147 2.236 42.32z" fill="url(#s)"/>
   <path d="M75.959 26.832a23.765 23.765 0 0 0-6.81-9.2l-0.069-0.049a13.613 13.613 0 0 0-0.23-0.158q-0.043-0.03-0.087-0.057-0.11-0.07-0.216-0.135l-0.084-0.05a7.863 7.863 0 0 0-0.288-0.159 35.137 35.137 0 0 1 0.306 0.615 33.589 33.589 0 0 1 0.186 0.383A39.735 39.735 0 0 1 72.1 28.786l0.008 0.065c1.376 8.977-3.195 17.674-10.341 23.555l-0.022 0.05c-8.883 7.225-17.52 8.013-23.312 7.159 5.771 1.078 14.874 0.623 24.25-7l0.021-0.05c7.146-5.881 11.718-14.578 10.342-23.555l-0.008-0.065a38.939 38.939 0 0 0-2.829-9.445 25.662 25.662 0 0 1 4.243 6.047 38.616 38.616 0 0 1 3.586 19c-0.03 0.495-0.055 0.989-0.093 1.48A38.63 38.63 0 0 1 41.533 79.82a39.649 39.649 0 0 1-7.661-0.312A38.837 38.837 0 0 0 78.3 47.8c0.065-0.5 0.118-0.995 0.176-1.495a39.8 39.8 0 0 0-2.517-19.473zm-3.842 2.032v-0.037z" fill="url(#t)"/>
   <path d="M96.972 23.986H118.4v5.8h-15.28v7.859h15.28v5.752h-15.28v12.642h-6.148zm28.716-2.239a3.447 3.447 0 0 1 3.557 3.6 3.579 3.579 0 0 1-7.157 0.088 3.555 3.555 0 0 1 3.6-3.688zm-3.03 10.581h6.06v23.711h-6.06zm23.623 6.587a4.894 4.894 0 0 0-2.942-1.054c-2.459 0-3.864 1.581-3.864 5.049v13.129h-6.015V32.328h5.752v3.425a5.649 5.649 0 0 1 5.664-3.644 7.191 7.191 0 0 1 4.04 1.229zm2.5 5.4a12.13 12.13 0 0 1 12.206-12.47c7.113 0 12.163 5.05 12.163 12.075v2.5h-18.439c0.659 2.986 2.986 4.962 6.543 4.962a6.357 6.357 0 0 0 5.884-3.513l5.049 3.03c-2.5 3.688-6.059 5.62-11.109 5.62-7.684 0.003-12.294-5.134-12.294-12.204zm6.015-2.678h12.47c-0.658-3.03-3.117-4.7-6.323-4.7a6.09 6.09 0 0 0-6.143 4.7zm19.847-9.309h4.259v-1.185c0-6.455 2.722-9.133 8.694-9.133h2.107v5.225h-1.712c-2.81 0-3.425 0.966-3.425 3.908v1.185h5.137v5.445h-5v18.266h-5.8V37.773h-4.259zm16.2 11.856a12.14 12.14 0 0 1 12.387-12.339 12.339 12.339 0 1 1 0 24.677 11.96 11.96 0 0 1-12.382-12.338zm18.88 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 1 0 13 0zm14.051-0.264l-8.562-11.592h7.113l5.05 7.289 5.181-7.289h6.981l-8.694 11.548 9.133 12.163h-7.069l-5.664-7.728-5.489 7.728h-7.064zm51.241-4.436a7.41 7.41 0 0 0 4.266-6.948c0-5.189-3.958-8.532-9.939-8.532h-13.721v32.1h14.161c6.068 0 10.158-3.43 10.158-9.059a7.711 7.711 0 0 0-4.925-7.561zm-15.744-12.137H269.3c3.913 0 6.332 2.111 6.332 5.189s-2.11 5.365-6.024 5.365h-10.337zm10.467 25.374h-10.467V41.287h10.291c4.4 0 6.685 2.331 6.685 5.717 0 3.342-2.547 5.717-6.509 5.717zm18.032-15.876V32.36h-3.47v23.747h3.563V43.09c0-5.233 2.286-7.52 6.244-7.52a5.2 5.2 0 0 1 2.9 0.748l1.5-3.43a7.758 7.758 0 0 0-3.958-0.88 6.576 6.576 0 0 0-6.779 4.837zm23.22-4.969a12.357 12.357 0 1 0 12.357 12.358 12.193 12.193 0 0 0-12.357-12.358zm0 21.285a8.607 8.607 0 0 1-8.663-8.927 8.69 8.69 0 1 1 17.371 0 8.642 8.642 0 0 1-8.708 8.927zm41.3-2.112l-7.084-18.689h-3.342l-7.256 18.821-5.981-18.821h-3.782l7.784 23.747h3.518l7.3-18.821 7.3 18.821H354l8.224-23.747h-3.738zm22.649-8.663c-3.694-0.747-6.553-1.231-6.553-3.693 0-2.2 1.5-3.782 5.146-3.782a7.666 7.666 0 0 1 6.509 3.166l2.99-2.023a11.479 11.479 0 0 0-9.5-4.221c-5.629-0.044-8.839 3.209-8.839 6.9 0 4.749 4.353 5.848 8.443 6.639 3.474 0.705 6.728 1.232 6.728 3.871 0 2.375-1.935 4.133-5.629 4.133a8.771 8.771 0 0 1-7.651-3.87l-3.123 2.112c2.111 3.034 5.5 4.968 10.686 4.968 6.2 0.044 9.367-3.649 9.367-7.387-0.002-4.877-4.487-6.021-8.577-6.813zm23.925-10.51a12.18 12.18 0 0 0-12.4 12.446c0 6.948 4.925 12.268 12.533 12.268a12.2 12.2 0 0 0 11.038-6.024l-3.078-1.8a8.489 8.489 0 0 1-7.96 4.573c-5.013 0-8.488-3.21-9.015-7.739h20.977v-1.631a11.714 11.714 0 0 0-12.098-12.093zm-8.8 10.554a8.821 8.821 0 0 1 8.8-7.344 8 8 0 0 1 8.4 7.344zm35.447-10.422a6.575 6.575 0 0 0-6.772 4.837V32.36h-3.475v23.747h3.563V43.09c0-5.233 2.286-7.52 6.244-7.52a5.2 5.2 0 0 1 2.9 0.748l1.5-3.43a7.754 7.754 0 0 0-3.958-0.88z" fill="context-fill #20123a"/>
-  <path d="M101.887 64.415h-4.915v14.774h4.978c4.542 0 7.874-3.177 7.874-7.387 0-4.189-3.104-7.387-7.937-7.387zm-0.124 12.1H99.93v-9.449h1.75c3.333 0 5.164 2.024 5.164 4.736 0 2.651-1.999 4.716-5.081 4.716zm10.359 2.671h10.227v-2.709h-7.289v-3.36h7.289v-2.691h-7.289v-3.319h7.289v-2.692h-10.227zm18.9-3.8l-4.082-10.969h-3.1l5.749 14.774h2.9l5.749-14.774h-3.083zm8.862 3.8h10.227v-2.709h-7.29v-3.36h7.29v-2.691h-7.29v-3.319h7.29v-2.692h-10.229zm15.732-14.774h-2.958v14.777h9.978v-2.773h-7.02zm15.525-0.2a7.593 7.593 0 1 0 7.81 7.589 7.669 7.669 0 0 0-7.812-7.588zm0 12.365a4.787 4.787 0 1 1 4.852-4.776 4.766 4.766 0 0 1-4.854 4.777zm16.088-12.163h-6v14.775h2.958v-4.027h3.021a5.384 5.384 0 1 0 0.02-10.747zm-0.188 8.095h-2.853v-5.483h2.853a2.747 2.747 0 1 1 0 5.484zm8.235 6.679H205.5v-2.711h-7.289v-3.36h7.289v-2.691h-7.289v-3.319h7.289v-2.692h-10.226zm21.858-5.4a4.792 4.792 0 0 0 2.666-4.372c0-2.813-2.084-5-5.583-5h-6.167v14.773h2.938v-4.654h3.412l2.437 4.654h3.291zm-3.146-1.862h-3v-4.879h3c1.874 0 2.832 0.93 2.832 2.387-0.002 1.315-0.897 2.49-2.834 2.49z" fill="url(#u)"/>
+  <path d="M101.887 64.415h-4.915v14.774h4.978c4.542 0 7.874-3.177 7.874-7.387 0-4.189-3.104-7.387-7.937-7.387zm-0.124 12.1H99.93v-9.449h1.75c3.333 0 5.164 2.024 5.164 4.736 0 2.651-1.999 4.716-5.081 4.716zm10.359 2.671h10.227v-2.709h-7.289v-3.36h7.289v-2.691h-7.289v-3.319h7.289v-2.692h-10.227zm18.9-3.8l-4.082-10.969h-3.1l5.749 14.774h2.9l5.749-14.774h-3.083zm8.862 3.8h10.227v-2.709h-7.29v-3.36h7.29v-2.691h-7.29v-3.319h7.29v-2.692h-10.229zm15.732-14.774h-2.958v14.777h9.978v-2.773h-7.02zm15.525-0.2a7.593 7.593 0 1 0 7.81 7.589 7.669 7.669 0 0 0-7.812-7.588zm0 12.365a4.787 4.787 0 1 1 4.852-4.776 4.766 4.766 0 0 1-4.854 4.777zm16.088-12.163h-6v14.775h2.958v-4.027h3.021a5.384 5.384 0 1 0 0.02-10.747zm-0.188 8.095h-2.853v-5.483h2.853a2.747 2.747 0 1 1 0 5.484zm8.235 6.679H205.5v-2.711h-7.289v-3.36h7.289v-2.691h-7.289v-3.319h7.289v-2.692h-10.226zm21.858-5.4a4.792 4.792 0 0 0 2.666-4.372c0-2.813-2.084-5-5.583-5h-6.167v14.773h2.938v-4.654h3.412l2.437 4.654h3.291zm-3.146-1.862h-3v-4.879h3c1.874 0 2.832 0.93 2.832 2.387-0.002 1.315-0.897 2.49-2.834 2.49z" class="channel-name"/>
 </svg>
--- a/browser/branding/aurora/pref/firefox-branding.js
+++ b/browser/branding/aurora/pref/firefox-branding.js
@@ -1,14 +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/. */
 
+// This file contains branding-specific prefs.
+
 pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%a2/firstrun/");
 pref("startup.homepage_welcome_url.additional", "");
 // The time interval between checks for a new version (in seconds)
 pref("app.update.interval", 28800); // 8 hours
 // Give the user x seconds to react before showing the big UI. default=192 hours
 pref("app.update.promptWaitTime", 691200);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
--- a/browser/branding/nightly/content/horizontal-lockup.svg
+++ b/browser/branding/nightly/content/horizontal-lockup.svg
@@ -105,17 +105,37 @@
       <stop offset=".589" stop-color="#0df" stop-opacity="0"/>
     </linearGradient>
     <linearGradient id="o" x1="75.658" y1="72" x2="203.22" y2="72" gradientUnits="userSpaceOnUse">
       <stop offset=".002" stop-color="#005e5e"/>
       <stop offset=".478" stop-color="#0250bb"/>
       <stop offset=".735" stop-color="#253ba3"/>
       <stop offset="1" stop-color="#45278d"/>
     </linearGradient>
+    <linearGradient id="p" x1="75.658" y1="72" x2="203.22" y2="72" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#54ffbd"/>
+      <stop offset=".45" stop-color="#0df"/>
+      <stop offset=".7" stop-color="#58c2ff"/>
+      <stop offset=".9" stop-color="#aba8ff"/>
+      <stop offset="1" stop-color="#cb9eff"/>
+    </linearGradient>
   </defs>
+  <style>
+    .channel-name {
+      fill: url(#o);
+    }
+
+    @supports -moz-bool-pref("browser.in-content.dark-mode") {
+    @media (prefers-color-scheme: dark) {
+      .channel-name {
+        fill: url(#p);
+      }
+    }
+    }
+  </style>
   <path d="M75.916 26.831c-1.684-4.052-5.1-8.427-7.775-9.81a40.266 40.266 0 0 1 3.925 11.764l.007.065C67.691 17.925 60.26 13.52 54.191 3.928c-.307-.485-.614-.971-.913-1.484-.171-.293-.308-.557-.427-.8a7.053 7.053 0 0 1-.578-1.535.1.1 0 0 0-.088-.1.138.138 0 0 0-.073 0c-.005 0-.013.009-.019.011s-.019.011-.028.015l.015-.026c-9.735 5.7-13.038 16.252-13.342 21.53a19.387 19.387 0 0 0-10.666 4.111 11.587 11.587 0 0 0-1-.758 17.968 17.968 0 0 1-.109-9.473 28.705 28.705 0 0 0-9.329 7.21h-.018c-1.536-1.947-1.428-8.367-1.34-9.708a6.928 6.928 0 0 0-1.294.687 28.225 28.225 0 0 0-3.788 3.245A33.845 33.845 0 0 0 7.571 21.2v.006-.007a32.733 32.733 0 0 0-5.2 11.743l-.052.256c-.073.341-.336 2.049-.381 2.42 0 .029-.006.056-.009.085a36.937 36.937 0 0 0-.629 5.343v.2A38.759 38.759 0 0 0 78.254 47.8c.065-.5.118-.995.176-1.5a39.857 39.857 0 0 0-2.514-19.469zm-44.67 30.338c.181.087.351.181.537.264l.027.017q-.282-.135-.564-.281zm8.878-23.376zm31.952-4.934v-.037l.007.041z" fill="url(#a)"/>
   <path d="M72.078 28.863l-.007-.041v.037z" fill="none"/>
   <path d="M75.916 26.831c-1.684-4.052-5.1-8.427-7.775-9.81a40.266 40.266 0 0 1 3.925 11.764v.037l.007.041a35.1 35.1 0 0 1-1.206 26.158c-4.442 9.531-15.194 19.3-32.024 18.825-18.185-.515-34.2-14.009-37.194-31.683-.545-2.787 0-4.2.274-6.465a28.876 28.876 0 0 0-.623 5.348v.2A38.759 38.759 0 0 0 78.254 47.8c.065-.5.118-.995.176-1.5a39.857 39.857 0 0 0-2.514-19.469z" fill="url(#b)"/>
   <path d="M75.916 26.831c-1.684-4.052-5.1-8.427-7.775-9.81a40.266 40.266 0 0 1 3.925 11.764v.037l.007.041a35.1 35.1 0 0 1-1.206 26.158c-4.442 9.531-15.194 19.3-32.024 18.825-18.185-.515-34.2-14.009-37.194-31.683-.545-2.787 0-4.2.274-6.465a28.876 28.876 0 0 0-.623 5.348v.2A38.759 38.759 0 0 0 78.254 47.8c.065-.5.118-.995.176-1.5a39.857 39.857 0 0 0-2.514-19.469z" fill="url(#c)"/>
   <path d="M57.082 31.387c.084.059.162.118.241.177a21.1 21.1 0 0 0-3.6-4.695C41.677 14.821 50.566.746 52.065.031l.015-.022c-9.735 5.7-13.038 16.252-13.342 21.53.452-.031.9-.069 1.362-.069a19.56 19.56 0 0 1 16.982 9.917z" fill="url(#d)"/>
   <path d="M40.125 33.793c-.064.964-3.47 4.289-4.661 4.289-11.021 0-12.81 6.667-12.81 6.667.488 5.614 4.4 10.238 9.129 12.684.216.112.435.213.654.312q.569.252 1.138.466a17.235 17.235 0 0 0 5.043.973c19.317.906 23.059-23.1 9.119-30.066a13.38 13.38 0 0 1 9.345 2.269A19.56 19.56 0 0 0 40.1 21.47c-.46 0-.91.038-1.362.069a19.387 19.387 0 0 0-10.666 4.111c.591.5 1.258 1.168 2.663 2.553 2.63 2.591 9.375 5.275 9.39 5.59z" fill="url(#e)"/>
   <path d="M40.125 33.793c-.064.964-3.47 4.289-4.661 4.289-11.021 0-12.81 6.667-12.81 6.667.488 5.614 4.4 10.238 9.129 12.684.216.112.435.213.654.312q.569.252 1.138.466a17.235 17.235 0 0 0 5.043.973c19.317.906 23.059-23.1 9.119-30.066a13.38 13.38 0 0 1 9.345 2.269A19.56 19.56 0 0 0 40.1 21.47c-.46 0-.91.038-1.362.069a19.387 19.387 0 0 0-10.666 4.111c.591.5 1.258 1.168 2.663 2.553 2.63 2.591 9.375 5.275 9.39 5.59z" fill="url(#f)"/>
   <path d="M31.246 57.169q.282.145.564.281l-.027-.017c-.183-.083-.356-.177-.537-.264z" fill="url(#g)"/>
@@ -123,12 +143,12 @@
   <path d="M26.265 24.361c.314.2.573.374.8.531a17.968 17.968 0 0 1-.109-9.473 28.705 28.705 0 0 0-9.329 7.21c.189-.005 5.811-.106 8.638 1.732z" fill="url(#i)"/>
   <path d="M1.654 42.163c2.991 17.674 19.009 31.168 37.194 31.683 16.83.476 27.582-9.294 32.024-18.825a35.1 35.1 0 0 0 1.206-26.158v-.037c0-.029-.006-.046 0-.037l.007.065c1.375 8.977-3.191 17.674-10.329 23.555l-.022.05c-13.908 11.327-27.218 6.834-29.912 5q-.282-.135-.564-.281c-8.109-3.876-11.459-11.264-10.741-17.6a9.953 9.953 0 0 1-9.181-5.775 14.618 14.618 0 0 1 14.249-.572 19.3 19.3 0 0 0 14.552.572c-.015-.315-6.76-3-9.39-5.59-1.405-1.385-2.072-2.052-2.663-2.553a11.587 11.587 0 0 0-1-.758c-.23-.157-.489-.327-.8-.531-2.827-1.838-8.449-1.737-8.635-1.732h-.018c-1.536-1.947-1.428-8.367-1.34-9.708a6.928 6.928 0 0 0-1.294.687 28.225 28.225 0 0 0-3.788 3.245A33.845 33.845 0 0 0 7.571 21.2v.006-.007a32.733 32.733 0 0 0-5.2 11.743c-.019.079-1.396 6.099-.717 9.221z" fill="url(#j)"/>
   <path fill="#ff4aa2" d="M40.125 33.793h-.001.001z"/>
   <path d="M53.725 26.869a21.1 21.1 0 0 1 3.6 4.7c.213.161.412.321.581.476 8.787 8.1 4.183 19.55 3.84 20.365 7.138-5.881 11.7-14.578 10.329-23.555C67.691 17.925 60.26 13.52 54.191 3.928c-.307-.485-.614-.971-.913-1.484-.171-.293-.308-.557-.427-.8a7.053 7.053 0 0 1-.578-1.535.1.1 0 0 0-.088-.1.138.138 0 0 0-.073 0c-.005 0-.013.009-.019.011s-.019.011-.028.015c-1.499.711-10.388 14.786 1.66 26.834z" fill="url(#k)"/>
   <path d="M57.9 32.04c-.169-.155-.368-.315-.581-.476-.079-.059-.157-.118-.241-.177a13.38 13.38 0 0 0-9.345-2.269c13.94 6.97 10.2 30.972-9.119 30.066a17.235 17.235 0 0 1-5.043-.973q-.569-.213-1.138-.466c-.219-.1-.438-.2-.654-.312l.027.017c2.694 1.839 16 6.332 29.912-5l.022-.05c.347-.81 4.951-12.263-3.84-20.36z" fill="url(#l)"/>
   <path d="M22.654 44.749s1.789-6.667 12.81-6.667c1.191 0 4.6-3.325 4.661-4.289a19.3 19.3 0 0 1-14.552-.572 14.618 14.618 0 0 0-14.249.572 9.953 9.953 0 0 0 9.181 5.775c-.718 6.337 2.632 13.725 10.741 17.6.181.087.351.181.537.264-4.733-2.445-8.641-7.069-9.129-12.683z" fill="url(#m)"/>
   <path fill="#ff4aa2" d="M49.458 38.459l-.001.001.001-.001z"/>
   <path d="M75.916 26.831c-1.684-4.052-5.1-8.427-7.775-9.81a40.266 40.266 0 0 1 3.925 11.764l.007.065C67.691 17.925 60.26 13.52 54.191 3.928c-.307-.485-.614-.971-.913-1.484-.171-.293-.308-.557-.427-.8a7.053 7.053 0 0 1-.578-1.535.1.1 0 0 0-.088-.1.138.138 0 0 0-.073 0c-.005 0-.013.009-.019.011s-.019.011-.028.015l.015-.026c-9.735 5.7-13.038 16.252-13.342 21.53.452-.031.9-.069 1.362-.069a19.56 19.56 0 0 1 16.982 9.917 13.38 13.38 0 0 0-9.345-2.269c13.94 6.97 10.2 30.972-9.119 30.066a17.235 17.235 0 0 1-5.043-.973q-.569-.213-1.138-.466c-.219-.1-.438-.2-.654-.312l.027.017q-.282-.135-.564-.281c.181.087.351.181.537.264-4.733-2.446-8.641-7.07-9.129-12.684 0 0 1.789-6.667 12.81-6.667 1.191 0 4.6-3.325 4.661-4.289-.015-.315-6.76-3-9.39-5.59-1.405-1.385-2.072-2.052-2.663-2.553a11.587 11.587 0 0 0-1-.758 17.968 17.968 0 0 1-.109-9.473 28.705 28.705 0 0 0-9.329 7.21h-.018c-1.536-1.947-1.428-8.367-1.34-9.708a6.928 6.928 0 0 0-1.294.687 28.225 28.225 0 0 0-3.788 3.245A33.845 33.845 0 0 0 7.571 21.2v.006-.007a32.733 32.733 0 0 0-5.2 11.743l-.052.256c-.073.341-.4 2.073-.447 2.445 0 .028 0-.029 0 0a45.094 45.094 0 0 0-.572 5.403v.2A38.759 38.759 0 0 0 78.254 47.8c.065-.5.118-.995.176-1.5a39.857 39.857 0 0 0-2.514-19.469zm-3.845 1.991l.007.041z" fill="url(#n)"/>
-  <path d="M96.972 23.986H118.4v5.8h-15.28v7.859h15.28v5.752h-15.28v12.642h-6.148zm28.716-2.239a3.447 3.447 0 0 1 3.557 3.6 3.579 3.579 0 0 1-7.157.088 3.555 3.555 0 0 1 3.6-3.688zm-3.03 10.581h6.06v23.711h-6.06zm23.623 6.587a4.894 4.894 0 0 0-2.942-1.054c-2.459 0-3.864 1.581-3.864 5.049v13.129h-6.015V32.328h5.752v3.425a5.649 5.649 0 0 1 5.664-3.644 7.191 7.191 0 0 1 4.04 1.229zm2.5 5.4a12.13 12.13 0 0 1 12.206-12.47c7.113 0 12.163 5.05 12.163 12.075v2.5h-18.439c.659 2.986 2.986 4.962 6.543 4.962a6.357 6.357 0 0 0 5.884-3.513l5.049 3.03c-2.5 3.688-6.059 5.62-11.109 5.62-7.684.003-12.294-5.134-12.294-12.204zm6.015-2.678h12.47c-.658-3.03-3.117-4.7-6.323-4.7a6.09 6.09 0 0 0-6.143 4.7zm19.847-9.309h4.259v-1.185c0-6.455 2.722-9.133 8.694-9.133h2.107v5.225h-1.712c-2.81 0-3.425.966-3.425 3.908v1.185h5.137v5.445h-5v18.266h-5.8V37.773h-4.259zm16.2 11.856a12.14 12.14 0 0 1 12.387-12.339 12.339 12.339 0 1 1 0 24.677 11.96 11.96 0 0 1-12.382-12.338zm18.88 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 1 0 13 0zm14.051-.264l-8.562-11.592h7.113l5.05 7.289 5.181-7.289h6.981l-8.694 11.548 9.133 12.163h-7.069l-5.664-7.728-5.489 7.728h-7.064z" fill="#20123a"/>
+  <path d="M96.972 23.986H118.4v5.8h-15.28v7.859h15.28v5.752h-15.28v12.642h-6.148zm28.716-2.239a3.447 3.447 0 0 1 3.557 3.6 3.579 3.579 0 0 1-7.157.088 3.555 3.555 0 0 1 3.6-3.688zm-3.03 10.581h6.06v23.711h-6.06zm23.623 6.587a4.894 4.894 0 0 0-2.942-1.054c-2.459 0-3.864 1.581-3.864 5.049v13.129h-6.015V32.328h5.752v3.425a5.649 5.649 0 0 1 5.664-3.644 7.191 7.191 0 0 1 4.04 1.229zm2.5 5.4a12.13 12.13 0 0 1 12.206-12.47c7.113 0 12.163 5.05 12.163 12.075v2.5h-18.439c.659 2.986 2.986 4.962 6.543 4.962a6.357 6.357 0 0 0 5.884-3.513l5.049 3.03c-2.5 3.688-6.059 5.62-11.109 5.62-7.684.003-12.294-5.134-12.294-12.204zm6.015-2.678h12.47c-.658-3.03-3.117-4.7-6.323-4.7a6.09 6.09 0 0 0-6.143 4.7zm19.847-9.309h4.259v-1.185c0-6.455 2.722-9.133 8.694-9.133h2.107v5.225h-1.712c-2.81 0-3.425.966-3.425 3.908v1.185h5.137v5.445h-5v18.266h-5.8V37.773h-4.259zm16.2 11.856a12.14 12.14 0 0 1 12.387-12.339 12.339 12.339 0 1 1 0 24.677 11.96 11.96 0 0 1-12.382-12.338zm18.88 0a6.5 6.5 0 1 0-13 0 6.5 6.5 0 1 0 13 0zm14.051-.264l-8.562-11.592h7.113l5.05 7.289 5.181-7.289h6.981l-8.694 11.548 9.133 12.163h-7.069l-5.664-7.728-5.489 7.728h-7.064z" fill="context-fill #20123a"/>
   <path d="M275.015 39.484a7.41 7.41 0 0 0 4.266-6.948c0-5.189-3.958-8.532-9.939-8.532h-13.721v32.1h14.161c6.068 0 10.158-3.43 10.158-9.059a7.711 7.711 0 0 0-4.925-7.561zm-15.744-12.137H269.3c3.913 0 6.332 2.111 6.332 5.189s-2.11 5.365-6.024 5.365h-10.337zm10.467 25.374h-10.467V41.287h10.291c4.4 0 6.685 2.331 6.685 5.717 0 3.342-2.547 5.717-6.509 5.717zm18.032-15.876V32.36h-3.47v23.747h3.563V43.09c0-5.233 2.286-7.52 6.244-7.52a5.2 5.2 0 0 1 2.9.748l1.5-3.43a7.758 7.758 0 0 0-3.958-.88 6.576 6.576 0 0 0-6.779 4.837zm23.22-4.969a12.357 12.357 0 1 0 12.357 12.358 12.193 12.193 0 0 0-12.357-12.358zm0 21.285a8.607 8.607 0 0 1-8.663-8.927 8.69 8.69 0 1 1 17.371 0 8.642 8.642 0 0 1-8.708 8.927zm41.3-2.112l-7.084-18.689h-3.342l-7.256 18.821-5.981-18.821h-3.782l7.784 23.747h3.518l7.3-18.821 7.3 18.821H354l8.224-23.747h-3.738zm22.649-8.663c-3.694-.747-6.553-1.231-6.553-3.693 0-2.2 1.5-3.782 5.146-3.782a7.666 7.666 0 0 1 6.509 3.166l2.99-2.023a11.479 11.479 0 0 0-9.5-4.221c-5.629-.044-8.839 3.209-8.839 6.9 0 4.749 4.353 5.848 8.443 6.639 3.474.705 6.728 1.232 6.728 3.871 0 2.375-1.935 4.133-5.629 4.133a8.771 8.771 0 0 1-7.651-3.87l-3.123 2.112c2.111 3.034 5.5 4.968 10.686 4.968 6.2.044 9.367-3.649 9.367-7.387-.002-4.877-4.487-6.021-8.577-6.813zm23.925-10.51a12.18 12.18 0 0 0-12.4 12.446c0 6.948 4.925 12.268 12.533 12.268a12.2 12.2 0 0 0 11.038-6.024l-3.078-1.8a8.489 8.489 0 0 1-7.96 4.573c-5.013 0-8.488-3.21-9.015-7.739h20.977v-1.631a11.714 11.714 0 0 0-12.098-12.093zm-8.8 10.554a8.821 8.821 0 0 1 8.8-7.344 8 8 0 0 1 8.4 7.344zm35.447-10.422a6.575 6.575 0 0 0-6.772 4.837V32.36h-3.475v23.747h3.563V43.09c0-5.233 2.286-7.52 6.244-7.52a5.2 5.2 0 0 1 2.9.748l1.5-3.43a7.754 7.754 0 0 0-3.958-.88z" fill="context-fill #20123a"/>
-  <path d="M107.313 74.816l-7.026-10.6h-3.315v15.57h3.008V68.843l7.245 10.943h3.075V64.213h-2.986zm6.518 4.97h3.14V64.213h-3.14zm14.007-6.058h5.094a4.376 4.376 0 0 1-4.567 3.37 5.011 5.011 0 0 1-5.226-5.1 5.086 5.086 0 0 1 5.182-5.142 4.882 4.882 0 0 1 4.237 2.155l2.613-1.771a8.279 8.279 0 0 0-6.85-3.24 8.006 8.006 0 1 0 .088 16 7.621 7.621 0 0 0 7.86-7.787v-1.3h-8.431zm20.962-3.243h-6.478v-6.272h-3.117v15.573h3.117v-6.357h6.478v6.357h3.1V64.213h-3.1zm6.035-3.5h4.465v12.8h3.052v-12.8h4.412v-2.772h-11.926zm17.979-2.773H169.7v15.574h10.516v-2.922h-7.4zm16.774 0l-3.62 6.188-3.623-6.187h-3.4l5.445 9v6.57h3.11V73.28l5.468-9.067z" fill="url(#o)"/>
+  <path d="M107.313 74.816l-7.026-10.6h-3.315v15.57h3.008V68.843l7.245 10.943h3.075V64.213h-2.986zm6.518 4.97h3.14V64.213h-3.14zm14.007-6.058h5.094a4.376 4.376 0 0 1-4.567 3.37 5.011 5.011 0 0 1-5.226-5.1 5.086 5.086 0 0 1 5.182-5.142 4.882 4.882 0 0 1 4.237 2.155l2.613-1.771a8.279 8.279 0 0 0-6.85-3.24 8.006 8.006 0 1 0 .088 16 7.621 7.621 0 0 0 7.86-7.787v-1.3h-8.431zm20.962-3.243h-6.478v-6.272h-3.117v15.573h3.117v-6.357h6.478v6.357h3.1V64.213h-3.1zm6.035-3.5h4.465v12.8h3.052v-12.8h4.412v-2.772h-11.926zm17.979-2.773H169.7v15.574h10.516v-2.922h-7.4zm16.774 0l-3.62 6.188-3.623-6.187h-3.4l5.445 9v6.57h3.11V73.28l5.468-9.067z" class="channel-name" />
 </svg>
--- a/browser/branding/nightly/pref/firefox-branding.js
+++ b/browser/branding/nightly/pref/firefox-branding.js
@@ -1,12 +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/. */
 
+// This file contains branding-specific prefs.
+
 pref("startup.homepage_override_url", "https://www.mozilla.org/projects/firefox/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
 pref("startup.homepage_welcome_url", "https://www.mozilla.org/projects/firefox/%VERSION%/firstrun/");
 pref("startup.homepage_welcome_url.additional", "");
 // The time interval between checks for a new version (in seconds)
 pref("app.update.interval", 7200); // 2 hours
 // Give the user x seconds to react before showing the big UI. default=12 hours
 pref("app.update.promptWaitTime", 43200);
 // URL user can browse to manually if for some reason all update installation
--- a/browser/branding/official/pref/firefox-branding.js
+++ b/browser/branding/official/pref/firefox-branding.js
@@ -1,12 +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/. */
 
+// This file contains branding-specific prefs.
+
 pref("startup.homepage_override_url", "");
 pref("startup.homepage_welcome_url", "about:welcome");
 pref("startup.homepage_welcome_url.additional", "");
 // Interval: Time between checks for a new version (in seconds)
 pref("app.update.interval", 43200); // 12 hours
 // Give the user x seconds to react before showing the big UI. default=192 hours
 pref("app.update.promptWaitTime", 691200);
 // app.update.url.manual: URL user can browse to manually if for some reason
--- a/browser/branding/unofficial/pref/firefox-branding.js
+++ b/browser/branding/unofficial/pref/firefox-branding.js
@@ -1,12 +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/. */
 
+// This file contains branding-specific prefs.
+
 pref("startup.homepage_override_url", "");
 pref("startup.homepage_welcome_url", "");
 pref("startup.homepage_welcome_url.additional", "");
 // The time interval between checks for a new version (in seconds)
 pref("app.update.interval", 86400); // 24 hours
 // Give the user x seconds to react before showing the big UI. default=24 hours
 pref("app.update.promptWaitTime", 86400);
 // URL user can browse to manually if for some reason all update installation
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -123,45 +123,32 @@ let ACTORS = {
     child: {
       moduleURI: "resource:///actors/SwitchDocumentDirectionChild.jsm",
 
       messages: ["SwitchDocumentDirection"],
     },
 
     allFrames: true,
   },
-
-  SubframeCrash: {
-    parent: {
-      moduleURI: "resource:///actors/SubframeCrashParent.jsm",
-    },
-
-    child: {
-      moduleURI: "resource:///actors/SubframeCrashChild.jsm",
-    },
-
-    allFrames: true,
-  },
 };
 
 let LEGACY_ACTORS = {
   AboutLogins: {
     child: {
       matches: ["about:logins", "about:logins?*"],
       module: "resource:///actors/AboutLoginsChild.jsm",
       events: {
         AboutLoginsCopyLoginDetail: { wantUntrusted: true },
         AboutLoginsCreateLogin: { wantUntrusted: true },
         AboutLoginsDeleteLogin: { wantUntrusted: true },
         AboutLoginsDismissBreachAlert: { wantUntrusted: true },
         AboutLoginsHideFooter: { wantUntrusted: true },
         AboutLoginsImport: { wantUntrusted: true },
         AboutLoginsInit: { wantUntrusted: true },
-        AboutLoginsOpenFAQ: { wantUntrusted: true },
-        AboutLoginsOpenFeedback: { wantUntrusted: true },
+        AboutLoginsGetHelp: { wantUntrusted: true },
         AboutLoginsOpenMobileAndroid: { wantUntrusted: true },
         AboutLoginsOpenMobileIos: { wantUntrusted: true },
         AboutLoginsOpenPreferences: { wantUntrusted: true },
         AboutLoginsOpenSite: { wantUntrusted: true },
         AboutLoginsRecordTelemetryEvent: { wantUntrusted: true },
         AboutLoginsSyncEnable: { wantUntrusted: true },
         AboutLoginsSyncOptions: { wantUntrusted: true },
         AboutLoginsUpdateLogin: { wantUntrusted: true },
@@ -514,31 +501,33 @@ XPCOMUtils.defineLazyModuleGetters(this,
   Corroborate: "resource://gre/modules/Corroborate.jsm",
   Discovery: "resource:///modules/Discovery.jsm",
   ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
   FirefoxMonitor: "resource:///modules/FirefoxMonitor.jsm",
   FxAccounts: "resource://gre/modules/FxAccounts.jsm",
   HomePage: "resource:///modules/HomePage.jsm",
   HybridContentTelemetry: "resource://gre/modules/HybridContentTelemetry.jsm",
   Integration: "resource://gre/modules/Integration.jsm",
+  LoginBreaches: "resource:///modules/LoginBreaches.jsm",
   LiveBookmarkMigrator: "resource:///modules/LiveBookmarkMigrator.jsm",
   NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
   Normandy: "resource://normandy/Normandy.jsm",
   ObjectUtils: "resource://gre/modules/ObjectUtils.jsm",
   OS: "resource://gre/modules/osfile.jsm",
   PageActions: "resource:///modules/PageActions.jsm",
   PageThumbs: "resource://gre/modules/PageThumbs.jsm",
   PdfJs: "resource://pdf.js/PdfJs.jsm",
   PermissionUI: "resource:///modules/PermissionUI.jsm",
   PingCentre: "resource:///modules/PingCentre.jsm",
   PlacesBackups: "resource://gre/modules/PlacesBackups.jsm",
   PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
   PluralForm: "resource://gre/modules/PluralForm.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
+  PublicSuffixList: "resource://gre/modules/netwerk-dns/PublicSuffixList.jsm",
   RemoteSettings: "resource://services-settings/remote-settings.js",
   RemoteSecuritySettings:
     "resource://gre/modules/psm/RemoteSecuritySettings.jsm",
   RFPHelper: "resource://gre/modules/RFPHelper.jsm",
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SaveToPocket: "chrome://pocket/content/SaveToPocket.jsm",
   SearchTelemetry: "resource:///modules/SearchTelemetry.jsm",
@@ -645,17 +634,17 @@ const listeners = {
   mm: {
     "AboutLogins:CreateLogin": ["AboutLoginsParent"],
     "AboutLogins:DeleteLogin": ["AboutLoginsParent"],
     "AboutLogins:DismissBreachAlert": ["AboutLoginsParent"],
     "AboutLogins:HideFooter": ["AboutLoginsParent"],
     "AboutLogins:Import": ["AboutLoginsParent"],
     "AboutLogins:MasterPasswordRequest": ["AboutLoginsParent"],
     "AboutLogins:OpenFAQ": ["AboutLoginsParent"],
-    "AboutLogins:OpenFeedback": ["AboutLoginsParent"],
+    "AboutLogins:GetHelp": ["AboutLoginsParent"],
     "AboutLogins:OpenPreferences": ["AboutLoginsParent"],
     "AboutLogins:OpenMobileAndroid": ["AboutLoginsParent"],
     "AboutLogins:OpenMobileIos": ["AboutLoginsParent"],
     "AboutLogins:OpenSite": ["AboutLoginsParent"],
     "AboutLogins:Subscribe": ["AboutLoginsParent"],
     "AboutLogins:SyncEnable": ["AboutLoginsParent"],
     "AboutLogins:SyncOptions": ["AboutLoginsParent"],
     "AboutLogins:UpdateLogin": ["AboutLoginsParent"],
@@ -985,16 +974,18 @@ BrowserGlue.prototype = {
         } else if (data == "migrateMatchBucketsPrefForUI66") {
           this._migrateMatchBucketsPrefForUI66().then(() => {
             Services.obs.notifyObservers(
               null,
               "browser-glue-test",
               "migrateMatchBucketsPrefForUI66-done"
             );
           });
+        } else if (data == "add-breaches-sync-handler") {
+          this._addBreachesSyncHandler();
         }
         break;
       case "initial-migration-will-import-default-bookmarks":
         this._migrationImportsDefaultBookmarks = true;
         break;
       case "initial-migration-did-import-default-bookmarks":
         this._initPlaces(true);
         break;
@@ -2198,23 +2189,44 @@ BrowserGlue.prototype = {
       this._gmpInstallManager = new obj.GMPInstallManager();
       // We don't really care about the results, if someone is interested they
       // can check the log.
       this._gmpInstallManager.simpleCheckAndInstall().catch(() => {});
     });
 
     Services.tm.idleDispatchToMainThread(() => {
       RemoteSettings.init();
+      this._addBreachesSyncHandler();
+    });
+
+    Services.tm.idleDispatchToMainThread(() => {
+      PublicSuffixList.init();
     });
 
     Services.tm.idleDispatchToMainThread(() => {
       RemoteSecuritySettings.init();
     });
   },
 
+  _addBreachesSyncHandler() {
+    if (
+      Services.prefs.getBoolPref(
+        "signon.management.page.breach-alerts.enabled",
+        false
+      )
+    ) {
+      RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).on(
+        "sync",
+        async event => {
+          await LoginBreaches.update(event.data.current);
+        }
+      );
+    }
+  },
+
   _onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {
     // If user has already dismissed quit request, then do nothing
     if (aCancelQuit instanceof Ci.nsISupportsPRBool && aCancelQuit.data) {
       return;
     }
 
     // There are several cases where we won't show a dialog here:
     // 1. There is only 1 tab open in 1 window
--- a/browser/components/about/AboutProtectionsHandler.jsm
+++ b/browser/components/about/AboutProtectionsHandler.jsm
@@ -10,30 +10,22 @@ var EXPORTED_SYMBOLS = ["AboutProtection
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 const { RemotePages } = ChromeUtils.import(
   "resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm"
 );
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "fxAccounts",
-  "resource://gre/modules/FxAccounts.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "LoginHelper",
-  "resource://gre/modules/LoginHelper.jsm"
-);
-
 XPCOMUtils.defineLazyModuleGetters(this, {
+  fxAccounts: "resource://gre/modules/FxAccounts.jsm",
   FXA_PWDMGR_HOST: "resource://gre/modules/FxAccountsCommon.js",
   FXA_PWDMGR_REALM: "resource://gre/modules/FxAccountsCommon.js",
+  LoginBreaches: "resource:///modules/LoginBreaches.jsm",
+  LoginHelper: "resource://gre/modules/LoginHelper.jsm",
 });
 
 XPCOMUtils.defineLazyServiceGetter(
   this,
   "TrackingDBService",
   "@mozilla.org/tracking-db-service;1",
   "nsITrackingDBService"
 );
@@ -208,17 +200,17 @@ var AboutProtectionsHandler = {
     try {
       if ((await fxAccounts.accountStatus()) && token) {
         monitorData = await this.fetchUserBreachStats(token);
 
         // Get the stats for number of potentially breached Lockwise passwords if no master
         // password is set.
         if (!LoginHelper.isMasterPasswordSet()) {
           const logins = await LoginHelper.getAllUserFacingLogins();
-          potentiallyBreachedLogins = await LoginHelper.getBreachesForLogins(
+          potentiallyBreachedLogins = await LoginBreaches.getPotentialBreachesByLoginGUID(
             logins
           );
         }
       } else {
         // If no account exists, then the user is not logged in with an fxAccount.
         monitorData = {
           errorMessage: "No account",
         };
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -242,19 +242,21 @@ class PrefRow {
         this.editButton.className = "primary button-save";
       } else {
         delete this.inputField;
         for (let type of ["Boolean", "Number", "String"]) {
           let radio = document.createElement("input");
           radio.type = "radio";
           radio.name = "type";
           radio.value = type;
+          radio.id = `add-type-${type}`;
           radio.checked = this.type == type;
           form.appendChild(radio);
-          let radioLabel = document.createElement("span");
+          let radioLabel = document.createElement("label");
+          radioLabel.setAttribute("for", radio.id);
           document.l10n.setAttributes(radioLabel, STRINGS_ADD_BY_TYPE[type]);
           form.appendChild(radioLabel);
         }
         form.addEventListener("click", event => {
           if (event.target.name != "type") {
             return;
           }
           let type = event.target.value;
--- a/browser/components/aboutlogins/AboutLoginsChild.jsm
+++ b/browser/components/aboutlogins/AboutLoginsChild.jsm
@@ -99,34 +99,30 @@ class AboutLoginsChild extends ActorChil
       case "AboutLoginsHideFooter": {
         this.mm.sendAsyncMessage("AboutLogins:HideFooter");
         break;
       }
       case "AboutLoginsImport": {
         this.mm.sendAsyncMessage("AboutLogins:Import");
         break;
       }
-      case "AboutLoginsOpenFAQ": {
-        this.mm.sendAsyncMessage("AboutLogins:OpenFAQ");
-        break;
-      }
       case "AboutLoginsOpenMobileAndroid": {
         this.mm.sendAsyncMessage("AboutLogins:OpenMobileAndroid", {
           source: event.detail,
         });
         break;
       }
       case "AboutLoginsOpenMobileIos": {
         this.mm.sendAsyncMessage("AboutLogins:OpenMobileIos", {
           source: event.detail,
         });
         break;
       }
-      case "AboutLoginsOpenFeedback": {
-        this.mm.sendAsyncMessage("AboutLogins:OpenFeedback");
+      case "AboutLoginsGetHelp": {
+        this.mm.sendAsyncMessage("AboutLogins:GetHelp");
         break;
       }
       case "AboutLoginsOpenPreferences": {
         this.mm.sendAsyncMessage("AboutLogins:OpenPreferences");
         break;
       }
       case "AboutLoginsOpenSite": {
         this.mm.sendAsyncMessage("AboutLogins:OpenSite", {
--- a/browser/components/aboutlogins/AboutLoginsParent.jsm
+++ b/browser/components/aboutlogins/AboutLoginsParent.jsm
@@ -4,57 +4,42 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["AboutLoginsParent"];
 
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
-ChromeUtils.defineModuleGetter(
-  this,
-  "E10SUtils",
-  "resource://gre/modules/E10SUtils.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "LoginHelper",
-  "resource://gre/modules/LoginHelper.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "MigrationUtils",
-  "resource:///modules/MigrationUtils.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "Services",
-  "resource://gre/modules/Services.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "UIState",
-  "resource://services-sync/UIState.jsm"
-);
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "PlacesUtils",
-  "resource://gre/modules/PlacesUtils.jsm"
-);
+XPCOMUtils.defineLazyModuleGetters(this, {
+  E10SUtils: "resource://gre/modules/E10SUtils.jsm",
+  LoginBreaches: "resource:///modules/LoginBreaches.jsm",
+  LoginHelper: "resource://gre/modules/LoginHelper.jsm",
+  MigrationUtils: "resource:///modules/MigrationUtils.jsm",
+  Services: "resource://gre/modules/Services.jsm",
+  UIState: "resource://services-sync/UIState.jsm",
+  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
+});
 
 XPCOMUtils.defineLazyGetter(this, "log", () => {
   return LoginHelper.createLogger("AboutLoginsParent");
 });
 XPCOMUtils.defineLazyPreferenceGetter(
   this,
   "BREACH_ALERTS_ENABLED",
   "signon.management.page.breach-alerts.enabled",
   false
 );
+XPCOMUtils.defineLazyPreferenceGetter(
+  this,
+  "FXA_ENABLED",
+  "identity.fxaccounts.enabled",
+  false
+);
 
 const ABOUT_LOGINS_ORIGIN = "about:logins";
 const MASTER_PASSWORD_NOTIFICATION_ID = "master-password-login-required";
 const PASSWORD_SYNC_NOTIFICATION_ID = "enable-password-sync";
 
 const HIDE_MOBILE_FOOTER_PREF = "signon.management.page.hideMobileFooter";
 
 // about:logins will always use the privileged content process,
@@ -80,22 +65,27 @@ const augmentVanillaLoginObject = login 
 };
 
 var AboutLoginsParent = {
   _l10n: null,
   _subscribers: new WeakSet(),
 
   // Listeners are added in BrowserGlue.jsm
   async receiveMessage(message) {
-    // Only respond to messages sent from about:logins.
-    if (
-      message.target.remoteType != EXPECTED_ABOUTLOGINS_REMOTE_TYPE ||
-      message.target.contentPrincipal.originNoSuffix != ABOUT_LOGINS_ORIGIN
-    ) {
-      return;
+    // Only respond to messages sent from a privlegedabout process. Ideally
+    // we would also check the contentPrincipal.originNoSuffix but this
+    // check has been removed due to bug 1576722.
+    if (message.target.remoteType != EXPECTED_ABOUTLOGINS_REMOTE_TYPE) {
+      throw new Error(
+        `AboutLoginsParent: Received ${
+          message.name
+        } message the remote type didn't match expectations: ${
+          message.target.remoteType
+        } == ${EXPECTED_ABOUTLOGINS_REMOTE_TYPE}`
+      );
     }
 
     switch (message.name) {
       case "AboutLogins:CreateLogin": {
         let newLogin = message.data.login;
         // Remove the path from the origin, if it was provided.
         let origin = LoginHelper.getLoginOrigin(newLogin.origin);
         if (!origin) {
@@ -116,19 +106,19 @@ var AboutLoginsParent = {
       case "AboutLogins:DeleteLogin": {
         let login = LoginHelper.vanillaObjectToLogin(message.data.login);
         Services.logins.removeLogin(login);
         break;
       }
       case "AboutLogins:DismissBreachAlert": {
         const login = message.data.login;
 
-        await LoginHelper.recordBreachAlertDismissal(login.guid);
+        await LoginBreaches.recordDismissal(login.guid);
         const logins = await this.getAllLogins();
-        const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+        const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
           logins
         );
         const messageManager = message.target.messageManager;
         messageManager.sendAsyncMessage(
           "AboutLogins:UpdateBreaches",
           breachesByLoginGUID
         );
         break;
@@ -152,30 +142,21 @@ var AboutLoginsParent = {
           MigrationUtils.showMigrationWizard(message.target.ownerGlobal, [
             MigrationUtils.MIGRATION_ENTRYPOINT_PASSWORDS,
           ]);
         } catch (ex) {
           Cu.reportError(ex);
         }
         break;
       }
-      case "AboutLogins:OpenFeedback": {
-        const FEEDBACK_URL_PREF = "signon.management.page.feedbackURL";
-        const FEEDBACK_URL = Services.urlFormatter.formatURLPref(
-          FEEDBACK_URL_PREF
-        );
-        message.target.ownerGlobal.openWebLinkIn(FEEDBACK_URL, "tab", {
-          relatedToCurrent: true,
-        });
-        break;
-      }
-      case "AboutLogins:OpenFAQ": {
-        const FAQ_URL_PREF = "signon.management.page.faqURL";
-        const FAQ_URL = Services.prefs.getStringPref(FAQ_URL_PREF);
-        message.target.ownerGlobal.openWebLinkIn(FAQ_URL, "tab", {
+      case "AboutLogins:GetHelp": {
+        const SUPPORT_URL =
+          Services.urlFormatter.formatURLPref("app.support.baseURL") +
+          "firefox-lockwise";
+        message.target.ownerGlobal.openWebLinkIn(SUPPORT_URL, "tab", {
           relatedToCurrent: true,
         });
         break;
       }
       case "AboutLogins:OpenMobileAndroid": {
         const MOBILE_ANDROID_URL_PREF =
           "signon.management.page.mobileAndroidURL";
         const linkTrackingSource = message.data.source;
@@ -277,19 +258,21 @@ var AboutLoginsParent = {
         this._subscribers.add(message.target);
 
         let messageManager = message.target.messageManager;
 
         const logins = await this.getAllLogins();
         try {
           messageManager.sendAsyncMessage("AboutLogins:AllLogins", logins);
 
-          let syncState = this.getSyncState();
-          messageManager.sendAsyncMessage("AboutLogins:SyncState", syncState);
-          this.updatePasswordSyncNotificationState();
+          if (FXA_ENABLED) {
+            let syncState = this.getSyncState();
+            messageManager.sendAsyncMessage("AboutLogins:SyncState", syncState);
+            this.updatePasswordSyncNotificationState();
+          }
 
           // App store badges sourced from https://developer.apple.com/app-store/marketing/guidelines/#section-badges.
           // This array mirrors the file names from the App store directory (./content/third-party/app-store)
           const appStoreLocales = [
             "az",
             "ar",
             "bg",
             "cs",
@@ -423,17 +406,17 @@ var AboutLoginsParent = {
           };
 
           messageManager.sendAsyncMessage(
             "AboutLogins:LocalizeBadges",
             selectedBadgeLanguages
           );
 
           if (BREACH_ALERTS_ENABLED) {
-            const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+            const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
               logins
             );
             messageManager.sendAsyncMessage(
               "AboutLogins:UpdateBreaches",
               breachesByLoginGUID
             );
           }
 
@@ -541,17 +524,17 @@ var AboutLoginsParent = {
         this.messageSubscribers("AboutLogins:AllLogins", []);
         break;
       }
     }
   },
 
   async getFavicon(login) {
     try {
-      const faviconData = await PlacesUtils.promiseFaviconData(login.hostname);
+      const faviconData = await PlacesUtils.promiseFaviconData(login.origin);
       return {
         faviconData,
         guid: login.guid,
       };
     } catch (ex) {
       return null;
     }
   },
copy from toolkit/components/passwordmgr/LoginHelper.jsm
copy to browser/components/aboutlogins/LoginBreaches.jsm
--- a/toolkit/components/passwordmgr/LoginHelper.jsm
+++ b/browser/components/aboutlogins/LoginBreaches.jsm
@@ -1,1143 +1,72 @@
 /* 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/. */
 
 /**
- * Contains functions shared by different Login Manager components.
- *
- * This JavaScript module exists in order to share code between the different
- * XPCOM components that constitute the Login Manager, including implementations
- * of nsILoginManager and nsILoginManagerStorage.
+ * Manages breach alerts for saved logins using data from Firefox Monitor via
+ * RemoteSettings.
  */
 
 "use strict";
 
-const EXPORTED_SYMBOLS = ["LoginHelper"];
-const REMOTE_SETTINGS_BREACHES_COLLECTION = "fxmonitor-breaches";
-
-// Globals
+const EXPORTED_SYMBOLS = ["LoginBreaches"];
 
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "RemoteSettings",
-  "resource://services-settings/remote-settings.js"
-);
-
-ChromeUtils.defineModuleGetter(
-  this,
-  "RemoteSettingsClient",
-  "resource://services-settings/RemoteSettingsClient.jsm"
-);
-
-/**
- * Contains functions shared by different Login Manager components.
- */
-this.LoginHelper = {
-  debug: null,
-  enabled: null,
-  formlessCaptureEnabled: null,
-  generationAvailable: null,
-  generationEnabled: null,
-  insecureAutofill: null,
-  managementURI: null,
-  privateBrowsingCaptureEnabled: null,
-  schemeUpgrades: null,
-  showAutoCompleteFooter: null,
-
-  init() {
-    // Watch for pref changes to update cached pref values.
-    Services.prefs.addObserver("signon.", () => this.updateSignonPrefs());
-    this.updateSignonPrefs();
-    Services.telemetry.setEventRecordingEnabled("pwmgr", true);
-  },
-
-  updateSignonPrefs() {
-    this.autofillForms = Services.prefs.getBoolPref("signon.autofillForms");
-    this.autofillAutocompleteOff = Services.prefs.getBoolPref(
-      "signon.autofillForms.autocompleteOff"
-    );
-    this.debug = Services.prefs.getBoolPref("signon.debug");
-    this.enabled = Services.prefs.getBoolPref("signon.rememberSignons");
-    this.formlessCaptureEnabled = Services.prefs.getBoolPref(
-      "signon.formlessCapture.enabled"
-    );
-    this.generationAvailable = Services.prefs.getBoolPref(
-      "signon.generation.available"
-    );
-    this.generationEnabled = Services.prefs.getBoolPref(
-      "signon.generation.enabled"
-    );
-    this.insecureAutofill = Services.prefs.getBoolPref(
-      "signon.autofillForms.http"
-    );
-    this.managementURI = Services.prefs.getStringPref(
-      "signon.management.overrideURI",
-      null
-    );
-    this.privateBrowsingCaptureEnabled = Services.prefs.getBoolPref(
-      "signon.privateBrowsingCapture.enabled"
-    );
-    this.schemeUpgrades = Services.prefs.getBoolPref("signon.schemeUpgrades");
-    this.showAutoCompleteFooter = Services.prefs.getBoolPref(
-      "signon.showAutoCompleteFooter"
-    );
-    this.storeWhenAutocompleteOff = Services.prefs.getBoolPref(
-      "signon.storeWhenAutocompleteOff"
-    );
-  },
-
-  createLogger(aLogPrefix) {
-    let getMaxLogLevel = () => {
-      return this.debug ? "Debug" : "Warn";
-    };
-
-    // Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
-    let consoleOptions = {
-      maxLogLevel: getMaxLogLevel(),
-      prefix: aLogPrefix,
-    };
-    let logger = console.createInstance(consoleOptions);
-
-    // Watch for pref changes and update this.debug and the maxLogLevel for created loggers
-    Services.prefs.addObserver("signon.debug", () => {
-      this.debug = Services.prefs.getBoolPref("signon.debug");
-      if (logger) {
-        logger.maxLogLevel = getMaxLogLevel();
-      }
-    });
-
-    return logger;
-  },
-
-  /**
-   * Due to the way the signons2.txt file is formatted, we need to make
-   * sure certain field values or characters do not cause the file to
-   * be parsed incorrectly.  Reject origins that we can't store correctly.
-   *
-   * @throws String with English message in case validation failed.
-   */
-  checkOriginValue(aOrigin) {
-    // Nulls are invalid, as they don't round-trip well.  Newlines are also
-    // invalid for any field stored as plaintext, and an origin made of a
-    // single dot cannot be stored in the legacy format.
-    if (
-      aOrigin == "." ||
-      aOrigin.includes("\r") ||
-      aOrigin.includes("\n") ||
-      aOrigin.includes("\0")
-    ) {
-      throw new Error("Invalid origin");
-    }
-  },
-
-  /**
-   * Due to the way the signons2.txt file is formatted, we need to make
-   * sure certain field values or characters do not cause the file to
-   * be parsed incorrectly.  Reject logins that we can't store correctly.
-   *
-   * @throws String with English message in case validation failed.
-   */
-  checkLoginValues(aLogin) {
-    function badCharacterPresent(l, c) {
-      return (
-        (l.formActionOrigin && l.formActionOrigin.includes(c)) ||
-        (l.httpRealm && l.httpRealm.includes(c)) ||
-        l.origin.includes(c) ||
-        l.usernameField.includes(c) ||
-        l.passwordField.includes(c)
-      );
-    }
-
-    // Nulls are invalid, as they don't round-trip well.
-    // Mostly not a formatting problem, although ".\0" can be quirky.
-    if (badCharacterPresent(aLogin, "\0")) {
-      throw new Error("login values can't contain nulls");
-    }
-
-    // In theory these nulls should just be rolled up into the encrypted
-    // values, but nsISecretDecoderRing doesn't use nsStrings, so the
-    // nulls cause truncation. Check for them here just to avoid
-    // unexpected round-trip surprises.
-    if (aLogin.username.includes("\0") || aLogin.password.includes("\0")) {
-      throw new Error("login values can't contain nulls");
-    }
-
-    // Newlines are invalid for any field stored as plaintext.
-    if (
-      badCharacterPresent(aLogin, "\r") ||
-      badCharacterPresent(aLogin, "\n")
-    ) {
-      throw new Error("login values can't contain newlines");
-    }
-
-    // A line with just a "." can have special meaning.
-    if (aLogin.usernameField == "." || aLogin.formActionOrigin == ".") {
-      throw new Error("login values can't be periods");
-    }
-
-    // An origin with "\ \(" won't roundtrip.
-    // eg host="foo (", realm="bar" --> "foo ( (bar)"
-    // vs host="foo", realm=" (bar" --> "foo ( (bar)"
-    if (aLogin.origin.includes(" (")) {
-      throw new Error("bad parens in origin");
-    }
-  },
-
-  /**
-   * Returns a new XPCOM property bag with the provided properties.
-   *
-   * @param {Object} aProperties
-   *        Each property of this object is copied to the property bag.  This
-   *        parameter can be omitted to return an empty property bag.
-   *
-   * @return A new property bag, that is an instance of nsIWritablePropertyBag,
-   *         nsIWritablePropertyBag2, nsIPropertyBag, and nsIPropertyBag2.
-   */
-  newPropertyBag(aProperties) {
-    let propertyBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
-      Ci.nsIWritablePropertyBag
-    );
-    if (aProperties) {
-      for (let [name, value] of Object.entries(aProperties)) {
-        propertyBag.setProperty(name, value);
-      }
-    }
-    return propertyBag
-      .QueryInterface(Ci.nsIPropertyBag)
-      .QueryInterface(Ci.nsIPropertyBag2)
-      .QueryInterface(Ci.nsIWritablePropertyBag2);
-  },
-
-  /**
-   * Helper to avoid the property bags when calling
-   * Services.logins.searchLogins from JS.
-   *
-   * @param {Object} aSearchOptions - A regular JS object to copy to a property bag before searching
-   * @return {nsILoginInfo[]} - The result of calling searchLogins.
-   */
-  searchLoginsWithObject(aSearchOptions) {
-    return Services.logins.searchLogins(this.newPropertyBag(aSearchOptions));
-  },
-
-  /**
-   * @param {string} aURL
-   * @returns {string} which is the hostPort of aURL if supported by the scheme
-   *                   otherwise, returns the original aURL.
-   */
-  maybeGetHostPortForURL(aURL) {
-    try {
-      let uri = Services.io.newURI(aURL);
-      return uri.hostPort;
-    } catch (ex) {
-      // No need to warn for javascript:/data:/about:/chrome:/etc.
-    }
-    return aURL;
-  },
-
-  /**
-   * Get the parts of the URL we want for identification.
-   * Strip out things like the userPass portion and handle javascript:.
-   */
-  getLoginOrigin(uriString, allowJS) {
-    let realm = "";
-    try {
-      let uri = Services.io.newURI(uriString);
-
-      if (allowJS && uri.scheme == "javascript") {
-        return "javascript:";
-      }
-      // TODO: Bug 1559205 - Add support for moz-proxy
-
-      // Build this manually instead of using prePath to avoid including the userPass portion.
-      realm = uri.scheme + "://" + uri.displayHostPort;
-    } catch (e) {
-      // bug 159484 - disallow url types that don't support a hostPort.
-      // (although we handle "javascript:..." as a special case above.)
-      log.warn("Couldn't parse origin for", uriString, e);
-      realm = null;
-    }
-
-    return realm;
-  },
-
-  getFormActionOrigin(form) {
-    let uriString = form.action;
-
-    // A blank or missing action submits to where it came from.
-    if (uriString == "") {
-      // ala bug 297761
-      uriString = form.baseURI;
-    }
-
-    return this.getLoginOrigin(uriString, true);
-  },
-
-  /**
-   * @param {String} aLoginOrigin - An origin value from a stored login's
-   *                                origin or formActionOrigin properties.
-   * @param {String} aSearchOrigin - The origin that was are looking to match
-   *                                 with aLoginOrigin. This would normally come
-   *                                 from a form or page that we are considering.
-   * @param {nsILoginFindOptions} aOptions - Options to affect whether the origin
-   *                                         from the login (aLoginOrigin) is a
-   *                                         match for the origin we're looking
-   *                                         for (aSearchOrigin).
-   */
-  isOriginMatching(
-    aLoginOrigin,
-    aSearchOrigin,
-    aOptions = {
-      schemeUpgrades: false,
-      acceptWildcardMatch: false,
-      acceptDifferentSubdomains: false,
-    }
-  ) {
-    if (aLoginOrigin == aSearchOrigin) {
-      return true;
-    }
-
-    if (!aOptions) {
-      return false;
-    }
-
-    if (aOptions.acceptWildcardMatch && aLoginOrigin == "") {
-      return true;
-    }
-
-    try {
-      let loginURI = Services.io.newURI(aLoginOrigin);
-      let searchURI = Services.io.newURI(aSearchOrigin);
-      let schemeMatches =
-        loginURI.scheme == "http" && searchURI.scheme == "https";
-
-      if (aOptions.acceptDifferentSubdomains) {
-        let loginBaseDomain = Services.eTLD.getBaseDomain(loginURI);
-        let searchBaseDomain = Services.eTLD.getBaseDomain(searchURI);
-        if (
-          loginBaseDomain == searchBaseDomain &&
-          (loginURI.scheme == searchURI.scheme ||
-            (aOptions.schemeUpgrades && schemeMatches))
-        ) {
-          return true;
-        }
-      }
-
-      if (
-        aOptions.schemeUpgrades &&
-        loginURI.host == searchURI.host &&
-        schemeMatches &&
-        loginURI.port == searchURI.port
-      ) {
-        return true;
-      }
-    } catch (ex) {
-      // newURI will throw for some values e.g. chrome://FirefoxAccounts
-      // uri.host and uri.port will throw for some values e.g. javascript:
-      return false;
-    }
-
-    return false;
-  },
-
-  doLoginsMatch(
-    aLogin1,
-    aLogin2,
-    { ignorePassword = false, ignoreSchemes = false }
-  ) {
-    if (
-      aLogin1.httpRealm != aLogin2.httpRealm ||
-      aLogin1.username != aLogin2.username
-    ) {
-      return false;
-    }
-
-    if (!ignorePassword && aLogin1.password != aLogin2.password) {
-      return false;
-    }
-
-    if (ignoreSchemes) {
-      let login1HostPort = this.maybeGetHostPortForURL(aLogin1.origin);
-      let login2HostPort = this.maybeGetHostPortForURL(aLogin2.origin);
-      if (login1HostPort != login2HostPort) {
-        return false;
-      }
-
-      if (
-        aLogin1.formActionOrigin != "" &&
-        aLogin2.formActionOrigin != "" &&
-        this.maybeGetHostPortForURL(aLogin1.formActionOrigin) !=
-          this.maybeGetHostPortForURL(aLogin2.formActionOrigin)
-      ) {
-        return false;
-      }
-    } else {
-      if (aLogin1.origin != aLogin2.origin) {
-        return false;
-      }
-
-      // If either formActionOrigin is blank (but not null), then match.
-      if (
-        aLogin1.formActionOrigin != "" &&
-        aLogin2.formActionOrigin != "" &&
-        aLogin1.formActionOrigin != aLogin2.formActionOrigin
-      ) {
-        return false;
-      }
-    }
-
-    // The .usernameField and .passwordField values are ignored.
-
-    return true;
-  },
-
-  /**
-   * Creates a new login object that results by modifying the given object with
-   * the provided data.
-   *
-   * @param aOldStoredLogin
-   *        Existing nsILoginInfo object to modify.
-   * @param aNewLoginData
-   *        The new login values, either as nsILoginInfo or nsIProperyBag.
-   *
-   * @return The newly created nsILoginInfo object.
-   *
-   * @throws String with English message in case validation failed.
-   */
-  buildModifiedLogin(aOldStoredLogin, aNewLoginData) {
-    function bagHasProperty(aPropName) {
-      try {
-        aNewLoginData.getProperty(aPropName);
-        return true;
-      } catch (ex) {}
-      return false;
-    }
-
-    aOldStoredLogin.QueryInterface(Ci.nsILoginMetaInfo);
-
-    let newLogin;
-    if (aNewLoginData instanceof Ci.nsILoginInfo) {
-      // Clone the existing login to get its nsILoginMetaInfo, then init it
-      // with the replacement nsILoginInfo data from the new login.
-      newLogin = aOldStoredLogin.clone();
-      newLogin.init(
-        aNewLoginData.origin,
-        aNewLoginData.formActionOrigin,
-        aNewLoginData.httpRealm,
-        aNewLoginData.username,
-        aNewLoginData.password,
-        aNewLoginData.usernameField,
-        aNewLoginData.passwordField
-      );
-      newLogin.QueryInterface(Ci.nsILoginMetaInfo);
-
-      // Automatically update metainfo when password is changed.
-      if (newLogin.password != aOldStoredLogin.password) {
-        newLogin.timePasswordChanged = Date.now();
-      }
-    } else if (aNewLoginData instanceof Ci.nsIPropertyBag) {
-      // Clone the existing login, along with all its properties.
-      newLogin = aOldStoredLogin.clone();
-      newLogin.QueryInterface(Ci.nsILoginMetaInfo);
-
-      // Automatically update metainfo when password is changed.
-      // (Done before the main property updates, lest the caller be
-      // explicitly updating both .password and .timePasswordChanged)
-      if (bagHasProperty("password")) {
-        let newPassword = aNewLoginData.getProperty("password");
-        if (newPassword != aOldStoredLogin.password) {
-          newLogin.timePasswordChanged = Date.now();
-        }
-      }
-
-      for (let prop of aNewLoginData.enumerator) {
-        switch (prop.name) {
-          // nsILoginInfo (fall through)
-          case "origin":
-          case "httpRealm":
-          case "formActionOrigin":
-          case "username":
-          case "password":
-          case "usernameField":
-          case "passwordField":
-          // nsILoginMetaInfo (fall through)
-          case "guid":
-          case "timeCreated":
-          case "timeLastUsed":
-          case "timePasswordChanged":
-          case "timesUsed":
-            newLogin[prop.name] = prop.value;
-            break;
-
-          // Fake property, allows easy incrementing.
-          case "timesUsedIncrement":
-            newLogin.timesUsed += prop.value;
-            break;
-
-          // Fail if caller requests setting an unknown property.
-          default:
-            throw new Error("Unexpected propertybag item: " + prop.name);
-        }
-      }
-    } else {
-      throw new Error("newLoginData needs an expected interface!");
-    }
-
-    // Sanity check the login
-    if (newLogin.origin == null || newLogin.origin.length == 0) {
-      throw new Error("Can't add a login with a null or empty origin.");
-    }
-
-    // For logins w/o a username, set to "", not null.
-    if (newLogin.username == null) {
-      throw new Error("Can't add a login with a null username.");
-    }
-
-    if (newLogin.password == null || newLogin.password.length == 0) {
-      throw new Error("Can't add a login with a null or empty password.");
-    }
-
-    if (newLogin.formActionOrigin || newLogin.formActionOrigin == "") {
-      // We have a form submit URL. Can't have a HTTP realm.
-      if (newLogin.httpRealm != null) {
-        throw new Error(
-          "Can't add a login with both a httpRealm and formActionOrigin."
-        );
-      }
-    } else if (newLogin.httpRealm) {
-      // We have a HTTP realm. Can't have a form submit URL.
-      if (newLogin.formActionOrigin != null) {
-        throw new Error(
-          "Can't add a login with both a httpRealm and formActionOrigin."
-        );
-      }
-    } else {
-      // Need one or the other!
-      throw new Error(
-        "Can't add a login without a httpRealm or formActionOrigin."
-      );
-    }
-
-    // Throws if there are bogus values.
-    this.checkLoginValues(newLogin);
-
-    return newLogin;
-  },
-
-  /**
-   * Remove http: logins when there is an https: login with the same username and hostPort.
-   * Sort order is preserved.
-   *
-   * @param {nsILoginInfo[]} logins
-   *        A list of logins we want to process for shadowing.
-   * @returns {nsILoginInfo[]} A subset of of the passed logins.
-   */
-  shadowHTTPLogins(logins) {
-    /**
-     * Map a (hostPort, username) to a boolean indicating whether `logins`
-     * contains an https: login for that combo.
-     */
-    let hasHTTPSByHostPortUsername = new Map();
-    for (let login of logins) {
-      let key = this.getUniqueKeyForLogin(login, ["hostPort", "username"]);
-      let hasHTTPSlogin = hasHTTPSByHostPortUsername.get(key) || false;
-      let loginURI = Services.io.newURI(login.origin);
-      hasHTTPSByHostPortUsername.set(
-        key,
-        loginURI.scheme == "https" || hasHTTPSlogin
-      );
-    }
-
-    return logins.filter(login => {
-      let key = this.getUniqueKeyForLogin(login, ["hostPort", "username"]);
-      let loginURI = Services.io.newURI(login.origin);
-      if (loginURI.scheme == "http" && hasHTTPSByHostPortUsername.get(key)) {
-        // If this is an http: login and we have an https: login for the
-        // (hostPort, username) combo then remove it.
-        return false;
-      }
-      return true;
-    });
-  },
+XPCOMUtils.defineLazyModuleGetters(this, {
+  LoginHelper: "resource://gre/modules/LoginHelper.jsm",
+  RemoteSettings: "resource://services-settings/remote-settings.js",
+  RemoteSettingsClient: "resource://services-settings/RemoteSettingsClient.jsm",
+});
 
-  /**
-   * Generate a unique key string from a login.
-   * @param {nsILoginInfo} login
-   * @param {string[]} uniqueKeys containing nsILoginInfo attribute names or "hostPort"
-   * @returns {string} to use as a key in a Map
-   */
-  getUniqueKeyForLogin(login, uniqueKeys) {
-    const KEY_DELIMITER = ":";
-    return uniqueKeys.reduce((prev, key) => {
-      let val = null;
-      if (key == "hostPort") {
-        val = Services.io.newURI(login.origin).hostPort;
-      } else {
-        val = login[key];
-      }
-
-      return prev + KEY_DELIMITER + val;
-    }, "");
-  },
-
-  /**
-   * Removes duplicates from a list of logins while preserving the sort order.
-   *
-   * @param {nsILoginInfo[]} logins
-   *        A list of logins we want to deduplicate.
-   * @param {string[]} [uniqueKeys = ["username", "password"]]
-   *        A list of login attributes to use as unique keys for the deduplication.
-   * @param {string[]} [resolveBy = ["timeLastUsed"]]
-   *        Ordered array of keyword strings used to decide which of the
-   *        duplicates should be used. "scheme" would prefer the login that has
-   *        a scheme matching `preferredOrigin`'s if there are two logins with
-   *        the same `uniqueKeys`. The default preference to distinguish two
-   *        logins is `timeLastUsed`. If there is no preference between two
-   *        logins, the first one found wins.
-   * @param {string} [preferredOrigin = undefined]
-   *        String representing the origin to use for preferring one login over
-   *        another when they are dupes. This is used with "scheme" for
-   *        `resolveBy` so the scheme from this origin will be preferred.
-   * @param {string} [preferredFormActionOrigin = undefined]
-   *        String representing the action origin to use for preferring one login over
-   *        another when they are dupes. This is used with "actionOrigin" for
-   *        `resolveBy` so the scheme from this action origin will be preferred.
-   *
-   * @returns {nsILoginInfo[]} list of unique logins.
-   */
-  dedupeLogins(
-    logins,
-    uniqueKeys = ["username", "password"],
-    resolveBy = ["timeLastUsed"],
-    preferredOrigin = undefined,
-    preferredFormActionOrigin = undefined
-  ) {
-    if (!preferredOrigin) {
-      if (resolveBy.includes("scheme")) {
-        throw new Error(
-          "dedupeLogins: `preferredOrigin` is required in order to " +
-            "prefer schemes which match it."
-        );
-      }
-      if (resolveBy.includes("subdomain")) {
-        throw new Error(
-          "dedupeLogins: `preferredOrigin` is required in order to " +
-            "prefer subdomains which match it."
-        );
-      }
-    }
-
-    let preferredOriginScheme;
-    if (preferredOrigin) {
-      try {
-        preferredOriginScheme = Services.io.newURI(preferredOrigin).scheme;
-      } catch (ex) {
-        // Handle strings that aren't valid URIs e.g. chrome://FirefoxAccounts
-      }
-    }
-
-    if (!preferredOriginScheme && resolveBy.includes("scheme")) {
-      log.warn(
-        "dedupeLogins: Deduping with a scheme preference but couldn't " +
-          "get the preferred origin scheme."
-      );
-    }
-
-    // We use a Map to easily lookup logins by their unique keys.
-    let loginsByKeys = new Map();
-
-    /**
-     * @return {bool} whether `login` is preferred over its duplicate (considering `uniqueKeys`)
-     *                `existingLogin`.
-     *
-     * `resolveBy` is a sorted array so we can return true the first time `login` is preferred
-     * over the existingLogin.
-     */
-    function isLoginPreferred(existingLogin, login) {
-      if (!resolveBy || resolveBy.length == 0) {
-        // If there is no preference, prefer the existing login.
-        return false;
-      }
-
-      for (let preference of resolveBy) {
-        switch (preference) {
-          case "actionOrigin": {
-            if (!preferredFormActionOrigin) {
-              break;
-            }
-            if (
-              LoginHelper.isOriginMatching(
-                existingLogin.formActionOrigin,
-                preferredFormActionOrigin,
-                { schemeUpgrades: LoginHelper.schemeUpgrades }
-              ) &&
-              !LoginHelper.isOriginMatching(
-                login.formActionOrigin,
-                preferredFormActionOrigin,
-                { schemeUpgrades: LoginHelper.schemeUpgrades }
-              )
-            ) {
-              return false;
-            }
-            break;
-          }
-          case "scheme": {
-            if (!preferredOriginScheme) {
-              break;
-            }
-
-            try {
-              // Only `origin` is currently considered
-              let existingLoginURI = Services.io.newURI(existingLogin.origin);
-              let loginURI = Services.io.newURI(login.origin);
-              // If the schemes of the two logins are the same or neither match the
-              // preferredOriginScheme then we have no preference and look at the next resolveBy.
-              if (
-                loginURI.scheme == existingLoginURI.scheme ||
-                (loginURI.scheme != preferredOriginScheme &&
-                  existingLoginURI.scheme != preferredOriginScheme)
-              ) {
-                break;
-              }
-
-              return loginURI.scheme == preferredOriginScheme;
-            } catch (ex) {
-              // Some URLs aren't valid nsIURI (e.g. chrome://FirefoxAccounts)
-              log.debug(
-                "dedupeLogins/shouldReplaceExisting: Error comparing schemes:",
-                existingLogin.origin,
-                login.origin,
-                "preferredOrigin:",
-                preferredOrigin,
-                ex
-              );
-            }
-            break;
-          }
-          case "subdomain": {
-            // Replace the existing login only if the new login is an exact match on the host.
-            let existingLoginURI = Services.io.newURI(existingLogin.origin);
-            let newLoginURI = Services.io.newURI(login.origin);
-            let preferredOriginURI = Services.io.newURI(preferredOrigin);
-            if (
-              existingLoginURI.hostPort != preferredOriginURI.hostPort &&
-              newLoginURI.hostPort == preferredOriginURI.hostPort
-            ) {
-              return true;
-            }
-            if (
-              existingLoginURI.host != preferredOriginURI.host &&
-              newLoginURI.host == preferredOriginURI.host
-            ) {
-              return true;
-            }
-            break;
-          }
-          case "timeLastUsed":
-          case "timePasswordChanged": {
-            // If we find a more recent login for the same key, replace the existing one.
-            let loginDate = login.QueryInterface(Ci.nsILoginMetaInfo)[
-              preference
-            ];
-            let storedLoginDate = existingLogin.QueryInterface(
-              Ci.nsILoginMetaInfo
-            )[preference];
-            if (loginDate == storedLoginDate) {
-              break;
-            }
-
-            return loginDate > storedLoginDate;
-          }
-          default: {
-            throw new Error(
-              "dedupeLogins: Invalid resolveBy preference: " + preference
-            );
-          }
-        }
-      }
-
-      return false;
-    }
-
-    for (let login of logins) {
-      let key = this.getUniqueKeyForLogin(login, uniqueKeys);
-
-      if (loginsByKeys.has(key)) {
-        if (!isLoginPreferred(loginsByKeys.get(key), login)) {
-          // If there is no preference for the new login, use the existing one.
-          continue;
-        }
-      }
-      loginsByKeys.set(key, login);
-    }
-
-    // Return the map values in the form of an array.
-    return [...loginsByKeys.values()];
-  },
-
-  /**
-   * Open the password manager window.
-   *
-   * @param {Window} window
-   *                 the window from where we want to open the dialog
-   *
-   * @param {object?} args
-   *                  params for opening the password manager
-   * @param {string} [args.filterString=""]
-   *                 the domain (not origin) to pass to the login manager dialog
-   *                 to pre-filter the results
-   * @param {string} args.entryPoint
-   *                 The name of the entry point, used for telemetry
-   */
-  openPasswordManager(window, { filterString = "", entryPoint = "" } = {}) {
-    Services.telemetry.recordEvent("pwmgr", "open_management", entryPoint);
-    if (this.managementURI && window.openTrustedLinkIn) {
-      let managementURL = this.managementURI.replace(
-        "%DOMAIN%",
-        window.encodeURIComponent(filterString)
-      );
-      window.openTrustedLinkIn(managementURL, "tab");
-      return;
-    }
-    let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager");
-    if (win) {
-      win.setFilter(filterString);
-      win.focus();
-    } else {
-      window.openDialog(
-        "chrome://passwordmgr/content/passwordManager.xul",
-        "Toolkit:PasswordManager",
-        "",
-        { filterString }
-      );
-    }
-  },
-
-  /**
-   * Checks if a field type is username compatible.
-   *
-   * @param {Element} element
-   *                  the field we want to check.
-   *
-   * @returns {Boolean} true if the field type is one
-   *                    of the username types.
-   */
-  isUsernameFieldType(element) {
-    if (ChromeUtils.getClassName(element) !== "HTMLInputElement") {
-      return false;
-    }
-
-    if (!element.isConnected) {
-      // If the element isn't connected then it isn't visible to the user so
-      // shouldn't be considered. It must have been connected in the past.
-      return false;
-    }
+this.LoginBreaches = {
+  REMOTE_SETTINGS_COLLECTION: "fxmonitor-breaches",
 
-    let fieldType = element.hasAttribute("type")
-      ? element.getAttribute("type").toLowerCase()
-      : element.type;
-    if (
-      !(
-        fieldType == "text" ||
-        fieldType == "email" ||
-        fieldType == "url" ||
-        fieldType == "tel" ||
-        fieldType == "number"
-      )
-    ) {
-      return false;
-    }
-
-    let acFieldName = element.getAutocompleteInfo().fieldName;
-    if (
-      !(
-        acFieldName == "username" ||
-        // Bug 1540154: Some sites use tel/email on their username fields.
-        acFieldName == "email" ||
-        acFieldName == "tel" ||
-        acFieldName == "tel-national" ||
-        acFieldName == "off" ||
-        acFieldName == "on" ||
-        acFieldName == ""
-      )
-    ) {
-      return false;
-    }
-    return true;
-  },
-
-  /**
-   * For each login, add the login to the password manager if a similar one
-   * doesn't already exist. Merge it otherwise with the similar existing ones.
-   *
-   * @param {Object[]} loginDatas - For each login, the data that needs to be added.
-   * @returns {nsILoginInfo[]} the newly added logins, filtered if no login was added.
-   */
-  async maybeImportLogins(loginDatas) {
-    let loginsToAdd = [];
-    let loginMap = new Map();
-    for (let loginData of loginDatas) {
-      // create a new login
-      let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
-        Ci.nsILoginInfo
-      );
-      login.init(
-        loginData.origin,
-        loginData.formActionOrigin ||
-          (typeof loginData.httpRealm == "string" ? null : ""),
-        typeof loginData.httpRealm == "string" ? loginData.httpRealm : null,
-        loginData.username,
-        loginData.password,
-        loginData.usernameElement || "",
-        loginData.passwordElement || ""
-      );
-
-      login.QueryInterface(Ci.nsILoginMetaInfo);
-      login.timeCreated = loginData.timeCreated;
-      login.timeLastUsed = loginData.timeLastUsed || loginData.timeCreated;
-      login.timePasswordChanged =
-        loginData.timePasswordChanged || loginData.timeCreated;
-      login.timesUsed = loginData.timesUsed || 1;
-
-      try {
-        // Ensure we only send checked logins through, since the validation is optimized
-        // out from the bulk APIs below us.
-        this.checkLoginValues(login);
-      } catch (e) {
-        Cu.reportError(e);
-        continue;
-      }
-
-      // First, we need to check the logins that we've already decided to add, to
-      // see if this is a duplicate. This should mirror the logic below for
-      // existingLogins, but only for the array of logins we're adding.
-      let newLogins = loginMap.get(login.origin) || [];
-      if (!newLogins) {
-        loginMap.set(login.origin, newLogins);
-      } else {
-        if (newLogins.some(l => login.matches(l, false /* ignorePassword */))) {
-          continue;
-        }
-        let foundMatchingNewLogin = false;
-        for (let newLogin of newLogins) {
-          if (login.username == newLogin.username) {
-            foundMatchingNewLogin = true;
-            newLogin.QueryInterface(Ci.nsILoginMetaInfo);
-            if (
-              (login.password != newLogin.password) &
-              (login.timePasswordChanged > newLogin.timePasswordChanged)
-            ) {
-              // if a login with the same username and different password already exists and it's older
-              // than the current one, update its password and timestamp.
-              newLogin.password = login.password;
-              newLogin.timePasswordChanged = login.timePasswordChanged;
-            }
-          }
-        }
-
-        if (foundMatchingNewLogin) {
-          continue;
-        }
-      }
-
-      // While here we're passing formActionOrigin and httpRealm, they could be empty/null and get
-      // ignored in that case, leading to multiple logins for the same username.
-      let existingLogins = Services.logins.findLogins(
-        login.origin,
-        login.formActionOrigin,
-        login.httpRealm
-      );
-      // Check for an existing login that matches *including* the password.
-      // If such a login exists, we do not need to add a new login.
-      if (
-        existingLogins.some(l => login.matches(l, false /* ignorePassword */))
-      ) {
-        continue;
-      }
-      // Now check for a login with the same username, where it may be that we have an
-      // updated password.
-      let foundMatchingLogin = false;
-      for (let existingLogin of existingLogins) {
-        if (login.username == existingLogin.username) {
-          foundMatchingLogin = true;
-          existingLogin.QueryInterface(Ci.nsILoginMetaInfo);
-          if (
-            (login.password != existingLogin.password) &
-            (login.timePasswordChanged > existingLogin.timePasswordChanged)
-          ) {
-            // if a login with the same username and different password already exists and it's older
-            // than the current one, update its password and timestamp.
-            let propBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
-              Ci.nsIWritablePropertyBag
-            );
-            propBag.setProperty("password", login.password);
-            propBag.setProperty(
-              "timePasswordChanged",
-              login.timePasswordChanged
-            );
-            Services.logins.modifyLogin(existingLogin, propBag);
-          }
-        }
-      }
-      // if the new login is an update or is older than an exiting login, don't add it.
-      if (foundMatchingLogin) {
-        continue;
-      }
-
-      newLogins.push(login);
-      loginsToAdd.push(login);
-    }
-    if (!loginsToAdd.length) {
-      return [];
-    }
-    return Services.logins.addLogins(loginsToAdd);
-  },
-
-  /**
-   * Convert an array of nsILoginInfo to vanilla JS objects suitable for
-   * sending over IPC.
-   *
-   * NB: All members of nsILoginInfo and nsILoginMetaInfo are strings.
-   */
-  loginsToVanillaObjects(logins) {
-    return logins.map(this.loginToVanillaObject);
-  },
-
-  /**
-   * Same as above, but for a single login.
-   */
-  loginToVanillaObject(login) {
-    let obj = {};
-    for (let i in login.QueryInterface(Ci.nsILoginMetaInfo)) {
-      if (typeof login[i] !== "function") {
-        obj[i] = login[i];
-      }
-    }
-
-    return obj;
-  },
-
-  /**
-   * Convert an object received from IPC into an nsILoginInfo (with guid).
-   */
-  vanillaObjectToLogin(login) {
-    let formLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
-      Ci.nsILoginInfo
-    );
-    // For compatibility for the Lockwise extension we fallback to hostname/formSubmitURL
-    formLogin.init(
-      login.origin || login.hostname,
-      "formSubmitURL" in login ? login.formSubmitURL : login.formActionOrigin,
-      login.httpRealm,
-      login.username,
-      login.password,
-      login.usernameField,
-      login.passwordField
-    );
-
-    formLogin.QueryInterface(Ci.nsILoginMetaInfo);
-    for (let prop of [
-      "guid",
-      "timeCreated",
-      "timeLastUsed",
-      "timePasswordChanged",
-      "timesUsed",
-    ]) {
-      formLogin[prop] = login[prop];
-    }
-    return formLogin;
-  },
-
-  /**
-   * As above, but for an array of objects.
-   */
-  vanillaObjectsToLogins(logins) {
-    return logins.map(this.vanillaObjectToLogin);
-  },
-
-  /**
-   * Returns true if the user has a master password set and false otherwise.
-   */
-  isMasterPasswordSet() {
-    let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(
-      Ci.nsIPK11TokenDB
-    );
-    let token = tokenDB.getInternalKeyToken();
-    return token.hasPassword;
-  },
-
-  /**
-   * Send a notification when stored data is changed.
-   */
-  notifyStorageChanged(changeType, data) {
-    let dataObject = data;
-    // Can't pass a raw JS string or array though notifyObservers(). :-(
-    if (Array.isArray(data)) {
-      dataObject = Cc["@mozilla.org/array;1"].createInstance(
-        Ci.nsIMutableArray
-      );
-      for (let i = 0; i < data.length; i++) {
-        dataObject.appendElement(data[i]);
-      }
-    } else if (typeof data == "string") {
-      dataObject = Cc["@mozilla.org/supports-string;1"].createInstance(
-        Ci.nsISupportsString
-      );
-      dataObject.data = data;
-    }
-    Services.obs.notifyObservers(
-      dataObject,
-      "passwordmgr-storage-changed",
-      changeType
-    );
-  },
-
-  isUserFacingLogin(login) {
-    return !login.origin.startsWith("chrome://");
-  },
-
-  async getAllUserFacingLogins() {
-    try {
-      let logins = await Services.logins.getAllLoginsAsync();
-      return logins.filter(this.isUserFacingLogin);
-    } catch (e) {
-      if (e.result == Cr.NS_ERROR_ABORT) {
-        // If the user cancels the MP prompt then return no logins.
-        return [];
-      }
-      throw e;
-    }
-  },
-
-  async recordBreachAlertDismissal(loginGuid) {
+  async recordDismissal(loginGuid) {
     await Services.logins.initializationPromise;
     const storageJSON =
       Services.logins.wrappedJSObject._storage.wrappedJSObject;
 
     return storageJSON.recordBreachAlertDismissal(loginGuid);
   },
 
-  async getBreachesForLogins(logins, breaches = null) {
+  async update(breaches = null) {
+    const logins = await LoginHelper.getAllUserFacingLogins();
+    await this.getPotentialBreachesByLoginGUID(logins, breaches);
+  },
+
+  /**
+   * Return a Map of login GUIDs to a potential breach affecting that login
+   * by considering only breaches affecting passwords.
+   *
+   * This only uses the breach `Domain` and `timePasswordChanged` to determine
+   * if a login may be breached which means it may contain false-positives if
+   * login timestamps are incorrect, the user didn't save their password change
+   * in Firefox, or the breach didn't contain all accounts, etc. As a result,
+   * consumers should avoid making stronger claims than the data supports.
+   *
+   * @param {nsILoginInfo[]} logins Saved logins to check for potential breaches.
+   * @param {object[]} [breaches = null] Only ones involving passwords will be used.
+   * @returns {Map} with a key for each login GUID potentially in a breach.
+   */
+  async getPotentialBreachesByLoginGUID(logins, breaches = null) {
     const breachesByLoginGUID = new Map();
     if (!breaches) {
       try {
-        breaches = await RemoteSettings(
-          REMOTE_SETTINGS_BREACHES_COLLECTION
-        ).get();
+        breaches = await RemoteSettings(this.REMOTE_SETTINGS_COLLECTION).get();
       } catch (ex) {
         if (ex instanceof RemoteSettingsClient.UnknownCollectionError) {
           log.warn(
             "Could not get Remote Settings collection.",
-            REMOTE_SETTINGS_BREACHES_COLLECTION,
+            this.REMOTE_SETTINGS_COLLECTION,
             ex
           );
           return breachesByLoginGUID;
         }
         throw ex;
       }
     }
     const BREACH_ALERT_URL = Services.prefs.getStringPref(
@@ -1158,44 +87,85 @@ this.LoginHelper = {
       let loginHost;
       try {
         // nsIURI.host can throw if the URI scheme doesn't have a host.
         loginHost = loginURI.host;
       } catch (ex) {
         continue;
       }
       for (const breach of breaches) {
-        if (!breach.Domain) {
+        if (
+          !breach.Domain ||
+          !Services.eTLD.hasRootDomain(loginHost, breach.Domain) ||
+          !this._breachInvolvedPasswords(breach) ||
+          !this._breachWasAfterPasswordLastChanged(breach, login)
+        ) {
           continue;
         }
-        const breachDate = new Date(breach.BreachDate).getTime();
-        const breachAddedDate = new Date(breach.AddedDate).getTime();
+
+        if (!storageJSON.isPotentiallyVulnerablePassword(login)) {
+          storageJSON.addPotentiallyVulnerablePassword(login);
+        }
+
         if (
-          Services.eTLD.hasRootDomain(loginHost, breach.Domain) &&
-          breach.hasOwnProperty("DataClasses") &&
-          breach.DataClasses.includes("Passwords") &&
-          login.timePasswordChanged < breachDate &&
-          (!dismissedBreachAlertsByLoginGUID[login.guid] ||
-            dismissedBreachAlertsByLoginGUID[login.guid]
-              .timeBreachAlertDismissed < breachAddedDate)
+          this._breachAlertIsDismissed(
+            login,
+            breach,
+            dismissedBreachAlertsByLoginGUID
+          )
         ) {
-          let breachAlertURL = new URL(breach.Name, baseBreachAlertURL);
-          breach.breachAlertURL = breachAlertURL.href;
-          breachesByLoginGUID.set(login.guid, breach);
+          continue;
         }
+
+        let breachAlertURL = new URL(breach.Name, baseBreachAlertURL);
+        breach.breachAlertURL = breachAlertURL.href;
+        breachesByLoginGUID.set(login.guid, breach);
       }
     }
     return breachesByLoginGUID;
   },
+
+  /**
+   * Return information about logins using passwords that were potentially in a
+   * breach.
+   * @see the caveats in the documentation for `getPotentialBreachesByLoginGUID`.
+   *
+   * @param {nsILoginInfo[]} logins to check the passwords of.
+   * @returns {Map} from login GUID to `true` for logins that have a password
+   *                that may be vulnerable.
+   */
+  getPotentiallyVulnerablePasswordsByLoginGUID(logins) {
+    const vulnerablePasswordsByLoginGUID = new Map();
+    const storageJSON =
+      Services.logins.wrappedJSObject._storage.wrappedJSObject;
+    for (const login of logins) {
+      if (storageJSON.isPotentiallyVulnerablePassword(login)) {
+        vulnerablePasswordsByLoginGUID.set(login.guid, true);
+      }
+    }
+    return vulnerablePasswordsByLoginGUID;
+  },
+
+  _breachAlertIsDismissed(login, breach, dismissedBreachAlerts) {
+    const breachAddedDate = new Date(breach.AddedDate).getTime();
+    const breachAlertIsDismissed =
+      dismissedBreachAlerts[login.guid] &&
+      dismissedBreachAlerts[login.guid].timeBreachAlertDismissed >
+        breachAddedDate;
+    return breachAlertIsDismissed;
+  },
+
+  _breachInvolvedPasswords(breach) {
+    return (
+      breach.hasOwnProperty("DataClasses") &&
+      breach.DataClasses.includes("Passwords")
+    );
+  },
+
+  _breachWasAfterPasswordLastChanged(breach, login) {
+    const breachDate = new Date(breach.BreachDate).getTime();
+    return login.timePasswordChanged < breachDate;
+  },
 };
 
-LoginHelper.init();
-
-XPCOMUtils.defineLazyPreferenceGetter(
-  LoginHelper,
-  "showInsecureFieldWarning",
-  "security.insecure_field_warning.contextual.enabled"
-);
-
 XPCOMUtils.defineLazyGetter(this, "log", () => {
-  let logger = LoginHelper.createLogger("LoginHelper");
-  return logger;
+  return LoginHelper.createLogger("LoginBreaches");
 });
--- a/browser/components/aboutlogins/content/aboutLogins.css
+++ b/browser/components/aboutlogins/content/aboutLogins.css
@@ -1,33 +1,35 @@
 /* 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/. */
 
 body {
+  --sidebar-width: 320px;
   display: grid;
-  grid-template-columns: 320px 1fr;
+  grid-template-columns: var(--sidebar-width) 1fr;
   grid-template-rows: 75px 1fr;
   grid-template-areas: "header header"
                        "logins login";
   height: 100vh;
 }
 
 header {
   display: flex;
   grid-area: header;
   align-items: center;
   background-color: var(--in-content-box-background);
   border-bottom: 1px solid var(--in-content-box-border-color);
-  padding-inline: 60px 23px;
+  padding-inline-end: 23px;
 }
 
 login-filter {
-  max-width: 30%;
-  margin: auto;
+  min-width: 320px;
+  max-width: 400px;
+  margin-inline: 40px auto;
   flex-grow: 1;
   align-self: center;
 }
 
 fxaccounts-button,
 menu-button {
   margin-inline-start: 18px;
 }
@@ -47,18 +49,19 @@ login-item {
   grid-area: login;
 }
 
 login-item {
   max-width: 700px;
 }
 
 #branding-logo {
+  flex-basis: var(--sidebar-width);
+  flex-shrink: 0;
   height: 32px;
-  margin-inline-end: 18px;
   -moz-context-properties: fill;
   fill: #20123a;
 }
 
 @supports -moz-bool-pref("browser.in-content.dark-mode") {
   @media (prefers-color-scheme: dark) {
     #branding-logo {
       fill: #fff;
--- a/browser/components/aboutlogins/content/aboutLogins.html
+++ b/browser/components/aboutlogins/content/aboutLogins.html
@@ -26,17 +26,17 @@
     <link rel="stylesheet" href="chrome://browser/content/aboutlogins/aboutLogins.css">
     <link rel="stylesheet" href="chrome://browser/content/aboutlogins/common.css">
     <link rel="icon" href="chrome://browser/content/aboutlogins/icons/favicon.svg">
   </head>
   <body>
     <header>
       <img id="branding-logo" src="chrome://branding/content/aboutlogins.svg" alt=""/>
       <login-filter></login-filter>
-      <fxaccounts-button></fxaccounts-button>
+      <fxaccounts-button hidden></fxaccounts-button>
       <menu-button></menu-button>
     </header>
     <login-list></login-list>
     <login-item></login-item>
     <login-intro></login-intro>
     <confirmation-dialog hidden></confirmation-dialog>
 
     <template id="confirmation-dialog-template">
@@ -93,16 +93,20 @@
       </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">
           <p data-l10n-id="login-list-intro-title"></p>
           <span data-l10n-id="login-list-intro-description"></span>
         </div>
+        <div class="empty-search-message">
+          <p data-l10n-id="about-logins-login-list-empty-search-title"></p>
+          <span data-l10n-id="about-logins-login-list-empty-search-description"></span>
+        </div>
       </div>
       <button class="create-login-button" data-l10n-id="create-login-button"></button>
     </template>
 
     <template id="login-list-item-template">
       <li class="login-list-item" role="option">
         <div class="favicon-wrapper">
           <img class="favicon" src="" alt=""/>
@@ -121,18 +125,18 @@
 
       <img class="illustration" src="chrome://browser/content/aboutlogins/icons/intro-illustration.svg"/>
       <h1 class="heading" data-l10n-id="login-intro-heading"></h1>
       <section>
         <p class="description" data-l10n-id="login-intro-description"></p>
         <ul>
           <li data-l10n-id="login-intro-instruction-fxa"></li>
           <li data-l10n-id="login-intro-instruction-fxa-settings"></li>
-          <li data-l10n-id="login-intro-instruction-faq">
-            <a data-l10n-name="faq" class="intro-faq-link" href="#"></a>
+          <li data-l10n-id="about-logins-intro-instruction-help">
+            <a data-l10n-name="help-link" class="intro-help-link" href="#"></a>
           </li>
         </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">
@@ -152,37 +156,51 @@
         </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>
-            <input type="url" name="origin" class="origin-input" required data-l10n-id="login-item-origin" dir="auto"/>
+            <!-- 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>
         <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"/>
+              <input type="text"
+                     name="username"
+                     data-l10n-id="login-item-username"
+                     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 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" required/>
+                <input type="password"
+                       name="password"
+                       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>
@@ -211,37 +229,36 @@
       <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/menu-button.css">
       <button class="menu-button ghost-button" data-l10n-id="menu"></button>
       <ul class="menu" role="menu" hidden>
         <button role="menuitem" class="menuitem-button menuitem-import ghost-button" hidden data-supported-platforms="Win32" data-event-name="AboutLoginsImport" data-l10n-id="menu-menuitem-import"></button>
         <button role="menuitem" class="menuitem-button menuitem-preferences ghost-button" data-event-name="AboutLoginsOpenPreferences" data-l10n-id="menu-menuitem-preferences"></button>
         <hr role="separator" class="menuitem-separator"></hr>
-        <button role="menuitem" class="menuitem-button menuitem-feedback ghost-button" data-event-name="AboutLoginsOpenFeedback" data-l10n-id="menu-menuitem-feedback"></button>
-        <button role="menuitem" class="menuitem-button menuitem-faq ghost-button" data-event-name="AboutLoginsOpenFAQ" data-l10n-id="menu-menuitem-faq"></button>
+        <button role="menuitem" class="menuitem-button menuitem-help ghost-button" data-event-name="AboutLoginsGetHelp" data-l10n-id="about-logins-menu-menuitem-help"></button>
         <hr role="separator" class="menuitem-separator"></hr>
         <button role="menuitem" class="menuitem-button menuitem-mobile menuitem-mobile-android ghost-button" data-event-name="AboutLoginsOpenMobileAndroid" data-l10n-id="menu-menuitem-android-app"></button>
         <button role="menuitem" class="menuitem-button menuitem-mobile menuitem-mobile-ios ghost-button" data-event-name="AboutLoginsOpenMobileIos" data-l10n-id="menu-menuitem-iphone-app"></button>
       </ul>
     </template>
 
     <template id="login-footer-template">
       <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
       <link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-footer.css">
       <footer>
-        <div class="footer-content message-bar">
-          <p>
-            <strong data-l10n-id="login-app-promo-title"></strong><br>
-            <span data-l10n-id="login-app-promo-subtitle"></span>
-          </p>
+        <p>
+          <strong data-l10n-id="login-app-promo-title"></strong><br>
+          <span data-l10n-id="login-app-promo-subtitle"></span>
+        </p>
+        <div class="buttons">
           <button class="app-store" data-event-name="AboutLoginsOpenMobileIos">
             <img class="image-app-store" data-l10n-id="login-app-promo-apple" src="" alt=""/>
           </button>
           <button class="play-store" data-event-name="AboutLoginsOpenMobileAndroid">
             <img class="image-play-store" data-l10n-id="login-app-promo-android" src="" alt=""/>
           </button>
-          <button class="close" data-event-name="AboutLoginsHideFooter"></button>
         </div>
+        <button class="close" data-event-name="AboutLoginsHideFooter"></button>
       </footer>
     </template>
   </body>
 </html>
--- a/browser/components/aboutlogins/content/components/fxaccounts-button.css
+++ b/browser/components/aboutlogins/content/components/fxaccounts-button.css
@@ -17,16 +17,19 @@
 
 .fxaccount-avatar,
 .fxaccounts-enable-button {
   margin-inline-start: 9px;
 }
 
 .fxaccounts-avatar-button {
   cursor: pointer;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
 }
 
 .fxaccount-email {
   font-weight: 600;
   font-size: .9em;
   vertical-align: middle;
 }
 
--- a/browser/components/aboutlogins/content/components/fxaccounts-button.js
+++ b/browser/components/aboutlogins/content/components/fxaccounts-button.js
@@ -2,17 +2,16 @@
  * 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/. */
 
 export default class FxAccountsButton extends HTMLElement {
   connectedCallback() {
     if (this.shadowRoot) {
       return;
     }
-
     let template = document.querySelector("#fxaccounts-button-template");
     let shadowRoot = this.attachShadow({ mode: "open" });
     document.l10n.connectRoot(shadowRoot);
     shadowRoot.appendChild(template.content.cloneNode(true));
 
     this._avatarButton = shadowRoot.querySelector(".fxaccounts-avatar-button");
     this._extraText = shadowRoot.querySelector(".fxaccounts-extra-text");
     this._enableButton = shadowRoot.querySelector(".fxaccounts-enable-button");
@@ -60,16 +59,17 @@ export default class FxAccountsButton ex
    *                   loggedIn: {Boolean} FxAccount authentication
    *                             status.
    *                   email: {String} Email address used with FxAccount. Must
    *                          be empty if `loggedIn` is false.
    *                   avatarURL: {String} URL of account avatar. Must
    *                              be empty if `loggedIn` is false.
    */
   updateState(state) {
+    this.hidden = false;
     this._loggedIn = state.loggedIn;
     this._email = state.email;
     this._avatarURL = state.avatarURL;
 
     this.render();
   }
 }
 customElements.define("fxaccounts-button", FxAccountsButton);
--- a/browser/components/aboutlogins/content/components/login-footer.css
+++ b/browser/components/aboutlogins/content/components/login-footer.css
@@ -1,58 +1,62 @@
 /* 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/. */
 
 footer {
-  position: fixed;
-  margin-inline-start: 0;
-  bottom: 40px;
+  background-color: var(--in-content-box-background);
+  border-radius: 4px;
+  box-shadow: var(--shadow-10);
+  position: relative;
+  padding-block: 8px;
+  padding-inline: 40px;
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
 }
 
-.footer-content {
-  background-color: var(--in-content-box-background);
-  box-shadow: var(--shadow-10);
-  max-width: 700px;
-  position: relative;
-  display: flex;
-  flex-flow: row nowrap;
-  align-items: center;
-  padding-inline-start: 40px;
-  padding-inline-end: 80px;
+footer > p {
+  display: inline-block;
+  line-height: 1.5;
+  padding-inline-end: 70px;
+  margin: 0;
+  margin-inline-end: auto;
 }
 
-.footer-content > p {
-  font-size: 15px;
-  margin: 0;
-  line-height: 1.5;
-  padding-inline-end: 40px;
+footer > .buttons {
+  display: inline-block;
+  margin-inline-end: auto;
 }
 
-.footer-content button {
-  background-color: transparent;
+footer button {
+  background-color: transparent !important; /* override common.css */
   padding: 0;
+  cursor: pointer;
+  vertical-align: middle;
 }
 
-.footer-content button:hover {
-  cursor: pointer;
-  background-color: transparent;
+footer .app-store {
+  margin-inline-start: 0;
 }
 
-.footer-content button img {
+footer button:not(.close) img {
   width: auto;
-  height: 40px;
   display: block;
 }
 
-.footer-content button + button img {
+footer .app-store img {
+  height: 40px;
+}
+
+footer .play-store img {
   height: 60px;
 }
 
-.footer-content .close {
+footer .close {
   -moz-context-properties: fill, fill-opacity;
   background-image: url("chrome://global/skin/icons/close.svg");
   background-repeat: no-repeat;
   background-position: center;
   cursor: pointer;
   display: block;
   fill: currentColor;
   fill-opacity: 0;
--- a/browser/components/aboutlogins/content/components/login-intro.js
+++ b/browser/components/aboutlogins/content/components/login-intro.js
@@ -12,20 +12,20 @@ export default class LoginIntro extends 
     let shadowRoot = this.attachShadow({ mode: "open" });
     document.l10n.connectRoot(shadowRoot);
     shadowRoot.appendChild(loginIntroTemplate.content.cloneNode(true));
 
     shadowRoot.addEventListener("click", this);
   }
 
   handleEvent(event) {
-    let faqLink = this.shadowRoot.querySelector(".intro-faq-link");
+    let helpLink = this.shadowRoot.querySelector(".intro-help-link");
 
-    if (event.type == "click" && event.originalTarget == faqLink) {
+    if (event.type == "click" && event.originalTarget == helpLink) {
       document.dispatchEvent(
-        new CustomEvent("AboutLoginsOpenFAQ", {
+        new CustomEvent("AboutLoginsGetHelp", {
           bubbles: true,
         })
       );
     }
   }
 }
 customElements.define("login-intro", LoginIntro);
--- a/browser/components/aboutlogins/content/components/login-item.css
+++ b/browser/components/aboutlogins/content/components/login-item.css
@@ -1,21 +1,27 @@
 /* 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;
 
   --reveal-checkbox-opacity: .8;
   --reveal-checkbox-opacity-hover: .6;
   --reveal-checkbox-opacity-active: 1;
   --success-color: #00c100;
 }
 
+form {
+  flex-grow: 1;
+}
+
 :host([data-editing]) .edit-button,
 :host([data-editing]) .copy-button,
 :host([data-editing]) login-footer,
 :host([data-is-new-login]) .delete-button,
 :host([data-is-new-login]) .origin-saved-value,
 :host([data-is-new-login]) .meta-info,
 :host([data-is-new-login]) login-footer,
 :host([data-is-new-login]) .login-item-title,
@@ -49,16 +55,17 @@ input[type="url"][readOnly] {
 }
 
 .title {
   margin-top: 0;
   margin-bottom: 0;
   flex-grow: 1;
   overflow: hidden;
   text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
 .delete-button,
 .edit-button {
   background-repeat: no-repeat;
   background-position: 8px;
   -moz-context-properties: fill;
   fill: currentColor;
@@ -66,17 +73,17 @@ input[type="url"][readOnly] {
 }
 
 .delete-button:dir(rtl),
 .edit-button:dir(rtl) {
   background-position-x: right 8px;
 }
 
 .delete-button {
-  background-image: url("chrome://browser/content/aboutlogins/icons/delete.svg");
+  background-image: url("chrome://global/skin/icons/delete.svg");
   padding-inline-start: 30px; /* 8px on each side, and 14px for icon width */
 }
 
 .edit-button {
   background-image: url("chrome://browser/content/aboutlogins/icons/edit.svg");
   padding-inline-start: 32px; /* 8px on each side, and 16px for icon width */
 }
 
@@ -128,16 +135,17 @@ input[type="url"][readOnly]:hover:active
 }
 
 :host([data-editing]) .detail-cell input:not([readOnly]):not([type="checkbox"]) {
   width: 280px;
 }
 
 .copy-button {
   margin-bottom: 0; /* Align button at the bottom of the row */
+  margin-inline-start: 20px;
 }
 
 .copy-button:not([data-copied]) .copied-button-text,
 .copy-button[data-copied] .copy-button-text {
   display: none;
 }
 
 .copy-button[data-copied] {
@@ -176,17 +184,17 @@ input[type="url"][readOnly]:hover:active
   font-family: monospace;
 }
 
 .reveal-password-checkbox {
   /* !important is needed to override common.css styling for checkboxes */
   background-color: transparent !important;
   border-width: 0 !important;
   background-image: url("chrome://browser/content/aboutlogins/icons/show-password.svg") !important;
-  margin-inline-start: 8px !important;
+  margin-inline: 10px 0 !important;
   cursor: pointer;
   -moz-context-properties: fill;
   fill: currentColor !important;
   opacity: var(--reveal-checkbox-opacity);
   flex-shrink: 0;
 }
 
 .reveal-password-checkbox:hover {
@@ -218,30 +226,33 @@ input[type="url"][readOnly]:hover:active
 .login-item-favicon-wrapper {
   margin-inline-end: 12px;
   height: 24px;
   width: 24px;
   flex-shrink: 0;
   background-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
   background-repeat: no-repeat;
   background-size: contain;
-  -moz-context-properties: fill;
+  -moz-context-properties: fill, fill-opacity;
+  fill: currentColor;
+  fill-opacity: 0.8;
 }
 
 .login-item-favicon-wrapper.hide-default-favicon {
   background-image: none;
 }
 
 .breach-alert {
   border-radius: 8px;
   border: 1px solid var(--in-content-border-color);
   background-color: var(--yellow-10);
   background-image: url("chrome://global/skin/icons/warning.svg");
   background-repeat: no-repeat;
   background-position: left 10px top 10px;
+  color: #0C0C0D;
   -moz-context-properties: fill;
   fill: var(--red-90);
   box-shadow: 0 2px 8px 0 rgba(12,12,13,0.1);
   font-size: .9em;
   font-weight: 300;
   line-height: 1.4;
   padding-block: 12px;
   padding-inline-start: 36px;
@@ -267,19 +278,19 @@ a.breach-alert-link {
   position: absolute;
   background-image: url("chrome://global/skin/icons/close.svg");
   background-repeat: no-repeat;
   background-size: contain;
   min-height: 16px;
   min-width: 16px;
   -moz-context-properties: fill, fill-opacity;
   fill-opacity: 0;
-  fill: var(--grey-90);
+  fill: currentColor;
   inset-inline-end: 12px;
-  inset-block-start: 12px
+  inset-block-start: 12px;
 }
 
 .dismiss-breach-alert,
 .dismiss-breach-alert:hover {
   background-color: transparent;
 }
 
 @supports -moz-bool-pref("browser.in-content.dark-mode") {
@@ -288,16 +299,11 @@ a.breach-alert-link {
       --reveal-checkbox-opacity: .8;
       --reveal-checkbox-opacity-hover: 1;
       --reveal-checkbox-opacity-active: .6;
       --success-color: #86DE74;
     }
 
     .breach-alert {
       box-shadow: 0 2px 8px 0 rgba(249,249,250,0.1);
-      color: #0C0C0D;
-    }
-
-    .login-item-favicon-wrapper {
-      fill: var(--in-content-border-hover);
     }
   }
 }
--- a/browser/components/aboutlogins/content/components/login-item.js
+++ b/browser/components/aboutlogins/content/components/login-item.js
@@ -75,16 +75,17 @@ export default class LoginItem extends H
     this._copyPasswordButton.addEventListener("click", this);
     this._copyUsernameButton.addEventListener("click", this);
     this._deleteButton.addEventListener("click", this);
     this._dismissBreachAlert.addEventListener("click", this);
     this._editButton.addEventListener("click", this);
     this._form.addEventListener("submit", this);
     this._originInput.addEventListener("click", this);
     this._revealCheckbox.addEventListener("click", this);
+    this._originInput.addEventListener("auxclick", this);
     window.addEventListener("AboutLoginsInitialLoginSelected", this);
     window.addEventListener("AboutLoginsLoadInitialFavicon", this);
     window.addEventListener("AboutLoginsLoginSelected", this);
     window.addEventListener("AboutLoginsShowBlankLogin", this);
   }
 
   async render() {
     this._breachAlert.hidden = true;
@@ -163,16 +164,22 @@ export default class LoginItem extends H
       case "AboutLoginsLoginSelected": {
         this.confirmPendingChangesOnEvent(event, event.detail);
         break;
       }
       case "AboutLoginsShowBlankLogin": {
         this.confirmPendingChangesOnEvent(event, {});
         break;
       }
+      case "auxclick": {
+        if (event.button == 1) {
+          this._handleOriginClick();
+        }
+        break;
+      }
       case "blur": {
         // Add https:// prefix if one was not provided.
         let originValue = this._originInput.value.trim();
         if (!originValue) {
           return;
         }
         if (!originValue.match(/:\/\//)) {
           this._originInput.value = "https://" + originValue;
@@ -271,28 +278,18 @@ export default class LoginItem extends H
           return;
         }
         if (classList.contains("edit-button")) {
           this._toggleEditing();
 
           recordTelemetryEvent({ object: "existing_login", method: "edit" });
           return;
         }
-        if (classList.contains("origin-input") && !this.readOnly) {
-          document.dispatchEvent(
-            new CustomEvent("AboutLoginsOpenSite", {
-              bubbles: true,
-              detail: this._login,
-            })
-          );
-
-          recordTelemetryEvent({
-            object: "existing_login",
-            method: "open_site",
-          });
+        if (classList.contains("origin-input")) {
+          this._handleOriginClick();
         }
         break;
       }
       case "submit": {
         // Prevent page navigation form submit behavior.
         event.preventDefault();
         if (!this._isFormValid({ reportErrors: true })) {
           return;
@@ -493,16 +490,27 @@ export default class LoginItem extends H
       return;
     }
 
     this._login = {};
     this._toggleEditing(false);
     this.render();
   }
 
+  _handleOriginClick() {
+    document.dispatchEvent(
+      new CustomEvent("AboutLoginsOpenSite", {
+        bubbles: true,
+        detail: this._login,
+      })
+    );
+
+    recordTelemetryEvent({ object: "existing_login", method: "open_site" });
+  }
+
   /**
    * Checks that the edit/new-login form has valid values present for their
    * respective required fields.
    *
    * @param {boolean} reportErrors If true, validation errors will be reported
    *                               to the user.
    */
   _isFormValid({ reportErrors } = {}) {
--- a/browser/components/aboutlogins/content/components/login-list.css
+++ b/browser/components/aboutlogins/content/components/login-list.css
@@ -17,17 +17,19 @@
   border-bottom: 1px solid var(--in-content-box-border-color);
   background-color: var(--in-content-box-background);
   color: var(--in-content-deemphasized-text);
   font-size: 0.8em;
 }
 
 #login-sort {
   background-color: transparent;
+  margin-inline-start: 0;
   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 > option {
   font-weight: normal;
@@ -38,56 +40,63 @@
   text-align: end;
   margin-inline-start: 18px;
 }
 
 .container {
   display: contents;
 }
 
+:host(.no-logins) .empty-search-message,
+:host(:not(.empty-search)) .empty-search-message,
+:host(.empty-search:not(.create-login-selected)) ol,
 :host(.no-logins:not(.create-login-selected)) ol,
 :host(:not(.no-logins)) .intro,
 :host(.create-login-selected) .intro,
+:host(.create-login-selected) .empty-search-message,
 :host(:not(.create-login-selected)) #new-login-list-item {
   display: none;
 }
 
+.empty-search-message,
 .intro {
   text-align: center;
   padding: 1em;
   max-width: 50ch; /* This should be kept in sync with login-list-item username and title max-width */
   flex-grow: 1;
   border-bottom: 1px solid var(--in-content-box-border-color);
 }
 
+.empty-search-message span,
 .intro span {
   font-size: 0.85em;
 }
 
 ol {
   margin-top: 0;
   margin-bottom: 0;
   padding-inline-start: 0;
   overflow: hidden auto;
   flex-grow: 1;
-  box-shadow: inset 0 -10px 10px -10px var(--grey-90-a20);
+  box-shadow: inset 0 -1px var(--in-content-box-border-color);
 }
 
 .create-login-button {
   margin: 16px;
 }
 
 .login-list-item {
   display: flex;
   align-items: center;
   padding: 10px;
   padding-inline-end: 18px;
   padding-inline-start: 12px;
   border-inline-start: 4px solid transparent;
   border-bottom: 1px solid var(--in-content-box-border-color);
+  user-select: none;
 }
 
 .login-list-item:hover {
   background-color: var(--in-content-box-background-hover);
 }
 
 .login-list-item:hover:active {
   background-color: var(--in-content-box-background-active);
@@ -112,25 +121,28 @@ ol {
   overflow: hidden;
 }
 
 .title,
 .username {
   display: block;
   text-overflow: ellipsis;
   overflow: hidden;
+  white-space: nowrap;
 }
 
 .favicon-wrapper {
   height: 16px;
   width: 16px;
   background-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
   background-repeat: no-repeat;
   margin-inline-end: 12px;
-  -moz-context-properties: fill;
+  -moz-context-properties: fill, fill-opacity;
+  fill: currentColor;
+  fill-opacity: 0.8;
 }
 
 .favicon-wrapper.hide-default-favicon {
   background-image: none;
 }
 
 .favicon {
   width: 16px;
@@ -154,14 +166,10 @@ ol {
   background-position: left 24px center;
 }
 
 @supports -moz-bool-pref("browser.in-content.dark-mode") {
   @media (prefers-color-scheme: dark) {
     .login-list-item.breached {
       fill: var(--red-60);
     }
-
-    .favicon-wrapper {
-      fill: var(--in-content-border-hover);
-    }
   }
 }
--- a/browser/components/aboutlogins/content/components/login-list.js
+++ b/browser/components/aboutlogins/content/components/login-list.js
@@ -66,16 +66,17 @@ export default class LoginList extends H
     this._list.addEventListener("click", this);
     this.addEventListener("keydown", this);
     this._createLoginButton.addEventListener("click", this);
   }
 
   async render() {
     let visibleLoginGuids = this._applyFilter();
     this._updateVisibleLoginCount(visibleLoginGuids.size);
+    this.classList.toggle("empty-search", visibleLoginGuids.size == 0);
 
     // Add all of the logins that are not in the DOM yet.
     let fragment = document.createDocumentFragment();
     for (let guid of this._loginGuidsSortedOrder) {
       if (this._logins[guid].listItem) {
         continue;
       }
       let login = this._logins[guid].login;
--- a/browser/components/aboutlogins/content/components/menu-button.css
+++ b/browser/components/aboutlogins/content/components/menu-button.css
@@ -56,27 +56,23 @@
 }
 
 .menuitem-separator {
   border-top-width: 2px;
   margin-block: 5px;
   width: 100%;
 }
 
+.menuitem-help {
+  background-image: url("chrome://global/skin/icons/help.svg");
+}
+
 .menuitem-import {
   background-image: url("chrome://browser/skin/save.svg");
 }
 
 .menuitem-preferences {
   background-image: url("chrome://browser/skin/settings.svg");
 }
 
-.menuitem-feedback {
-  background-image: url("chrome://browser/skin/notification-icons/desktop-notification.svg");
-}
-
-.menuitem-faq {
-  background-image: url("chrome://global/skin/icons/help.svg");
-}
-
 .menuitem-mobile {
   background-image: url("chrome://browser/skin/device-phone.svg");
 }
deleted file mode 100644
--- a/browser/components/aboutlogins/content/icons/delete.svg
+++ /dev/null
@@ -1,6 +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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16" fill="context-fill">
-  <path d="M6,12.0025063 C6.27614237,12.0025063 6.5,11.7786487 6.5,11.5025063 L6.5,5.50250628 C6.5,5.22636391 6.27614237,5.00250628 6,5.00250628 C5.72385763,5.00250628 5.5,5.22636391 5.5,5.50250628 L5.5,11.5025063 C5.5,11.7786487 5.72385763,12.0025063 6,12.0025063 Z M8,12.0025063 C8.27614237,12.0025063 8.5,11.7786487 8.5,11.5025063 L8.5,5.50250628 C8.5,5.22636391 8.27614237,5.00250628 8,5.00250628 C7.72385763,5.00250628 7.5,5.22636391 7.5,5.50250628 L7.5,11.5025063 C7.5,11.7786487 7.72385763,12.0025063 8,12.0025063 Z M10,12.0025063 C10.2761424,12.0025063 10.5,11.7786487 10.5,11.5025063 L10.5,5.50250628 C10.5,5.22636391 10.2761424,5.00250628 10,5.00250628 C9.72385763,5.00250628 9.5,5.22636391 9.5,5.50250628 L9.5,11.5025063 C9.5,11.7786487 9.72385763,12.0025063 10,12.0025063 Z M13.5,2.00250628 L10.45,2.00250628 C10.2134038,0.837344292 9.18894081,-1.91253263e-16 8,0 C6.81105919,1.91253263e-16 5.78659623,0.837344292 5.55,2.00250628 L2.5,2.00250628 C1.94771525,2.00250628 1.5,2.45022153 1.5,3.00250628 C1.5,3.55479103 1.94771525,4.00250628 2.5,4.00250628 L2.5,13.0025063 C2.5,14.6593605 3.84314575,16.0025063 5.5,16.0025063 L10.5,16.0025063 C12.1568542,16.0025063 13.5,14.6593605 13.5,13.0025063 L13.5,4.00250628 C14.0522847,4.00250628 14.5,3.55479103 14.5,3.00250628 C14.5,2.45022153 14.0522847,2.00250628 13.5,2.00250628 L13.5,2.00250628 Z M8,1.00250628 C8.62819604,1.00902136 9.18471788,1.40910895 9.391,2.00250628 L6.609,2.00250628 C6.81528212,1.40910895 7.37180396,1.00902136 8,1.00250628 Z M11.5,13.0025063 C11.5,13.554791 11.0522847,14.0025063 10.5,14.0025063 L5.5,14.0025063 C4.94771525,14.0025063 4.5,13.554791 4.5,13.0025063 L4.5,4.00250628 L11.5,4.00250628 L11.5,13.0025063 Z"/>
-</svg>
--- a/browser/components/aboutlogins/jar.mn
+++ b/browser/components/aboutlogins/jar.mn
@@ -17,17 +17,16 @@ browser.jar:
   content/browser/aboutlogins/components/login-footer.js       (content/components/login-footer.js)
   content/browser/aboutlogins/components/login-item.css        (content/components/login-item.css)
   content/browser/aboutlogins/components/login-item.js         (content/components/login-item.js)
   content/browser/aboutlogins/components/login-list.css        (content/components/login-list.css)
   content/browser/aboutlogins/components/login-list.js         (content/components/login-list.js)
   content/browser/aboutlogins/components/login-list-item.js    (content/components/login-list-item.js)
   content/browser/aboutlogins/components/menu-button.css       (content/components/menu-button.css)
   content/browser/aboutlogins/components/menu-button.js        (content/components/menu-button.js)
-  content/browser/aboutlogins/icons/delete.svg        (content/icons/delete.svg)
   content/browser/aboutlogins/icons/edit.svg          (content/icons/edit.svg)
   content/browser/aboutlogins/icons/favicon.svg       (content/icons/favicon.svg)
   content/browser/aboutlogins/icons/hide-password.svg (content/icons/hide-password.svg)
   content/browser/aboutlogins/icons/show-password.svg (content/icons/show-password.svg)
   content/browser/aboutlogins/icons/intro-illustration.svg (content/icons/intro-illustration.svg)
   content/browser/aboutlogins/aboutLogins.css   (content/aboutLogins.css)
   content/browser/aboutlogins/aboutLogins.js    (content/aboutLogins.js)
   content/browser/aboutlogins/aboutLogins.html  (content/aboutLogins.html)
--- a/browser/components/aboutlogins/moz.build
+++ b/browser/components/aboutlogins/moz.build
@@ -6,16 +6,17 @@
 
 JAR_MANIFESTS += ['jar.mn']
 
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Password Manager')
 
 EXTRA_JS_MODULES += [
     'AboutLoginsParent.jsm',
+    'LoginBreaches.jsm',
 ]
 
 FINAL_TARGET_FILES.actors += [
     'AboutLoginsChild.jsm',
 ]
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
--- a/browser/components/aboutlogins/tests/browser/browser.ini
+++ b/browser/components/aboutlogins/tests/browser/browser.ini
@@ -4,16 +4,17 @@ prefs =
 support-files =
   head.js
 
 # Run first so content events from previous tests won't trickle in.
 # Skip ASAN and debug since waiting for content events is already slow.
 [browser_aaa_eventTelemetry_run_first.js]
 skip-if = asan || debug
 [browser_breachAlertDismissals.js]
+skip-if = asan || debug || verify # bug 1574023
 [browser_confirmDeleteDialog.js]
 [browser_contextmenuFillLogins.js]
 [browser_copyToClipboardButton.js]
 [browser_createLogin.js]
 [browser_deleteLogin.js]
 [browser_dismissFooter.js]
 [browser_fxAccounts.js]
 [browser_loginListChanges.js]
@@ -21,9 +22,10 @@ skip-if = asan || debug
 skip-if = (os == 'linux') # bug 1569789
 [browser_noLoginsView.js]
 [browser_openFiltered.js]
 [browser_openImport.js]
 skip-if = (os != "win") # import is only available on Windows
 [browser_openPreferences.js]
 [browser_openPreferencesExternal.js]
 [browser_openSite.js]
+[browser_sessionRestore.js]
 [browser_updateLogin.js]
--- a/browser/components/aboutlogins/tests/browser/browser_breachAlertDismissals.js
+++ b/browser/components/aboutlogins/tests/browser/browser_breachAlertDismissals.js
@@ -1,11 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+let { LoginBreaches } = ChromeUtils.import(
+  "resource:///modules/LoginBreaches.jsm"
+);
+
 const TEST_BREACHES = [
   {
     AddedDate: "2019-12-20T23:56:26Z",
     BreachDate: "2018-12-16",
     Domain: "breached.com",
     Name: "Breached",
     PwnCount: 1643100,
     DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
@@ -26,17 +30,17 @@ add_task(async function setup() {
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
     Services.logins.removeAllLogins();
   });
 });
 
 add_task(async function test_show_login() {
   let browser = gBrowser.selectedBrowser;
   TEST_LOGIN3.timePasswordChanged = 12345;
-  let testBreaches = await LoginHelper.getBreachesForLogins(
+  let testBreaches = await LoginBreaches.getPotentialBreachesByLoginGUID(
     [TEST_LOGIN3],
     TEST_BREACHES
   );
   browser.messageManager.sendAsyncMessage(
     "AboutLogins:UpdateBreaches",
     testBreaches
   );
   await ContentTask.spawn(browser, TEST_LOGIN3, async () => {
--- a/browser/components/aboutlogins/tests/browser/browser_openPreferencesExternal.js
+++ b/browser/components/aboutlogins/tests/browser/browser_openPreferencesExternal.js
@@ -9,26 +9,20 @@ add_task(async function setup() {
   registerCleanupFunction(() => {
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   });
 });
 
 add_task(async function test_open_feedback() {
   const menuArray = [
     {
-      urlFinal: "https://example.com/feedback",
-      urlBase: "https://example.com/feedback",
-      pref: "signon.management.page.feedbackURL",
-      selector: ".menuitem-feedback",
-    },
-    {
-      urlFinal: "https://example.com/faqs",
-      urlBase: "https://example.com/faqs",
-      pref: "signon.management.page.faqURL",
-      selector: ".menuitem-faq",
+      urlFinal: "https://example.com/firefox-lockwise",
+      urlBase: "https://example.com/",
+      pref: "app.support.baseURL",
+      selector: ".menuitem-help",
     },
     {
       urlFinal: "https://example.com/android?utm_creative=Elipsis_Menu",
       urlBase: "https://example.com/android?utm_creative=",
       pref: "signon.management.page.mobileAndroidURL",
       selector: ".menuitem-mobile-android",
     },
     {
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutlogins/tests/browser/browser_sessionRestore.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { TabState } = ChromeUtils.import(
+  "resource:///modules/sessionstore/TabState.jsm"
+);
+
+async function checkLoginDisplayed(browser, testGuid) {
+  await ContentTask.spawn(browser, testGuid, async function(guid) {
+    let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
+    let loginFound = await ContentTaskUtils.waitForCondition(() => {
+      return (
+        loginList._loginGuidsSortedOrder.length == 1 &&
+        loginList._loginGuidsSortedOrder[0] == guid
+      );
+    }, "Waiting for login to be displayed in page");
+    ok(loginFound, "Confirming that login is displayed in page");
+  });
+}
+
+add_task(async function() {
+  TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
+  registerCleanupFunction(() => {
+    Services.logins.removeAllLogins();
+  });
+
+  const testGuid = TEST_LOGIN1.guid;
+  const tab = BrowserTestUtils.addTab(gBrowser, "about:logins");
+  const browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  await checkLoginDisplayed(browser, testGuid);
+
+  BrowserTestUtils.removeTab(tab);
+  info("Adding a lazy about:logins tab...");
+  let lazyTab = BrowserTestUtils.addTab(gBrowser, "about:logins", {
+    createLazyBrowser: true,
+  });
+
+  is(lazyTab.linkedPanel, "", "Tab is lazy");
+  let tabLoaded = new Promise(resolve => {
+    gBrowser.addTabsProgressListener({
+      async onLocationChange(aBrowser) {
+        if (lazyTab.linkedBrowser == aBrowser) {
+          gBrowser.removeTabsProgressListener(this);
+          await Promise.resolve();
+          resolve();
+        }
+      },
+    });
+  });
+
+  info("Switching tab to cause it to get restored");
+  await BrowserTestUtils.switchTab(gBrowser, lazyTab);
+
+  await tabLoaded;
+
+  let lazyBrowser = lazyTab.linkedBrowser;
+  await checkLoginDisplayed(lazyBrowser, testGuid);
+
+  BrowserTestUtils.removeTab(lazyTab);
+});
--- a/browser/components/aboutlogins/tests/chrome/chrome.ini
+++ b/browser/components/aboutlogins/tests/chrome/chrome.ini
@@ -1,10 +1,12 @@
 [DEFAULT]
 scheme = https
+prefs =
+   identity.fxaccounts.enabled=true
 support-files =
    aboutlogins_common.js
 
 [test_confirm_delete_dialog.html]
 [test_fxaccounts_button.html]
 [test_login_filter.html]
 [test_login_item.html]
 [test_login_list.html]
--- a/browser/components/aboutlogins/tests/chrome/test_login_item.html
+++ b/browser/components/aboutlogins/tests/chrome/test_login_item.html
@@ -79,24 +79,46 @@ add_task(async function test_empty_item(
 });
 
 add_task(async function test_set_login() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   await asyncElementRendered();
 
   ok(!gLoginItem.dataset.editing, "loginItem should not be in 'edit' mode");
   ok(!gLoginItem.dataset.isNewLogin, "loginItem should not be in 'isNewLogin' mode");
-  is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be populated");
+  let originInput = gLoginItem.shadowRoot.querySelector("input[name='origin']");
+  is(originInput.value, TEST_LOGIN_1.origin, "origin should be populated");
   is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be populated");
   is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be populated");
   is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-created")).args.timeCreated, TEST_LOGIN_1.timeCreated, "time-created should be populated");
   is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-changed")).args.timeChanged, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
   is(document.l10n.getAttributes(gLoginItem.shadowRoot.querySelector(".time-used")).args.timeUsed, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
   let copyButtons = [...gLoginItem.shadowRoot.querySelectorAll(".copy-button")];
   ok(copyButtons.every(button => !isHidden(button)), "The copy buttons should be visible when viewing a login");
+
+  let openSiteEventDispatched = false;
+  document.addEventListener("AboutLoginsOpenSite", event => {
+    is(event.detail.guid, TEST_LOGIN_1.guid, "event should include guid");
+    openSiteEventDispatched = true;
+  }, {once: true});
+  originInput.click();
+  ok(openSiteEventDispatched, "Clicking the .origin-input should dispatch the AboutLoginsOpenSite event");
+
+  openSiteEventDispatched = false;
+  document.addEventListener("AboutLoginsOpenSite", event => {
+    is(event.detail.guid, TEST_LOGIN_1.guid, "event should include guid");
+    openSiteEventDispatched = true;
+  }, {once: true});
+  synthesizeMouseAtCenter(originInput, {button: 1});
+  ok(openSiteEventDispatched, "Middle-clicking the .origin-input should dispatch the AboutLoginsOpenSite event");
+
+  document.addEventListener("AboutLoginsOpenSite", event => {
+    ok(false, "right-clicking the .origin-input should not trigger the AboutLoginsOpenSite event");
+  }, {once: true});
+  synthesizeMouseAtCenter(originInput, {button: 2});
 });
 
 add_task(async function test_update_breaches() {
   gLoginItem.setLogin(TEST_LOGIN_1);
   gLoginItem.updateBreaches(TEST_BREACHES_MAP);
   await asyncElementRendered();
 
   let correspondingBreach = TEST_BREACHES_MAP.get(gLoginItem._login.guid);
--- a/browser/components/aboutlogins/tests/chrome/test_login_list.html
+++ b/browser/components/aboutlogins/tests/chrome/test_login_list.html
@@ -96,16 +96,44 @@ add_task(async function setup() {
 
   gLoginList = document.createElement("login-list");
   displayEl.appendChild(gLoginList);
 });
 
 add_task(async function test_empty_list() {
   ok(gLoginList, "loginList exists");
   is(gLoginList.textContent, "", "Initially empty");
+  gLoginList.classList.add("no-logins");
+  let loginListBox = gLoginList.shadowRoot.querySelector("ol");
+  let introText = gLoginList.shadowRoot.querySelector(".intro");
+  let emptySearchText = gLoginList.shadowRoot.querySelector(".empty-search-message");
+  ok(isHidden(loginListBox), "The login-list ol should be hidden when there are no logins");
+  ok(!isHidden(introText), "The intro text should be visible when the list is empty");
+  ok(isHidden(emptySearchText), "The empty-search text should be hidden when there are no logins");
+
+  gLoginList.classList.add("create-login-selected");
+  ok(!isHidden(loginListBox), "The login-list ol should be visible when the create-login mode is active");
+  ok(isHidden(introText), "The intro text should be hidden when the create-login mode is active");
+  ok(isHidden(emptySearchText), "The empty-search text should be hidden when the create-login mode is active");
+  gLoginList.classList.remove("create-login-selected");
+
+  window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
+    bubbles: true,
+    detail: "foo",
+  }));
+  ok(isHidden(loginListBox), "The login-list ol should be hidden when there are no logins");
+  ok(!isHidden(introText), "The intro text should be visible when the list is empty");
+  ok(isHidden(emptySearchText), "The empty-search text should be hidden when there are no logins even if a filter is applied");
+
+  // Clean up state for next test
+  gLoginList.classList.remove("no-logins");
+  window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
+    bubbles: true,
+    detail: "",
+  }));
 });
 
 add_task(async function test_keyboard_navigation() {
   gLoginList.setLogins([TEST_LOGIN_1, TEST_LOGIN_2, TEST_LOGIN_3]);
 
   while (document.activeElement != gLoginList &&
          gLoginList.shadowRoot.querySelector("#login-sort") != gLoginList.shadowRoot.activeElement) {
     sendKey("TAB");
@@ -185,56 +213,63 @@ add_task(async function test_populated_l
 add_task(async function test_breach_indicator() {
   gLoginList.updateBreaches(TEST_BREACHES_MAP);
   let loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item:not(#new-login-list-item):not([hidden])");
   ok(loginListItems[0].classList.contains("breached"), "The first login should have the .breached class.");
   ok(!loginListItems[1].classList.contains("breached"), "The second login should not have the .breached class");
 });
 
 add_task(async function test_filtered_list() {
+  let emptySearchText = gLoginList.shadowRoot.querySelector(".empty-search-message");
+  ok(isHidden(emptySearchText), "The empty search text should be hidden when there are results in the list");
   is(gLoginList.shadowRoot.querySelectorAll(".login-list-item:not(#new-login-list-item):not([hidden])").length, 2, "Both logins should be visible");
   let countSpan = gLoginList.shadowRoot.querySelector(".count");
   is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should match full list length");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "user1",
   }));
   is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 1, "Count should match result amount");
+  ok(isHidden(emptySearchText), "The empty search text should be hidden when there are results in the list");
   let loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item[data-guid]");
   is(loginListItems[0].querySelector(".username").textContent, "user1", "user1 is expected first");
   ok(!loginListItems[0].hidden, "user1 should remain visible");
   ok(loginListItems[1].hidden, "user2 should be hidden");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "user2",
   }));
   is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 1, "Count should match result amount");
+  ok(isHidden(emptySearchText), "The empty search text should be hidden when there are results in the list");
   loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item[data-guid]");
   ok(loginListItems[0].hidden, "user1 should be hidden");
   ok(!loginListItems[1].hidden, "user2 should be visible");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "user",
   }));
   is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should match result amount");
+  ok(isHidden(emptySearchText), "The empty search text should be hidden when there are results in the list");
   loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item[data-guid]");
   ok(!loginListItems[0].hidden, "user1 should be visible");
   ok(!loginListItems[1].hidden, "user2 should be visible");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "foo",
   }));
   is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 0, "Count should match result amount");
+  ok(!isHidden(emptySearchText), "The empty search text should be visible when there are no results in the list");
   loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item[data-guid]");
   ok(loginListItems[0].hidden, "user1 should be hidden");
   ok(loginListItems[1].hidden, "user2 should be hidden");
   window.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
     bubbles: true,
     detail: "",
   }));
+  ok(isHidden(emptySearchText), "The empty search text should be hidden when there are results in the list");
   is(JSON.parse(countSpan.getAttribute("data-l10n-args")).count, 2, "Count should be reset to full list length");
   loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item[data-guid]");
   ok(!loginListItems[0].hidden, "user1 should be visible");
   ok(!loginListItems[1].hidden, "user2 should be visible");
 
   info("Add an HTTP Auth login");
   gLoginList.setLogins([TEST_LOGIN_1, TEST_LOGIN_2, TEST_HTTP_AUTH_LOGIN_1]);
   await asyncElementRendered();
--- a/browser/components/aboutlogins/tests/chrome/test_menu_button.html
+++ b/browser/components/aboutlogins/tests/chrome/test_menu_button.html
@@ -118,18 +118,17 @@ add_task(async function test_menu_keyboa
   }
 
   function getFocusedMenuItem() {
     return gMenuButton.shadowRoot.querySelector(".menuitem-button:focus");
   }
 
   let allItems = [
     "menuitem-preferences",
-    "menuitem-feedback",
-    "menuitem-faq",
+    "menuitem-help",
     "menuitem-mobile-android",
     "menuitem-mobile-ios",
   ];
   if (navigator.platform == "Win32") {
     allItems = ["menuitem-import", ...allItems];
   }
 
   let menu = gMenuButton.shadowRoot.querySelector(".menu");
rename from browser/components/aboutlogins/tests/unit/test_getBreachesForLogins.js
rename to browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
--- a/browser/components/aboutlogins/tests/unit/test_getBreachesForLogins.js
+++ b/browser/components/aboutlogins/tests/unit/test_getPotentialBreachesByLoginGUID.js
@@ -1,23 +1,26 @@
 /**
- * Test LoginHelper.getBreachesForLogins
+ * Test LoginBreaches.getPotentialBreachesByLoginGUID
  */
 
 "use strict";
 
+const { RemoteSettings } = ChromeUtils.import(
+  "resource://services-settings/remote-settings.js"
+);
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { AboutLoginsParent } = ChromeUtils.import(
-  "resource:///modules/AboutLoginsParent.jsm"
+const gBrowserGlue = Cc["@mozilla.org/browser/browserglue;1"].getService(
+  Ci.nsIObserver
 );
 
 ChromeUtils.defineModuleGetter(
   this,
-  "LoginHelper",
-  "resource://gre/modules/LoginHelper.jsm"
+  "LoginBreaches",
+  "resource:///modules/LoginBreaches.jsm"
 );
 
 const TEST_BREACHES = [
   {
     AddedDate: "2018-12-20T23:56:26Z",
     BreachDate: "2018-12-16",
     Domain: "breached.com",
     Name: "Breached",
@@ -54,17 +57,17 @@ const TEST_BREACHES = [
   },
 ];
 
 const NOT_BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
   origin: "https://www.example.com",
   formActionOrigin: "https://www.example.com",
   username: "username",
   password: "password",
-  timePasswordChanged: Date.now(),
+  timePasswordChanged: new Date("2018-12-15").getTime(),
 });
 const BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
   origin: "https://www.breached.com",
   formActionOrigin: "https://www.breached.com",
   username: "username",
   password: "password",
   timePasswordChanged: new Date("2018-12-15").getTime(),
 });
@@ -93,135 +96,198 @@ const LOGIN_FOR_BREACHED_SITE_WITHOUT_PA
 const LOGIN_WITH_NON_STANDARD_URI = LoginTestUtils.testData.formLogin({
   origin: "someApp://random/path/to/login",
   formActionOrigin: "someApp://random/path/to/login",
   username: "username",
   password: "password",
   timePasswordChanged: new Date("2018-12-15").getTime(),
 });
 
-add_task(async function test_getBreachesForLogins_notBreachedLogin() {
+add_task(async function test_notBreachedLogin() {
   Services.logins.addLogin(NOT_BREACHED_LOGIN);
 
-  const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
     [NOT_BREACHED_LOGIN],
     TEST_BREACHES
   );
   Assert.strictEqual(
     breachesByLoginGUID.size,
     0,
     "Should be 0 breached logins."
   );
 });
 
-add_task(async function test_getBreachesForLogins_breachedLogin() {
+add_task(async function test_breachedLogin() {
   Services.logins.addLogin(BREACHED_LOGIN);
 
-  const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
     [NOT_BREACHED_LOGIN, BREACHED_LOGIN],
     TEST_BREACHES
   );
   Assert.strictEqual(
     breachesByLoginGUID.size,
     1,
     "Should be 1 breached login: " + BREACHED_LOGIN.origin
   );
 });
 
-add_task(async function test_getBreachesForLogins_notBreachedSubdomain() {
+add_task(async function test_notBreachedSubdomain() {
   Services.logins.addLogin(NOT_BREACHED_SUBDOMAIN_LOGIN);
 
-  const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
     [NOT_BREACHED_LOGIN, NOT_BREACHED_SUBDOMAIN_LOGIN],
     TEST_BREACHES
   );
   Assert.strictEqual(
     breachesByLoginGUID.size,
     0,
     "Should be 0 breached logins."
   );
 });
 
-add_task(async function test_getBreachesForLogins_breachedSubdomain() {
+add_task(async function test_breachedSubdomain() {
   Services.logins.addLogin(BREACHED_SUBDOMAIN_LOGIN);
 
-  const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
     [NOT_BREACHED_SUBDOMAIN_LOGIN, BREACHED_SUBDOMAIN_LOGIN],
     TEST_BREACHES
   );
   Assert.strictEqual(
     breachesByLoginGUID.size,
     1,
     "Should be 1 breached login: " + BREACHED_SUBDOMAIN_LOGIN.origin
   );
 });
 
-add_task(
-  async function test_getBreachesForLogins_breachedSiteWithoutPasswords() {
-    Services.logins.addLogin(LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS);
+add_task(async function test_breachedSiteWithoutPasswords() {
+  Services.logins.addLogin(LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS);
 
-    const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
-      [LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS],
-      TEST_BREACHES
-    );
-    Assert.strictEqual(
-      breachesByLoginGUID.size,
-      0,
-      "Should be 0 breached login: " +
-        LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS.origin
-    );
-  }
-);
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
+    [LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS],
+    TEST_BREACHES
+  );
+  Assert.strictEqual(
+    breachesByLoginGUID.size,
+    0,
+    "Should be 0 breached login: " +
+      LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS.origin
+  );
+});
+
+add_task(async function test_breachAlertHiddenAfterDismissal() {
+  BREACHED_LOGIN.guid = "{d2de5ac1-4de6-e544-a7af-1f75abcba92b}";
+
+  await Services.logins.initializationPromise;
+  const storageJSON = Services.logins.wrappedJSObject._storage.wrappedJSObject;
+
+  storageJSON.recordBreachAlertDismissal(BREACHED_LOGIN.guid);
 
-add_task(
-  async function test_getBreachesForLogins_breachAlertHiddenAfterDismissal() {
-    BREACHED_LOGIN.guid = "{d2de5ac1-4de6-e544-a7af-1f75abcba92b}";
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
+    [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
+    TEST_BREACHES
+  );
+  Assert.strictEqual(
+    breachesByLoginGUID.size,
+    0,
+    "Should be 0 breached logins after dismissal: " + BREACHED_LOGIN.origin
+  );
 
-    await Services.logins.initializationPromise;
-    const storageJSON =
-      Services.logins.wrappedJSObject._storage.wrappedJSObject;
-
-    storageJSON.recordBreachAlertDismissal(BREACHED_LOGIN.guid);
+  info("Clear login storage");
+  Services.logins.removeAllLogins();
 
-    const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
-      [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
-      TEST_BREACHES
-    );
-    Assert.strictEqual(
-      breachesByLoginGUID.size,
-      0,
-      "Should be 0 breached logins after dismissal: " + BREACHED_LOGIN.origin
-    );
-  }
-);
+  const breachesByLoginGUID2 = await LoginBreaches.getPotentialBreachesByLoginGUID(
+    [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
+    TEST_BREACHES
+  );
+  Assert.strictEqual(
+    breachesByLoginGUID2.size,
+    1,
+    "Breached login should re-appear after clearing storage: " +
+      BREACHED_LOGIN.origin
+  );
+});
 
-add_task(async function test_getBreachesForLogins_newBreachAfterDismissal() {
+add_task(async function test_newBreachAfterDismissal() {
   TEST_BREACHES[0].AddedDate = new Date().toISOString();
 
-  const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
     [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
     TEST_BREACHES
   );
 
   Assert.strictEqual(
     breachesByLoginGUID.size,
     1,
     "Should be 1 breached login after new breach following the dismissal of a previous breach: " +
       BREACHED_LOGIN.origin
   );
 });
 
-add_task(
-  async function test_getBreachesForLogins_ExceptionsThrownByNonStandardURIsAreCaught() {
-    Services.logins.addLogin(LOGIN_WITH_NON_STANDARD_URI);
+add_task(async function test_ExceptionsThrownByNonStandardURIsAreCaught() {
+  Services.logins.addLogin(LOGIN_WITH_NON_STANDARD_URI);
+
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
+    [LOGIN_WITH_NON_STANDARD_URI, BREACHED_LOGIN],
+    TEST_BREACHES
+  );
+
+  Assert.strictEqual(
+    breachesByLoginGUID.size,
+    1,
+    "Exceptions thrown by logins with non-standard URIs should be caught."
+  );
+});
 
-    const breachesByLoginGUID = await LoginHelper.getBreachesForLogins(
-      [LOGIN_WITH_NON_STANDARD_URI, BREACHED_LOGIN],
-      TEST_BREACHES
-    );
-
-    Assert.strictEqual(
-      breachesByLoginGUID.size,
-      1,
-      "Exceptions thrown by logins with non-standard URIs should be caught."
+add_task(async function test_updateBreachesFromRemoteSettingsSync() {
+  const login = NOT_BREACHED_SUBDOMAIN_LOGIN;
+  const nowExampleIsInBreachedRecords = [
+    {
+      AddedDate: "2018-12-20T23:56:26Z",
+      BreachDate: "2018-12-16",
+      Domain: "not-breached-subdomain.host.com",
+      Name: "not-breached-subdomain.host.com is now breached!",
+      PwnCount: 1643100,
+      DataClasses: [
+        "Email addresses",
+        "Usernames",
+        "Passwords",
+        "IP addresses",
+      ],
+      _status: "synced",
+      id: "047940fe-d2fd-4314-b636-b4a952ee0044",
+      last_modified: "1541615610052",
+      schema: "1541615609018",
+    },
+  ];
+  async function emitSync() {
+    await RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).emit(
+      "sync",
+      { data: { current: nowExampleIsInBreachedRecords } }
     );
   }
-);
+
+  const beforeSyncBreachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
+    [login]
+  );
+  Assert.strictEqual(
+    beforeSyncBreachesByLoginGUID.size,
+    0,
+    "Should be 0 breached login before not-breached-subdomain.host.com is added to fxmonitor-breaches collection and synced: "
+  );
+  gBrowserGlue.observe(null, "browser-glue-test", "add-breaches-sync-handler");
+  const collection = await RemoteSettings(
+    LoginBreaches.REMOTE_SETTINGS_COLLECTION
+  ).openCollection();
+  await collection.create(nowExampleIsInBreachedRecords[0], {
+    useRecordId: true,
+  });
+  await collection.db.saveLastModified(42);
+  await emitSync();
+
+  const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
+    [login]
+  );
+  Assert.strictEqual(
+    breachesByLoginGUID.size,
+    1,
+    "Should be 1 breached login after not-breached-subdomain.host.com is added to fxmonitor-breaches collection and synced: "
+  );
+});
--- a/browser/components/aboutlogins/tests/unit/xpcshell.ini
+++ b/browser/components/aboutlogins/tests/unit/xpcshell.ini
@@ -1,5 +1,5 @@
 [DEFAULT]
 head = head.js
 firefox-appdir = browser
 
-[test_getBreachesForLogins.js]
+[test_getPotentialBreachesByLoginGUID.js]
--- a/browser/components/controlcenter/content/identityPanel.inc.xul
+++ b/browser/components/controlcenter/content/identityPanel.inc.xul
@@ -86,17 +86,16 @@
                 label="&identity.clearSiteData;"
                 oncommand="gIdentityHandler.clearSiteData(event); gIdentityHandler.recordClick('clear_sitedata');"/>
       </vbox>
     </panelview>
 
     <!-- Security SubView -->
     <panelview id="identity-popup-securityView"
                role="document"
-               title="&identity.securityView.label2;"
                descriptionheightworkaround="true">
       <vbox class="identity-popup-security-content">
         <vbox class="identity-popup-security-connection">
           <description class="identity-popup-connection-not-secure"
                        when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecureSecurityView;</description>
           <description class="identity-popup-connection-secure"
                        when-connection="secure secure-ev">&identity.connectionVerified3;</description>
         </vbox>
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -228,17 +228,17 @@ var CustomizableUIInternal = {
       "spring",
       "downloads-button",
       "library-button",
       "sidebar-button",
       "fxa-toolbar-menu-button",
     ];
 
     if (AppConstants.MOZ_DEV_EDITION) {
-      navbarPlacements.splice(2, 0, "developer-button");
+      navbarPlacements.splice(7, 0, "developer-button");
     }
 
     this.registerArea(
       CustomizableUI.AREA_NAVBAR,
       {
         type: CustomizableUI.TYPE_TOOLBAR,
         overflowable: true,
         defaultPlacements: navbarPlacements,
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -1326,19 +1326,19 @@ var PanelView = class extends Associated
    */
   set headerText(value) {
     // If the header already exists, update or remove it as requested.
     let header = this.node.firstElementChild;
     if (header && header.classList.contains("panel-header")) {
       if (value) {
         // The back button has a label in it - we want to select
         // the label that's a direct child of the header.
-        header
-          .querySelector(".panel-header > label")
-          .setAttribute("value", value);
+        header.querySelector(
+          ".panel-header > label > span"
+        ).textContent = value;
       } else {
         header.remove();
       }
       return;
     }
 
     // The header doesn't exist, only create it if needed.
     if (!value) {
@@ -1359,17 +1359,19 @@ var PanelView = class extends Associated
     );
     backButton.addEventListener("command", () => {
       // The panelmultiview element may change if the view is reused.
       this.node.panelMultiView.goBack();
       backButton.blur();
     });
 
     let label = this.document.createXULElement("label");
-    label.setAttribute("value", value);
+    let span = this.document.createElement("span");
+    span.textContent = value;
+    label.appendChild(span);
 
     header.append(backButton, label);
     this.node.prepend(header);
   }
 
   /**
    * Also make sure that the correct method is called on CustomizableWidget.
    */
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -973,16 +973,22 @@ var Policies = {
   },
 
   OfferToSaveLogins: {
     onBeforeUIStartup(manager, param) {
       setAndLockPref("signon.rememberSignons", param);
     },
   },
 
+  OfferToSaveLoginsDefault: {
+    onBeforeUIStartup(manager, param) {
+      setDefaultPref("signon.rememberSignons", param);
+    },
+  },
+
   OverrideFirstRunPage: {
     onProfileAfterChange(manager, param) {
       let url = param ? param.href : "";
       setAndLockPref("startup.homepage_welcome_url", url);
       setAndLockPref("trailhead.firstrun.branches", "nofirstrun");
     },
   },
 
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -492,16 +492,20 @@
     "NoDefaultBookmarks": {
       "type": "boolean"
     },
 
     "OfferToSaveLogins": {
       "type": "boolean"
     },
 
+    "OfferToSaveLoginsDefault": {
+      "type": "boolean"
+    },
+
     "OverrideFirstRunPage": {
       "type": "URLorEmpty"
     },
 
     "OverridePostUpdatePage": {
       "type": "URLorEmpty"
     },
 
--- a/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
@@ -451,16 +451,26 @@ const POLICIES_TESTS = [
         Locked: true,
       },
     },
     lockedPrefs: {
       "browser.newtabpage.activity-stream.feeds.snippets": false,
       "browser.newtabpage.activity-stream.feeds.section.topstories": false,
     },
   },
+
+  // POLICY: OfferToSaveLoginsDefault
+  {
+    policies: {
+      OfferToSaveLoginsDefault: false,
+    },
+    unlockedPrefs: {
+      "signon.rememberSignons": false,
+    },
+  },
 ];
 
 add_task(async function test_policy_simple_prefs() {
   for (let test of POLICIES_TESTS) {
     await setupPolicyEngineWithJson({
       policies: test.policies,
     });
 
--- a/browser/components/extensions/moz.build
+++ b/browser/components/extensions/moz.build
@@ -17,17 +17,15 @@ EXTRA_JS_MODULES += [
     'ExtensionControlledPopup.jsm',
     'ExtensionPopups.jsm',
 ]
 
 DIRS += ['schemas']
 
 BROWSER_CHROME_MANIFESTS += [
     'test/browser/browser-private.ini',
-    'test/browser/browser-remote.ini',
     'test/browser/browser.ini',
 ]
 
 MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
 XPCSHELL_TESTS_MANIFESTS += [
-    'test/xpcshell/xpcshell-remote.ini',
     'test/xpcshell/xpcshell.ini',
 ]
--- a/browser/components/extensions/parent/ext-tabs.js
+++ b/browser/components/extensions/parent/ext-tabs.js
@@ -200,17 +200,19 @@ const restricted = new Set(["url", "favI
 class TabsUpdateFilterEventManager extends EventManager {
   constructor(context) {
     let { extension } = context;
     let { tabManager } = extension;
 
     let register = (fire, filterProps) => {
       let filter = { ...filterProps };
       if (filter.urls) {
-        filter.urls = new MatchPatternSet(filter.urls);
+        filter.urls = new MatchPatternSet(filter.urls, {
+          restrictSchemes: false,
+        });
       }
       let needsModified = true;
       if (filter.properties) {
         // Default is to listen for all events.
         needsModified = filter.properties.some(p => allAttrs.has(p));
         filter.properties = new Set(filter.properties);
         // TODO Bug 1465520 remove warning when ready.
         if (filter.properties.has("isarticle")) {
@@ -939,17 +941,19 @@ this.tabs = class extends ExtensionAPI {
                   'The "tabs" permission is required to use the query API with the "url" or "title" parameters',
               });
             }
           }
 
           queryInfo = Object.assign({}, queryInfo);
 
           if (queryInfo.url !== null) {
-            queryInfo.url = new MatchPatternSet([].concat(queryInfo.url));
+            queryInfo.url = new MatchPatternSet([].concat(queryInfo.url), {
+              restrictSchemes: false,
+            });
           }
           if (queryInfo.title !== null) {
             queryInfo.title = new MatchGlob(queryInfo.title);
           }
 
           return Array.from(tabManager.query(queryInfo, context), tab =>
             tab.convert()
           );
deleted file mode 100644
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ /dev/null
@@ -1,272 +0,0 @@
-[DEFAULT]
-prefs =
-    dom.animations-api.core.enabled=true
-    dom.animations-api.timelines.enabled=true
-support-files =
-  silence.ogg
-  head_browserAction.js
-  head_pageAction.js
-  head_sessions.js
-  head_webNavigation.js
-  context.html
-  context_frame.html
-  ctxmenu-image.png
-  context_tabs_onUpdated_page.html
-  context_tabs_onUpdated_iframe.html
-  file_clearplugindata.html
-  file_find_frames.html
-  file_popup_api_injection_a.html
-  file_popup_api_injection_b.html
-  file_iframe_document.html
-  file_slowed_document.sjs
-  file_bypass_cache.sjs
-  file_language_fr_en.html
-  file_language_ja.html
-  file_language_tlh.html
-  file_dummy.html
-  file_title.html
-  file_indexedDB.html
-  file_serviceWorker.html
-  webNav_createdTarget.html
-  webNav_createdTargetSource.html
-  webNav_createdTargetSource_subframe.html
-  serviceWorker.js
-  searchSuggestionEngine.xml
-  searchSuggestionEngine.sjs
-  ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js
-  ../../../../../toolkit/components/extensions/test/mochitest/redirection.sjs
-  ../../../../../toolkit/components/reader/test/readerModeNonArticle.html
-  ../../../../../toolkit/components/reader/test/readerModeArticle.html
-
-[browser_ExtensionControlledPopup.js]
-[browser_ext_addon_debugging_netmonitor.js]
-[browser_ext_autoplayInBackground.js]
-[browser_ext_browserAction_area.js]
-[browser_ext_browserAction_experiment.js]
-[browser_ext_browserAction_context.js]
-skip-if = os == 'linux' && debug # Bug 1504096
-[browser_ext_browserAction_contextMenu.js]
-# bug 1369197
-skip-if = os == 'linux'
-[browser_ext_browserAction_disabled.js]
-[browser_ext_browserAction_incognito.js]
-[browser_ext_browserAction_pageAction_icon.js]
-[browser_ext_browserAction_pageAction_icon_permissions.js]
-[browser_ext_browserAction_popup.js]
-skip-if =
-  (debug && os == 'linux' && bits == 32) || # Bug 1313372
-  fission && debug # Causes shutdown crashes under Fission.
-[browser_ext_browserAction_popup_port.js]
-[browser_ext_browserAction_popup_preload.js]
-skip-if = (os == 'win' && !debug) || (verify && debug && (os == 'mac')) # bug 1352668
-[browser_ext_browserAction_popup_resize.js]
-skip-if = fission && debug # Causes shutdown crashes under Fission.
-[browser_ext_browserAction_popup_resize_bottom.js]
-skip-if = debug # Bug 1522164
-[browser_ext_browserAction_simple.js]
-[browser_ext_browserAction_telemetry.js]
-[browser_ext_browserAction_theme_icons.js]
-skip-if = (os == 'mac') # macosx1014 due to 1479256
-[browser_ext_browsingData_formData.js]
-[browser_ext_browsingData_history.js]
-[browser_ext_browsingData_indexedDB.js]
-[browser_ext_browsingData_localStorage.js]
-[browser_ext_browsingData_pluginData.js]
-skip-if = (os == 'mac' && debug) # Plugin test causes Mac window to lose active state and times out other tests.
-[browser_ext_browsingData_serviceWorkers.js]
-[browser_ext_chrome_settings_overrides_home.js]
-[browser_ext_commands_execute_browser_action.js]
-skip-if = fission && debug # Causes shutdown crashes under Fission.
-[browser_ext_commands_execute_page_action.js]
-skip-if = (verify && (os == 'linux' || os == 'mac'))
-[browser_ext_commands_execute_sidebar_action.js]
-[browser_ext_commands_getAll.js]
-[browser_ext_commands_onCommand.js]
-skip-if = (webrender && debug) # bug 1553577
-[browser_ext_commands_update.js]
-[browser_ext_connect_and_move_tabs.js]
-[browser_ext_contentscript_connect.js]
-[browser_ext_contextMenus.js]
-support-files = !/browser/components/places/tests/browser/head.js
-[browser_ext_contextMenus_checkboxes.js]
-[browser_ext_contextMenus_commands.js]
-[browser_ext_contextMenus_icons.js]
-[browser_ext_contextMenus_onclick.js]
-[browser_ext_contextMenus_radioGroups.js]
-[browser_ext_contextMenus_targetUrlPatterns.js]
-[browser_ext_contextMenus_uninstall.js]
-[browser_ext_contextMenus_urlPatterns.js]
-[browser_ext_currentWindow.js]
-[browser_ext_find.js]
-skip-if = (verify && (os == 'linux' || os == 'mac'))
-[browser_ext_getViews.js]
-[browser_ext_history_redirect.js]
-[browser_ext_identity_indication.js]
-[browser_ext_incognito_views.js]
-[browser_ext_incognito_popup.js]
-[browser_ext_lastError.js]
-[browser_ext_management.js]
-[browser_ext_menus.js]
-[browser_ext_menus_accesskey.js]
-[browser_ext_menus_activeTab.js]
-[browser_ext_menus_capture_secondary_click.js]
-[browser_ext_menus_errors.js]
-[browser_ext_menus_event_order.js]
-[browser_ext_menus_events.js]
-skip-if = os == 'linux' #Bug 1433892
-[browser_ext_menus_incognito.js]
-[browser_ext_menus_refresh.js]
-[browser_ext_menus_replace_menu.js]
-[browser_ext_menus_replace_menu_context.js]
-[browser_ext_menus_replace_menu_permissions.js]
-[browser_ext_menus_targetElement.js]
-[browser_ext_menus_targetElement_extension.js]
-[browser_ext_menus_targetElement_shadow.js]
-[browser_ext_menus_visible.js]
-[browser_ext_menus_viewType.js]
-[browser_ext_omnibox.js]
-[browser_ext_openPanel.js]
-skip-if = (verify && !debug && (os == 'linux' || os == 'mac'))
-[browser_ext_optionsPage_browser_style.js]
-[browser_ext_optionsPage_modals.js]
-[browser_ext_optionsPage_privileges.js]
-[browser_ext_pageAction_context.js]
-skip-if = (verify && !debug && (os == 'linux'))
-[browser_ext_pageAction_contextMenu.js]
-[browser_ext_pageAction_popup.js]
-[browser_ext_pageAction_popup_resize.js]
-skip-if = (verify && debug && (os == 'mac'))
-[browser_ext_pageAction_show_matches.js]
-[browser_ext_pageAction_simple.js]
-[browser_ext_pageAction_telemetry.js]
-[browser_ext_pageAction_title.js]
-[browser_ext_popup_api_injection.js]
-[browser_ext_popup_background.js]
-[browser_ext_popup_corners.js]
-[browser_ext_popup_focus.js]
-disabled = bug 1438663
-[browser_ext_popup_sendMessage.js]
-[browser_ext_popup_shutdown.js]
-[browser_ext_port_disconnect_on_crash.js]
-skip-if = !e10s || !crashreporter # the tab's process is killed during the test. Without e10s the parent process would die too
-[browser_ext_port_disconnect_on_window_close.js]
-[browser_ext_runtime_openOptionsPage.js]
-[browser_ext_runtime_openOptionsPage_uninstall.js]
-[browser_ext_search.js]
-[browser_ext_search_favicon.js]
-[browser_ext_runtime_setUninstallURL.js]
-[browser_ext_sessions_forgetClosedTab.js]
-[browser_ext_sessions_forgetClosedWindow.js]
-[browser_ext_sessions_incognito.js]
-[browser_ext_sessions_getRecentlyClosed.js]
-[browser_ext_sessions_getRecentlyClosed_private.js]
-[browser_ext_sessions_getRecentlyClosed_tabs.js]
-[browser_ext_sessions_restore.js]
-[browser_ext_sessions_restoreTab.js]
-[browser_ext_sessions_window_tab_value.js]
-skip-if = debug # Bug 1394984 disable debug builds on all platforms
-[browser_ext_settings_overrides_default_search.js]
-[browser_ext_sidebarAction.js]
-[browser_ext_sidebarAction_browser_style.js]
-[browser_ext_sidebarAction_click.js]
-[browser_ext_sidebarAction_context.js]
-[browser_ext_sidebarAction_contextMenu.js]
-[browser_ext_sidebarAction_incognito.js]
-skip-if = (os == "win" && os_version == "10.0") || ('mac' && os_version == '10.14' && debug) # Bug 1575369
-[browser_ext_sidebarAction_runtime.js]
-[browser_ext_sidebarAction_tabs.js]
-[browser_ext_sidebarAction_windows.js]
-[browser_ext_simple.js]
-[browser_ext_slow_script.js]
-skip-if = !e10s || debug || asan || (os == "win" && processor == "aarch64") # windows10-aarch64 due to 1534857
-[browser_ext_tab_runtimeConnect.js]
-[browser_ext_tabs_attention.js]
-[browser_ext_tabs_audio.js]
-[browser_ext_tabs_captureTab.js]
-[browser_ext_tabs_captureVisibleTab.js]
-[browser_ext_tabs_create.js]
-skip-if = os == "linux" && debug && bits == 32 # Bug 1350189
-[browser_ext_tabs_create_url.js]
-[browser_ext_tabs_create_invalid_url.js]
-[browser_ext_tabs_detectLanguage.js]
-[browser_ext_tabs_discard.js]
-skip-if = !e10s
-[browser_ext_tabs_discarded.js]
-fail-if = fission
-[browser_ext_tabs_duplicate.js]
-[browser_ext_tabs_events.js]
-skip-if = true # Bug 1521363
-[browser_ext_tabs_events_order.js]
-[browser_ext_tabs_executeScript.js]
-skip-if = (verify && !debug && (os == 'mac'))
-[browser_ext_tabs_executeScript_good.js]
-[browser_ext_tabs_executeScript_bad.js]
-[browser_ext_tabs_executeScript_multiple.js]
-[browser_ext_tabs_executeScript_no_create.js]
-[browser_ext_tabs_executeScript_runAt.js]
-[browser_ext_tabs_getCurrent.js]
-[browser_ext_tabs_hide.js]
-[browser_ext_tabs_hide_update.js]
-[browser_ext_tabs_highlight.js]
-[browser_ext_tabs_incognito_not_allowed.js]
-[browser_ext_tabs_insertCSS.js]
-[browser_ext_tabs_lastAccessed.js]
-[browser_ext_tabs_lazy.js]
-[browser_ext_tabs_removeCSS.js]
-[browser_ext_tabs_move_array.js]
-[browser_ext_tabs_move_discarded.js]
-[browser_ext_tabs_move_window.js]
-[browser_ext_tabs_move_window_multiple.js]
-[browser_ext_tabs_move_window_pinned.js]
-[browser_ext_tabs_onCreated.js]
-[browser_ext_tabs_onHighlighted.js]
-[browser_ext_tabs_onUpdated.js]
-[browser_ext_tabs_onUpdated_filter.js]
-[browser_ext_tabs_opener.js]
-[browser_ext_tabs_printPreview.js]
-[browser_ext_tabs_query.js]
-[browser_ext_tabs_readerMode.js]
-skip-if = fission
-[browser_ext_tabs_reload.js]
-[browser_ext_tabs_reload_bypass_cache.js]
-[browser_ext_tabs_saveAsPDF.js]
-skip-if = os == 'mac' # Save as PDF not supported on Mac OS X
-[browser_ext_tabs_sendMessage.js]
-[browser_ext_tabs_sharingState.js]
-[browser_ext_tabs_successors.js]
-[browser_ext_tabs_cookieStoreId.js]
-[browser_ext_tabs_update.js]
-[browser_ext_tabs_update_highlighted.js]
-[browser_ext_tabs_update_url.js]
-[browser_ext_tabs_zoom.js]
-[browser_ext_themes_validation.js]
-[browser_ext_topSites.js]
-[browser_ext_url_overrides_newtab.js]
-[browser_ext_urlbar_contextual_tip.js]
-[browser_ext_user_events.js]
-[browser_ext_webRequest.js]
-[browser_ext_webNavigation_frameId0.js]
-[browser_ext_webNavigation_getFrames.js]
-[browser_ext_webNavigation_onCreatedNavigationTarget.js]
-[browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js]
-[browser_ext_webNavigation_onCreatedNavigationTarget_named_window.js]
-[browser_ext_webNavigation_onCreatedNavigationTarget_subframe_window_open.js]
-[browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js]
-[browser_ext_webNavigation_urlbar_transitions.js]
-[browser_ext_windows.js]
-[browser_ext_windows_create.js]
-skip-if = (verify && (os == 'mac'))
-tags = fullscreen
-[browser_ext_windows_create_cookieStoreId.js]
-[browser_ext_windows_create_params.js]
-[browser_ext_windows_create_tabId.js]
-[browser_ext_windows_create_url.js]
-[browser_ext_windows_events.js]
-[browser_ext_windows_incognito.js]
-[browser_ext_windows_remove.js]
-[browser_ext_windows_size.js]
-skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode
-[browser_ext_windows_update.js]
-skip-if = (verify && (os == 'mac'))
-tags = fullscreen
-[browser_ext_contentscript_animate.js]
deleted file mode 100644
--- a/browser/components/extensions/test/browser/browser-remote.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-[DEFAULT]
-# This is a horrible hack:
-# In order to run tests under two configurations, we create two browser test
-# manifests, and include a manifest with a common set of tests from each. In
-# order to detect which manifest we're running from, we install the tests listed
-# in this manifest to the sub-directory "test-oop-extensions", and then check
-# whether we're running from that directory from head.js
-install-to-subdir = test-oop-extensions
-prefs =
-  extensions.webextensions.remote=true
-  # We don't want to reset this at the end of the test, so that we don't have
-  # to spawn a new extension child process for each test unit.
-  dom.ipc.keepProcessesAlive.extension=1
-
-tags = webextensions remote-webextensions
-skip-if = !e10s
-support-files =
-  head.js
-  head_devtools.js
-  file_inspectedwindow_reload_target.sjs
-
-[browser_ext_contentscript_nontab_connect.js]
-skip-if = fission
-[browser_ext_devtools_inspectedWindow.js]
-[browser_ext_devtools_inspectedWindow_eval_bindings.js]
-[browser_ext_devtools_inspectedWindow_reload.js]
-[browser_ext_devtools_network.js]
-skip-if = fission || os == 'linux' || (os == 'mac' && debug) || (debug && os == 'win' && bits == 64) # Bug1570478
-[browser_ext_devtools_page.js]
-[browser_ext_devtools_page_incognito.js]
-[browser_ext_devtools_panel.js]
-[browser_ext_devtools_panels_elements.js]
-[browser_ext_devtools_panels_elements_sidebar.js]
-support-files =
-  ../../../../../devtools/client/inspector/extensions/test/head_devtools_inspector_sidebar.js
-[browser_ext_optionsPage_popups.js]
-[browser_ext_popup_select.js]
-skip-if = debug || os != 'win' # FIXME: re-enable on debug build (bug 1442822)
-
-[include:browser-common.ini]
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -1,13 +1,299 @@
 [DEFAULT]
-tags = webextensions in-process-webextensions
+tags = webextensions
+prefs =
+    # We don't want to reset this at the end of the test, so that we don't have
+    # to spawn a new extension child process for each test unit.
+    dom.ipc.keepProcessesAlive.extension=1
+    dom.animations-api.core.enabled=true
+    dom.animations-api.timelines.enabled=true
 support-files =
   head.js
-prefs =
-  extensions.webextensions.remote=false
+  head_devtools.js
+  file_inspectedwindow_reload_target.sjs
+  silence.ogg
+  head_browserAction.js
+  head_pageAction.js
+  head_sessions.js
+  head_webNavigation.js
+  context.html
+  context_frame.html
+  ctxmenu-image.png
+  context_tabs_onUpdated_page.html
+  context_tabs_onUpdated_iframe.html
+  file_clearplugindata.html
+  file_find_frames.html
+  file_popup_api_injection_a.html
+  file_popup_api_injection_b.html
+  file_iframe_document.html
+  file_slowed_document.sjs
+  file_bypass_cache.sjs
+  file_language_fr_en.html
+  file_language_ja.html
+  file_language_tlh.html
+  file_dummy.html
+  file_title.html
+  file_indexedDB.html
+  file_serviceWorker.html
+  webNav_createdTarget.html
+  webNav_createdTargetSource.html
+  webNav_createdTargetSource_subframe.html
+  serviceWorker.js
+  searchSuggestionEngine.xml
+  searchSuggestionEngine.sjs
+  ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js
+  ../../../../../toolkit/components/extensions/test/mochitest/redirection.sjs
+  ../../../../../toolkit/components/reader/test/readerModeNonArticle.html
+  ../../../../../toolkit/components/reader/test/readerModeArticle.html
 
+[browser_ExtensionControlledPopup.js]
+[browser_ext_addon_debugging_netmonitor.js]
 [browser_ext_autocompletepopup.js]
+disabled = bug 1438663 # same focus issue as Bug 1438663
+[browser_ext_autoplayInBackground.js]
+[browser_ext_browserAction_area.js]
+[browser_ext_browserAction_experiment.js]
+[browser_ext_browserAction_context.js]
+skip-if = os == 'linux' && debug # Bug 1504096
+[browser_ext_browserAction_contextMenu.js]
+# bug 1369197
+skip-if = os == 'linux'
+[browser_ext_browserAction_disabled.js]
+[browser_ext_browserAction_incognito.js]
+[browser_ext_browserAction_pageAction_icon.js]
+[browser_ext_browserAction_pageAction_icon_permissions.js]
+[browser_ext_browserAction_popup.js]
+skip-if =
+  (debug && os == 'linux' && bits == 32) || # Bug 1313372
+  fission && debug # Causes shutdown crashes under Fission.
+[browser_ext_browserAction_popup_port.js]
+[browser_ext_browserAction_popup_preload.js]
+skip-if = (os == 'win' && !debug) || (verify && debug && (os == 'mac')) # bug 1352668
+[browser_ext_browserAction_popup_resize.js]
+skip-if = fission && debug # Causes shutdown crashes under Fission.
+[browser_ext_browserAction_popup_resize_bottom.js]
+skip-if = debug # Bug 1522164
+[browser_ext_browserAction_simple.js]
+[browser_ext_browserAction_telemetry.js]
+[browser_ext_browserAction_theme_icons.js]
+skip-if = (os == 'mac') # macosx1014 due to 1479256
+[browser_ext_browsingData_formData.js]
+[browser_ext_browsingData_history.js]
+[browser_ext_browsingData_indexedDB.js]
+[browser_ext_browsingData_localStorage.js]
+[browser_ext_browsingData_pluginData.js]
+skip-if = (os == 'mac' && debug) # Plugin test causes Mac window to lose active state and times out other tests.
+[browser_ext_browsingData_serviceWorkers.js]
+[browser_ext_chrome_settings_overrides_home.js]
+[browser_ext_commands_execute_browser_action.js]
+skip-if = fission && debug # Causes shutdown crashes under Fission.
+[browser_ext_commands_execute_page_action.js]
+skip-if = (verify && (os == 'linux' || os == 'mac'))
+[browser_ext_commands_execute_sidebar_action.js]
+[browser_ext_commands_getAll.js]
+[browser_ext_commands_onCommand.js]
+skip-if = (webrender && debug) # bug 1553577
+[browser_ext_commands_update.js]
+[browser_ext_connect_and_move_tabs.js]
+[browser_ext_contentscript_connect.js]
+[browser_ext_contentscript_nontab_connect.js]
+skip-if = fission
+[browser_ext_contextMenus.js]
+support-files = !/browser/components/places/tests/browser/head.js
+[browser_ext_contextMenus_checkboxes.js]
+[browser_ext_contextMenus_commands.js]
+[browser_ext_contextMenus_icons.js]
+[browser_ext_contextMenus_onclick.js]
+[browser_ext_contextMenus_radioGroups.js]
+[browser_ext_contextMenus_targetUrlPatterns.js]
+[browser_ext_contextMenus_uninstall.js]
+[browser_ext_contextMenus_urlPatterns.js]
+[browser_ext_currentWindow.js]
+[browser_ext_devtools_inspectedWindow.js]
+[browser_ext_devtools_inspectedWindow_eval_bindings.js]
+[browser_ext_devtools_inspectedWindow_reload.js]
+[browser_ext_devtools_network.js]
+skip-if = fission || os == 'linux' || (os == 'mac' && debug) || (debug && os == 'win' && bits == 64) # Bug1570478
+[browser_ext_devtools_page.js]
+[browser_ext_devtools_page_incognito.js]
+[browser_ext_devtools_panel.js]
+[browser_ext_devtools_panels_elements.js]
+[browser_ext_devtools_panels_elements_sidebar.js]
+support-files =
+  ../../../../../devtools/client/inspector/extensions/test/head_devtools_inspector_sidebar.js
+[browser_ext_find.js]
+skip-if = (verify && (os == 'linux' || os == 'mac'))
+[browser_ext_getViews.js]
+[browser_ext_history_redirect.js]
+[browser_ext_identity_indication.js]
+[browser_ext_incognito_views.js]
+[browser_ext_incognito_popup.js]
+[browser_ext_lastError.js]
+[browser_ext_management.js]
+[browser_ext_menus.js]
+[browser_ext_menus_accesskey.js]
+[browser_ext_menus_activeTab.js]
+[browser_ext_menus_capture_secondary_click.js]
+[browser_ext_menus_errors.js]
+[browser_ext_menus_event_order.js]
+[browser_ext_menus_events.js]
+skip-if = os == 'linux' #Bug 1433892
+[browser_ext_menus_incognito.js]
+[browser_ext_menus_refresh.js]
+[browser_ext_menus_replace_menu.js]
+[browser_ext_menus_replace_menu_context.js]
+[browser_ext_menus_replace_menu_permissions.js]
+[browser_ext_menus_targetElement.js]
+[browser_ext_menus_targetElement_extension.js]
+[browser_ext_menus_targetElement_shadow.js]
+[browser_ext_menus_visible.js]
+[browser_ext_menus_viewType.js]
+[browser_ext_omnibox.js]
+[browser_ext_openPanel.js]
+skip-if = (verify && !debug && (os == 'linux' || os == 'mac'))
+[browser_ext_optionsPage_browser_style.js]
+[browser_ext_optionsPage_modals.js]
+[browser_ext_optionsPage_popups.js]
+[browser_ext_optionsPage_privileges.js]
+[browser_ext_pageAction_context.js]
+skip-if = (verify && !debug && (os == 'linux'))
+[browser_ext_pageAction_contextMenu.js]
+[browser_ext_pageAction_popup.js]
+[browser_ext_pageAction_popup_resize.js]
+skip-if = (verify && debug && (os == 'mac'))
+[browser_ext_pageAction_show_matches.js]
+[browser_ext_pageAction_simple.js]
+[browser_ext_pageAction_telemetry.js]
+[browser_ext_pageAction_title.js]
+skip-if = fission # Timeouts Bug 1574926
+[browser_ext_popup_api_injection.js]
+[browser_ext_popup_background.js]
+[browser_ext_popup_corners.js]
+[browser_ext_popup_focus.js]
+disabled = bug 1438663
+[browser_ext_popup_select.js]
+skip-if = debug || os != 'win' # FIXME: re-enable on debug build (bug 1442822)
+[browser_ext_popup_sendMessage.js]
+[browser_ext_popup_shutdown.js]
+[browser_ext_port_disconnect_on_crash.js]
+skip-if = !e10s || !crashreporter # the tab's process is killed during the test. Without e10s the parent process would die too
+[browser_ext_port_disconnect_on_window_close.js]
+[browser_ext_runtime_openOptionsPage.js]
+[browser_ext_runtime_openOptionsPage_uninstall.js]
+[browser_ext_search.js]
+[browser_ext_search_favicon.js]
+[browser_ext_runtime_setUninstallURL.js]
+[browser_ext_sessions_forgetClosedTab.js]
+[browser_ext_sessions_forgetClosedWindow.js]
+[browser_ext_sessions_incognito.js]
+[browser_ext_sessions_getRecentlyClosed.js]
+[browser_ext_sessions_getRecentlyClosed_private.js]
+[browser_ext_sessions_getRecentlyClosed_tabs.js]
+[browser_ext_sessions_restore.js]
+[browser_ext_sessions_restoreTab.js]
+[browser_ext_sessions_window_tab_value.js]
+skip-if = debug # Bug 1394984 disable debug builds on all platforms
+[browser_ext_settings_overrides_default_search.js]
+[browser_ext_sidebarAction.js]
+[browser_ext_sidebarAction_browser_style.js]
+[browser_ext_sidebarAction_click.js]
+[browser_ext_sidebarAction_context.js]
+[browser_ext_sidebarAction_contextMenu.js]
+[browser_ext_sidebarAction_incognito.js]
+[browser_ext_sidebarAction_runtime.js]
+[browser_ext_sidebarAction_tabs.js]
+[browser_ext_sidebarAction_windows.js]
+[browser_ext_simple.js]
+[browser_ext_slow_script.js]
+skip-if = !e10s || debug || asan || (os == "win" && processor == "aarch64") # windows10-aarch64 due to 1534857
+[browser_ext_tab_runtimeConnect.js]
+[browser_ext_tabs_attention.js]
+[browser_ext_tabs_audio.js]
+[browser_ext_tabs_captureTab.js]
+[browser_ext_tabs_captureVisibleTab.js]
+[browser_ext_tabs_create.js]
+skip-if = os == "linux" && debug && bits == 32 # Bug 1350189
+[browser_ext_tabs_create_url.js]
+[browser_ext_tabs_create_invalid_url.js]
+[browser_ext_tabs_detectLanguage.js]
+[browser_ext_tabs_discard.js]
+skip-if = !e10s
+[browser_ext_tabs_discarded.js]
+fail-if = fission
+[browser_ext_tabs_duplicate.js]
+[browser_ext_tabs_events.js]
+skip-if = true # Bug 1521363
+[browser_ext_tabs_events_order.js]
+[browser_ext_tabs_executeScript.js]
+skip-if = (verify && !debug && (os == 'mac'))
+[browser_ext_tabs_executeScript_good.js]
+[browser_ext_tabs_executeScript_bad.js]
+[browser_ext_tabs_executeScript_multiple.js]
+[browser_ext_tabs_executeScript_no_create.js]
+[browser_ext_tabs_executeScript_runAt.js]
+[browser_ext_tabs_getCurrent.js]
+[browser_ext_tabs_hide.js]
+[browser_ext_tabs_hide_update.js]
+[browser_ext_tabs_highlight.js]
+[browser_ext_tabs_incognito_not_allowed.js]
+[browser_ext_tabs_insertCSS.js]
+[browser_ext_tabs_lastAccessed.js]
+[browser_ext_tabs_lazy.js]
+[browser_ext_tabs_removeCSS.js]
+[browser_ext_tabs_move_array.js]
+[browser_ext_tabs_move_discarded.js]
+[browser_ext_tabs_move_window.js]
+[browser_ext_tabs_move_window_multiple.js]
+[browser_ext_tabs_move_window_pinned.js]
+[browser_ext_tabs_onCreated.js]
+[browser_ext_tabs_onHighlighted.js]
+[browser_ext_tabs_onUpdated.js]
+[browser_ext_tabs_onUpdated_filter.js]
+[browser_ext_tabs_opener.js]
+[browser_ext_tabs_printPreview.js]
+[browser_ext_tabs_query.js]
+[browser_ext_tabs_readerMode.js]
+skip-if = fission
+[browser_ext_tabs_reload.js]
+[browser_ext_tabs_reload_bypass_cache.js]
+[browser_ext_tabs_saveAsPDF.js]
+skip-if = os == 'mac' # Save as PDF not supported on Mac OS X
+[browser_ext_tabs_sendMessage.js]
+[browser_ext_tabs_sharingState.js]
+[browser_ext_tabs_successors.js]