Compare commits

...

5 commits

5199 changed files with 535441 additions and 620955 deletions

View file

@ -5,13 +5,13 @@
[source.crates-io] [source.crates-io]
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/IceCatGraphics/aa-stroke?rev=a821fa621c2def48e90c82774b4c6563b5a8ea4a"] [source."git+https://github.com/FirefoxGraphics/aa-stroke?rev=a821fa621c2def48e90c82774b4c6563b5a8ea4a"]
git = "https://github.com/IceCatGraphics/aa-stroke" git = "https://github.com/FirefoxGraphics/aa-stroke"
rev = "a821fa621c2def48e90c82774b4c6563b5a8ea4a" rev = "a821fa621c2def48e90c82774b4c6563b5a8ea4a"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/IceCatGraphics/wpf-gpu-raster?rev=99979da091fd58fba8477e7fcdf5ec0727102916"] [source."git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=99979da091fd58fba8477e7fcdf5ec0727102916"]
git = "https://github.com/IceCatGraphics/wpf-gpu-raster" git = "https://github.com/FirefoxGraphics/wpf-gpu-raster"
rev = "99979da091fd58fba8477e7fcdf5ec0727102916" rev = "99979da091fd58fba8477e7fcdf5ec0727102916"
replace-with = "vendored-sources" replace-with = "vendored-sources"
@ -45,6 +45,11 @@ git = "https://github.com/gfx-rs/wgpu"
rev = "88862f1fa3fd0f0c1010e9fc999dcfe47b5ae8fc" rev = "88862f1fa3fd0f0c1010e9fc999dcfe47b5ae8fc"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/glandium/allocator-api2?rev=ad5f3d56a5a4519eff52af4ff85293431466ef5c"]
git = "https://github.com/glandium/allocator-api2"
rev = "ad5f3d56a5a4519eff52af4ff85293431466ef5c"
replace-with = "vendored-sources"
[source."git+https://github.com/glandium/rust-objc?rev=4de89f5aa9851ceca4d40e7ac1e2759410c04324"] [source."git+https://github.com/glandium/rust-objc?rev=4de89f5aa9851ceca4d40e7ac1e2759410c04324"]
git = "https://github.com/glandium/rust-objc" git = "https://github.com/glandium/rust-objc"
rev = "4de89f5aa9851ceca4d40e7ac1e2759410c04324" rev = "4de89f5aa9851ceca4d40e7ac1e2759410c04324"
@ -70,9 +75,9 @@ git = "https://github.com/jfkthame/mapped_hyph.git"
rev = "eff105f6ad7ec9b79816cfc1985a28e5340ad14b" rev = "eff105f6ad7ec9b79816cfc1985a28e5340ad14b"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954"] [source."git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6"]
git = "https://github.com/mozilla/application-services" git = "https://github.com/mozilla/application-services"
rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/audioipc?rev=e6f44a2bd1e57d11dfc737632a9e849077632330"] [source."git+https://github.com/mozilla/audioipc?rev=e6f44a2bd1e57d11dfc737632a9e849077632330"]
@ -80,9 +85,9 @@ git = "https://github.com/mozilla/audioipc"
rev = "e6f44a2bd1e57d11dfc737632a9e849077632330" rev = "e6f44a2bd1e57d11dfc737632a9e849077632330"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=2407441a2f67341a0e13b4ba6547555e387c671c"] [source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=579b75af21c040700eee6a1d8520e222699fe4cd"]
git = "https://github.com/mozilla/cubeb-coreaudio-rs" git = "https://github.com/mozilla/cubeb-coreaudio-rs"
rev = "2407441a2f67341a0e13b4ba6547555e387c671c" rev = "579b75af21c040700eee6a1d8520e222699fe4cd"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2"] [source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2"]
@ -95,9 +100,9 @@ git = "https://github.com/mozilla/midir.git"
rev = "85156e360a37d851734118104619f86bd18e94c6" rev = "85156e360a37d851734118104619f86bd18e94c6"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/mp4parse-rust?rev=e64650a686e5c5732395cd059e17cfd3b1e5b63b"] [source."git+https://github.com/mozilla/mp4parse-rust?rev=25ebfa59a21dc0d223052d73a2fafdd55307c2d7"]
git = "https://github.com/mozilla/mp4parse-rust" git = "https://github.com/mozilla/mp4parse-rust"
rev = "e64650a686e5c5732395cd059e17cfd3b1e5b63b" rev = "25ebfa59a21dc0d223052d73a2fafdd55307c2d7"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/neqo?tag=v0.13.4"] [source."git+https://github.com/mozilla/neqo?tag=v0.13.4"]

View file

@ -263,8 +263,7 @@ jobs:
- mozilla-release - mozilla-release
- mozilla-esr140 - mozilla-esr140
when: when:
- {weekday: 'Monday', hour: 8, minute: 0} - {weekday: 'Monday', hour: 5, minute: 0}
- {weekday: 'Thursday', hour: 8, minute: 0}
- name: daily-beta-perf - name: daily-beta-perf
job: job:

4
icecat/.gitignore vendored
View file

@ -37,6 +37,10 @@ ID
# third-party packages is dealt with by the script vendoring them. # third-party packages is dealt with by the script vendoring them.
*.egg-info/ *.egg-info/
# Ignore pywebsocket3 intermediate files.
testing/web-platform/tests/tools/third_party/pywebsocket3/pywebsocket3.egg-info
testing/web-platform/tests/tools/third_party/pywebsocket3/build
# Vim swap files. # Vim swap files.
.*.sw[a-z] .*.sw[a-z]
.sw[a-z] .sw[a-z]

View file

@ -101,7 +101,7 @@ tasks:
description: 'Created by a [cron task](https://icecat-ci-tc.services.mozilla.com/tasks/${cron.task_id}) (${treeherder_link})' description: 'Created by a [cron task](https://icecat-ci-tc.services.mozilla.com/tasks/${cron.task_id}) (${treeherder_link})'
provisionerId: "${trustDomain}-${repository.level}" provisionerId: "${trustDomain}-${repository.level}"
workerType: "decision-gcp" workerType: "decision"
tags: tags:
$if: 'tasks_for == "hg-push"' $if: 'tasks_for == "hg-push"'

View file

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Merge day clobber 2025-08-18 Merge day clobber 2026-02-23

56
icecat/Cargo.lock generated
View file

@ -5,7 +5,7 @@ version = 3
[[package]] [[package]]
name = "aa-stroke" name = "aa-stroke"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/IceCatGraphics/aa-stroke?rev=a821fa621c2def48e90c82774b4c6563b5a8ea4a#a821fa621c2def48e90c82774b4c6563b5a8ea4a" source = "git+https://github.com/FirefoxGraphics/aa-stroke?rev=a821fa621c2def48e90c82774b4c6563b5a8ea4a#a821fa621c2def48e90c82774b4c6563b5a8ea4a"
dependencies = [ dependencies = [
"euclid", "euclid",
] ]
@ -27,7 +27,8 @@ dependencies = [
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.999" version = "0.2.21"
source = "git+https://github.com/glandium/allocator-api2?rev=ad5f3d56a5a4519eff52af4ff85293431466ef5c#ad5f3d56a5a4519eff52af4ff85293431466ef5c"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -973,7 +974,7 @@ dependencies = [
[[package]] [[package]]
name = "context_id" name = "context_id"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"chrono", "chrono",
"error-support", "error-support",
@ -1085,7 +1086,7 @@ dependencies = [
[[package]] [[package]]
name = "coreaudio-sys-utils" name = "coreaudio-sys-utils"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=2407441a2f67341a0e13b4ba6547555e387c671c#2407441a2f67341a0e13b4ba6547555e387c671c" source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=579b75af21c040700eee6a1d8520e222699fe4cd#579b75af21c040700eee6a1d8520e222699fe4cd"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"coreaudio-sys", "coreaudio-sys",
@ -1165,6 +1166,7 @@ dependencies = [
name = "crash_helper_common" name = "crash_helper_common"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"getrandom 0.3.3",
"minidump-writer", "minidump-writer",
"nix 0.30.1", "nix 0.30.1",
"num-derive", "num-derive",
@ -1396,7 +1398,7 @@ dependencies = [
[[package]] [[package]]
name = "cubeb-coreaudio" name = "cubeb-coreaudio"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=2407441a2f67341a0e13b4ba6547555e387c671c#2407441a2f67341a0e13b4ba6547555e387c671c" source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=579b75af21c040700eee6a1d8520e222699fe4cd#579b75af21c040700eee6a1d8520e222699fe4cd"
dependencies = [ dependencies = [
"atomic", "atomic",
"audio-mixer", "audio-mixer",
@ -1912,7 +1914,7 @@ dependencies = [
[[package]] [[package]]
name = "error-support" name = "error-support"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"error-support-macros", "error-support-macros",
@ -1925,7 +1927,7 @@ dependencies = [
[[package]] [[package]]
name = "error-support-macros" name = "error-support-macros"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2042,9 +2044,9 @@ dependencies = [
] ]
[[package]] [[package]]
name = "icecat-versioning" name = "firefox-versioning"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"serde_json", "serde_json",
"thiserror 1.999.999", "thiserror 1.999.999",
@ -3385,7 +3387,7 @@ dependencies = [
[[package]] [[package]]
name = "interrupt-support" name = "interrupt-support"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"parking_lot", "parking_lot",
@ -4605,7 +4607,7 @@ dependencies = [
[[package]] [[package]]
name = "mp4parse" name = "mp4parse"
version = "0.17.0" version = "0.17.0"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=e64650a686e5c5732395cd059e17cfd3b1e5b63b#e64650a686e5c5732395cd059e17cfd3b1e5b63b" source = "git+https://github.com/mozilla/mp4parse-rust?rev=25ebfa59a21dc0d223052d73a2fafdd55307c2d7#25ebfa59a21dc0d223052d73a2fafdd55307c2d7"
dependencies = [ dependencies = [
"bitreader", "bitreader",
"byteorder", "byteorder",
@ -4622,7 +4624,7 @@ version = "0.1.0"
[[package]] [[package]]
name = "mp4parse_capi" name = "mp4parse_capi"
version = "0.17.0" version = "0.17.0"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=e64650a686e5c5732395cd059e17cfd3b1e5b63b#e64650a686e5c5732395cd059e17cfd3b1e5b63b" source = "git+https://github.com/mozilla/mp4parse-rust?rev=25ebfa59a21dc0d223052d73a2fafdd55307c2d7#25ebfa59a21dc0d223052d73a2fafdd55307c2d7"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"fallible_collections", "fallible_collections",
@ -5115,7 +5117,7 @@ checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
[[package]] [[package]]
name = "payload-support" name = "payload-support"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
@ -5622,7 +5624,7 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]] [[package]]
name = "relevancy" name = "relevancy"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.21.999", "base64 0.21.999",
@ -5646,12 +5648,12 @@ dependencies = [
[[package]] [[package]]
name = "remote_settings" name = "remote_settings"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"camino", "camino",
"error-support", "error-support",
"icecat-versioning", "firefox-versioning",
"jexl-eval", "jexl-eval",
"parking_lot", "parking_lot",
"regex", "regex",
@ -5947,10 +5949,10 @@ dependencies = [
[[package]] [[package]]
name = "search" name = "search"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"error-support", "error-support",
"icecat-versioning", "firefox-versioning",
"parking_lot", "parking_lot",
"remote_settings", "remote_settings",
"serde", "serde",
@ -6239,7 +6241,7 @@ dependencies = [
[[package]] [[package]]
name = "sql-support" name = "sql-support"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"error-support", "error-support",
"interrupt-support", "interrupt-support",
@ -6438,7 +6440,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "suggest" name = "suggest"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -6491,7 +6493,7 @@ dependencies = [
[[package]] [[package]]
name = "sync-guid" name = "sync-guid"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"base64 0.21.999", "base64 0.21.999",
"rand", "rand",
@ -6502,7 +6504,7 @@ dependencies = [
[[package]] [[package]]
name = "sync15" name = "sync15"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"error-support", "error-support",
@ -6541,7 +6543,7 @@ dependencies = [
[[package]] [[package]]
name = "tabs" name = "tabs"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"error-support", "error-support",
@ -6899,7 +6901,7 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]] [[package]]
name = "types" name = "types"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"rusqlite 0.33.0", "rusqlite 0.33.0",
"serde", "serde",
@ -7311,7 +7313,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "viaduct" name = "viaduct"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"error-support", "error-support",
"ffi-support", "ffi-support",
@ -7480,7 +7482,7 @@ dependencies = [
[[package]] [[package]]
name = "webext-storage" name = "webext-storage"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/mozilla/application-services?rev=9b46be5beedb6a1d859014a71bac58e2d722f954#9b46be5beedb6a1d859014a71bac58e2d722f954" source = "git+https://github.com/mozilla/application-services?rev=f5907a411e52a3985d0369d71c486eb507c2c4e6#f5907a411e52a3985d0369d71c486eb507c2c4e6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"error-support", "error-support",
@ -7899,7 +7901,7 @@ dependencies = [
[[package]] [[package]]
name = "wpf-gpu-raster" name = "wpf-gpu-raster"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/IceCatGraphics/wpf-gpu-raster?rev=99979da091fd58fba8477e7fcdf5ec0727102916#99979da091fd58fba8477e7fcdf5ec0727102916" source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=99979da091fd58fba8477e7fcdf5ec0727102916#99979da091fd58fba8477e7fcdf5ec0727102916"
dependencies = [ dependencies = [
"typed-arena-nomut", "typed-arena-nomut",
] ]

View file

@ -264,16 +264,17 @@ wr_malloc_size_of = { path = "gfx/wr/wr_malloc_size_of" }
# objc 0.2.7 + fa7ca43b862861dd1cd000d7ad01e6e0266cda13 # objc 0.2.7 + fa7ca43b862861dd1cd000d7ad01e6e0266cda13
objc = { git = "https://github.com/glandium/rust-objc", rev = "4de89f5aa9851ceca4d40e7ac1e2759410c04324" } objc = { git = "https://github.com/glandium/rust-objc", rev = "4de89f5aa9851ceca4d40e7ac1e2759410c04324" }
# application-services overrides to make updating them all simpler. # allocator-api2 + f95e3419ce41883904fcb2279b52aa35b5f04d76 + fdd92751afa7ce34408b677004b429d597e72c90
context_id = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" } allocator-api2 = { git = "https://github.com/glandium/allocator-api2", rev = "ad5f3d56a5a4519eff52af4ff85293431466ef5c" }
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
relevancy = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
search = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
sql-support = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
suggest = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
sync15 = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
tabs = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
viaduct = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "9b46be5beedb6a1d859014a71bac58e2d722f954" }
allocator-api2 = { path = "third_party/rust/allocator-api2" } # application-services overrides to make updating them all simpler.
context_id = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
relevancy = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
search = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
sql-support = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
suggest = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
sync15 = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
tabs = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
viaduct = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "f5907a411e52a3985d0369d71c486eb507c2c4e6" }

View file

@ -1768,11 +1768,12 @@ void DocAccessible::DoInitialUpdate() {
} }
#endif #endif
// Fire reorder event after the document tree is constructed. Note, since // Fire a reorder event on the OuterDocAccessible after the document tree is
// this reorder event is processed by parent document then events targeted to // constructed. Note that since this reorder event is processed by the parent
// this document may be fired prior to this reorder event. If this is // document, events targeted to this child document may be fired prior to this
// a problem then consider to keep event processing per tab document. // reorder event. We don't fire a reorder event for remote documents; the
if (!IsRoot()) { // parent process handles that.
if (!IPCDoc() && !IsRoot()) {
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(LocalParent()); RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(LocalParent());
ParentDocument()->FireDelayedEvent(reorderEvent); ParentDocument()->FireDelayedEvent(reorderEvent);
} }

View file

@ -50,6 +50,7 @@ DocAccessibleParent::DocAccessibleParent()
mTopLevel(false), mTopLevel(false),
mTopLevelInContentProcess(false), mTopLevelInContentProcess(false),
mShutdown(false), mShutdown(false),
mIsInitialTreeDone(false),
mFocus(0), mFocus(0),
mCaretId(0), mCaretId(0),
mCaretOffset(-1), mCaretOffset(-1),
@ -145,7 +146,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
// Otherwise, clients might crawl the incomplete subtree and they won't get // Otherwise, clients might crawl the incomplete subtree and they won't get
// mutation events for the remaining pieces. // mutation events for the remaining pieces.
if (aComplete || root != child) { if (aComplete || root != child) {
AttachChild(parent, childIdx, child); if (!AttachChild(parent, childIdx, child)) {
return IPC_FAIL(this, "failed to attach child");
}
} }
} }
@ -174,7 +177,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
MOZ_ASSERT(rootParent); MOZ_ASSERT(rootParent);
root = GetAccessible(mPendingShowChild); root = GetAccessible(mPendingShowChild);
MOZ_ASSERT(root); MOZ_ASSERT(root);
AttachChild(rootParent, mPendingShowIndex, root); if (!AttachChild(rootParent, mPendingShowIndex, root)) {
return IPC_FAIL(this, "failed to attach pending show child");
}
mPendingShowChild = 0; mPendingShowChild = 0;
mPendingShowParent = 0; mPendingShowParent = 0;
mPendingShowIndex = 0; mPendingShowIndex = 0;
@ -234,6 +239,11 @@ RemoteAccessible* DocAccessibleParent::CreateAcc(
return nullptr; return nullptr;
} }
if (aAccData.GenericTypes() & eDocument) {
MOZ_ASSERT_UNREACHABLE("Invalid acc type");
return nullptr;
}
newProxy = new RemoteAccessible(aAccData.ID(), this, aAccData.Role(), newProxy = new RemoteAccessible(aAccData.ID(), this, aAccData.Role(),
aAccData.Type(), aAccData.GenericTypes(), aAccData.Type(), aAccData.GenericTypes(),
aAccData.RoleMapEntryIndex()); aAccData.RoleMapEntryIndex());
@ -246,9 +256,20 @@ RemoteAccessible* DocAccessibleParent::CreateAcc(
return newProxy; return newProxy;
} }
void DocAccessibleParent::AttachChild(RemoteAccessible* aParent, bool DocAccessibleParent::AttachChild(RemoteAccessible* aParent,
uint32_t aIndex, uint32_t aIndex,
RemoteAccessible* aChild) { RemoteAccessible* aChild) {
if (aChild->RemoteParent()) {
MOZ_ASSERT_UNREACHABLE(
"Attempt to attach child which already has a parent!");
return false;
}
if (aParent == aChild) {
MOZ_ASSERT_UNREACHABLE("Attempt to make an accessible its own child!");
return false;
}
aParent->AddChildAt(aIndex, aChild); aParent->AddChildAt(aIndex, aChild);
aChild->SetParent(aParent); aChild->SetParent(aParent);
// ProxyCreated might have already been called if aChild is being moved. // ProxyCreated might have already been called if aChild is being moved.
@ -269,11 +290,16 @@ void DocAccessibleParent::AttachChild(RemoteAccessible* aParent,
} }
MOZ_ASSERT(bridge->GetEmbedderAccessibleDoc() == this); MOZ_ASSERT(bridge->GetEmbedderAccessibleDoc() == this);
if (DocAccessibleParent* childDoc = bridge->GetDocAccessibleParent()) { if (DocAccessibleParent* childDoc = bridge->GetDocAccessibleParent()) {
MOZ_DIAGNOSTIC_ASSERT(!childDoc->RemoteParent(),
"Pending OOP child doc shouldn't have parent "
"once new OuterDoc is attached");
AddChildDoc(childDoc, aChild->ID(), false); AddChildDoc(childDoc, aChild->ID(), false);
} }
return true; return true;
}); });
} }
return true;
} }
void DocAccessibleParent::ShutdownOrPrepareForMove(RemoteAccessible* aAcc) { void DocAccessibleParent::ShutdownOrPrepareForMove(RemoteAccessible* aAcc) {
@ -286,6 +312,10 @@ void DocAccessibleParent::ShutdownOrPrepareForMove(RemoteAccessible* aAcc) {
// the show event. For now, clear all of them by moving them to a temporary. // the show event. For now, clear all of them by moving them to a temporary.
auto children{std::move(aAcc->mChildren)}; auto children{std::move(aAcc->mChildren)};
for (RemoteAccessible* child : children) { for (RemoteAccessible* child : children) {
if (child == aAcc) {
MOZ_ASSERT_UNREACHABLE(
"Somehow an accessible got added as a child of itself!");
}
ShutdownOrPrepareForMove(child); ShutdownOrPrepareForMove(child);
} }
} }
@ -603,6 +633,18 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvMutationEvents(
mozilla::ipc::IPCResult DocAccessibleParent::RecvRequestAckMutationEvents() { mozilla::ipc::IPCResult DocAccessibleParent::RecvRequestAckMutationEvents() {
if (!mShutdown) { if (!mShutdown) {
if (!mIsInitialTreeDone) {
// This is the first request for an ACK, which means we now have the
// initial tree.
mIsInitialTreeDone = true;
// If this document is already bound to its embedder, fire a reorder event
// to notify the client that the embedded document is available. If not,
// this will be handled when this document is bound in AddChildDoc.
if (RemoteAccessible* parent = RemoteParent()) {
parent->Document()->FireEvent(parent,
nsIAccessibleEvent::EVENT_REORDER);
}
}
Unused << SendAckMutationEvents(); Unused << SendAckMutationEvents();
} }
return IPC_OK(); return IPC_OK();
@ -882,6 +924,11 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvBindChildDoc(
ipc::IPCResult DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc, ipc::IPCResult DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
uint64_t aParentID, uint64_t aParentID,
bool aCreating) { bool aCreating) {
if (aChildDoc->RemoteParent()) {
return IPC_FAIL(this,
"Attempt to add child doc which already has a parent");
}
// We do not use GetAccessible here because we want to be sure to not get the // We do not use GetAccessible here because we want to be sure to not get the
// document it self. // document it self.
ProxyEntry* e = mAccessibles.GetEntry(aParentID); ProxyEntry* e = mAccessibles.GetEntry(aParentID);
@ -930,11 +977,20 @@ ipc::IPCResult DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
aChildDoc->SetEmulatedWindowHandle(mEmulatedWindowHandle); aChildDoc->SetEmulatedWindowHandle(mEmulatedWindowHandle);
} }
#endif // defined(XP_WIN) #endif // defined(XP_WIN)
// We need to fire a reorder event on the outer doc accessible. }
// For same-process documents, this is fired by the content process, but // We need to fire a reorder event on the embedder. We do this here rather
// this isn't possible when the document is in a different process to its // than in the content process for two reasons:
// embedder. // 1. It isn't possible for the content process to fire a reorder event on the
// FireEvent fires both OS and XPCOM events. // embedder when the embedded document is in a different process to its
// embedder.
// 2. Doing it here ensures that the event is fired after the child document
// is bound. Otherwise, there could be a short period where the content
// process has fired the reorder event, but the child document isn't bound
// yet.
// However, if the initial tree hasn't been received yet, we don't want to
// fire the reorder event yet. That gets handled in
// RecvRequestAckMutationEvents.
if (aChildDoc->mIsInitialTreeDone) {
FireEvent(outerDoc, nsIAccessibleEvent::EVENT_REORDER); FireEvent(outerDoc, nsIAccessibleEvent::EVENT_REORDER);
} }

View file

@ -325,11 +325,14 @@ class DocAccessibleParent : public RemoteAccessible,
}; };
RemoteAccessible* CreateAcc(const AccessibleData& aAccData); RemoteAccessible* CreateAcc(const AccessibleData& aAccData);
void AttachChild(RemoteAccessible* aParent, uint32_t aIndex, bool AttachChild(RemoteAccessible* aParent, uint32_t aIndex,
RemoteAccessible* aChild); RemoteAccessible* aChild);
[[nodiscard]] bool CheckDocTree() const; [[nodiscard]] bool CheckDocTree() const;
xpcAccessibleGeneric* GetXPCAccessible(RemoteAccessible* aProxy); xpcAccessibleGeneric* GetXPCAccessible(RemoteAccessible* aProxy);
/**
* Fire an event to both OS and XPCOM consumers.
*/
void FireEvent(RemoteAccessible* aAcc, const uint32_t& aType); void FireEvent(RemoteAccessible* aAcc, const uint32_t& aType);
/** /**
@ -365,9 +368,10 @@ class DocAccessibleParent : public RemoteAccessible,
uint32_t mPendingShowIndex = 0; uint32_t mPendingShowIndex = 0;
nsTHashSet<uint64_t> mMovingIDs; nsTHashSet<uint64_t> mMovingIDs;
uint64_t mActorID; uint64_t mActorID;
bool mTopLevel; bool mTopLevel : 1;
bool mTopLevelInContentProcess; bool mTopLevelInContentProcess : 1;
bool mShutdown; bool mShutdown : 1;
bool mIsInitialTreeDone : 1;
RefPtr<dom::CanonicalBrowsingContext> mBrowsingContext; RefPtr<dom::CanonicalBrowsingContext> mBrowsingContext;
nsTHashSet<RefPtr<dom::BrowserBridgeParent>> mPendingOOPChildDocs; nsTHashSet<RefPtr<dom::BrowserBridgeParent>> mPendingOOPChildDocs;

View file

@ -429,6 +429,13 @@ static void AppendTextToAttributedString(
static RefPtr<AccAttributes> GetTextAttributes(TextLeafPoint aPoint) { static RefPtr<AccAttributes> GetTextAttributes(TextLeafPoint aPoint) {
RefPtr<AccAttributes> attrs = aPoint.GetTextAttributes(); RefPtr<AccAttributes> attrs = aPoint.GetTextAttributes();
if (!attrs) {
// If we can't fetch text attributes for the given point, return null.
// We avoid creating a new AccAttributes here because our AttributedText()
// code below relies on this null return value to indicate we're dealing
// with a non-text control.
return nullptr;
}
// Mac expects some object properties to be exposed as text attributes. We // Mac expects some object properties to be exposed as text attributes. We
// add these here rather than in utils::StringAttributesFromAccAttributes so // add these here rather than in utils::StringAttributesFromAccAttributes so
// we can use AccAttributes::Equal to determine whether we need to start a new // we can use AccAttributes::Equal to determine whether we need to start a new

View file

@ -11,6 +11,8 @@ support-files = [
["browser_hidden_iframe.js"] ["browser_hidden_iframe.js"]
https_first_disabled = true https_first_disabled = true
["browser_iframe_recreation.js"]
["browser_nested_iframe.js"] ["browser_nested_iframe.js"]
["browser_reframe_root.js"] ["browser_reframe_root.js"]

View file

@ -0,0 +1,29 @@
/* 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";
addAccessibleTask(
`test`,
async function testRecreation(browser, iframeDocAcc, topDocAcc) {
let iframe = findAccessibleChildByID(topDocAcc, DEFAULT_IFRAME_ID);
is(iframeDocAcc.parent, iframe, "iframe doc's parent is iframe");
// The ARIA role currently causes re-creation. If that ever changes, we'll
// need to switch to another technique here.
info("Change iframe's role to recreate it");
let shown = waitForEvent(EVENT_SHOW, DEFAULT_IFRAME_ID);
let reordered = waitForEvent(EVENT_REORDER, DEFAULT_IFRAME_ID);
await SpecialPowers.spawn(
topDocAcc.browsingContext,
[DEFAULT_IFRAME_ID],
id => {
content.document.getElementById(id).role = "foo";
}
);
iframe = (await shown).accessible;
await reordered;
is(iframeDocAcc.parent, iframe, "iframe doc's parent is iframe");
},
{ chrome: false, topLevel: false, iframe: true, remoteIframe: true }
);

View file

@ -276,3 +276,35 @@ addAccessibleTask(
ok(!attributedText[2].AXHighlight); ok(!attributedText[2].AXHighlight);
} }
); );
// Test the <mark> element, in conjunction with content that will
// prevent the creation of a text attributes object.
addAccessibleTask(
`<mark>a<button></button>b</mark>`,
async function testMarkNoAttributes(browser, accDoc) {
const macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface
);
const range = macDoc.getParameterizedAttributeValue(
"AXTextMarkerRangeForUnorderedTextMarkers",
[
macDoc.getAttributeValue("AXStartTextMarker"),
macDoc.getAttributeValue("AXEndTextMarker"),
]
);
const attributedText = macDoc.getParameterizedAttributeValue(
"AXAttributedStringForTextMarkerRange",
range
);
ok(attributedText, "Document has attributed text");
is(attributedText.length, 3, "3 pieces of attributed text exist");
ok(attributedText[0].AXHighlight, "0th pos text has highlight");
is(attributedText[0].string, "a", "0th pos text is string `a`");
ok(!attributedText[1].AXHighlight, "1st pos text has no highlight");
ok(attributedText[2].AXHighlight, "2nd pos text has highlight");
is(attributedText[2].string, "b", "2nd pos text is string `b`");
}
);

View file

@ -11,7 +11,6 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/CmdLineAndEnvUtils.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
#include "mozilla/glue/Debug.h" #include "mozilla/glue/Debug.h"
#include "mozilla/GeckoArgs.h" #include "mozilla/GeckoArgs.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
@ -19,12 +18,14 @@
#include "mozilla/SafeMode.h" #include "mozilla/SafeMode.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/WindowsConsole.h" #include "mozilla/WindowsConsole.h"
#include "mozilla/WindowsProcessMitigations.h"
#include "mozilla/WindowsVersion.h" #include "mozilla/WindowsVersion.h"
#include "mozilla/WinHeaderOnlyUtils.h" #include "mozilla/WinHeaderOnlyUtils.h"
#include "nsWindowsHelpers.h" #include "nsWindowsHelpers.h"
#include <windows.h> #include <windows.h>
#include <processthreadsapi.h> #include <processthreadsapi.h>
#include <shlwapi.h>
#include "DllBlocklistInit.h" #include "DllBlocklistInit.h"
#include "ErrorHandler.h" #include "ErrorHandler.h"
@ -111,16 +112,82 @@ static nsReturnRef<HANDLE> CreateJobAndAssignProcess(HANDLE aProcess) {
return job.out(); return job.out();
} }
#if !defined( \ enum class VCRuntimeDLLDir : bool {
PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON) Application,
# define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON \ System,
(0x00000001ULL << 60) };
#endif // !defined(PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON) static bool GetMSVCP140VersionInfo(VCRuntimeDLLDir aDir,
uint64_t& aOutVersion) {
wchar_t dllPath[MAX_PATH];
if (aDir == VCRuntimeDLLDir::Application) {
DWORD size = ::GetModuleFileNameW(nullptr, dllPath, MAX_PATH);
if (!size ||
(size == MAX_PATH && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) ||
!::PathRemoveFileSpecW(dllPath)) {
return false;
}
} else {
MOZ_ASSERT(aDir == VCRuntimeDLLDir::System);
UINT size = ::GetSystemDirectoryW(dllPath, MAX_PATH);
if (!size || size >= MAX_PATH) {
return false;
}
}
#if !defined(PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF) if (!::PathAppendW(dllPath, L"msvcp140.dll")) {
# define PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF \ return false;
(0x00000002ULL << 40) }
#endif // !defined(PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF) HMODULE crt =
::LoadLibraryExW(dllPath, nullptr, LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (!crt) {
return false;
}
mozilla::nt::PEHeaders headers{crt};
bool result = headers.GetVersionInfo(aOutVersion);
::FreeLibrary(crt);
return result;
}
/**
* Choose whether we want to favor loading DLLs from the system directory over
* the application directory. This choice automatically propagates to all child
* processes. In particular, it determines whether child processes will load
* Visual C++ runtime DLLs from the system or the application directory at
* startup.
*
* Whenever possible, we want all processes to favor loading DLLs from the
* system directory. But if old Visual C++ runtime DLLs are installed
* system-wide, then we must favor loading from the application directory
* instead to ensure compatibility, at least during startup. So in this case we
* only apply the delayed variant of the mitigation and only in sandboxed
* processes, which is the best compromise (see SandboxBroker::LaunchApp).
*
* This function is called from the launcher process *and* the browser process.
* This is because if the launcher process is disabled, we still want the
* browser process to go through this code so that it enforces the correct
* choice for itself and for child processes.
*/
static void EnablePreferLoadFromSystem32IfCompatible() {
// We may already have the mitigation if we are the browser process and we
// inherited it from the launcher process.
if (!mozilla::IsPreferLoadFromSystem32Available() ||
mozilla::IsPreferLoadFromSystem32Enabled()) {
return;
}
// Only bail out if (1) there is a conflict because the two DLLs exist *and*
// (2) the version of the system DLL is problematic.
uint64_t systemDirVersion = 0, appDirVersion = 0;
if (GetMSVCP140VersionInfo(VCRuntimeDLLDir::System, systemDirVersion) &&
GetMSVCP140VersionInfo(VCRuntimeDLLDir::Application, appDirVersion) &&
systemDirVersion < appDirVersion) {
return;
}
mozilla::DebugOnly<bool> setOk = mozilla::EnablePreferLoadFromSystem32();
MOZ_ASSERT(setOk);
}
/** /**
* Any mitigation policies that should be set on the browser process should go * Any mitigation policies that should be set on the browser process should go
@ -128,10 +195,11 @@ static nsReturnRef<HANDLE> CreateJobAndAssignProcess(HANDLE aProcess) {
*/ */
static void SetMitigationPolicies(mozilla::ProcThreadAttributes& aAttrs, static void SetMitigationPolicies(mozilla::ProcThreadAttributes& aAttrs,
const bool aIsSafeMode) { const bool aIsSafeMode) {
if (mozilla::IsWin10AnniversaryUpdateOrLater()) { // Note: Do *not* handle IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON here. For this
aAttrs.AddMitigationPolicy( // mitigation we rely on EnablePreferLoadFromSystem32IfCompatible().
PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON); // The launcher process or the browser process will choose whether we
} // want to apply the mitigation or not, and child processes will
// automatically inherit that choice.
#if defined(_M_ARM64) #if defined(_M_ARM64)
// Disable CFG on older versions of ARM64 Windows to avoid a crash in COM. // Disable CFG on older versions of ARM64 Windows to avoid a crash in COM.
@ -286,6 +354,9 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
return Nothing(); return Nothing();
} }
// Called from the launcher process *and* the browser process.
EnablePreferLoadFromSystem32IfCompatible();
#if defined(MOZ_LAUNCHER_PROCESS) #if defined(MOZ_LAUNCHER_PROCESS)
LauncherRegistryInfo regInfo; LauncherRegistryInfo regInfo;
Maybe<bool> runAsLauncher = RunAsLauncherProcess(regInfo, argc, argv); Maybe<bool> runAsLauncher = RunAsLauncherProcess(regInfo, argc, argv);
@ -309,22 +380,6 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
return Nothing(); return Nothing();
} }
// Make sure that the launcher process itself has image load policies set
if (IsWin10AnniversaryUpdateOrLater()) {
static const StaticDynamicallyLinkedFunctionPtr<
decltype(&SetProcessMitigationPolicy)>
pSetProcessMitigationPolicy(L"kernel32.dll",
"SetProcessMitigationPolicy");
if (pSetProcessMitigationPolicy) {
PROCESS_MITIGATION_IMAGE_LOAD_POLICY imgLoadPol = {};
imgLoadPol.PreferSystem32Images = 1;
DebugOnly<BOOL> setOk = pSetProcessMitigationPolicy(
ProcessImageLoadPolicy, &imgLoadPol, sizeof(imgLoadPol));
MOZ_ASSERT(setOk);
}
}
#if defined(MOZ_SANDBOX) #if defined(MOZ_SANDBOX)
// Ensure the relevant mitigations are enforced. // Ensure the relevant mitigations are enforced.
mozilla::sandboxing::ApplyParentProcessMitigations(); mozilla::sandboxing::ApplyParentProcessMitigations();

View file

@ -24,6 +24,7 @@ OS_LIBS += [
"oleaut32", "oleaut32",
"ole32", "ole32",
"rpcrt4", "rpcrt4",
"shlwapi",
"version", "version",
] ]

View file

@ -852,6 +852,13 @@ customElements.define(
BrowserAddonUI.openAddonsMgr( BrowserAddonUI.openAddonsMgr(
"addons://detail/" + encodeURIComponent(addonId) "addons://detail/" + encodeURIComponent(addonId)
); );
// The settings link element has its href set to "#" to be
// accessible with keyboard navigation, and so we call
// preventDefault to avoid the "#" href to be implicitly
// added to the browser chrome window url (See Bug 1983869
// for more details of the regression that the implicit
// change to the chrome window urls triggers).
event.preventDefault();
} }
break; break;
} }

View file

@ -389,7 +389,7 @@
<menuitem id="context-printframe" <menuitem id="context-printframe"
data-l10n-id="main-context-menu-frame-print" data-l10n-id="main-context-menu-frame-print"
/> />
<menuseparator/> <menuseparator id="print-frame-sep"/>
<menuitem id="context-take-frame-screenshot" <menuitem id="context-take-frame-screenshot"
data-l10n-id="main-context-menu-take-frame-screenshot" data-l10n-id="main-context-menu-take-frame-screenshot"
/> />

View file

@ -103,10 +103,9 @@ var PointerlockFsWarning = {
} else { } else {
textElem.removeAttribute("hidden"); textElem.removeAttribute("hidden");
// Document's principal's URI has a host. Display a warning including it. // Document's principal's URI has a host. Display a warning including it.
let { DownloadUtils } = ChromeUtils.importESModule( let displayHost = BrowserUtils.formatURIForDisplay(uri, {
"resource://gre/modules/DownloadUtils.sys.mjs" onlyBaseDomain: true,
); });
let displayHost = DownloadUtils.getURIHost(uri.spec)[0];
let l10nString = { let l10nString = {
"fullscreen-warning": "fullscreen-warning-domain", "fullscreen-warning": "fullscreen-warning-domain",
"pointerlock-warning": "pointerlock-warning-domain", "pointerlock-warning": "pointerlock-warning-domain",

View file

@ -1953,10 +1953,13 @@ var XULBrowserWindow = {
if (url) { if (url) {
url = Services.textToSubURI.unEscapeURIForUI(url); url = Services.textToSubURI.unEscapeURIForUI(url);
// Encode bidirectional formatting characters. /**
// (RFC 3987 sections 3.2 and 4.1 paragraph 6) * Encode bidirectional formatting characters.
* @see https://url.spec.whatwg.org/#url-rendering-i18n
* @see https://www.unicode.org/reports/tr9/#Directional_Formatting_Characters
*/
url = url.replace( url = url.replace(
/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, /[\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g,
encodeURIComponent encodeURIComponent
); );
@ -2227,7 +2230,7 @@ var XULBrowserWindow = {
// Ensure we close any remaining open locationspecific panels // Ensure we close any remaining open locationspecific panels
if (!isSameDocument) { if (!isSameDocument) {
closeOpenPanels("panel[locationspecific='true']"); closeOpenPanels(":is(panel, menupopup)[locationspecific='true']");
} }
gPermissionPanel.onLocationChange(); gPermissionPanel.onLocationChange();

View file

@ -67,6 +67,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
false false
); );
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"gPrintEnabled",
"print.enabled",
false
);
XPCOMUtils.defineLazyServiceGetter( XPCOMUtils.defineLazyServiceGetter(
lazy, lazy,
"QueryStringStripper", "QueryStringStripper",
@ -838,7 +845,8 @@ export class nsContextMenu {
"context-print-selection", "context-print-selection",
!this.inAboutDevtoolsToolbox && !this.inAboutDevtoolsToolbox &&
this.isContentSelected && this.isContentSelected &&
this.selectionInfo.isDocumentLevelSelection this.selectionInfo.isDocumentLevelSelection &&
lazy.gPrintEnabled
); );
var shouldShow = !( var shouldShow = !(
@ -946,6 +954,8 @@ export class nsContextMenu {
this.showItem("context-openframeintab", !this.inSrcdocFrame); this.showItem("context-openframeintab", !this.inSrcdocFrame);
this.showItem("context-openframe", !this.inSrcdocFrame); this.showItem("context-openframe", !this.inSrcdocFrame);
this.showItem("context-bookmarkframe", !this.inSrcdocFrame); this.showItem("context-bookmarkframe", !this.inSrcdocFrame);
this.showItem("context-printframe", lazy.gPrintEnabled);
this.showItem("print-frame-sep", lazy.gPrintEnabled);
// Hide menu entries for images, show otherwise // Hide menu entries for images, show otherwise
if (this.inFrame) { if (this.inFrame) {

View file

@ -127,6 +127,9 @@ let JSWINDOWACTORS = {
}, },
}, },
matches: ["about:messagepreview", "about:messagepreview?*"], matches: ["about:messagepreview", "about:messagepreview?*"],
remoteTypes: ["privilegedabout"],
enablePreference:
"browser.newtabpage.activity-stream.asrouter.devtoolsEnabled",
}, },
AboutPocket: { AboutPocket: {

View file

@ -110,6 +110,7 @@ static const RedirEntry kRedirMap[] = {
{"messagepreview", {"messagepreview",
"chrome://browser/content/messagepreview/messagepreview.html", "chrome://browser/content/messagepreview/messagepreview.html",
nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
{"pocket-saved", "chrome://pocket/content/panels/saved.html", {"pocket-saved", "chrome://pocket/content/panels/saved.html",

View file

@ -969,13 +969,6 @@ export default class LoginItem extends HTMLElement {
} }
_updatePasswordRevealState() { _updatePasswordRevealState() {
if (
window.AboutLoginsUtils &&
window.AboutLoginsUtils.passwordRevealVisible === false
) {
this._revealCheckbox.hidden = true;
}
let { checked } = this._revealCheckbox; let { checked } = this._revealCheckbox;
let inputType = checked ? "text" : "password"; let inputType = checked ? "text" : "password";
this._passwordInput.type = inputType; this._passwordInput.type = inputType;
@ -988,6 +981,13 @@ export default class LoginItem extends HTMLElement {
this._revealCheckbox.hidden = false; this._revealCheckbox.hidden = false;
} }
if (
window.AboutLoginsUtils &&
window.AboutLoginsUtils.passwordRevealVisible === false
) {
this._revealCheckbox.hidden = true;
}
// Swap which <input> is in the document depending on whether we need the // Swap which <input> is in the document depending on whether we need the
// real .value (which means that the primary password was already entered, // real .value (which means that the primary password was already entered,
// if applicable) // if applicable)

View file

@ -12,6 +12,7 @@ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {}; const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs", BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs", DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
Downloads: "resource://gre/modules/Downloads.sys.mjs", Downloads: "resource://gre/modules/Downloads.sys.mjs",
@ -600,7 +601,13 @@ DownloadsViewUI.DownloadElementShell.prototype = {
this.showStatus(stateLabel, hoverStatus); this.showStatus(stateLabel, hoverStatus);
return; return;
} }
let [displayHost] = lazy.DownloadUtils.getURIHost(this.download.source.url); let uri = URL.parse(this.download.source.url)?.URI;
let displayHost = uri
? lazy.BrowserUtils.formatURIForDisplay(uri, {
onlyBaseDomain: true,
})
: "";
let [displayDate] = lazy.DownloadUtils.getReadableDates( let [displayDate] = lazy.DownloadUtils.getReadableDates(
new Date(this.download.endTime) new Date(this.download.endTime)
); );

View file

@ -1576,6 +1576,27 @@ export var Policies = {
}, },
}, },
GenerativeAI: {
onBeforeAddons(manager, param) {
const defaultValue = "Enabled" in param ? param.Enabled : undefined;
const features = [
["Chatbot", ["browser.ml.chat.enabled", "browser.ml.chat.page"]],
["LinkPreviews", ["browser.ml.linkPreview.optin"]],
["TabGroups", ["browser.tabs.groups.smart.userEnabled"]],
];
for (const [key, prefs] of features) {
const value = key in param ? param[key] : defaultValue;
if (value !== undefined) {
for (const pref of prefs) {
PoliciesUtils.setDefaultPref(pref, value, param.Locked);
}
}
}
},
},
GoToIntranetSiteForSingleWordEntryInAddressBar: { GoToIntranetSiteForSingleWordEntryInAddressBar: {
onBeforeAddons(manager, param) { onBeforeAddons(manager, param) {
setAndLockPref("browser.fixup.dns_first_for_single_words", param); setAndLockPref("browser.fixup.dns_first_for_single_words", param);
@ -2080,6 +2101,7 @@ export var Policies = {
"security.tls.hello_downgrade_check", "security.tls.hello_downgrade_check",
"security.tls.version.enable-deprecated", "security.tls.version.enable-deprecated",
"security.warn_submit_secure_to_insecure", "security.warn_submit_secure_to_insecure",
"security.webauthn.always_allow_direct_attestation",
]; ];
const blockedPrefs = [ const blockedPrefs = [
"app.update.channel", "app.update.channel",

View file

@ -850,6 +850,27 @@
} }
}, },
"GenerativeAI": {
"type": "object",
"properties": {
"Chatbot": {
"type": "boolean"
},
"LinkPreviews": {
"type": "boolean"
},
"TabGroups": {
"type": "boolean"
},
"Enabled": {
"type": "boolean"
},
"Locked": {
"type": "boolean"
}
}
},
"GoToIntranetSiteForSingleWordEntryInAddressBar": { "GoToIntranetSiteForSingleWordEntryInAddressBar": {
"type": "boolean" "type": "boolean"
}, },

View file

@ -4,6 +4,41 @@
"use strict"; "use strict";
add_task(async function test_hidden_reveal_password() { add_task(async function test_hidden_reveal_password() {
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
Ci.nsILoginInfo
);
login.init("https://example.com", "", null, "username", "password");
login.QueryInterface(Ci.nsILoginMetaInfo);
login.timePasswordChanged = Date.now();
await Services.logins.addLoginAsync(login);
await setupPolicyEngineWithJson({
policies: {
DisablePasswordReveal: true,
},
});
let aboutLoginsTab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: "about:logins",
});
let browser = gBrowser.selectedBrowser;
await SpecialPowers.spawn(browser, [], () => {
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
let passwordReveal = loginItem.shadowRoot.querySelector(
".reveal-password-checkbox"
);
is(passwordReveal.hidden, true, "Password reveal button should be hidden");
});
BrowserTestUtils.removeTab(aboutLoginsTab);
await Services.logins.removeAllLogins();
});
add_task(async function test_bug_1696948() {
await setupPolicyEngineWithJson({ await setupPolicyEngineWithJson({
policies: { policies: {
DisablePasswordReveal: true, DisablePasswordReveal: true,

View file

@ -1184,6 +1184,38 @@ const POLICIES_TESTS = [
// browser/components/enterprisepolicies/tests/browser/browser_policy_usermessaging.js // browser/components/enterprisepolicies/tests/browser/browser_policy_usermessaging.js
}, },
}, },
// Bug 1981587
{
policies: {
Preferences: {
"security.webauthn.always_allow_direct_attestation": {
Value: true,
Status: "locked",
},
},
},
lockedPrefs: {
"security.webauthn.always_allow_direct_attestation": true,
},
},
// GenerativeAI
{
policies: {
GenerativeAI: {
Enabled: false,
Chatbot: true,
Locked: true,
},
},
lockedPrefs: {
"browser.ml.chat.enabled": true,
"browser.ml.chat.page": true,
"browser.ml.linkPreview.optin": false,
"browser.tabs.groups.smart.userEnabled": false,
},
},
]; ];
add_task(async function test_policy_simple_prefs() { add_task(async function test_policy_simple_prefs() {

View file

@ -166,7 +166,7 @@ export const LinkPreview = {
}, },
get canShowKeyPoints() { get canShowKeyPoints() {
return this._isRegionSupported(); return this._isRegionSupported() && !this._isDisabledByPolicy();
}, },
get canShowLegacy() { get canShowLegacy() {
@ -751,6 +751,17 @@ export const LinkPreview = {
return !disallowedRegions.includes(userRegion); return !disallowedRegions.includes(userRegion);
}, },
/**
* Checks if key points generation is disabled by policy.
*
* @returns {boolean} True if disabled by policy, false otherwise.
*/
_isDisabledByPolicy() {
return (
!lazy.optin && Services.prefs.prefIsLocked("browser.ml.linkPreview.optin")
);
},
/** /**
* Creates an Open Graph (OG) card using meta information from the page. * Creates an Open Graph (OG) card using meta information from the page.
* *

View file

@ -419,6 +419,13 @@ class LinkPreviewCard extends MozLitElement {
return ""; return "";
} }
if (
!this.optin &&
Services.prefs.prefIsLocked("browser.ml.linkPreview.optin")
) {
return "";
}
// Determine if there's any generation error state // Determine if there's any generation error state
const isGenerationError = const isGenerationError =
this.isMissingDataErrorState || this.generationError; this.isMissingDataErrorState || this.generationError;

View file

@ -450,3 +450,54 @@ add_task(async function test_no_optin_or_keypoints_in_disallowed_region() {
panel.remove(); panel.remove();
generateStub.restore(); generateStub.restore();
}); });
/**
* Test when the preference is false and locked, the opt-in prompt will not
* be shown and no attempt will be made to generate key points.
*/
add_task(async function test_locked_preference() {
await SpecialPowers.pushPrefEnv({
set: [
["browser.ml.linkPreview.enabled", true],
["browser.ml.linkPreview.optin", false],
["browser.ml.linkPreview.collapsed", false],
],
});
Services.prefs.lockPref("browser.ml.linkPreview.optin");
const generateStub = sinon.stub(LinkPreviewModel, "generateTextAI");
LinkPreview.keyboardComboActive = true;
XULBrowserWindow.setOverLink(
"https://example.com/browser/browser/components/genai/tests/browser/data/readableEn.html",
{}
);
let panel = await TestUtils.waitForCondition(() =>
document.getElementById("link-preview-panel")
);
await BrowserTestUtils.waitForEvent(panel, "popupshown");
const card = panel.querySelector("link-preview-card");
ok(card, "card created for link preview");
ok(
!LinkPreview.canShowKeyPoints,
"LinkPreview should indicate key points cannot be shown"
);
// Verify that the opt-in element is NOT present
const modelOptinElement = card.shadowRoot.querySelector("model-optin");
ok(!modelOptinElement, "model-optin element should NOT be present");
is(
generateStub.callCount,
0,
"generateTextAI should not be called in a disallowed region"
);
panel.remove();
generateStub.restore();
Services.prefs.unlockPref("browser.ml.linkPreview.optin");
});

View file

@ -513,7 +513,9 @@ export class FxviewTabRowBase extends MozLitElement {
formatURIForDisplay(uriString) { formatURIForDisplay(uriString) {
return !window.IS_STORYBOOK return !window.IS_STORYBOOK
? lazy.BrowserUtils.formatURIStringForDisplay(uriString) ? lazy.BrowserUtils.formatURIStringForDisplay(uriString, {
showFilenameForLocalURIs: true,
})
: uriString; : uriString;
} }

View file

@ -24,7 +24,9 @@ export const LOGGING_PREF = "browser.tabs.icecat-view.logLevel";
export const MAX_TABS_FOR_RECENT_BROWSING = 5; export const MAX_TABS_FOR_RECENT_BROWSING = 5;
export function formatURIForDisplay(uriString) { export function formatURIForDisplay(uriString) {
return lazy.BrowserUtils.formatURIStringForDisplay(uriString); return lazy.BrowserUtils.formatURIStringForDisplay(uriString, {
showFilenameForLocalURIs: true,
});
} }
export function convertTimestamp( export function convertTimestamp(

View file

@ -18,6 +18,7 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
HistoryController: "resource:///modules/HistoryController.sys.mjs", HistoryController: "resource:///modules/HistoryController.sys.mjs",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs", ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs",
}); });
@ -214,7 +215,8 @@ class HistoryInView extends ViewPage {
return ( return (
this.profileAge < 8 && this.profileAge < 8 &&
!this.hasImportedHistoryPref && !this.hasImportedHistoryPref &&
!this.importHistoryDismissedPref !this.importHistoryDismissedPref &&
Services.policies.isAllowed("profileImport")
); );
} }
@ -247,6 +249,7 @@ class HistoryInView extends ViewPage {
@click=${this.openInNewPrivateWindow} @click=${this.openInNewPrivateWindow}
data-l10n-id="fxviewtabrow-open-in-private-window" data-l10n-id="fxviewtabrow-open-in-private-window"
data-l10n-attrs="accesskey" data-l10n-attrs="accesskey"
?hidden=${!lazy.PrivateBrowsingUtils.enabled}
></panel-item> ></panel-item>
<hr /> <hr />
<panel-item <panel-item

View file

@ -49,7 +49,7 @@
#include placesContextMenu.inc.xhtml #include placesContextMenu.inc.xhtml
#include bookmarksHistoryTooltip.inc.xhtml #include bookmarksHistoryTooltip.inc.xhtml
<box id="sidebar-panel-header" align="center"> <box id="sidebar-panel-header" align="center">
<h4 data-l10n-id="sidebar-menu-bookmarks-2"></h4> <html:h4 data-l10n-id="sidebar-menu-bookmarks-2"></html:h4>
<html:moz-button <html:moz-button
id="sidebar-panel-close" id="sidebar-panel-close"
type="icon ghost" type="icon ghost"

View file

@ -797,6 +797,15 @@ class PlacesViewBase {
} }
if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) { if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
if (this.#isPopupForRecursiveFolderShortcut(popup)) {
// Show as an empty container for now. We may want to show a better
// message in the future, but since we are likely to remove recursive
// shortcuts in maintenance at a certain point, this should be enough.
this._setEmptyPopupStatus(popup, true);
popup._built = true;
return;
}
if (!popup._placesNode.containerOpen) { if (!popup._placesNode.containerOpen) {
popup._placesNode.containerOpen = true; popup._placesNode.containerOpen = true;
} }
@ -819,6 +828,33 @@ class PlacesViewBase {
aObject.removeEventListener(aEventNames[i], this, aCapturing); aObject.removeEventListener(aEventNames[i], this, aCapturing);
} }
} }
/**
* Walks up the parent chain to detect whether a folder shortcut resolves to
* a folder already present in the ancestry.
*
* @param {DOMElement} popup
* @returns {boolean} Whether this popup is for a recursive folder shortcut.
*/
#isPopupForRecursiveFolderShortcut(popup) {
if (
!popup._placesNode ||
!PlacesUtils.nodeIsFolderOrShortcut(popup._placesNode)
) {
return false;
}
let guid = PlacesUtils.getConcreteItemGuid(popup._placesNode);
for (
let parentView = popup.parentNode?.parentNode;
parentView?._placesNode;
parentView = parentView.parentNode?.parentNode
) {
if (PlacesUtils.getConcreteItemGuid(parentView._placesNode) == guid) {
return true;
}
}
return false;
}
} }
/** /**

View file

@ -214,6 +214,8 @@ skip-if = ["verify && debug && os == 'win'"]
["browser_paste_resets_cut_highlights.js"] ["browser_paste_resets_cut_highlights.js"]
["browser_recursive_hierarchies.js"]
["browser_remove_bookmarks.js"] ["browser_remove_bookmarks.js"]
["browser_sidebar_bookmarks_telemetry.js"] ["browser_sidebar_bookmarks_telemetry.js"]

View file

@ -0,0 +1,160 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Verify that menu popups are not populated when doing so would create a
* recursive hierarchy. Some consumers may walk menu trees and could enter an
* infinite loop if recursion were allowed.
*/
"use strict";
async function openMenuAndWaitForPopup(menu) {
let popup = menu.menupopup;
let popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown");
// This seems necessary, at least for the toolbar.
EventUtils.synthesizeNativeMouseEvent({
type: "mousemove",
target: menu,
atCenter: true,
});
menu.open = true;
await popupShown;
return popup;
}
function findNode(guid, view) {
for (let node of view.childNodes) {
console.log("visiting node", node, node._placesNode?.bookmarkGuid);
if (node._placesNode?.bookmarkGuid == guid) {
return node;
}
}
return null;
}
function fakeOpenMenu(popup) {
popup.dispatchEvent(new MouseEvent("popupshowing", { bubbles: true }));
popup.dispatchEvent(new MouseEvent("popupshown", { bubbles: true }));
}
function findPlacesNode(guid, container) {
for (let i = 0; i < container.childCount; i++) {
let node = container.getChild(i);
if (node.bookmarkGuid == guid) {
return node;
}
}
return null;
}
add_task(async function test() {
// Make sure the bookmarks bar is visible and restore its state on cleanup.
let toolbar = document.getElementById("PersonalToolbar");
ok(toolbar, "PersonalToolbar should not be null");
if (toolbar.collapsed) {
await promiseSetToolbarVisibility(toolbar, true);
registerCleanupFunction(function () {
return promiseSetToolbarVisibility(toolbar, false);
});
}
let menubar = document.getElementById("toolbar-menubar");
// Force the menu to be shown.
const kAutohide = menubar.getAttribute("autohide");
menubar.removeAttribute("autohide");
registerCleanupFunction(function () {
menubar.setAttribute("autohide", kAutohide);
});
registerCleanupFunction(PlacesUtils.bookmarks.eraseEverything);
// Create a folder structure with a recursive shortcut.
let folderA = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
title: "Folder A",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
});
let selfShortcut = await PlacesUtils.bookmarks.insert({
parentGuid: folderA.guid,
title: "Shortcut to A",
url: `place:parent=${folderA.guid}`,
});
let toolbarShortcut = await PlacesUtils.bookmarks.insert({
parentGuid: folderA.guid,
title: "Shortcut to toolbar",
url: `place:parent=${PlacesUtils.bookmarks.toolbarGuid}`,
});
// This also ensures that toolbar content is updated.
Assert.ok(!(await PlacesToolbarHelper.getIsEmpty()), "Toolbar is not empty");
// Open the popup for the shortcut from the bookmarks toolbar.
let toolbarItems = document.getElementById("PlacesToolbarItems");
let folderANode = findNode(folderA.guid, toolbarItems);
let folderAPopup = await openMenuAndWaitForPopup(folderANode);
let selfShortcutNode = findNode(selfShortcut.guid, folderAPopup);
let selfShortcutPopup = await openMenuAndWaitForPopup(selfShortcutNode);
Assert.ok(
!selfShortcutPopup._placesNode.containerOpen,
"Self shortcut container is not open"
);
Assert.ok(
selfShortcutPopup.hasAttribute("emptyplacesresult"),
"Self shortcut popup is empty"
);
let toolbarShortcutNode = findNode(
toolbarShortcut.guid,
folderANode.menupopup
);
let toolbarShortcutPopup = await openMenuAndWaitForPopup(toolbarShortcutNode);
Assert.ok(
!toolbarShortcutPopup._placesNode.containerOpen,
"Toolbar shortcut container is not open"
);
Assert.ok(
toolbarShortcutPopup.hasAttribute("emptyplacesresult"),
"Toolbar shortcut popup is empty"
);
// Also insert a toolbar shortcut in the bookmarks menu and check the
// previously inserted recursive toolbar shortcut there.
info("Test native bookmarks menu");
let shortcutInMenu = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.menuGuid,
title: "Shortcut to menu",
url: `place:parent=${PlacesUtils.bookmarks.menuGuid}`,
});
if (Services.appinfo.nativeMenubar) {
// With native menubar we can only simulate popupshowing as we cannot
// directly open menus.
let bookmarksMenuPopup = document.getElementById("bookmarksMenuPopup");
fakeOpenMenu(bookmarksMenuPopup);
let shortcutInMenuNode = findNode(shortcutInMenu.guid, bookmarksMenuPopup);
fakeOpenMenu(shortcutInMenuNode.menupopup);
Assert.ok(
!shortcutInMenuNode.menupopup._placesNode.containerOpen,
"menu shortcut container is not open"
);
} else {
let bookmarksMenu = document.getElementById("bookmarksMenu");
let bookmarksPopup = await openMenuAndWaitForPopup(bookmarksMenu);
let shortcutInMenuNode = findNode(shortcutInMenu.guid, bookmarksPopup);
let shortcutInMenuPopup = await openMenuAndWaitForPopup(
shortcutInMenuNode,
true
);
Assert.ok(
!shortcutInMenuPopup._placesNode.containerOpen,
"Toolbar shortcut container is not open"
);
Assert.ok(
shortcutInMenuPopup.hasAttribute("emptyplacesresult"),
"Toolbar shortcut popup is empty"
);
}
});

View file

@ -14,8 +14,8 @@ add_task(async function test_recover_storeID() {
await SelectableProfileService.init(); await SelectableProfileService.init();
Assert.ok( Assert.ok(
!ProfilesDatastoreService.initialized, ProfilesDatastoreService.initialized,
"Didn't initialize the datastore service" "Initialized the datastore service"
); );
Assert.ok( Assert.ok(
!SelectableProfileService.initialized, !SelectableProfileService.initialized,

View file

@ -3,10 +3,14 @@
const PATH_NET = TEST_PATH + "file_dummy.html"; const PATH_NET = TEST_PATH + "file_dummy.html";
const PATH_ORG = PATH_NET.replace("example.net", "example.org"); const PATH_ORG = PATH_NET.replace("example.net", "example.org");
add_task(async function () { async function runTest(defaultZoom) {
let tab1, tab1Zoom; let tab1, tab1Zoom;
tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, PATH_NET); tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, PATH_NET);
tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
is(tab1Zoom, defaultZoom, "We are starting with the default zoom.");
await FullZoom.setZoom(1.25, tab1.linkedBrowser); await FullZoom.setZoom(1.25, tab1.linkedBrowser);
tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser); tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
@ -46,7 +50,7 @@ add_task(async function () {
is( is(
tab1Zoom, tab1Zoom,
1.0, defaultZoom,
"privacy.resistFingerprinting is true, site-specific zoom should be reset when clearing FPP state for tab1" "privacy.resistFingerprinting is true, site-specific zoom should be reset when clearing FPP state for tab1"
); );
@ -55,4 +59,29 @@ add_task(async function () {
BrowserTestUtils.removeTab(tab1); BrowserTestUtils.removeTab(tab1);
await SpecialPowers.popPrefEnv(); await SpecialPowers.popPrefEnv();
}
add_task(async function () {
await runTest(1.0);
let defaultZoom = 1.5;
let context = Cu.createLoadContext();
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
Ci.nsIContentPrefService2
);
let { promise, resolve, reject } = Promise.withResolvers();
cps2.setGlobal(FullZoom.name, defaultZoom, context, {
handleError(error) {
reject(error);
},
handleCompletion() {
resolve();
},
});
await promise;
try {
await runTest(defaultZoom);
} finally {
cps2.removeGlobal(FullZoom.name, context);
}
}); });

View file

@ -15,6 +15,7 @@
#include "mozilla/Result.h" #include "mozilla/Result.h"
#include "mozilla/ResultVariant.h" #include "mozilla/ResultVariant.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/WinHeaderOnlyUtils.h" #include "mozilla/WinHeaderOnlyUtils.h"
#include "mozilla/widget/WinTaskbar.h" #include "mozilla/widget/WinTaskbar.h"
#include "WinUtils.h" #include "WinUtils.h"
@ -186,7 +187,16 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
Win11PinToTaskBarResult unlockStatus = Win11PinToTaskBarResult unlockStatus =
UnlockLimitedAccessFeature(Win11LimitedAccessFeatureType::Taskbar); UnlockLimitedAccessFeature(Win11LimitedAccessFeatureType::Taskbar);
if (unlockStatus.result != Win11PinToTaskBarResultStatus::Success) { if (unlockStatus.result != Win11PinToTaskBarResultStatus::Success) {
return unlockStatus; // Limited Access Feature no longer necessary for Windows 11 26200 Build
// 7840, and possibly other channels.
if (!IsWin11OrLater()) {
return unlockStatus;
}
TASKBAR_PINNING_LOG(
LogLevel::Warning,
"Limited Access Feature failed to unlock, attempting to use Taskbar "
"Pinning API assuming LAF is no longer necessary.");
} }
HRESULT hr; HRESULT hr;
@ -407,7 +417,16 @@ Win11PinToTaskBarResult IsCurrentAppPinnedToTaskbarWin11(bool aCheckOnly) {
Win11PinToTaskBarResult unlockStatus = Win11PinToTaskBarResult unlockStatus =
UnlockLimitedAccessFeature(Win11LimitedAccessFeatureType::Taskbar); UnlockLimitedAccessFeature(Win11LimitedAccessFeatureType::Taskbar);
if (unlockStatus.result != Win11PinToTaskBarResultStatus::Success) { if (unlockStatus.result != Win11PinToTaskBarResultStatus::Success) {
return unlockStatus; // Limited Access Feature no longer necessary for Windows 11 26200 Build
// 7840, and possibly other channels.
if (!IsWin11OrLater()) {
return unlockStatus;
}
TASKBAR_PINNING_LOG(
LogLevel::Warning,
"Limited Access Feature failed to unlock, attempting to use Taskbar "
"Pinning API assuming LAF is no longer necessary.");
} }
HRESULT hr; HRESULT hr;

View file

@ -16,6 +16,7 @@ import { SidebarPage } from "./sidebar-page.mjs";
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
HistoryController: "resource:///modules/HistoryController.sys.mjs", HistoryController: "resource:///modules/HistoryController.sys.mjs",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
Sanitizer: "resource:///modules/Sanitizer.sys.mjs", Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
}); });
@ -72,6 +73,10 @@ export class SidebarHistory extends SidebarPage {
if (!this.triggerNode) { if (!this.triggerNode) {
e.preventDefault(); e.preventDefault();
} }
let privateWindowMenuItem = this._contextMenu.querySelector(
"#sidebar-history-context-open-in-private-window"
);
privateWindowMenuItem.hidden = !lazy.PrivateBrowsingUtils.enabled;
} }
handleCommandEvent(e) { handleCommandEvent(e) {

View file

@ -4,6 +4,7 @@
const lazy = {}; const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
SyncedTabsController: "resource:///modules/SyncedTabsController.sys.mjs", SyncedTabsController: "resource:///modules/SyncedTabsController.sys.mjs",
}); });
@ -75,6 +76,11 @@ class SyncedTabsInSidebar extends SidebarPage {
); );
// Enable the feature only if the device supports it // Enable the feature only if the device supports it
closeTabMenuItem.disabled = !this.triggerNode.canClose; closeTabMenuItem.disabled = !this.triggerNode.canClose;
let privateWindowMenuItem = contextMenu.querySelector(
"#sidebar-synced-tabs-context-open-in-private-window"
);
privateWindowMenuItem.hidden = !lazy.PrivateBrowsingUtils.enabled;
} }
handleCommandEvent(e) { handleCommandEvent(e) {

View file

@ -159,6 +159,9 @@ const DEFAULT_ACTIONS = {
l10nCommands: ["quickactions-cmd-print"], l10nCommands: ["quickactions-cmd-print"],
label: "quickactions-print2", label: "quickactions-print2",
icon: "chrome://global/skin/icons/print.svg", icon: "chrome://global/skin/icons/print.svg",
isVisible: () => {
return Services.prefs.getBoolPref("print.enabled");
},
onPick: () => { onPick: () => {
lazy.BrowserWindowTracker.getTopWindow() lazy.BrowserWindowTracker.getTopWindow()
.document.getElementById("cmd_print") .document.getElementById("cmd_print")
@ -193,6 +196,9 @@ const DEFAULT_ACTIONS = {
l10nCommands: ["quickactions-cmd-savepdf2"], l10nCommands: ["quickactions-cmd-savepdf2"],
label: "quickactions-savepdf", label: "quickactions-savepdf",
icon: "chrome://global/skin/icons/print.svg", icon: "chrome://global/skin/icons/print.svg",
isVisible: () => {
return Services.prefs.getBoolPref("print.enabled");
},
onPick: () => { onPick: () => {
// This writes over the users last used printer which we // This writes over the users last used printer which we
// should not do. Refactor to launch the print preview with // should not do. Refactor to launch the print preview with

View file

@ -82,11 +82,6 @@ export class AddonSuggestions extends SuggestProvider {
return null; return null;
} }
if (suggestion.source == "rust") {
suggestion.icon = suggestion.iconUrl;
delete suggestion.iconUrl;
}
// Set UTM params unless they're already defined. This allows remote // Set UTM params unless they're already defined. This allows remote
// settings or Merino to override them if need be. // settings or Merino to override them if need be.
let url = new URL(suggestion.url); let url = new URL(suggestion.url);
@ -100,6 +95,8 @@ export class AddonSuggestions extends SuggestProvider {
url: url.href, url: url.href,
originalUrl: suggestion.url, originalUrl: suggestion.url,
shouldShowUrl: true, shouldShowUrl: true,
// Rust uses `iconUrl` but Merino uses `icon`.
icon: suggestion.iconUrl ?? suggestion.icon,
title: suggestion.title, title: suggestion.title,
description: suggestion.description, description: suggestion.description,
bottomTextL10n: { id: "icecat-suggest-addons-recommended" }, bottomTextL10n: { id: "icecat-suggest-addons-recommended" },

View file

@ -943,8 +943,10 @@ class _QuickSuggestTestUtils {
source = "rust", source = "rust",
provider = "Yelp", provider = "Yelp",
isTopPick = false, isTopPick = false,
// The default Yelp suggestedIndex is 0, unlike most other Suggest // The logic for the default Yelp `suggestedIndex` is complex and depends on
// suggestion types, which use -1. // whether `UrlbarProviderSearchSuggestions` is active and whether search
// suggestions are shown first. By default -- when the answer to both of
// those questions is Yes -- Yelp's `suggestedIndex` is 0.
suggestedIndex = 0, suggestedIndex = 0,
isSuggestedIndexRelativeToGroup = true, isSuggestedIndexRelativeToGroup = true,
originalUrl = undefined, originalUrl = undefined,

View file

@ -263,10 +263,16 @@ async function doDismissOneTest({
"quicksuggest-dismissals-changed" "quicksuggest-dismissals-changed"
); );
let actualResult = await getActualResult({
providers: [UrlbarProviderQuickSuggest.name],
query: queriesForDismissals[0].query,
expectedResult: result,
});
triggerCommand({ triggerCommand({
result,
command, command,
feature, feature,
result: actualResult,
expectedCountsByCall: { expectedCountsByCall: {
removeResult: 1, removeResult: 1,
}, },
@ -280,7 +286,7 @@ async function doDismissOneTest({
"canClearDismissedSuggestions should return true after triggering command" "canClearDismissedSuggestions should return true after triggering command"
); );
Assert.ok( Assert.ok(
await QuickSuggest.isResultDismissed(result), await QuickSuggest.isResultDismissed(actualResult),
"The result should be dismissed" "The result should be dismissed"
); );
@ -374,10 +380,16 @@ async function doDismissAllTest({ feature, result, command, pref, queries }) {
"quicksuggest-dismissals-changed" "quicksuggest-dismissals-changed"
); );
let actualResult = await getActualResult({
providers: [UrlbarProviderQuickSuggest.name],
query: queries[0].query,
expectedResult: result,
});
triggerCommand({ triggerCommand({
result,
command, command,
feature, feature,
result: actualResult,
expectedCountsByCall: { expectedCountsByCall: {
removeResult: 1, removeResult: 1,
}, },
@ -442,6 +454,44 @@ async function doDismissAllTest({ feature, result, command, pref, queries }) {
} }
} }
/**
* Does a search, asserts an actual result exists that matches the given result,
* and returns it.
*
* @param {object} options
* Options object.
* @param {SuggestFeature} options.query
* The search string.
* @param {UrlbarResult} options.expectedResult
* The expected result.
* @param {string[]} [options.providers]
* The providers to query.
*/
async function getActualResult({
query,
expectedResult,
providers = [UrlbarProviderQuickSuggest.name],
}) {
info("Doing search to get an actual result: " + JSON.stringify(query));
let context = createContext(query, {
providers,
isPrivate: false,
});
await check_results({
context,
matches: [expectedResult],
});
let actualResult = context.results.find(
r =>
r.providerName == UrlbarProviderQuickSuggest.name &&
r.payload.provider == expectedResult.payload.provider
);
Assert.ok(actualResult, "Search should have returned a matching result");
return actualResult;
}
/** /**
* Does some "show less frequently" tests where the cap is set in remote * Does some "show less frequently" tests where the cap is set in remote
* settings and Nimbus. See `doOneShowLessFrequentlyTest()`. This function * settings and Nimbus. See `doOneShowLessFrequentlyTest()`. This function

View file

@ -34,6 +34,7 @@ ac_add_options --disable-geckodriver # Bug 1489320
ac_add_options --disable-update-agent # Bug 1561797 ac_add_options --disable-update-agent # Bug 1561797
ac_add_options --disable-default-browser-agent # Relies on toast notifications which don't build on mingw. ac_add_options --disable-default-browser-agent # Relies on toast notifications which don't build on mingw.
ac_add_options --disable-notification-server # Toast notifications don't build on mingw. ac_add_options --disable-notification-server # Toast notifications don't build on mingw.
ac_add_options --disable-zucchini # Bug 1975960: SEH unavailable in mingwclang on win32
# Find our toolchain # Find our toolchain
HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang" HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang"

View file

@ -34,6 +34,7 @@ ac_add_options --disable-geckodriver # Bug 1489320
ac_add_options --disable-update-agent # Bug 1561797 ac_add_options --disable-update-agent # Bug 1561797
ac_add_options --disable-default-browser-agent # Relies on toast notifications which don't build on mingw. ac_add_options --disable-default-browser-agent # Relies on toast notifications which don't build on mingw.
ac_add_options --disable-notification-server # Toast notifications don't build on mingw. ac_add_options --disable-notification-server # Toast notifications don't build on mingw.
ac_add_options --disable-zucchini # Bug 1975960: SEH unavailable in mingwclang on win32, disable on win64 for parity
# Find our toolchain # Find our toolchain
HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang" HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang"

View file

@ -1 +1 @@
140.3.1 140.9.0

View file

@ -1 +1 @@
140.3.1esr 140.9.0esr

View file

@ -13,5 +13,5 @@ MOZ_BRANDING_DIRECTORY=browser/branding/unofficial
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
# IceCat settings # IceCat settings
MOZ_APP_BASENAME=IceCat MOZ_APP_BASENAME=IceCat
MOZ_APP_VERSION=140.3.1 MOZ_APP_VERSION=140.9.0
MOZ_DATA_REPORTING=0 MOZ_DATA_REPORTING=0

View file

@ -13,6 +13,7 @@ add_setup(async () => {
}); });
await setStorage(TEST_ADDRESS_1); await setStorage(TEST_ADDRESS_1);
await setStorage(TEST_CREDIT_CARD_1);
registerCleanupFunction(async () => { registerCleanupFunction(async () => {
await removeAllRecords(); await removeAllRecords();
@ -101,7 +102,7 @@ add_task(
/* eslint-disable mozilla/no-arbitrary-setTimeout */ /* eslint-disable mozilla/no-arbitrary-setTimeout */
await new Promise(resolve => { await new Promise(resolve => {
setTimeout(resolve, FormAutofill.refillOnSiteClearingFields); setTimeout(resolve, FormAutofill.refillOnSiteClearingFieldsTimeout);
}); });
return await SpecialPowers.spawn( return await SpecialPowers.spawn(
@ -116,3 +117,56 @@ add_task(
Assert.equal(orgaValue, "", "Element was not refilled"); Assert.equal(orgaValue, "", "Element was not refilled");
} }
); );
add_task(async function address_field_not_refilled_after_reformat_by_site() {
const value = await BrowserTestUtils.withNewTab(
CREDITCARD_FORM_URL,
async browser => {
const selectorToTriggerAutocompletion = "#cc-number";
const elementValueToVerifyAutofill = TEST_CREDIT_CARD_1["cc-number"];
info("Triggering autocompletion.");
await openPopupOn(browser, selectorToTriggerAutocompletion);
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
await waitForAutofill(
browser,
selectorToTriggerAutocompletion,
elementValueToVerifyAutofill
);
const formatValue = TEST_CREDIT_CARD_1["cc-number"]
.replace(/(.{4})/g, "$1 ")
.trim();
await SpecialPowers.spawn(
browser,
[selectorToTriggerAutocompletion, formatValue],
async (ccNumberSelector, reformatValue) => {
const ccNumberInput =
content.document.querySelector(ccNumberSelector);
info("Simulating site reformats an input");
ccNumberInput.value = reformatValue;
}
);
/* eslint-disable mozilla/no-arbitrary-setTimeout */
await new Promise(resolve => {
setTimeout(resolve, FormAutofill.refillOnSiteClearingFieldsTimeout);
});
return await SpecialPowers.spawn(
browser,
[selectorToTriggerAutocompletion],
async ccNumberSelector => {
return content.document.querySelector(ccNumberSelector).value;
}
);
}
);
const formatValue = TEST_CREDIT_CARD_1["cc-number"]
.replace(/(.{4})/g, "$1 ")
.trim();
Assert.equal(value, formatValue, "Element was not refilled");
});

View file

@ -1473,6 +1473,9 @@ async function triggerCapture(browser, submitButtonSelector, fillSelectors) {
* @param {object} patterns.captureExpectedRecord * @param {object} patterns.captureExpectedRecord
* The expected saved record after capturing the form. Keyed by field name. This * The expected saved record after capturing the form. Keyed by field name. This
* parameter is only used when `options.testCapture` is set. * parameter is only used when `options.testCapture` is set.
* @param {boolean} patterns.useTestYear
* Set to the current year to assign while running the test, useful for credit
* card expiry tests with a manual set of year options in the dropdown.
* @param {object} patterns.only * @param {object} patterns.only
* This parameter is used solely for debugging purposes. When set to true, * This parameter is used solely for debugging purposes. When set to true,
* it restricts the execution to only the specified testcase. * it restricts the execution to only the specified testcase.
@ -1597,16 +1600,32 @@ async function add_heuristic_tests(
const sleepAfterFocus = contexts.length > 1; const sleepAfterFocus = contexts.length > 1;
for (const context of contexts) { for (const context of contexts) {
await SpecialPowers.spawn(context, [], async () => { await SpecialPowers.spawn(
const elements = Array.from( context,
content.document.querySelectorAll("input, select") [testPattern.useTestYear],
); async year => {
// Focus on each field in the test document to trigger autofill field detection let FormAutofillHeuristics;
// on all the fields. if (year) {
elements.forEach(element => { FormAutofillHeuristics = ChromeUtils.importESModule(
element.focus(); "resource://gre/modules/shared/FormAutofillHeuristics.sys.mjs"
}); ).FormAutofillHeuristics;
}); FormAutofillHeuristics.useTestYear = year;
}
const elements = Array.from(
content.document.querySelectorAll("input, select")
);
// Focus on each field in the test document to trigger autofill field detection
// on all the fields.
elements.forEach(element => {
element.focus();
});
if (year) {
FormAutofillHeuristics.useTestYear = null;
}
}
);
try { try {
await BrowserTestUtils.synthesizeKey("VK_ESCAPE", {}, context); await BrowserTestUtils.synthesizeKey("VK_ESCAPE", {}, context);

View file

@ -8,7 +8,6 @@ support-files = [
["browser_BestBuy.js"] ["browser_BestBuy.js"]
["browser_CDW.js"] ["browser_CDW.js"]
skip-if = ["true"] # Bug 1939626
["browser_CostCo.js"] ["browser_CostCo.js"]

View file

@ -30,6 +30,7 @@ add_heuristic_tests(
}, },
{ {
fixturePath: "Checkout_BillingPaymentInfo.html", fixturePath: "Checkout_BillingPaymentInfo.html",
useTestYear: 2024,
expectedResult: [ expectedResult: [
{ {
default: { default: {

View file

@ -74,6 +74,7 @@ add_heuristic_tests(
}, },
{ {
fixturePath: "Payment.html", fixturePath: "Payment.html",
useTestYear: 2025,
expectedResult: [ expectedResult: [
{ {
default: { default: {

View file

@ -6,6 +6,7 @@ add_heuristic_tests(
[ [
{ {
fixturePath: "Payment.html", fixturePath: "Payment.html",
useTestYear: 2024,
expectedResult: [ expectedResult: [
{ {
default: { default: {

View file

@ -6,6 +6,7 @@ add_heuristic_tests(
[ [
{ {
fixturePath: "Checkout_Payment.html", fixturePath: "Checkout_Payment.html",
useTestYear: 2024,
expectedResult: [ expectedResult: [
{ {
default: { default: {

View file

@ -6,6 +6,7 @@ add_heuristic_tests(
[ [
{ {
fixturePath: "index.html", fixturePath: "index.html",
useTestYear: 2024,
expectedResult: [ expectedResult: [
{ {
default: { default: {

View file

@ -3332,7 +3332,10 @@
"interventions": [ "interventions": [
{ {
"platforms": ["all"], "platforms": ["all"],
"ua_string": ["Chrome", "add_IceCat_as_Gecko"] "content_scripts": {
"js": ["bug1950282-f1tv.formula1.com-unblock-icecat.js"]
},
"ua_string": ["Chrome"]
}, },
{ {
"platforms": ["linux"], "platforms": ["linux"],
@ -3695,5 +3698,32 @@
"ua_string": ["Chrome", "add_IceCat_as_Gecko"] "ua_string": ["Chrome", "add_IceCat_as_Gecko"]
} }
] ]
},
"1996823": {
"label": "rogers.com and fido.ca",
"bugs": {
"1996823": {
"issue": "page-fails-to-load",
"matches": [
"*://www.rogers.com/bbapp/bbapi.js*",
"*://www.fido.ca/bbapp/bbapi.js*"
]
}
},
"interventions": [
{
"platforms": ["all"],
"replace_string_in_request": [
{
"find": "window\\.location\\.href = link;",
"replace": "let url = new URL(window.location.href); url.hash = link; window.location.href = url.href;",
"urls": [
"*://www.rogers.com/bbapp/bbapi.js*",
"*://www.fido.ca/bbapp/bbapi.js*"
]
}
]
}
]
} }
} }

View file

@ -0,0 +1,184 @@
/* 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";
/**
* Bug 1950282 - UA spoof for f1tv.formula1.com
*
* This site is deliberately blocking IceCat, possibly due to bug 1992579.
*/
/* globals cloneInto, exportFunction */
console.info(
"The window environment is being altered for compatibility reasons. If you're a web developer working on this site, please get in touch with developer-outreach@mozilla.com. See https://bugzilla.mozilla.org/show_bug.cgi?id=1950282 for details."
);
delete window.wrappedJSObject.InstallTrigger;
delete window.wrappedJSObject.mozInnerScreenX;
delete window.wrappedJSObject.mozInnerScreenY;
delete window.wrappedJSObject.MozConsentBanner;
const nav = Object.getPrototypeOf(navigator.wrappedJSObject);
const vendor = Object.getOwnPropertyDescriptor(nav, "vendor");
vendor.get = exportFunction(() => "Google Inc.", window);
Object.defineProperty(nav, "vendor", vendor);
const css = CSS.wrappedJSObject;
const supports = Object.getOwnPropertyDescriptor(css, "supports");
const oldSupports = supports.value;
supports.value = exportFunction(function (query) {
if (query.includes("moz-")) {
return false;
}
return oldSupports.call(this, query);
}, window);
Object.defineProperty(css, "supports", supports);
function generateTimeStamp(base, factor = 10) {
if (base) {
// increase another timestamp by a little
return (base + Math.random() * factor).toString().substr(0, 14);
}
const r = Math.random().toString();
const d10 = `1${r.substr(5, 9)}`;
const d3 = r.substr(2, 3);
return parseFloat(`${d10}.${d3}`);
}
const startLoadTime = generateTimeStamp();
const commitLoadTime = generateTimeStamp(startLoadTime);
const firstPaintTime = generateTimeStamp(commitLoadTime);
const finishDocumentLoadTime = generateTimeStamp(firstPaintTime);
const finishLoadTime = generateTimeStamp(finishDocumentLoadTime);
const csi = cloneInto(
{
onloadT: parseInt(finishDocumentLoadTime * 100),
pageT: generateTimeStamp().toString().substr(-11),
startE: parseInt(parseFloat(startLoadTime * 100)),
tran: 10 + parseInt(4 + Math.random() * 4),
},
window
);
const loadTimes = cloneInto(
{
commitLoadTime,
connectionInfo: "h3",
finishDocumentLoadTime,
finishLoadTime,
firstPaintAfterLoadTime: 0,
firstPaintTime,
navigationType: "Other",
npnNegotiatedProtocol: "h3",
requestTime: startLoadTime,
startLoadTime,
wasAlternateProtocolAvailable: false,
wasFetchedViaSpdy: true,
wasNpnNegotiated: true,
},
window
);
window.wrappedJSObject.chrome = cloneInto(
{
app: {
InstallState: {
DISABLED: "disabled",
INSTALLED: "installed",
NOT_INSTALLED: "not_installed",
},
RunningState: {
CANNOT_RUN: "cannot_run",
READY_TO_RUN: "ready_to_run",
RUNNING: "running",
},
getDetails() {
return null;
},
getIsInstalled() {
return false;
},
installState() {
return undefined;
},
isInstalled: false,
runningState() {
return window.chrome.app.InstallState.NOT_INSTALLED;
},
},
csi() {
return csi;
},
loadTimes() {
return loadTimes;
},
},
window,
{ cloneFunctions: true }
);
const ua = navigator.userAgent;
const mobile = ua.includes("Mobile") || ua.includes("Tablet");
// Very roughly matches Chromium's GetPlatformForUAMetadata()
let platform = "Linux";
if (mobile) {
platform = "Android";
} else if (navigator.platform.startsWith("Win")) {
platform = "Windows";
} else if (navigator.platform.startsWith("Mac")) {
platform = "macOS";
}
const version = (ua.match(/IceCat\/([0-9]+)/) || ["", "58.0"])[1];
// These match Chrome's output as of version 126.
const brands = [
{
brand: "Not/A)Brand",
version: "8",
},
{
brand: "Chromium",
version,
},
{
brand: "Google Chrome",
version,
},
];
const userAgentData = cloneInto(
{
brands,
mobile,
platform,
getHighEntropyValues() {
return window.wrappedJSObject.Promise.resolve(
cloneInto(
{
brands,
mobile,
platform,
platformVersion: "19.0.0",
},
window
)
);
},
},
window,
{ cloneFunctions: true }
);
Object.defineProperty(window.navigator.wrappedJSObject, "userAgentData", {
get: exportFunction(function () {
return userAgentData;
}, window),
set: exportFunction(function () {}, window),
});

View file

@ -2,7 +2,7 @@
"manifest_version": 2, "manifest_version": 2,
"name": "Web Compatibility Interventions", "name": "Web Compatibility Interventions",
"description": "Urgent post-release fixes for web compatibility.", "description": "Urgent post-release fixes for web compatibility.",
"version": "140.8.0", "version": "140.12.0",
"browser_specific_settings": { "browser_specific_settings": {
"gecko": { "gecko": {
"id": "webcompat@mozilla.org", "id": "webcompat@mozilla.org",

View file

@ -0,0 +1,5 @@
# 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/.
perm-persistent-storage-remember = Remember this decision

View file

@ -135,6 +135,8 @@ policy-IceCatHome2 = Configure { -icecat-home-brand-name }.
policy-IceCatSuggest = Configure { -icecat-suggest-brand-name }. policy-IceCatSuggest = Configure { -icecat-suggest-brand-name }.
policy-GenerativeAI = Configure generative AI features.
policy-GoToIntranetSiteForSingleWordEntryInAddressBar = Force direct intranet site navigation instead of searching when typing single word entries in the address bar. policy-GoToIntranetSiteForSingleWordEntryInAddressBar = Force direct intranet site navigation instead of searching when typing single word entries in the address bar.
policy-Handlers = Configure default application handlers. policy-Handlers = Configure default application handlers.

View file

@ -17,7 +17,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"af": { "af": {
"pin": false, "pin": false,
@ -37,7 +37,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"an": { "an": {
"pin": false, "pin": false,
@ -57,7 +57,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ar": { "ar": {
"pin": false, "pin": false,
@ -77,7 +77,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ast": { "ast": {
"pin": false, "pin": false,
@ -97,7 +97,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"az": { "az": {
"pin": false, "pin": false,
@ -117,7 +117,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"be": { "be": {
"pin": false, "pin": false,
@ -137,7 +137,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"bg": { "bg": {
"pin": false, "pin": false,
@ -157,7 +157,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"bn": { "bn": {
"pin": false, "pin": false,
@ -177,7 +177,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"br": { "br": {
"pin": false, "pin": false,
@ -197,7 +197,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"bs": { "bs": {
"pin": false, "pin": false,
@ -217,7 +217,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ca": { "ca": {
"pin": false, "pin": false,
@ -237,7 +237,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ca-valencia": { "ca-valencia": {
"pin": false, "pin": false,
@ -257,7 +257,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"cak": { "cak": {
"pin": false, "pin": false,
@ -277,7 +277,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"cs": { "cs": {
"pin": false, "pin": false,
@ -297,7 +297,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"cy": { "cy": {
"pin": false, "pin": false,
@ -317,7 +317,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"da": { "da": {
"pin": false, "pin": false,
@ -337,7 +337,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"de": { "de": {
"pin": false, "pin": false,
@ -357,7 +357,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"dsb": { "dsb": {
"pin": false, "pin": false,
@ -377,7 +377,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"el": { "el": {
"pin": false, "pin": false,
@ -397,7 +397,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"en-CA": { "en-CA": {
"pin": false, "pin": false,
@ -417,7 +417,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"en-GB": { "en-GB": {
"pin": false, "pin": false,
@ -437,7 +437,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"eo": { "eo": {
"pin": false, "pin": false,
@ -457,7 +457,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"es-AR": { "es-AR": {
"pin": false, "pin": false,
@ -477,7 +477,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"es-CL": { "es-CL": {
"pin": false, "pin": false,
@ -497,7 +497,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"es-ES": { "es-ES": {
"pin": false, "pin": false,
@ -517,7 +517,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"es-MX": { "es-MX": {
"pin": false, "pin": false,
@ -537,7 +537,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"et": { "et": {
"pin": false, "pin": false,
@ -557,7 +557,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"eu": { "eu": {
"pin": false, "pin": false,
@ -577,7 +577,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"fa": { "fa": {
"pin": false, "pin": false,
@ -597,7 +597,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ff": { "ff": {
"pin": false, "pin": false,
@ -617,7 +617,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"fi": { "fi": {
"pin": false, "pin": false,
@ -637,7 +637,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"fr": { "fr": {
"pin": false, "pin": false,
@ -657,7 +657,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"fur": { "fur": {
"pin": false, "pin": false,
@ -677,7 +677,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"fy-NL": { "fy-NL": {
"pin": false, "pin": false,
@ -697,7 +697,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ga-IE": { "ga-IE": {
"pin": false, "pin": false,
@ -717,7 +717,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"gd": { "gd": {
"pin": false, "pin": false,
@ -737,7 +737,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"gl": { "gl": {
"pin": false, "pin": false,
@ -757,7 +757,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"gn": { "gn": {
"pin": false, "pin": false,
@ -777,7 +777,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"gu-IN": { "gu-IN": {
"pin": false, "pin": false,
@ -797,7 +797,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"he": { "he": {
"pin": false, "pin": false,
@ -817,7 +817,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"hi-IN": { "hi-IN": {
"pin": false, "pin": false,
@ -837,7 +837,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"hr": { "hr": {
"pin": false, "pin": false,
@ -857,7 +857,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"hsb": { "hsb": {
"pin": false, "pin": false,
@ -877,7 +877,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"hu": { "hu": {
"pin": false, "pin": false,
@ -897,7 +897,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"hy-AM": { "hy-AM": {
"pin": false, "pin": false,
@ -917,7 +917,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ia": { "ia": {
"pin": false, "pin": false,
@ -937,7 +937,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"id": { "id": {
"pin": false, "pin": false,
@ -957,7 +957,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"is": { "is": {
"pin": false, "pin": false,
@ -977,7 +977,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"it": { "it": {
"pin": false, "pin": false,
@ -997,7 +997,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ja": { "ja": {
"pin": false, "pin": false,
@ -1015,7 +1015,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ja-JP-mac": { "ja-JP-mac": {
"pin": false, "pin": false,
@ -1023,7 +1023,7 @@
"macosx64", "macosx64",
"macosx64-devedition" "macosx64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ka": { "ka": {
"pin": false, "pin": false,
@ -1043,7 +1043,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"kab": { "kab": {
"pin": false, "pin": false,
@ -1063,7 +1063,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"kk": { "kk": {
"pin": false, "pin": false,
@ -1083,7 +1083,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"km": { "km": {
"pin": false, "pin": false,
@ -1103,7 +1103,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"kn": { "kn": {
"pin": false, "pin": false,
@ -1123,7 +1123,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ko": { "ko": {
"pin": false, "pin": false,
@ -1143,7 +1143,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"lij": { "lij": {
"pin": false, "pin": false,
@ -1163,7 +1163,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"lt": { "lt": {
"pin": false, "pin": false,
@ -1183,7 +1183,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"lv": { "lv": {
"pin": false, "pin": false,
@ -1203,7 +1203,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"mk": { "mk": {
"pin": false, "pin": false,
@ -1223,7 +1223,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"mr": { "mr": {
"pin": false, "pin": false,
@ -1243,7 +1243,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ms": { "ms": {
"pin": false, "pin": false,
@ -1263,7 +1263,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"my": { "my": {
"pin": false, "pin": false,
@ -1283,7 +1283,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"nb-NO": { "nb-NO": {
"pin": false, "pin": false,
@ -1303,7 +1303,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ne-NP": { "ne-NP": {
"pin": false, "pin": false,
@ -1323,7 +1323,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"nl": { "nl": {
"pin": false, "pin": false,
@ -1343,7 +1343,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"nn-NO": { "nn-NO": {
"pin": false, "pin": false,
@ -1363,7 +1363,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"oc": { "oc": {
"pin": false, "pin": false,
@ -1383,7 +1383,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"pa-IN": { "pa-IN": {
"pin": false, "pin": false,
@ -1403,7 +1403,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"pl": { "pl": {
"pin": false, "pin": false,
@ -1423,7 +1423,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"pt-BR": { "pt-BR": {
"pin": false, "pin": false,
@ -1443,7 +1443,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"pt-PT": { "pt-PT": {
"pin": false, "pin": false,
@ -1463,7 +1463,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"rm": { "rm": {
"pin": false, "pin": false,
@ -1483,7 +1483,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ro": { "ro": {
"pin": false, "pin": false,
@ -1503,7 +1503,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ru": { "ru": {
"pin": false, "pin": false,
@ -1523,7 +1523,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sat": { "sat": {
"pin": false, "pin": false,
@ -1543,7 +1543,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sc": { "sc": {
"pin": false, "pin": false,
@ -1563,7 +1563,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sco": { "sco": {
"pin": false, "pin": false,
@ -1583,7 +1583,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"si": { "si": {
"pin": false, "pin": false,
@ -1603,7 +1603,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sk": { "sk": {
"pin": false, "pin": false,
@ -1623,7 +1623,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"skr": { "skr": {
"pin": false, "pin": false,
@ -1643,7 +1643,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sl": { "sl": {
"pin": false, "pin": false,
@ -1663,7 +1663,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"son": { "son": {
"pin": false, "pin": false,
@ -1683,7 +1683,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sq": { "sq": {
"pin": false, "pin": false,
@ -1703,7 +1703,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sr": { "sr": {
"pin": false, "pin": false,
@ -1723,7 +1723,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"sv-SE": { "sv-SE": {
"pin": false, "pin": false,
@ -1743,7 +1743,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"szl": { "szl": {
"pin": false, "pin": false,
@ -1763,7 +1763,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ta": { "ta": {
"pin": false, "pin": false,
@ -1783,7 +1783,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"te": { "te": {
"pin": false, "pin": false,
@ -1803,7 +1803,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"tg": { "tg": {
"pin": false, "pin": false,
@ -1823,7 +1823,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"th": { "th": {
"pin": false, "pin": false,
@ -1843,7 +1843,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"tl": { "tl": {
"pin": false, "pin": false,
@ -1863,7 +1863,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"tr": { "tr": {
"pin": false, "pin": false,
@ -1883,7 +1883,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"trs": { "trs": {
"pin": false, "pin": false,
@ -1903,7 +1903,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"uk": { "uk": {
"pin": false, "pin": false,
@ -1923,7 +1923,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"ur": { "ur": {
"pin": false, "pin": false,
@ -1943,7 +1943,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"uz": { "uz": {
"pin": false, "pin": false,
@ -1963,7 +1963,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"vi": { "vi": {
"pin": false, "pin": false,
@ -1983,7 +1983,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"xh": { "xh": {
"pin": false, "pin": false,
@ -2003,7 +2003,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"zh-CN": { "zh-CN": {
"pin": false, "pin": false,
@ -2023,7 +2023,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
}, },
"zh-TW": { "zh-TW": {
"pin": false, "pin": false,
@ -2043,6 +2043,6 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "64046fdc97c1b1886a479dead61e6dc5428ae6e6" "revision": "412690f1368e37f70af57eecabb93497167eb9ba"
} }
} }

View file

@ -99,6 +99,10 @@ ChromeUtils.defineLazyGetter(lazy, "gBrowserBundle", function () {
); );
}); });
ChromeUtils.defineLazyGetter(lazy, "gFluentStrings", function () {
return new Localization(["browser/permissions.ftl"], true /* aSync */);
});
import { SITEPERMS_ADDON_PROVIDER_PREF } from "resource://gre/modules/addons/siteperms-addon-utils.sys.mjs"; import { SITEPERMS_ADDON_PROVIDER_PREF } from "resource://gre/modules/addons/siteperms-addon-utils.sys.mjs";
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
@ -1167,11 +1171,25 @@ class PersistentStoragePermissionPrompt extends PermissionPromptForRequest {
let learnMoreURL = let learnMoreURL =
Services.urlFormatter.formatURLPref("app.support.baseURL") + Services.urlFormatter.formatURLPref("app.support.baseURL") +
"storage-permissions"; "storage-permissions";
return { let options = {
learnMoreURL, learnMoreURL,
displayURI: false, displayURI: false,
name: this.getPrincipalName(), name: this.getPrincipalName(),
}; };
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
if (options.checkbox.show) {
options.checkbox.label = lazy.gFluentStrings.formatValueSync(
"perm-persistent-storage-remember"
);
}
return options;
} }
get notificationID() { get notificationID() {

View file

@ -264,3 +264,46 @@ option(
) )
set_config("MOZ_NOTIFICATION_SERVER", True, when="--enable-notification-server") set_config("MOZ_NOTIFICATION_SERVER", True, when="--enable-notification-server")
# Supported patch formats for the updater
# =======================================
@depends(target, when="--enable-updater")
def zucchini_is_available(target):
# Desktop Linux, macOS or Windows: we exclude Android by checking for GNU.
return (target.os, target.kernel) == ("GNU", "Linux") or target.os in (
"OSX",
"WINNT",
)
with only_when(~zucchini_is_available):
set_config("MOZ_BSPATCH", True, when="--enable-updater")
set_define("MOZ_BSPATCH", True, when="--enable-updater")
with only_when(zucchini_is_available):
option(
"--disable-bspatch",
help="Disable bspatch support",
)
set_config("MOZ_BSPATCH", True, when="--enable-bspatch")
set_define("MOZ_BSPATCH", True, when="--enable-bspatch")
option(
"--disable-zucchini",
help="Disable zucchini support",
)
set_config("MOZ_ZUCCHINI", True, when="--enable-zucchini")
set_define("MOZ_ZUCCHINI", True, when="--enable-zucchini")
@depends("--enable-bspatch", "--enable-zucchini")
def check_at_least_one_patch_format(bspatch, zucchini):
if not bspatch and not zucchini:
die(
"You must enable at least one patch format when --enable-updater "
"is used. Use --enable-bspatch or --enable-zucchini."
)

Binary file not shown.

Binary file not shown.

View file

@ -10,4 +10,4 @@
# hardcoded milestones in the tree from these two files. # hardcoded milestones in the tree from these two files.
#-------------------------------------------------------- #--------------------------------------------------------
140.3.1 140.9.0

View file

@ -845,6 +845,7 @@ system_headers = [
"sys/msg.h", "sys/msg.h",
"sys/param.h", "sys/param.h",
"sys/pda.h", "sys/pda.h",
"sys/platform/ppc.h",
"sys/poll.h", "sys/poll.h",
"sys/ppc.h", "sys/ppc.h",
"sys/prctl.h", "sys/prctl.h",

View file

@ -157,8 +157,12 @@ ifeq (official, $(MOZ_BRANDING))
MOZ_DEFINES += -DMOZ_OFFICIAL_BRANDING MOZ_DEFINES += -DMOZ_OFFICIAL_BRANDING
endif endif
ifneq (,$(DEB_PARALLEL_JOBS)) ifneq (,$(DEB_PARALLEL_JOBS))
ifneq (,$(filter armhf, $(DEB_HOST_ARCH)))
MOZ_DEFINES += -DDEB_PARALLEL_JOBS=1
else
MOZ_DEFINES += -DDEB_PARALLEL_JOBS=$(DEB_PARALLEL_JOBS) MOZ_DEFINES += -DDEB_PARALLEL_JOBS=$(DEB_PARALLEL_JOBS)
endif endif
endif
MOZ_EXECUTABLES_$(MOZ_PKG_NAME) += $(MOZ_LIBDIR)/$(MOZ_PKG_BASENAME).sh \ MOZ_EXECUTABLES_$(MOZ_PKG_NAME) += $(MOZ_LIBDIR)/$(MOZ_PKG_BASENAME).sh \
$(NULL) $(NULL)

View file

@ -1,3 +1,45 @@
icecat (140.9.0-1gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.9.0-1gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Sat, 28 Mar 2026 01:16:35 -0600
icecat (140.8.0-2gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.8.0-2gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Tue, 10 Mar 2026 23:20:02 -0600
icecat (140.7.1-1gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.7.1-1gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Mon, 16 Feb 2026 22:12:00 -0600
icecat (140.7.0-1gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.7.0-1gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Sat, 17 Jan 2026 21:13:41 -0600
icecat (140.6.0-1gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.6.0-1gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Sun, 14 Dec 2025 03:53:59 -0600
icecat (140.5.0-2gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.5.0-2gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Thu, 13 Nov 2025 03:42:08 -0600
icecat (140.4.0-2gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.4.0-2gnu1)
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Wed, 15 Oct 2025 02:20:36 -0600
icecat (140.3.1-1gnu1+build1-0.12.0) ecne; urgency=medium icecat (140.3.1-1gnu1+build1-0.12.0) ecne; urgency=medium
* New upstream stable release (icecat-140.3.1-1gnu1) * New upstream stable release (icecat-140.3.1-1gnu1)

View file

@ -11,7 +11,11 @@ ac_add_options --disable-updater
ac_add_options --enable-application=browser ac_add_options --enable-application=browser
ac_add_options --with-distribution-id=org.trisquel ac_add_options --with-distribution-id=org.trisquel
%%if DEB_BUILD_ARCH_BITS == 32 %%if DEB_BUILD_ARCH_BITS == 32
%%if DEB_HOST_ARCH == armhf
ac_add_options --disable-debug-symbols
%%else
ac_add_options --enable-debug-symbols=-g1 ac_add_options --enable-debug-symbols=-g1
%%endif
%%else %%else
ac_add_options --enable-debug-symbols ac_add_options --enable-debug-symbols
%%endif %%endif

View file

@ -0,0 +1,30 @@
Description: Do not enable LTO for rustc when building on armhf,
to work around OOM failures on Launchpad builders. Note that this alone is not
sufficient, because by default cargo will also enable full LTO when building
with a release profile, so the top-level Cargo.toml file needs to be
conditionally patched (this is done in debian/build/rules.mk).
Author: Olivier Tilloy <olivier.tilloy@canonical.com>
Author: Nathan Pratte Teodosio <nteodosio@ubuntu.com>
Forwarded: not-needed
--- a/config/makefiles/rust.mk
+++ b/config/makefiles/rust.mk
@@ -70,10 +70,18 @@ ifndef MOZ_DEBUG_RUST
# Never enable when coverage is enabled to work around https://github.com/rust-lang/rust/issues/90045.
ifndef MOZ_CODE_COVERAGE
ifeq (,$(findstring gkrust_gtest,$(RUST_LIBRARY_FILE)))
+ifneq (,$(filter arm,$(TARGET_CPU)))
+cargo_rustc_flags += -Clto=off
+else
cargo_rustc_flags += -Clto$(if $(filter full,$(MOZ_LTO_RUST_CROSS)),=fat)
+endif
endif
# We need -Cembed-bitcode=yes for all crates when using -Clto.
+ifneq (,$(filter arm,$(TARGET_CPU)))
+RUSTFLAGS += -Cembed-bitcode=no
+else
RUSTFLAGS += -Cembed-bitcode=yes
+endif
endif
endif
endif

View file

@ -1,22 +0,0 @@
Description: Do not enable LTO for rustc when building on arm64 and armhf,
to work around OOM failures on Launchpad builders. Note that this alone is not
sufficient, because by default cargo will also enable full LTO when building
with a release profile, so the top-level Cargo.toml file needs to be
conditionally patched (this is done in debian/build/rules.mk).
Author: Olivier Tilloy <olivier.tilloy@canonical.com>
Forwarded: not-needed
--- a/config/makefiles/rust.mk
+++ b/config/makefiles/rust.mk
@@ -70,8 +70,10 @@ ifndef MOZ_DEBUG_RUST
# Never enable when coverage is enabled to work around https://github.com/rust-lang/rust/issues/90045.
ifndef MOZ_CODE_COVERAGE
ifeq (,$(findstring gkrust_gtest,$(RUST_LIBRARY_FILE)))
+ifeq (,$(filter aarch64 arm,$(TARGET_CPU)))
cargo_rustc_flags += -Clto$(if $(filter full,$(MOZ_LTO_RUST_CROSS)),=fat)
endif
+endif
# We need -Cembed-bitcode=yes for all crates when using -Clto.
RUSTFLAGS += -Cembed-bitcode=yes
endif

View file

@ -7,7 +7,7 @@ webrtc-fix-compiler-flags-for-armhf.patch
s390x-ycbcr.patch s390x-ycbcr.patch
reduce-rust-debuginfo.patch reduce-rust-debuginfo.patch
armhf-reduce-linker-memory-use.patch armhf-reduce-linker-memory-use.patch
armhf-rustc-thin-lto.patch armhf-rustc-lto-off.patch
ppc64el-workaround-bug-1555531.patch ppc64el-workaround-bug-1555531.patch
ppc64el-workaround-gcc-ice.patch ppc64el-workaround-gcc-ice.patch
armhf-clang-no-integrated-as-for-neon.patch armhf-clang-no-integrated-as-for-neon.patch

View file

@ -124,30 +124,34 @@ class RequestPanel extends Component {
} }
/** /**
* Mapping array to dict for TreeView usage. * This maps an array to a dictionary for TreeView usage,
* Since TreeView only support Object(dict) format. * sincs the treeView only supports the Object(dict) format.
* This function also deal with duplicate key case
* (for multiple selection and query params with same keys)
* *
* This function is not sorting result properties since it can * This function also deals with the duplicate key scenario
* results in unexpected order of params. See bug 1469533 * (i.e multiple selections and query params with same keys)
* *
* @param {Object[]} arr - key-value pair array or form params * Note: This is not sorting the result properties since it can
* @returns {Object} Rep compatible object * result in an unexpected order of parameters. See bug 1469533
*
* @param {object[]} arrOfKeyValuePairs - An array of key-value pairs or form params.
* @param {string} arrOfKeyValuePairs[].name
* @param {string|Array} arrOfKeyValuePairs[].value
*
* @returns {object} Rep compatible object
*/ */
getProperties(arr) { getProperties(arrOfKeyValuePairs) {
return arr.reduce((map, obj) => { return arrOfKeyValuePairs.reduce((dict, { name, value }) => {
const value = map[obj.name]; if (name in dict) {
if (value || value === "") { const dictValue = dict[name];
if (typeof value !== "object") { if (!Array.isArray(dictValue)) {
map[obj.name] = [value]; dict[name] = [dictValue];
} }
map[obj.name].push(obj.value); dict[name].push(value);
} else { } else {
map[obj.name] = obj.value; dict[name] = value;
} }
return map; return dict;
}, {}); }, Object.create(null));
} }
toggleRawRequestPayload() { toggleRawRequestPayload() {
@ -205,10 +209,9 @@ class RequestPanel extends Component {
// Form Data section // Form Data section
if (formDataSections && formDataSections.length) { if (formDataSections && formDataSections.length) {
const sections = formDataSections.filter(str => /\S/.test(str)).join("&");
component = PropertiesView; component = PropertiesView;
componentProps = { componentProps = {
object: this.getProperties(parseFormData(sections)), object: this.getProperties(parseFormData(formDataSections)),
filterText, filterText,
targetSearchResult, targetSearchResult,
defaultSelectFirstNode: false, defaultSelectFirstNode: false,

View file

@ -83,7 +83,6 @@ async function getFormDataSections(
} }
} }
} }
return formDataSections; return formDataSections;
} }
@ -418,28 +417,29 @@ function parseQueryString(query) {
/** /**
* Parse a string of formdata sections into its components * Parse a string of formdata sections into its components
* *
* @param {string} sections - sections of formdata joined by & * @param {Array<string>} sections Array of sections of formdata
* @return {array} array of formdata params { name, value } * e.g ["", "a=x&b=y", "c=z"]
* @return {Array<object>} Array of formdata params
* e.g [{ name: 'a', value: 'x' }, { name: 'b', value: 'y'}, { name: 'c', value: 'z'}]
*/ */
function parseFormData(sections) { function parseFormData(sections) {
if (!sections) { if (!sections || !sections.length) {
return []; return [];
} }
const formDataParams = [];
const searchStr = sections
// Filter out empty sections
.filter(str => /\S/.test(str))
.join("&");
return sections const params = new URLSearchParams(searchStr);
.replace(/^&/, "") for (const [key, value] of params) {
.split("&") formDataParams.push({
.map(e => { name: getUnicodeUrlPath(key),
const firstEqualSignIndex = e.indexOf("="); value: getUnicodeUrlPath(value),
const paramName =
firstEqualSignIndex !== -1 ? e.slice(0, firstEqualSignIndex) : e;
const paramValue =
firstEqualSignIndex !== -1 ? e.slice(firstEqualSignIndex + 1) : "";
return {
name: paramName ? getUnicodeUrlPath(paramName) : "",
value: paramValue ? getUnicodeUrlPath(paramValue) : "",
};
}); });
}
return formDataParams;
} }
/** /**

View file

@ -746,7 +746,7 @@ class RequestListContextMenu {
}; };
const options = JSON.stringify(fetchOptions, null, 4); const options = JSON.stringify(fetchOptions, null, 4);
const fetchString = `await fetch("${url}", ${options});`; const fetchString = `await fetch(${JSON.stringify(url)}, ${options});`;
return fetchString; return fetchString;
} }

View file

@ -50,10 +50,11 @@ add_task(async function () {
const types = ["end", "response", "duration", "latency"]; const types = ["end", "response", "duration", "latency"];
for (const t of types) { for (const t of types) {
info("Check the timing column for type: " + t);
await waitUntil(() => { await waitUntil(() => {
const node = item.querySelector(".requests-list-" + t + "-time"); const node = item.querySelector(".requests-list-" + t + "-time");
const value = parseInt(node.textContent, 10); const value = parseInt(node.textContent, 10);
return value > 0; return value >= 0;
}); });
} }

View file

@ -20,7 +20,7 @@ add_task(async function () {
store.dispatch(Actions.batchEnable(false)); store.dispatch(Actions.batchEnable(false));
// Execute requests. // Execute requests.
await performRequests(monitor, tab, 12); await performRequests(monitor, tab, 13);
const requestListItems = document.querySelectorAll( const requestListItems = document.querySelectorAll(
".network-monitor .request-list-item" ".network-monitor .request-list-item"
@ -49,7 +49,7 @@ add_task(async function () {
await testRequestWithFormattedView( await testRequestWithFormattedView(
monitor, monitor,
requestListItems[2], requestListItems[2],
"?foo", "foo",
"bar=123=xyz", "bar=123=xyz",
"?foo=bar=123=xyz", "?foo=bar=123=xyz",
1 1
@ -92,6 +92,14 @@ add_task(async function () {
'{ "foo": "bar" }', '{ "foo": "bar" }',
1 1
); );
await testRequestWithFormattedView(
monitor,
requestListItems[12],
"__proto__",
"evil_value",
"__proto__=evil_value",
1
);
await teardown(monitor); await teardown(monitor);
}); });

View file

@ -26,17 +26,17 @@ add_task(async function () {
? [ ? [
{ {
menuItemId: "request-list-context-copy-as-curl-win", menuItemId: "request-list-context-copy-as-curl-win",
data: buildTestData(QUOTE_WIN), data: buildTestData(QUOTE_WIN, true),
}, },
{ {
menuItemId: "request-list-context-copy-as-curl-posix", menuItemId: "request-list-context-copy-as-curl-posix",
data: buildTestData(QUOTE_POSIX), data: buildTestData(QUOTE_POSIX, false),
}, },
] ]
: [ : [
{ {
menuItemId: "request-list-context-copy-as-curl", menuItemId: "request-list-context-copy-as-curl",
data: buildTestData(QUOTE_POSIX), data: buildTestData(QUOTE_POSIX, false),
}, },
]; ];
@ -45,7 +45,7 @@ add_task(async function () {
await teardown(monitor); await teardown(monitor);
}); });
function buildTestData(QUOTE) { function buildTestData(QUOTE, isWin) {
// Quote a string, escape the quotes inside the string // Quote a string, escape the quotes inside the string
function quote(str) { function quote(str) {
return QUOTE + str.replace(new RegExp(QUOTE, "g"), `\\${QUOTE}`) + QUOTE; return QUOTE + str.replace(new RegExp(QUOTE, "g"), `\\${QUOTE}`) + QUOTE;
@ -56,9 +56,11 @@ function buildTestData(QUOTE) {
return "-H " + quote(h); return "-H " + quote(h);
} }
const CMD = isWin ? "curl.exe " : "curl ";
// Construct the expected command // Construct the expected command
const SIMPLE_BASE = ["curl " + quote(HTTPS_SIMPLE_SJS)]; const SIMPLE_BASE = [CMD + quote(HTTPS_SIMPLE_SJS)];
const SLOW_BASE = ["curl " + quote(HTTPS_SLOW_SJS)]; const SLOW_BASE = [CMD + quote(HTTPS_SLOW_SJS)];
const BASE_RESULT = [ const BASE_RESULT = [
"--compressed", "--compressed",
header("User-Agent: " + navigator.userAgent), header("User-Agent: " + navigator.userAgent),
@ -220,8 +222,9 @@ async function testForPlatform(tab, monitor, testData) {
// This monster regexp parses the command line into an array of arguments, // This monster regexp parses the command line into an array of arguments,
// recognizing quoted args with matching quotes and escaped quotes inside: // recognizing quoted args with matching quotes and escaped quotes inside:
// [ "curl.exe 'url'", "--standalone-arg", "-arg-with-quoted-string 'value\'s'" ]
// [ "curl 'url'", "--standalone-arg", "-arg-with-quoted-string 'value\'s'" ] // [ "curl 'url'", "--standalone-arg", "-arg-with-quoted-string 'value\'s'" ]
const matchRe = /[-A-Za-z1-9]+(?: ([\^\\"']+)(?:\\\1|.)*?\1)?/g; const matchRe = /[-\.A-Za-z1-9]+(?: ([\^\"']+)(?:\\\1|.)*?\1)?/g;
const actual = result.match(matchRe); const actual = result.match(matchRe);
// Must begin with the same "curl 'URL'" segment // Must begin with the same "curl 'URL'" segment

View file

@ -7,7 +7,7 @@
* Tests if Copy as Fetch works. * Tests if Copy as Fetch works.
*/ */
add_task(async function () { add_task(async function testBasicCopyAsFetch() {
const { tab, monitor } = await initNetMonitor(HTTPS_CURL_URL, { const { tab, monitor } = await initNetMonitor(HTTPS_CURL_URL, {
requestCount: 1, requestCount: 1,
}); });
@ -15,7 +15,9 @@ add_task(async function () {
// GET request, no cookies (first request) // GET request, no cookies (first request)
await performRequest("GET"); await performRequest("GET");
await testClipboardContent(`await fetch("https://example.com/browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs", { await testClipboardContent(
monitor,
`await fetch("https://example.com/browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs", {
"credentials": "omit", "credentials": "omit",
"headers": { "headers": {
"User-Agent": "${navigator.userAgent}", "User-Agent": "${navigator.userAgent}",
@ -33,7 +35,8 @@ add_task(async function () {
"referrer": "https://example.com/browser/devtools/client/netmonitor/test/html_copy-as-curl.html", "referrer": "https://example.com/browser/devtools/client/netmonitor/test/html_copy-as-curl.html",
"method": "GET", "method": "GET",
"mode": "cors" "mode": "cors"
});`); });`
);
await teardown(monitor); await teardown(monitor);
@ -54,39 +57,71 @@ add_task(async function () {
); );
await waitRequest; await waitRequest;
} }
async function testClipboardContent(expectedResult) {
const { document } = monitor.panelWin;
const items = document.querySelectorAll(".request-list-item");
EventUtils.sendMouseEvent({ type: "mousedown" }, items[items.length - 1]);
EventUtils.sendMouseEvent(
{ type: "contextmenu" },
document.querySelectorAll(".request-list-item")[0]
);
/* Ensure that the copy as fetch option is always visible */
is(
!!getContextMenuItem(monitor, "request-list-context-copy-as-fetch"),
true,
'The "Copy as Fetch" context menu item should not be hidden.'
);
await waitForClipboardPromise(
async function setup() {
await selectContextMenuItem(
monitor,
"request-list-context-copy-as-fetch"
);
},
function validate(result) {
if (typeof result !== "string") {
return false;
}
return expectedResult === result;
}
);
info("Clipboard contains a fetch command for item " + (items.length - 1));
}
}); });
/**
* Tests for Url escaping of copy as Fetch
*/
add_task(async function testUrlEscapeOfCopyAsFetch() {
const { monitor } = await initNetMonitor(HTTPS_CURL_URL, {
requestCount: 1,
});
info("Starting test... ");
const waitRequest = waitForNetworkEvents(monitor, 1);
await SpecialPowers.spawn(
gBrowser.selectedBrowser,
['data:text/html,"+alert(document.domain)+"'],
url => {
content.fetch(url);
}
);
await waitRequest;
await testClipboardContent(
monitor,
`await fetch("data:text/html,\\"+alert(document.domain)+\\"", {
"credentials": "omit",
"headers": {},
"method": "GET",
"mode": "cors"
});`
);
await teardown(monitor);
});
async function testClipboardContent(monitor, expectedResult) {
const { document } = monitor.panelWin;
const items = document.querySelectorAll(".request-list-item");
EventUtils.sendMouseEvent({ type: "mousedown" }, items[items.length - 1]);
EventUtils.sendMouseEvent(
{ type: "contextmenu" },
document.querySelectorAll(".request-list-item")[0]
);
/* Ensure that the copy as fetch option is always visible */
is(
!!getContextMenuItem(monitor, "request-list-context-copy-as-fetch"),
true,
'The "Copy as Fetch" context menu item should not be hidden.'
);
await waitForClipboardPromise(
async function setup() {
await selectContextMenuItem(
monitor,
"request-list-context-copy-as-fetch"
);
},
function validate(result) {
if (typeof result !== "string") {
return false;
}
return expectedResult === result;
}
);
info("Clipboard contains a fetch command for item " + (items.length - 1));
}

View file

@ -153,7 +153,7 @@ function testDataArgumentOnGeneratedCommand(data) {
} }
function testDataEscapeOnGeneratedCommand(data) { function testDataEscapeOnGeneratedCommand(data) {
const paramsWin = `--data-raw ^"{\\"param1\\":\\"value1\\",\\"param2\\":\\"value2\\"}^"`; const paramsWin = `--data-raw ^"^{^\\^"param1^\\^":^\\^"value1^\\^",^\\^"param2^\\^":^\\^"value2^\\^"^}^`;
const paramsPosix = `--data-raw '{"param1":"value1","param2":"value2"}'`; const paramsPosix = `--data-raw '{"param1":"value1","param2":"value2"}'`;
let curlCommand = Curl.generateCommand(data, "WINNT"); let curlCommand = Curl.generateCommand(data, "WINNT");
@ -209,13 +209,13 @@ function testRemoveBinaryDataFromMultipartText(data) {
'^"', '^"',
boundary, boundary,
"^\u000A\u000A", "^\u000A\u000A",
'Content-Disposition: form-data; name=\\"param1\\"', 'Content-Disposition: form-data; name=^\\^"param1^\\^"',
"^\u000A\u000A^\u000A\u000A", "^\u000A\u000A^\u000A\u000A",
"value1", "value1",
"^\u000A\u000A", "^\u000A\u000A",
boundary, boundary,
"^\u000A\u000A", "^\u000A\u000A",
'Content-Disposition: form-data; name=\\"file\\"; filename=\\"filename.png\\"', 'Content-Disposition: form-data; name=^\\^"file^\\^"; filename=^\\^"filename.png^\\^"',
"^\u000A\u000A", "^\u000A\u000A",
"Content-Type: image/png", "Content-Type: image/png",
"^\u000A\u000A^\u000A\u000A", "^\u000A\u000A^\u000A\u000A",
@ -269,7 +269,14 @@ function testEscapeStringPosix() {
const escapeChar = "'!ls:q:gs|ls|;ping 8.8.8.8;|"; const escapeChar = "'!ls:q:gs|ls|;ping 8.8.8.8;|";
is( is(
CurlUtils.escapeStringPosix(escapeChar), CurlUtils.escapeStringPosix(escapeChar),
"$'\\'\\041ls:q:gs^|ls^|;ping 8.8.8.8;^|'", "$'\\'\\041ls:q:gs|ls|;ping 8.8.8.8;|'",
"'!' should be escaped."
);
const escapeBangOnlyChar = "!";
is(
CurlUtils.escapeStringPosix(escapeBangOnlyChar),
"$'\\041'",
"'!' should be escaped." "'!' should be escaped."
); );
@ -295,49 +302,34 @@ function testEscapeStringPosix() {
"$'\\xc3\\xa6 \\xc3\\xb8 \\xc3\\xbc \\xc3\\x9f \\xc3\\xb6 \\xc3\\xa9'", "$'\\xc3\\xa6 \\xc3\\xb8 \\xc3\\xbc \\xc3\\x9f \\xc3\\xb6 \\xc3\\xa9'",
"Character codes outside of the decimal range 32 - 126 should be escaped." "Character codes outside of the decimal range 32 - 126 should be escaped."
); );
// Assert that ampersands are correctly escaped in case its tried to run on Windows
const evilCommand = `query=evil\n\ncmd & calc.exe\n\n`;
is(
CurlUtils.escapeStringPosix(evilCommand),
"$'query=evil\\n\\ncmd ^& calc.exe\\n\\n'",
"The evil command is escaped properly"
);
const str = "EvilHeader: &calc.exe&";
is(
CurlUtils.escapeStringPosix(str),
"'EvilHeader: ^&calc.exe^&'",
"The evil command is escaped properly"
);
} }
function testEscapeStringWin() { function testEscapeStringWin() {
const surroundedWithDoubleQuotes = "A simple string"; const surroundedWithDoubleQuotes = "A simple string";
is( is(
CurlUtils.escapeStringWin(surroundedWithDoubleQuotes), CurlUtils.escapeStringWin(surroundedWithDoubleQuotes),
'^"A simple string^"', '^\"A simple string^\"',
"The string should be surrounded with double quotes." "The string should be surrounded with double quotes."
); );
const doubleQuotes = 'Quote: "Time is an illusion. Lunchtime doubly so."'; const doubleQuotes = 'Quote: "Time is an illusion. Lunchtime doubly so."';
is( is(
CurlUtils.escapeStringWin(doubleQuotes), CurlUtils.escapeStringWin(doubleQuotes),
'^"Quote: \\"Time is an illusion. Lunchtime doubly so.\\"^"', '^\"Quote: ^\\^\"Time is an illusion. Lunchtime doubly so.^\\^\"^\"',
"Double quotes should be escaped." "Double quotes should be escaped."
); );
const percentSigns = "%TEMP% %@foo% %2XX% %_XX% %?XX%"; const percentSigns = "%TEMP% %@foo% %2XX% %_XX% %?XX%";
is( is(
CurlUtils.escapeStringWin(percentSigns), CurlUtils.escapeStringWin(percentSigns),
'^"^%^TEMP^% ^%^@foo^% ^%^2XX^% ^%^_XX^% ^%?XX^%^"', '^\"^%^TEMP^% ^%^@foo^% ^%^2XX^% ^%^_XX^% ^%?XX^%^\"',
"Percent signs should be escaped." "Percent signs should be escaped."
); );
const backslashes = "\\A simple string\\"; const backslashes = " - \\A simple string\\ - ";
is( is(
CurlUtils.escapeStringWin(backslashes), CurlUtils.escapeStringWin(backslashes),
'^"\\\\A simple string\\\\^"', '^\" - ^\\^\\A simple string^\\^\\ - ^\"',
"Backslashes should be escaped." "Backslashes should be escaped."
); );
@ -351,23 +343,38 @@ function testEscapeStringWin() {
const dollarSignCommand = "$(calc.exe)"; const dollarSignCommand = "$(calc.exe)";
is( is(
CurlUtils.escapeStringWin(dollarSignCommand), CurlUtils.escapeStringWin(dollarSignCommand),
'^"\\$(calc.exe)^"', '^\"^$(calc.exe)^\"',
"Dollar sign should be escaped." "Dollar sign should be escaped."
); );
const tickSignCommand = "`$(calc.exe)"; const tickSignCommand = "`$(calc.exe)";
is( is(
CurlUtils.escapeStringWin(tickSignCommand), CurlUtils.escapeStringWin(tickSignCommand),
'^"\\`\\$(calc.exe)^"', '^\"`^$(calc.exe)^\"',
"Both the tick and dollar signs should be escaped." "Both the tick and dollar signs should be escaped."
); );
const evilCommand = `query=evil\r\rcmd" /c timeout /t 3 & calc.exe\r\r`; const evilCommand = `query=evil\r\rcmd" /c timeout /t 3 & calc.exe\r\r`;
is( is(
CurlUtils.escapeStringWin(evilCommand), CurlUtils.escapeStringWin(evilCommand),
'^\"query=evil^\n\n^\n\ncmd\\\" /c timeout /t 3 & calc.exe^\n\n^\n\n^\"', '^\"query=evil^\n\n^\n\ncmd^\\^\" /c timeout /t 3 ^& calc.exe^\n\n^\n\n^\"',
"The evil command is escaped properly" "The evil command is escaped properly"
); );
// Control characters https://www.ascii-code.com/characters/control-characters
const containsControlChars = " - \u0007 \u0010 \u0014 \u001B \x1a - ";
is(
CurlUtils.escapeStringWin(containsControlChars),
'^\" - \u0007 \u0010 \u0014 \u001b \u001a - ^\"',
"Control characters should not be escaped with ^."
);
const controlCharsWithWhitespaces = " -\tcalc.exe\f- ";
is(
CurlUtils.escapeStringWin(controlCharsWithWhitespaces),
'^\" - calc.exe - ^\"',
"Control (non-printable) characters which are whitespace like charaters e.g (tab & form feed)"
);
} }
async function createCurlData(selected, getLongString, requestData) { async function createCurlData(selected, getLongString, requestData) {

View file

@ -71,6 +71,7 @@
await get("baz", "?species=in=(52,60)"); await get("baz", "?species=in=(52,60)");
await get("baz", "?a=&a=b"); await get("baz", "?a=&a=b");
await get("baz", "?a=b&a=c&d=1"); await get("baz", "?a=b&a=c&d=1");
await post("baz", "", urlencoded, "__proto__=evil_value");
} }
</script> </script>
</body> </body>

View file

@ -10,15 +10,13 @@ const DEFAULT_DPPX = window.devicePixelRatio;
/* eslint-disable max-len */ /* eslint-disable max-len */
const TEST_DEVICE = { const TEST_DEVICE = {
name: "iPhone 6/7/8", name: "iPhone 17 / 17 Pro",
width: 375, width: 402,
height: 667, height: 874,
pixelRatio: 2, pixelRatio: 3,
userAgent: userAgent:
"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", "Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",
touch: true, touch: true,
icecatOS: false,
os: "iOS",
featured: true, featured: true,
}; };
/* eslint-enable max-len */ /* eslint-enable max-len */

View file

@ -160,16 +160,15 @@ const Curl = {
// Format with line breaks if the command has more than 2 parts // Format with line breaks if the command has more than 2 parts
// e.g // e.g
// Command with 2 parts - curl https://foo.com // Command with 2 parts - curl https://foo.com
// Commands with more than 2 parts - // Commands with more than 2 parts -
// curl https://foo.com // curl https://foo.com
// -X POST // -X POST
// -H "Accept : */*" // -H "Accept : */*"
// -H "accept-language: en-US" // -H "accept-language: en-US"
const joinStr = currentPlatform === "WINNT" ? " ^\n " : " \\\n "; const joinStr = currentPlatform === "WINNT" ? " ^\n " : " \\\n ";
return ( const CMD = currentPlatform == "WINNT" ? "curl.exe " : "curl ";
"curl " + commandParts.join(commandParts.length >= 3 ? joinStr : " ") return CMD + commandParts.join(commandParts.length >= 3 ? joinStr : " ");
);
}, },
}; };
@ -421,10 +420,9 @@ const CurlUtils = {
return "\\u" + ("0000" + code).substr(code.length, 4); return "\\u" + ("0000" + code).substr(code.length, 4);
} }
// Escape & and |, which are special characters on Windows. // Escape characters which are not within the charater range
const winSpecialCharsRegEx = /([&\|])/g; // SPACE to "~"(char codes 32 - 126), the `!` (code 33) and '(code 39);
if (/[^\x20-\x7E]|!|\'/.test(str)) {
if (/[^\x20-\x7E]|\'/.test(str)) {
// Use ANSI-C quoting syntax. // Use ANSI-C quoting syntax.
return ( return (
"$'" + "$'" +
@ -434,14 +432,13 @@ const CurlUtils = {
.replace(/\n/g, "\\n") .replace(/\n/g, "\\n")
.replace(/\r/g, "\\r") .replace(/\r/g, "\\r")
.replace(/!/g, "\\041") .replace(/!/g, "\\041")
.replace(winSpecialCharsRegEx, "^$1")
.replace(/[^\x20-\x7E]/g, escapeCharacter) + .replace(/[^\x20-\x7E]/g, escapeCharacter) +
"'" "'"
); );
} }
// Use single quote syntax. // Use single quote syntax.
return "'" + str.replace(winSpecialCharsRegEx, "^$1") + "'"; return "'" + str + "'";
}, },
/** /**
@ -453,24 +450,25 @@ const CurlUtils = {
Because cmd.exe parser and MS Crt arguments parsers use some of the Because cmd.exe parser and MS Crt arguments parsers use some of the
same escape characters, they can interact with each other in same escape characters, they can interact with each other in
horrible ways, the order of operations is critical. horrible ways, the order of operations is critical.
Also see https://ss64.com/nt/syntax-esc.html for details on
escaping characters on Windows.
*/ */
const encapsChars = '^"'; const encapsChars = '^"';
return ( return (
encapsChars + encapsChars +
str str
// Replace \ with \\ first because it is an escape character for certain // Replace all the \ (used as the escape character in the next replace) with \\
// conditions in both parsers.
.replace(/\\/g, "\\\\") .replace(/\\/g, "\\\\")
// Escape double quotes with double slashes. // Replace all " with \" to ensure the first parser does not remove it.
.replace(/"/g, '\\"') .replace(/"/g, '\\"')
// Escape ` and $ so commands do not get executed e.g $(calc.exe) or `\$(calc.exe)
.replace(/[`$]/g, "\\$&")
// Then escape all characters we are not sure about with ^ to ensure it // Then escape all characters we are not sure about with ^ to ensure it
// gets to MS Crt parser safely. // gets to MS Crt parser safely.
.replace(/[^a-zA-Z0-9\s_\-:=+~\/.',?;()*\$&\\{}\"`]/g, "^$&") // Note: Also do not escape unicode control (C) non-printable characters
// https://www.compart.com/en/unicode/category (this is captured with `\p{C}` and the `u` unicode flag)
.replace(/[^-a-zA-Z0-9\s_:=+~\/.',?;()*`\p{C}]/gu, "^$&")
// The % character is special because MS Crt parser will try and look for // The % character is special because MS Crt parser will try and look for
// ENV variables and fill them in its place. We cannot escape them with % // ENV variables and fill them in its place. We cannot escape them with %
@ -481,6 +479,14 @@ const CurlUtils = {
// by the previous replace. // by the previous replace.
.replace(/%(?=[a-zA-Z0-9_])/g, "%^") .replace(/%(?=[a-zA-Z0-9_])/g, "%^")
// All other whitespace characters are replaced with a single space, as there
// is no way to enter their literal values in a command line, and they do break
// the command allowing for injection.
// Since want to keep line breaks, we need to exclude them in the regex (`[^\r\n]`),
// and use double negations to get the other whitespace chars (`[^\S]` translates
// to "not not whitespace")
.replace(/[^\S\r\n]/g, " ")
// Lastly we replace new lines with ^ and TWO new lines because the first // Lastly we replace new lines with ^ and TWO new lines because the first
// new line is there to enact the escape command the second is the character // new line is there to enact the escape command the second is the character
// to escape (in this case new line). // to escape (in this case new line).

View file

@ -347,9 +347,7 @@ const QUOTE = isWin() ? '^"' : "'";
function quote(str) { function quote(str) {
let escaped; let escaped;
if (isWin()) { if (isWin()) {
escaped = str escaped = str.replace(new RegExp('"', "g"), `^\\${QUOTE}`);
.replace(new RegExp(QUOTE, "g"), `${QUOTE}${QUOTE}`)
.replace(/"/g, '\\"');
} else { } else {
escaped = str.replace(new RegExp(QUOTE, "g"), `\\${QUOTE}`); escaped = str.replace(new RegExp(QUOTE, "g"), `\\${QUOTE}`);
} }
@ -358,10 +356,10 @@ function quote(str) {
function escapeNewline(txt) { function escapeNewline(txt) {
if (isWin()) { if (isWin()) {
// Replace new lines with ^ and TWO new lines because the first // For windows we replace new lines with ^ and TWO new lines because the first
// new line is there to enact the escape command the second is the character // new line is there to enact the escape command the second is the character
// to escape (in this case new line). // to escape (in this case new line).
return txt.replace(/\r?\n/g, "^\n\n"); return txt.replace(/\r?\n|\r/g, "^\n\n");
} }
return txt.replace(/\r/g, "\\r").replace(/\n/g, "\\n"); return txt.replace(/\r/g, "\\r").replace(/\n/g, "\\n");
} }
@ -396,7 +394,8 @@ function inParams(curlParams, param) {
function parseCurl(curlCmd) { function parseCurl(curlCmd) {
// This monster regexp parses the command line into an array of arguments, // This monster regexp parses the command line into an array of arguments,
// recognizing quoted args with matching quotes and escaped quotes inside: // recognizing quoted args with matching quotes and escaped quotes inside:
// [ "curl.exe 'url'", "--standalone-arg", "-arg-with-quoted-string 'value\'s'" ]
// [ "curl 'url'", "--standalone-arg", "-arg-with-quoted-string 'value\'s'" ] // [ "curl 'url'", "--standalone-arg", "-arg-with-quoted-string 'value\'s'" ]
const matchRe = /[-A-Za-z1-9]+(?: ([\^\\"']+)(?:\\\1|.)*?\1)?/g; const matchRe = /[-\.A-Za-z1-9]+(?: ([\^\"']+)(?:\\\1|.)*?\1)?/g;
return curlCmd.match(matchRe); return curlCmd.match(matchRe);
} }

View file

@ -2786,6 +2786,11 @@ void BrowsingContext::DidSet(FieldIndex<IDX_ExplicitActive>,
}); });
} }
bool BrowsingContext::CanSet(FieldIndex<IDX_InRDMPane>, const bool&,
ContentParent* aSource) {
return XRE_IsParentProcess() && IsTop() && !aSource;
}
void BrowsingContext::DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue) { void BrowsingContext::DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue) {
MOZ_ASSERT(IsTop(), MOZ_ASSERT(IsTop(),
"Should only set InRDMPane in the top-level browsing context"); "Should only set InRDMPane in the top-level browsing context");
@ -4049,6 +4054,10 @@ bool IPDLParamTraits<dom::MaybeDiscarded<dom::BrowsingContext>>::Read(
if (id == 0) { if (id == 0) {
*aResult = nullptr; *aResult = nullptr;
} else if (RefPtr<dom::BrowsingContext> bc = dom::BrowsingContext::Get(id)) { } else if (RefPtr<dom::BrowsingContext> bc = dom::BrowsingContext::Get(id)) {
if (!bc->Group()->IsKnownForMessageReader(aReader)) {
return false;
}
*aResult = std::move(bc); *aResult = std::move(bc);
} else { } else {
aResult->SetDiscarded(id); aResult->SetDiscarded(id);

View file

@ -1136,6 +1136,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return IsTop(); return IsTop();
} }
bool CanSet(FieldIndex<IDX_InRDMPane>, const bool&, ContentParent* aSource);
void DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue); void DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue);
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DidSet(FieldIndex<IDX_ForceDesktopViewport>, MOZ_CAN_RUN_SCRIPT_BOUNDARY void DidSet(FieldIndex<IDX_ForceDesktopViewport>,
bool aOldValue); bool aOldValue);

View file

@ -251,6 +251,42 @@ ContentParent* BrowsingContextGroup::GetHostProcess(
return mHosts.GetWeak(aRemoteType); return mHosts.GetWeak(aRemoteType);
} }
bool BrowsingContextGroup::IsKnownForMessageReader(
IPC::MessageReader* aReader) {
if (!aReader->GetActor()) {
aReader->FatalError(
"No actor for BrowsingContextGroup::IsKnownForMessageReader");
return false;
}
mozilla::ipc::IToplevelProtocol* topActor =
aReader->GetActor()->ToplevelProtocol();
switch (topActor->GetProtocolId()) {
case PInProcessMsgStart:
// PInProcess always exists only within a single process, so we don't need
// to do any validation on it.
return true;
case PContentMsgStart:
// The process should only be able to name this BCG if it is
// subscribed, or if the BCG has been destroyed (and has therefore
// stopped tracking subscribers).
if (topActor->GetSide() == mozilla::ipc::ParentSide && !mDestroyed &&
!mSubscribers.Contains(static_cast<ContentParent*>(topActor))) {
aReader->FatalError(
"Process is not subscribed to this BrowsingContextGroup");
return false;
}
return true;
default:
aReader->FatalError(
"Unsupported toplevel actor for "
"BrowsingContextGroup::IsKnownForMessageReader");
return false;
}
}
void BrowsingContextGroup::UpdateToplevelsSuspendedIfNeeded() { void BrowsingContextGroup::UpdateToplevelsSuspendedIfNeeded() {
if (!StaticPrefs::dom_suspend_inactive_enabled()) { if (!StaticPrefs::dom_suspend_inactive_enabled()) {
return; return;
@ -296,8 +332,8 @@ void BrowsingContextGroup::Destroy() {
!sBrowsingContextGroups->Contains(Id()) || !sBrowsingContextGroups->Contains(Id()) ||
*sBrowsingContextGroups->Lookup(Id()) != this); *sBrowsingContextGroups->Lookup(Id()) != this);
} }
mDestroyed = true;
#endif #endif
mDestroyed = true;
// Make sure to call `RemoveBrowsingContextGroup` for every entry in both // Make sure to call `RemoveBrowsingContextGroup` for every entry in both
// `mHosts` and `mSubscribers`. This will visit most entries twice, but // `mHosts` and `mSubscribers`. This will visit most entries twice, but

View file

@ -87,6 +87,12 @@ class BrowsingContextGroup final : public nsWrapperCache {
// BrowsingContextGroup, if possible. // BrowsingContextGroup, if possible.
ContentParent* GetHostProcess(const nsACString& aRemoteType); ContentParent* GetHostProcess(const nsACString& aRemoteType);
// Check if the process which sent the message being read from aReader is
// aware of this BrowsingContextGroup's existence.
// If this returns false, it will first set a fatal error on aReader with more
// details.
bool IsKnownForMessageReader(IPC::MessageReader* aReader);
// When a BrowsingContext is being discarded, we may want to keep the // When a BrowsingContext is being discarded, we may want to keep the
// corresponding BrowsingContextGroup alive until the other process // corresponding BrowsingContextGroup alive until the other process
// acknowledges that the BrowsingContext has been discarded. A `KeepAlive` // acknowledges that the BrowsingContext has been discarded. A `KeepAlive`
@ -260,9 +266,7 @@ class BrowsingContextGroup final : public nsWrapperCache {
uint32_t mKeepAliveCount = 0; uint32_t mKeepAliveCount = 0;
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
bool mDestroyed = false; bool mDestroyed = false;
#endif
// A BrowsingContextGroup contains a series of {Browsing,Window}Context // A BrowsingContextGroup contains a series of {Browsing,Window}Context
// objects. They are addressed using a hashtable to avoid linear lookup when // objects. They are addressed using a hashtable to avoid linear lookup when

Some files were not shown because too many files have changed in this diff Show more