icecat: add release icecat-140.6.0-1gnu1 for ecne

This commit is contained in:
Ark74 2026-01-17 19:26:27 -06:00
parent 618c9f4145
commit 63e7d5afc7
3382 changed files with 457689 additions and 569094 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"]

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 2025-11-10

47
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",
@ -1912,7 +1913,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 +1926,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 +2043,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 +3386,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",
@ -5115,7 +5116,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 +5623,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 +5647,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 +5948,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 +6240,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 +6439,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 +6492,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 +6503,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 +6542,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 +6900,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 +7312,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 +7481,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 +7900,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

@ -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

@ -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

@ -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

@ -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
); );

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

@ -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

@ -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

@ -214,7 +214,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")
); );
} }

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

@ -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

@ -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.6.0

View file

@ -1 +1 @@
140.3.1esr 140.6.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.6.0
MOZ_DATA_REPORTING=0 MOZ_DATA_REPORTING=0

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,122 @@
/* 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 }
);

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.11.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."
)

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.6.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

@ -1,3 +1,21 @@
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

@ -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

@ -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

@ -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,22 @@ 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 " with \" to ensure the first parser does not remove it.
// conditions in both parsers.
.replace(/\\/g, "\\\\")
// Escape double quotes with double slashes.
.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 +476,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

@ -131,7 +131,7 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType,
nsresult rv; nsresult rv;
NS_ENSURE_ARG_POINTER(aContentHandler); NS_ENSURE_ARG_POINTER(aContentHandler);
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
RefPtr<nsDocShell> docShell = mDocShell; RefPtr<nsDocShell> docShell = mDocShell.get();
*aAbortProcess = false; *aAbortProcess = false;

View file

@ -11,8 +11,9 @@
#include "nsIURIContentListener.h" #include "nsIURIContentListener.h"
#include "nsWeakReference.h" #include "nsWeakReference.h"
#include "nsITimer.h" #include "nsITimer.h"
#include "mozilla/WeakPtr.h"
#include "nsDocShell.h"
class nsDocShell;
class nsIInterfaceRequestor; class nsIInterfaceRequestor;
class nsIWebNavigationInfo; class nsIWebNavigationInfo;
class nsPIDOMWindowOuter; class nsPIDOMWindowOuter;
@ -85,7 +86,7 @@ class nsDSURIContentListener final : public nsIURIContentListener,
} }
protected: protected:
nsDocShell* mDocShell; mozilla::MainThreadWeakPtr<nsDocShell> mDocShell;
// Hack to handle multipart images without creating a new viewer // Hack to handle multipart images without creating a new viewer
nsCOMPtr<nsIStreamListener> mExistingJPEGStreamListener; nsCOMPtr<nsIStreamListener> mExistingJPEGStreamListener;
nsCOMPtr<nsIChannel> mExistingJPEGRequest; nsCOMPtr<nsIChannel> mExistingJPEGRequest;

View file

@ -17,7 +17,7 @@
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
nsDocShellEditorData::nsDocShellEditorData(nsIDocShell* aOwningDocShell) nsDocShellEditorData::nsDocShellEditorData(nsDocShell* aOwningDocShell)
: mDocShell(aOwningDocShell), : mDocShell(aOwningDocShell),
mDetachedEditingState(Document::EditingState::eOff), mDetachedEditingState(Document::EditingState::eOff),
mMakeEditable(false), mMakeEditable(false),
@ -121,7 +121,7 @@ nsresult nsDocShellEditorData::DetachFromWindow() {
return NS_OK; return NS_OK;
} }
nsresult nsDocShellEditorData::ReattachToWindow(nsIDocShell* aDocShell) { nsresult nsDocShellEditorData::ReattachToWindow(nsDocShell* aDocShell) {
mDocShell = aDocShell; mDocShell = aDocShell;
nsCOMPtr<nsPIDOMWindowOuter> domWindow = nsCOMPtr<nsPIDOMWindowOuter> domWindow =

View file

@ -12,8 +12,9 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "mozilla/WeakPtr.h"
#include "nsDocShell.h"
class nsIDocShell;
class nsEditingSession; class nsEditingSession;
namespace mozilla { namespace mozilla {
@ -22,7 +23,7 @@ class HTMLEditor;
class nsDocShellEditorData { class nsDocShellEditorData {
public: public:
explicit nsDocShellEditorData(nsIDocShell* aOwningDocShell); explicit nsDocShellEditorData(nsDocShell* aOwningDocShell);
~nsDocShellEditorData(); ~nsDocShellEditorData();
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult MakeEditable(bool aWaitForUriLoad); MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult MakeEditable(bool aWaitForUriLoad);
@ -33,14 +34,14 @@ class nsDocShellEditorData {
SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor); SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor);
MOZ_CAN_RUN_SCRIPT_BOUNDARY void TearDownEditor(); MOZ_CAN_RUN_SCRIPT_BOUNDARY void TearDownEditor();
nsresult DetachFromWindow(); nsresult DetachFromWindow();
nsresult ReattachToWindow(nsIDocShell* aDocShell); nsresult ReattachToWindow(nsDocShell* aDocShell);
bool WaitingForLoad() const { return mMakeEditable; } bool WaitingForLoad() const { return mMakeEditable; }
protected: protected:
void EnsureEditingSession(); void EnsureEditingSession();
// The doc shell that owns us. Weak ref, since it always outlives us. // The doc shell that owns us. Weak ref, since it always outlives us.
nsIDocShell* mDocShell; mozilla::WeakPtr<nsDocShell> mDocShell;
// Only present for the content root docShell. Session is owned here. // Only present for the content root docShell. Session is owned here.
RefPtr<nsEditingSession> mEditingSession; RefPtr<nsEditingSession> mEditingSession;

View file

@ -276,6 +276,7 @@
#include "mozilla/gfx/ScaleFactor.h" #include "mozilla/gfx/ScaleFactor.h"
#include "mozilla/glean/DomMetrics.h" #include "mozilla/glean/DomMetrics.h"
#include "mozilla/glean/DomUseCounterMetrics.h" #include "mozilla/glean/DomUseCounterMetrics.h"
#include "mozilla/intl/EncodingToLang.h"
#include "mozilla/intl/LocaleService.h" #include "mozilla/intl/LocaleService.h"
#include "mozilla/ipc/IdleSchedulerChild.h" #include "mozilla/ipc/IdleSchedulerChild.h"
#include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/MessageChannel.h"
@ -417,7 +418,6 @@
#include "nsIXULRuntime.h" #include "nsIXULRuntime.h"
#include "nsImageLoadingContent.h" #include "nsImageLoadingContent.h"
#include "nsImportModule.h" #include "nsImportModule.h"
#include "nsLanguageAtomService.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsMimeTypes.h" #include "nsMimeTypes.h"
#include "nsNetCID.h" #include "nsNetCID.h"
@ -1500,6 +1500,7 @@ Document::Document(const char* aContentType)
mInteractiveWidgetMode( mInteractiveWidgetMode(
InteractiveWidgetUtils::DefaultInteractiveWidgetMode()), InteractiveWidgetUtils::DefaultInteractiveWidgetMode()),
mHeaderData(nullptr), mHeaderData(nullptr),
mLanguageFromCharset(nullptr),
mServoRestyleRootDirtyBits(0), mServoRestyleRootDirtyBits(0),
mThrowOnDynamicMarkupInsertionCounter(0), mThrowOnDynamicMarkupInsertionCounter(0),
mIgnoreOpensDuringUnloadCounter(0), mIgnoreOpensDuringUnloadCounter(0),
@ -19746,7 +19747,7 @@ nsAtom* Document::GetLanguageForStyle() const {
if (nsAtom* lang = GetContentLanguageAsAtomForStyle()) { if (nsAtom* lang = GetContentLanguageAsAtomForStyle()) {
return lang; return lang;
} }
return mLanguageFromCharset.get(); return mLanguageFromCharset;
} }
void Document::GetContentLanguageForBindings(DOMString& aString) const { void Document::GetContentLanguageForBindings(DOMString& aString) const {
@ -19755,7 +19756,7 @@ void Document::GetContentLanguageForBindings(DOMString& aString) const {
const LangGroupFontPrefs* Document::GetFontPrefsForLang( const LangGroupFontPrefs* Document::GetFontPrefsForLang(
nsAtom* aLanguage, bool* aNeedsToCache) const { nsAtom* aLanguage, bool* aNeedsToCache) const {
nsAtom* lang = aLanguage ? aLanguage : mLanguageFromCharset.get(); nsAtom* lang = aLanguage ? aLanguage : mLanguageFromCharset;
return StaticPresData::Get()->GetFontPrefsForLang(lang, aNeedsToCache); return StaticPresData::Get()->GetFontPrefsForLang(lang, aNeedsToCache);
} }
@ -19763,7 +19764,7 @@ void Document::DoCacheAllKnownLangPrefs() {
MOZ_ASSERT(mMayNeedFontPrefsUpdate); MOZ_ASSERT(mMayNeedFontPrefsUpdate);
RefPtr<nsAtom> lang = GetLanguageForStyle(); RefPtr<nsAtom> lang = GetLanguageForStyle();
StaticPresData* data = StaticPresData::Get(); StaticPresData* data = StaticPresData::Get();
data->GetFontPrefsForLang(lang ? lang.get() : mLanguageFromCharset.get()); data->GetFontPrefsForLang(lang ? lang.get() : mLanguageFromCharset);
data->GetFontPrefsForLang(nsGkAtoms::x_math); data->GetFontPrefsForLang(nsGkAtoms::x_math);
// https://bugzilla.mozilla.org/show_bug.cgi?id=1362599#c12 // https://bugzilla.mozilla.org/show_bug.cgi?id=1362599#c12
data->GetFontPrefsForLang(nsGkAtoms::Unicode); data->GetFontPrefsForLang(nsGkAtoms::Unicode);
@ -19774,29 +19775,14 @@ void Document::DoCacheAllKnownLangPrefs() {
} }
void Document::RecomputeLanguageFromCharset() { void Document::RecomputeLanguageFromCharset() {
RefPtr<nsAtom> language; nsAtom* language = mozilla::intl::EncodingToLang::Lookup(mCharacterSet);
// Optimize the default character sets.
if (mCharacterSet == WINDOWS_1252_ENCODING) {
language = nsGkAtoms::x_western;
} else {
nsLanguageAtomService* service = nsLanguageAtomService::GetService();
if (mCharacterSet == UTF_8_ENCODING) {
language = nsGkAtoms::Unicode;
} else {
language = service->LookupCharSet(mCharacterSet);
}
if (language == nsGkAtoms::Unicode) {
language = service->GetLocaleLanguage();
}
}
if (language == mLanguageFromCharset) { if (language == mLanguageFromCharset) {
return; return;
} }
mMayNeedFontPrefsUpdate = true; mMayNeedFontPrefsUpdate = true;
mLanguageFromCharset = std::move(language); mLanguageFromCharset = language;
} }
nsICookieJarSettings* Document::CookieJarSettings() { nsICookieJarSettings* Document::CookieJarSettings() {

View file

@ -5489,7 +5489,9 @@ class Document : public nsINode,
nsTHashSet<RefPtr<nsAtom>> mLanguagesUsed; nsTHashSet<RefPtr<nsAtom>> mLanguagesUsed;
// TODO(emilio): Is this hot enough to warrant to be cached? // TODO(emilio): Is this hot enough to warrant to be cached?
RefPtr<nsAtom> mLanguageFromCharset; // EncodingToLang.cpp keeps the atom alive until shutdown, so
// no need for a RefPtr.
nsAtom* mLanguageFromCharset;
// Restyle root for servo's style system. // Restyle root for servo's style system.
// //

View file

@ -1948,7 +1948,8 @@ static JS::CompartmentIterResult FindSameOriginCompartment(
} }
auto* compartmentPrivate = xpc::CompartmentPrivate::Get(aCompartment); auto* compartmentPrivate = xpc::CompartmentPrivate::Get(aCompartment);
if (!compartmentPrivate->CanShareCompartmentWith(data->principal)) { if (!compartmentPrivate ||
!compartmentPrivate->CanShareCompartmentWith(data->principal)) {
// Can't reuse this one, keep going. // Can't reuse this one, keep going.
return JS::CompartmentIterResult::KeepGoing; return JS::CompartmentIterResult::KeepGoing;
} }

View file

@ -54,6 +54,7 @@
#include "mozilla/dom/ImageTracker.h" #include "mozilla/dom/ImageTracker.h"
#include "mozilla/dom/PageLoadEventUtils.h" #include "mozilla/dom/PageLoadEventUtils.h"
#include "mozilla/dom/ReferrerInfo.h" #include "mozilla/dom/ReferrerInfo.h"
#include "mozilla/dom/ResponsiveImageSelector.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"
#include "mozilla/intl/LocaleService.h" #include "mozilla/intl/LocaleService.h"
#include "mozilla/intl/Locale.h" #include "mozilla/intl/Locale.h"
@ -1275,18 +1276,100 @@ already_AddRefed<Promise> nsImageLoadingContent::RecognizeCurrentImageText(
return domPromise.forget(); return domPromise.forget();
} }
CSSIntSize nsImageLoadingContent::NaturalSize(
DoDensityCorrection aDensityCorrection) {
if (!mCurrentRequest) {
return {};
}
nsCOMPtr<imgIContainer> image;
mCurrentRequest->GetImage(getter_AddRefs(image));
if (!image) {
return {};
}
mozilla::image::ImageIntrinsicSize intrinsicSize;
nsresult rv = image->GetIntrinsicSize(&intrinsicSize);
if (NS_FAILED(rv)) {
return {};
}
CSSIntSize size; // defaults to 0,0
if (!StaticPrefs::image_natural_size_fallback_enabled()) {
size.width = intrinsicSize.mWidth.valueOr(0);
size.height = intrinsicSize.mHeight.valueOr(0);
} else {
// Fallback case, for web-compatibility!
// See https://github.com/whatwg/html/issues/11287 and bug 1935269.
// If we lack an intrinsic size in either axis, then use the fallback size,
// unless we can transfer the size through the aspect ratio.
// (And if we *only* have an intrinsic aspect ratio, use the fallback width
// and transfer that through the aspect ratio to produce a height.)
size.width = intrinsicSize.mWidth.valueOr(kFallbackIntrinsicWidthInPixels);
size.height =
intrinsicSize.mHeight.valueOr(kFallbackIntrinsicHeightInPixels);
AspectRatio ratio = image->GetIntrinsicRatio();
if (ratio) {
if (!intrinsicSize.mHeight) {
// Compute the height from the width & ratio. (Note that the width we
// use here might be kFallbackIntrinsicWidthInPixels, and that's fine.)
size.height = ratio.Inverted().ApplyTo(size.width);
} else if (!intrinsicSize.mWidth) {
// Compute the width from the height & ratio.
size.width = ratio.ApplyTo(size.height);
}
}
}
ImageResolution resolution = image->GetResolution();
if (aDensityCorrection == DoDensityCorrection::Yes) {
// NOTE(emilio): What we implement here matches the image-set() spec, but
// it's unclear whether this is the right thing to do, see
// https://github.com/whatwg/html/pull/5574#issuecomment-826335244.
if (auto* image = HTMLImageElement::FromNode(AsContent())) {
if (auto* sel = image->GetResponsiveImageSelector()) {
float density = sel->GetSelectedImageDensity();
MOZ_ASSERT(density >= 0.0);
resolution.ScaleBy(density);
}
}
}
resolution.ApplyTo(size.width, size.height);
return size;
}
CSSIntSize nsImageLoadingContent::GetWidthHeightForImage() { CSSIntSize nsImageLoadingContent::GetWidthHeightForImage() {
Element* element = AsContent()->AsElement(); Element* element = AsContent()->AsElement();
if (nsIFrame* frame = element->GetPrimaryFrame(FlushType::Layout)) { if (nsIFrame* frame = element->GetPrimaryFrame(FlushType::Layout)) {
return CSSIntSize::FromAppUnitsRounded(frame->GetContentRect().Size()); return CSSIntSize::FromAppUnitsRounded(frame->GetContentRect().Size());
} }
const nsAttrValue* value;
CSSIntSize size;
nsCOMPtr<imgIContainer> image; nsCOMPtr<imgIContainer> image;
if (mCurrentRequest) { if (StaticPrefs::image_natural_size_fallback_enabled()) {
// Our image is not rendered (we don't have any frame); so we should should
// return the natural size, per:
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-width
//
// Note that the spec says to use the "density-corrected natural width and
// height of the image", but we don't do that -- we specifically request
// the NaturalSize *without* density-correction here. This handles a case
// where browsers deviate from the spec in an interoperable way, which
// hopefully we'll address in the spec soon. See case (2) in this comment
// for more:
// https://github.com/whatwg/html/issues/11287#issuecomment-2923467541
size = NaturalSize(DoDensityCorrection::No);
} else if (mCurrentRequest) {
mCurrentRequest->GetImage(getter_AddRefs(image)); mCurrentRequest->GetImage(getter_AddRefs(image));
} }
CSSIntSize size; // If we have width or height attrs, we'll let those stomp on whatever
// NaturalSize we may have gotten above. This handles a case where browsers
// deviate from the spec in an interoperable way, which hopefully we'll
// address in the spec soon. See case (1) in this comment for more:
// https://github.com/whatwg/html/issues/11287#issuecomment-2923467541
const nsAttrValue* value;
if ((value = element->GetParsedAttr(nsGkAtoms::width)) && if ((value = element->GetParsedAttr(nsGkAtoms::width)) &&
value->Type() == nsAttrValue::eInteger) { value->Type() == nsAttrValue::eInteger) {
size.width = value->GetIntegerValue(); size.width = value->GetIntegerValue();

View file

@ -239,6 +239,17 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
virtual mozilla::dom::FetchPriority GetFetchPriorityForImage() const; virtual mozilla::dom::FetchPriority GetFetchPriorityForImage() const;
/**
* Get the natural size of the current request, as defined here:
* https://html.spec.whatwg.org/multipage/images.html#preferred-density-corrected-dimensions
*
* By default, we return the density-corrected natural size, though we skip
* density-correction if DoDensityCorrection::No is passed.
*/
enum class DoDensityCorrection : bool { No, Yes };
mozilla::CSSIntSize NaturalSize(
DoDensityCorrection = DoDensityCorrection::Yes);
/** /**
* Get width and height of the current request, using given image request if * Get width and height of the current request, using given image request if
* attributes are unset. * attributes are unset.

View file

@ -701,7 +701,6 @@ nsObjectLoadingContent::UpdateObjectParameters() {
nsresult rv; nsresult rv;
nsAutoCString newMime; nsAutoCString newMime;
nsAutoString typeAttr;
nsCOMPtr<nsIURI> newURI; nsCOMPtr<nsIURI> newURI;
nsCOMPtr<nsIURI> newBaseURI; nsCOMPtr<nsIURI> newBaseURI;
ObjectType newType; ObjectType newType;
@ -729,7 +728,6 @@ nsObjectLoadingContent::UpdateObjectParameters() {
el->HasNonEmptyAttr(nsGkAtoms::classid)) { el->HasNonEmptyAttr(nsGkAtoms::classid)) {
// We don't support class ID plugin references, so we should always treat // We don't support class ID plugin references, so we should always treat
// having class Ids as attributes as invalid, and fallback accordingly. // having class Ids as attributes as invalid, and fallback accordingly.
newMime.Truncate();
stateInvalid = true; stateInvalid = true;
} }
@ -759,16 +757,6 @@ nsObjectLoadingContent::UpdateObjectParameters() {
newBaseURI = docBaseURI; newBaseURI = docBaseURI;
} }
nsAutoString rawTypeAttr;
el->GetAttr(nsGkAtoms::type, rawTypeAttr);
if (!rawTypeAttr.IsEmpty()) {
typeAttr = rawTypeAttr;
nsAutoString params;
nsAutoString mime;
nsContentUtils::SplitMimeType(rawTypeAttr, mime, params);
CopyUTF16toUTF8(mime, newMime);
}
/// ///
/// URI /// URI
/// ///
@ -803,6 +791,41 @@ nsObjectLoadingContent::UpdateObjectParameters() {
} }
} }
///
/// type
///
nsAutoString rawTypeAttr;
el->GetAttr(nsGkAtoms::type, rawTypeAttr);
// YouTube embeds might be using type="application/x-shockwave-flash"
// which needs to be allowed, but must not override the text/html MIME set
// above.
if (!mRewrittenYoutubeEmbed && !rawTypeAttr.IsEmpty()) {
nsAutoString params;
nsAutoString mime;
nsContentUtils::SplitMimeType(rawTypeAttr, mime, params);
if (!StaticPrefs::dom_object_embed_type_hint_enabled()) {
NS_ConvertUTF16toUTF8 mimeUTF8(mime);
if (imgLoader::SupportImageWithMimeType(mimeUTF8)) {
// Normally the type attribute should not be used as a hint, but for
// images it does seem to happen in Chrome and Safari. Images generally
// don't lead to code execution and we don't use
// AcceptedMimeTypes::IMAGES_AND_DOCUMENTS above.
newMime = mimeUTF8;
} else if (GetTypeOfContent(mimeUTF8) != ObjectType::Document) {
LOG(
("OBJLC [%p]: MIME '%s' from type attribute is not supported, "
"forcing fallback.",
this, mimeUTF8.get()));
stateInvalid = true;
}
// Don't use the type attribute as a Content-Type hint in other cases.
} else {
CopyUTF16toUTF8(mime, newMime);
}
}
/// ///
/// Check if the original (pre-channel) content-type or URI changed, and /// Check if the original (pre-channel) content-type or URI changed, and
/// record mOriginal{ContentType,URI} /// record mOriginal{ContentType,URI}

View file

@ -2,18 +2,25 @@
support-files = [ support-files = [
"external_importMap.js", "external_importMap.js",
"insert_a_base_element.js", "insert_a_base_element.js",
"module_1979050.mjs",
"module_simpleImportMap.mjs", "module_simpleImportMap.mjs",
"module_simpleImportMap_dir.mjs", "module_simpleImportMap_dir.mjs",
"module_simpleImportMap_remap.mjs", "module_simpleImportMap_remap.mjs",
"module_simpleImportMap_remap_https.mjs", "module_simpleImportMap_remap_https.mjs",
"module_simpleExport.mjs", "module_simpleExport.mjs",
"module_sortedImportMap.mjs", "module_sortedImportMap.mjs",
"scope1/module_1979050.mjs",
"scope1/module_simpleExport.mjs", "scope1/module_simpleExport.mjs",
"scope1/module_simpleImportMap.mjs", "scope1/module_simpleImportMap.mjs",
"scope1/scope2/module_1979050.mjs",
"scope1/scope2/module_simpleExport.mjs", "scope1/scope2/module_simpleExport.mjs",
"scope1/scope2/module_simpleImportMap.mjs", "scope1/scope2/module_simpleImportMap.mjs",
] ]
["test_1979050.html"]
["test_1979050_2.html"]
["test_dynamic_import_reject_importMap.html"] ["test_dynamic_import_reject_importMap.html"]
["test_externalImportMap.html"] ["test_externalImportMap.html"]

View file

@ -0,0 +1,3 @@
import { x } from "./module_simpleExport.mjs";
result = x;

View file

@ -0,0 +1,5 @@
import { x } from "./module_simpleExport.mjs";
result2 = x;
export let y = x;

View file

@ -0,0 +1,5 @@
import { x } from "./module_simpleExport.mjs";
result3 = x;
export let z = x;

View file

@ -0,0 +1,50 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test bug 1979050</title>
<script>
Object.prototype.imports = {
"./module_simpleExport.mjs": "./scope1/module_simpleExport.mjs",
};
Object.prototype.scopes = {
"chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/": {
"./scope1/module_simpleExport.mjs": "/content/chrome/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs"
}
};
Object.prototype.integrity = {
"./scope1/scope2/module_simpleExport.mjs": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
};
</script>
<script type="importmap">
{}
</script>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="module" src="module_1979050.mjs"></script>
<script type="module" src="./scope1/module_1979050.mjs"></script>
<script type="module" src="./scope1/scope2/module_1979050.mjs"></script>
<script>
var result, result2, result3;
SimpleTest.waitForExplicitFinish();
// eslint-disable-next-line no-unused-vars
function testLoaded() {
ok(result == 42, 'Check static imported value result: ' + result);
ok(result2 == 84, 'Check static imported value result2: ' + result2);
ok(result3 == 126, 'Check static imported value result3: ' + result3);
import("./module_simpleExport.mjs").then((ns) => {
ok(ns.x == 42, 'Check dynamic imported value result: ' + ns.x);
return import("./scope1/module_1979050.mjs");
}).then((ns) => {
ok(ns.y == 84, 'Check dynamic imported value ns.y: ' + ns.y);
return import("./scope1/scope2/module_1979050.mjs");
}).then((ns) => {
ok(ns.z == 126, 'Check dynamic imported value ns.z: ' + ns.z);
SimpleTest.finish();
});
}
</script>
<body onload='testLoaded()'></body>

View file

@ -0,0 +1,69 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test bug 1979050</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
Object.defineProperty(Object.prototype, "imports",
{
get() {
ok(false, "imports getter");
return {
"./module_simpleExport.mjs": "./scope1/module_simpleExport.mjs",
};
}
});
Object.defineProperty(Object.prototype, "scopes",
{
get() {
ok(false, "scopes getter");
return {
"chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/": {
"./scope1/module_simpleExport.mjs": "/content/chrome/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs"
}
};
}
});
Object.defineProperty(Object.prototype, "integrity ",
{
get() {
ok(false, "scopes getter");
return {
"./scope1/scope2/module_simpleExport.mjs": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
};
}
});
</script>
<script type="importmap">
{}
</script>
<script type="module" src="module_1979050.mjs"></script>
<script type="module" src="./scope1/module_1979050.mjs"></script>
<script type="module" src="./scope1/scope2/module_1979050.mjs"></script>
<script>
var result, result2, result3;
SimpleTest.waitForExplicitFinish();
// eslint-disable-next-line no-unused-vars
function testLoaded() {
ok(result == 42, 'Check static imported value result: ' + result);
ok(result2 == 84, 'Check static imported value result2: ' + result2);
ok(result3 == 126, 'Check static imported value result3: ' + result3);
import("./module_simpleExport.mjs").then((ns) => {
ok(ns.x == 42, 'Check dynamic imported value result: ' + ns.x);
return import("./scope1/module_1979050.mjs");
}).then((ns) => {
ok(ns.y == 84, 'Check dynamic imported value ns.y: ' + ns.y);
return import("./scope1/scope2/module_1979050.mjs");
}).then((ns) => {
ok(ns.z == 126, 'Check dynamic imported value ns.z: ' + ns.z);
SimpleTest.finish();
});
}
</script>
<body onload='testLoaded()'></body>

View file

@ -5503,20 +5503,20 @@ static Matrix ComputeRotationMatrix(gfxFloat aRotatedWidth,
// - // -
Maybe<layers::SurfaceDescriptor> ValidSurfaceDescriptorForRemoteCanvas2d( bool ValidSurfaceDescriptorForRemoteCanvas2d(
const layers::SurfaceDescriptor& sdConst) { const layers::SurfaceDescriptor& aSd,
auto sd = sdConst; // Copy, so we can mutate it. Maybe<layers::SurfaceDescriptor>* aResultSd) {
if (sd.type() != layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo) { if (aSd.type() != layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo) {
return Nothing(); return false;
} }
auto& sdv = sd.get_SurfaceDescriptorGPUVideo(); const auto& sdv = aSd.get_SurfaceDescriptorGPUVideo();
if (sdv.type() != if (sdv.type() !=
layers::SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder) { layers::SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder) {
return Nothing(); return false;
} }
auto& sdrd = sdv.get_SurfaceDescriptorRemoteDecoder(); const auto& sdrd = sdv.get_SurfaceDescriptorRemoteDecoder();
auto& subdesc = sdrd.subdesc(); const auto& subdesc = sdrd.subdesc();
switch (subdesc.type()) { switch (subdesc.type()) {
case layers::RemoteDecoderVideoSubDescriptor::Tnull_t: case layers::RemoteDecoderVideoSubDescriptor::Tnull_t:
break; break;
@ -5525,7 +5525,7 @@ Maybe<layers::SurfaceDescriptor> ValidSurfaceDescriptorForRemoteCanvas2d(
TSurfaceDescriptorMacIOSurface: { TSurfaceDescriptorMacIOSurface: {
const auto& ssd = subdesc.get_SurfaceDescriptorMacIOSurface(); const auto& ssd = subdesc.get_SurfaceDescriptorMacIOSurface();
if (ssd.gpuFence()) { if (ssd.gpuFence()) {
return Nothing(); return false;
} }
break; break;
} }
@ -5533,18 +5533,31 @@ Maybe<layers::SurfaceDescriptor> ValidSurfaceDescriptorForRemoteCanvas2d(
#ifdef XP_WIN #ifdef XP_WIN
case layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorD3D10: { case layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorD3D10: {
if (!StaticPrefs::gfx_canvas_remote_use_draw_image_fast_path_d3d()) { if (!StaticPrefs::gfx_canvas_remote_use_draw_image_fast_path_d3d()) {
return Nothing(); return false;
} }
auto& ssd = subdesc.get_SurfaceDescriptorD3D10(); const auto& ssd = subdesc.get_SurfaceDescriptorD3D10();
ssd.handle() = if (aResultSd) {
nullptr; // Not IPC-able, but it's just an optimization to have this. *aResultSd = Some(aSd);
break; // Not IPC-able, but it's just an optimization to have this.
aResultSd->ref()
.get_SurfaceDescriptorGPUVideo()
.get_SurfaceDescriptorRemoteDecoder()
.subdesc()
.get_SurfaceDescriptorD3D10()
.handle() = nullptr;
} else if (ssd.handle()) {
return false;
}
return true;
} }
#endif #endif
default: default:
return Nothing(); return false;
} }
return Some(sd); if (aResultSd) {
*aResultSd = Some(aSd);
}
return true;
} }
static Maybe<layers::SurfaceDescriptor> static Maybe<layers::SurfaceDescriptor>
@ -5558,9 +5571,13 @@ MaybeGetSurfaceDescriptorForRemoteCanvas(
return Nothing(); return Nothing();
} }
const auto sd = aResult.mLayersImage->GetDesc(); if (const auto sd = aResult.mLayersImage->GetDesc()) {
if (!sd) return Nothing(); Maybe<layers::SurfaceDescriptor> result;
return ValidSurfaceDescriptorForRemoteCanvas2d(*sd); if (ValidSurfaceDescriptorForRemoteCanvas2d(*sd, &result)) {
return result;
}
}
return Nothing();
} }
// drawImage(in HTMLImageElement image, in float dx, in float dy); // drawImage(in HTMLImageElement image, in float dx, in float dy);

View file

@ -89,8 +89,9 @@ class CanvasRenderingContextHelper {
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext; nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
}; };
Maybe<layers::SurfaceDescriptor> ValidSurfaceDescriptorForRemoteCanvas2d( bool ValidSurfaceDescriptorForRemoteCanvas2d(
const layers::SurfaceDescriptor&); const layers::SurfaceDescriptor& aSd,
Maybe<layers::SurfaceDescriptor>* aResultSd = nullptr);
} // namespace dom } // namespace dom
namespace CanvasUtils { namespace CanvasUtils {

View file

@ -413,8 +413,14 @@ void SharedContextWebgl::ClearCachesIfNecessary() {
// not exceed the available texture limits and that shader creation succeeded. // not exceed the available texture limits and that shader creation succeeded.
bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format, bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format,
const RefPtr<SharedContextWebgl>& aSharedContext) { const RefPtr<SharedContextWebgl>& aSharedContext) {
MOZ_ASSERT(format == SurfaceFormat::B8G8R8A8 || switch (format) {
format == SurfaceFormat::B8G8R8X8); case SurfaceFormat::B8G8R8A8:
case SurfaceFormat::B8G8R8X8:
break;
default:
MOZ_ASSERT_UNREACHABLE("Unsupported format for DrawTargetWebgl.");
return false;
}
mSize = size; mSize = size;
mFormat = format; mFormat = format;
@ -1775,6 +1781,10 @@ void DrawTargetWebgl::PushDeviceSpaceClipRects(const IntRect* aRects,
} }
void DrawTargetWebgl::PopClip() { void DrawTargetWebgl::PopClip() {
if (mClipStack.empty()) {
return;
}
mClipChanged = true; mClipChanged = true;
mRefreshClipState = true; mRefreshClipState = true;
mSkia->PopClip(); mSkia->PopClip();
@ -2022,10 +2032,29 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
const IntPoint& aDstOffset, bool aInit, const IntPoint& aDstOffset, bool aInit,
bool aZero, bool aZero,
const RefPtr<WebGLTexture>& aTex) { const RefPtr<WebGLTexture>& aTex) {
webgl::TexUnpackBlobDesc texDesc = { webgl::TexUnpackBlobDesc texDesc = {LOCAL_GL_TEXTURE_2D};
LOCAL_GL_TEXTURE_2D, IntRect srcRect(aSrcRect);
{uint32_t(aSrcRect.width), uint32_t(aSrcRect.height), 1}}; IntPoint dstOffset(aDstOffset);
if (srcRect.IsEmpty()) {
return true;
}
if (aData) { if (aData) {
// If the source rect could not possibly overlap the surface, then it is
// effectively empty with nothing to upload.
srcRect = srcRect.SafeIntersect(IntRect(IntPoint(0, 0), aData->GetSize()));
if (srcRect.IsEmpty()) {
return true;
}
// If there is a non-empty rect remaining, then ensure the dest offset
// reflects the change in source rect.
dstOffset += srcRect.TopLeft() - aSrcRect.TopLeft();
// Ensure source data matches the expected format size.
int32_t bpp = BytesPerPixel(aFormat);
if (bpp != BytesPerPixel(aData->GetFormat())) {
return false;
}
// The surface needs to be uploaded to its backing texture either to // The surface needs to be uploaded to its backing texture either to
// initialize or update the texture handle contents. Map the data // initialize or update the texture handle contents. Map the data
// contents of the surface so it can be read. // contents of the surface so it can be read.
@ -2034,13 +2063,11 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
return false; return false;
} }
int32_t stride = map.GetStride(); int32_t stride = map.GetStride();
int32_t bpp = BytesPerPixel(aFormat);
// Get the data pointer range considering the sampling rect offset and // Get the data pointer range considering the sampling rect offset and
// size. // size.
Span<const uint8_t> range( Span<const uint8_t> range(
map.GetData() + aSrcRect.y * size_t(stride) + aSrcRect.x * bpp, map.GetData() + srcRect.y * size_t(stride) + srcRect.x * bpp,
std::max(aSrcRect.height - 1, 0) * size_t(stride) + std::max(srcRect.height - 1, 0) * size_t(stride) + srcRect.width * bpp);
aSrcRect.width * bpp);
texDesc.cpuData = Some(range); texDesc.cpuData = Some(range);
// If the stride happens to be 4 byte aligned, assume that is the // If the stride happens to be 4 byte aligned, assume that is the
// desired alignment regardless of format (even A8). Otherwise, we // desired alignment regardless of format (even A8). Otherwise, we
@ -2050,10 +2077,16 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
} else if (aZero) { } else if (aZero) {
// Create a PBO filled with zero data to initialize the texture data and // Create a PBO filled with zero data to initialize the texture data and
// avoid slow initialization inside WebGL. // avoid slow initialization inside WebGL.
MOZ_ASSERT(aSrcRect.TopLeft() == IntPoint(0, 0)); if (srcRect.TopLeft() != IntPoint(0, 0)) {
size_t size = MOZ_ASSERT_UNREACHABLE("Invalid origin for texture initialization.");
size_t(GetAlignedStride<4>(aSrcRect.width, BytesPerPixel(aFormat))) * return false;
aSrcRect.height; }
int32_t stride = GetAlignedStride<4>(srcRect.width, BytesPerPixel(aFormat));
if (stride <= 0) {
MOZ_ASSERT_UNREACHABLE("Invalid stride for texture initialization.");
return false;
}
size_t size = size_t(stride) * srcRect.height;
if (!mZeroBuffer || size > mZeroSize) { if (!mZeroBuffer || size > mZeroSize) {
ClearZeroBuffer(); ClearZeroBuffer();
mZeroBuffer = mWebgl->CreateBuffer(); mZeroBuffer = mWebgl->CreateBuffer();
@ -2069,6 +2102,7 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
} }
texDesc.pboOffset = Some(0); texDesc.pboOffset = Some(0);
} }
texDesc.size = uvec3(uint32_t(srcRect.width), uint32_t(srcRect.height), 1);
// Upload as RGBA8 to avoid swizzling during upload. Surfaces provide // Upload as RGBA8 to avoid swizzling during upload. Surfaces provide
// data as BGRA, but we manually swizzle that in the shader. An A8 // data as BGRA, but we manually swizzle that in the shader. An A8
// surface will be stored as an R8 texture that will also be swizzled // surface will be stored as an R8 texture that will also be swizzled
@ -2083,7 +2117,7 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
mWebgl->BindTexture(LOCAL_GL_TEXTURE_2D, aTex); mWebgl->BindTexture(LOCAL_GL_TEXTURE_2D, aTex);
} }
mWebgl->TexImage(0, aInit ? intFormat : 0, mWebgl->TexImage(0, aInit ? intFormat : 0,
{uint32_t(aDstOffset.x), uint32_t(aDstOffset.y), 0}, texPI, {uint32_t(dstOffset.x), uint32_t(dstOffset.y), 0}, texPI,
texDesc); texDesc);
if (aTex) { if (aTex) {
mWebgl->BindTexture(LOCAL_GL_TEXTURE_2D, mLastTexture); mWebgl->BindTexture(LOCAL_GL_TEXTURE_2D, mLastTexture);

View file

@ -438,8 +438,22 @@ struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
!view.ReadParam(&stride)) { !view.ReadParam(&stride)) {
return false; return false;
} }
const size_t dataSize = stride * surfSize.height; if (!CheckedInt32(stride).isValid() || surfSize.IsEmpty()) {
const auto range = view.template ReadRange<uint8_t>(dataSize); return false;
}
int32_t bpp = BytesPerPixel(format);
CheckedInt<size_t> minStride(bpp);
minStride *= surfSize.width;
if (!minStride.isValid() || minStride.value() <= 0 ||
stride < minStride.value()) {
return false;
}
CheckedInt<size_t> dataSize(stride);
dataSize *= surfSize.height;
if (!dataSize.isValid()) {
return false;
}
const auto range = view.template ReadRange<uint8_t>(dataSize.value());
if (!range) return false; if (!range) return false;
// DataSourceSurface demands pointer-to-mutable. // DataSourceSurface demands pointer-to-mutable.

View file

@ -406,6 +406,21 @@ bool TexUnpackBlob::ConvertIfNeeded(
if (!rowLength || !rowCount) return true; if (!rowLength || !rowCount) return true;
auto minSrcStride =
CheckedInt<size_t>(
WebGLTexelConversions::TexelBytesForFormat(srcFormat)) *
rowLength;
auto minDstStride =
CheckedInt<size_t>(
WebGLTexelConversions::TexelBytesForFormat(dstFormat)) *
rowLength;
if (srcStride <= 0 || dstStride <= 0 || !minSrcStride.isValid() ||
!minDstStride.isValid() || size_t(srcStride) < minSrcStride.value() ||
size_t(dstStride) < minDstStride.value()) {
webgl->ErrorInvalidOperation("Invalid stride.");
return false;
}
const auto srcIsPremult = (mDesc.srcAlphaType == gfxAlphaType::Premult); const auto srcIsPremult = (mDesc.srcAlphaType == gfxAlphaType::Premult);
auto dstIsPremult = unpacking.premultiplyAlpha; auto dstIsPremult = unpacking.premultiplyAlpha;
const auto fnHasPremultMismatch = [&]() { const auto fnHasPremultMismatch = [&]() {
@ -997,9 +1012,20 @@ bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec,
const auto& data = sdb.data(); const auto& data = sdb.data();
MOZ_ASSERT(data.type() == layers::MemoryOrShmem::TShmem); MOZ_ASSERT(data.type() == layers::MemoryOrShmem::TShmem);
const auto& shmem = data.get_Shmem(); const auto& shmem = data.get_Shmem();
surf = gfx::Factory::CreateWrappingDataSourceSurface( size_t shmemSize = shmem.Size<uint8_t>();
shmem.get<uint8_t>(), layers::ImageDataSerializer::GetRGBStride(rgb), int32_t stride = layers::ImageDataSerializer::GetRGBStride(rgb);
if (stride <= 0) {
gfxCriticalError() << "TexUnpackSurface failed to get rgb stride";
return false;
}
size_t bufSize = layers::ImageDataSerializer::ComputeRGBBufferSize(
rgb.size(), rgb.format()); rgb.size(), rgb.format());
if (!bufSize || bufSize > shmemSize) {
gfxCriticalError() << "TexUnpackSurface failed to get rgb buffer size";
return false;
}
surf = gfx::Factory::CreateWrappingDataSourceSurface(
shmem.get<uint8_t>(), stride, rgb.size(), rgb.format());
} else if (SDIsNullRemoteDecoder(sd)) { } else if (SDIsNullRemoteDecoder(sd)) {
const auto& sdrd = sd.get_SurfaceDescriptorGPUVideo() const auto& sdrd = sd.get_SurfaceDescriptorGPUVideo()
.get_SurfaceDescriptorRemoteDecoder(); .get_SurfaceDescriptorRemoteDecoder();
@ -1106,12 +1132,10 @@ bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec,
// - // -
const auto dstFormat = FormatForPackingInfo(dstPI); const auto dstFormat = FormatForPackingInfo(dstPI);
const auto dstBpp = BytesPerPixel(dstPI); const size_t dstBpp = BytesPerPixel(dstPI);
const size_t dstUsedBytesPerRow = dstBpp * surf->GetSize().width; const size_t dstUsedBytesPerRow = dstBpp * surf->GetSize().width;
auto dstStride = dstUsedBytesPerRow; size_t dstStride = dstFormat == srcFormat ? srcStride // Try To match
if (dstFormat == srcFormat) { : dstUsedBytesPerRow;
dstStride = srcStride; // Try to match.
}
// - // -

View file

@ -1345,6 +1345,11 @@ template <typename SrcType, typename DstType>
MOZ_ALWAYS_INLINE void convertType(const SrcType* __restrict src, MOZ_ALWAYS_INLINE void convertType(const SrcType* __restrict src,
DstType* __restrict dst) { DstType* __restrict dst) {
MOZ_ASSERT(false, "Unimplemented texture format conversion"); MOZ_ASSERT(false, "Unimplemented texture format conversion");
// Default construct dst values, ensuring they are *some* value.
dst[0] = DstType();
dst[1] = DstType();
dst[2] = DstType();
dst[3] = DstType();
} }
template <> template <>

View file

@ -6,6 +6,7 @@
#include "EventStateManager.h" #include "EventStateManager.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/AsyncEventDispatcher.h" #include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/EditorBase.h" #include "mozilla/EditorBase.h"
@ -302,7 +303,10 @@ NS_IMPL_ISUPPORTS(UITimerCallback, nsITimerCallback, nsINamed)
NS_IMETHODIMP NS_IMETHODIMP
UITimerCallback::Notify(nsITimer* aTimer) { UITimerCallback::Notify(nsITimer* aTimer) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) return NS_ERROR_FAILURE; // ObserverService shutdown happens after XPCOMShutdownThreads.
if (!obs || AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads)) {
return NS_ERROR_FAILURE;
}
if ((gMouseOrKeyboardEventCounter == mPreviousCount) || !aTimer) { if ((gMouseOrKeyboardEventCounter == mPreviousCount) || !aTimer) {
gMouseOrKeyboardEventCounter = 0; gMouseOrKeyboardEventCounter = 0;
obs->NotifyObservers(nullptr, "user-interaction-inactive", nullptr); obs->NotifyObservers(nullptr, "user-interaction-inactive", nullptr);

View file

@ -612,64 +612,6 @@ uint32_t HTMLImageElement::Height() { return GetWidthHeightForImage().height; }
uint32_t HTMLImageElement::Width() { return GetWidthHeightForImage().width; } uint32_t HTMLImageElement::Width() { return GetWidthHeightForImage().width; }
CSSIntSize HTMLImageElement::NaturalSize() {
if (!mCurrentRequest) {
return {};
}
nsCOMPtr<imgIContainer> image;
mCurrentRequest->GetImage(getter_AddRefs(image));
if (!image) {
return {};
}
mozilla::image::ImageIntrinsicSize intrinsicSize;
nsresult rv = image->GetIntrinsicSize(&intrinsicSize);
if (NS_FAILED(rv)) {
return {};
}
CSSIntSize size; // defaults to 0,0
if (!StaticPrefs::image_natural_size_fallback_enabled()) {
size.width = intrinsicSize.mWidth.valueOr(0);
size.height = intrinsicSize.mHeight.valueOr(0);
} else {
// Fallback case, for web-compatibility!
// See https://github.com/whatwg/html/issues/11287 and bug 1935269.
// If we lack an intrinsic size in either axis, then use the fallback size,
// unless we can transfer the size through the aspect ratio.
// (And if we *only* have an intrinsic aspect ratio, use the fallback width
// and transfer that through the aspect ratio to produce a height.)
size.width = intrinsicSize.mWidth.valueOr(kFallbackIntrinsicWidthInPixels);
size.height =
intrinsicSize.mHeight.valueOr(kFallbackIntrinsicHeightInPixels);
AspectRatio ratio = image->GetIntrinsicRatio();
if (ratio) {
if (!intrinsicSize.mHeight) {
// Compute the height from the width & ratio. (Note that the width we
// use here might be kFallbackIntrinsicWidthInPixels, and that's fine.)
size.height = ratio.Inverted().ApplyTo(size.width);
} else if (!intrinsicSize.mWidth) {
// Compute the width from the height & ratio.
size.width = ratio.ApplyTo(size.height);
}
}
}
ImageResolution resolution = image->GetResolution();
// NOTE(emilio): What we implement here matches the image-set() spec, but it's
// unclear whether this is the right thing to do, see
// https://github.com/whatwg/html/pull/5574#issuecomment-826335244.
if (mResponsiveSelector) {
float density = mResponsiveSelector->GetSelectedImageDensity();
MOZ_ASSERT(density >= 0.0);
resolution.ScaleBy(density);
}
resolution.ApplyTo(size.width, size.height);
return size;
}
nsresult HTMLImageElement::CopyInnerTo(HTMLImageElement* aDest) { nsresult HTMLImageElement::CopyInnerTo(HTMLImageElement* aDest) {
MOZ_TRY(nsGenericHTMLElement::CopyInnerTo(aDest)); MOZ_TRY(nsGenericHTMLElement::CopyInnerTo(aDest));

View file

@ -94,7 +94,6 @@ class HTMLImageElement final : public nsGenericHTMLElement,
SetUnsignedIntAttr(nsGkAtoms::height, aHeight, 0, aError); SetUnsignedIntAttr(nsGkAtoms::height, aHeight, 0, aError);
} }
CSSIntSize NaturalSize();
uint32_t NaturalHeight() { return NaturalSize().height; } uint32_t NaturalHeight() { return NaturalSize().height; }
uint32_t NaturalWidth() { return NaturalSize().width; } uint32_t NaturalWidth() { return NaturalSize().width; }

View file

@ -2488,6 +2488,12 @@ void TextControlState::UnbindFromFrame(nsTextControlFrame* aFrame) {
DebugOnly<bool> ok = SetValue(value, ValueSetterOption::ByInternalAPI); DebugOnly<bool> ok = SetValue(value, ValueSetterOption::ByInternalAPI);
// TODO Find something better to do if this fails... // TODO Find something better to do if this fails...
NS_WARNING_ASSERTION(ok, "SetValue() couldn't allocate memory"); NS_WARNING_ASSERTION(ok, "SetValue() couldn't allocate memory");
// And mark the selection as dirty to make sure the selection will be
// restored properly in RestoreSelectionState. See bug 1993351.
if (IsSelectionCached()) {
SelectionProperties& props = GetSelectionProperties();
props.SetIsDirty();
}
} }
} }

View file

@ -740,27 +740,33 @@ nsresult HTMLContentSink::OpenBody() {
mCurrentContext->mStack[parentIndex].mContent; mCurrentContext->mStack[parentIndex].mContent;
int32_t numFlushed = mCurrentContext->mStack[parentIndex].mNumFlushed; int32_t numFlushed = mCurrentContext->mStack[parentIndex].mNumFlushed;
int32_t childCount = parent->GetChildCount(); int32_t childCount = parent->GetChildCount();
NS_ASSERTION(numFlushed < childCount, "Already notified on the body?"); if (numFlushed < childCount) {
int32_t insertionPoint =
mCurrentContext->mStack[parentIndex].mInsertionPoint;
int32_t insertionPoint = // XXX: I have yet to see a case where numFlushed is non-zero and
mCurrentContext->mStack[parentIndex].mInsertionPoint; // insertionPoint is not -1, but this code will try to handle
// those cases too.
// XXX: I have yet to see a case where numFlushed is non-zero and uint32_t oldUpdates = mUpdatesInNotification;
// insertionPoint is not -1, but this code will try to handle mUpdatesInNotification = 0;
// those cases too. if (insertionPoint != -1) {
NotifyInsert(parent, mBody);
uint32_t oldUpdates = mUpdatesInNotification; } else {
mUpdatesInNotification = 0; NotifyAppend(parent, numFlushed);
if (insertionPoint != -1) { }
NotifyInsert(parent, mBody); mCurrentContext->mStack[parentIndex].mNumFlushed = childCount;
if (mUpdatesInNotification > 1) {
UpdateChildCounts();
}
mUpdatesInNotification = oldUpdates;
} else { } else {
NotifyAppend(parent, numFlushed); MOZ_ASSERT(
false,
"This isn't supposed to happen but per bug 1782501 actually does "
"with the NoScript extension. Please debug if this assertion fails.");
mCurrentContext->mStack[parentIndex].mNumFlushed = childCount;
} }
mCurrentContext->mStack[parentIndex].mNumFlushed = childCount;
if (mUpdatesInNotification > 1) {
UpdateChildCounts();
}
mUpdatesInNotification = oldUpdates;
} }
StartLayout(false); StartLayout(false);

View file

@ -3571,11 +3571,10 @@ MediaTrackGraphImpl* MediaTrackGraphImpl::GetInstance(
MOZ_ASSERT(aGraphDriverRequested != OFFLINE_THREAD_DRIVER, MOZ_ASSERT(aGraphDriverRequested != OFFLINE_THREAD_DRIVER,
"Use CreateNonRealtimeInstance() for offline graphs"); "Use CreateNonRealtimeInstance() for offline graphs");
GraphHashSet* graphs = Graphs(); MediaTrackGraphImpl* graph =
GraphHashSet::AddPtr addPtr = GetInstanceIfExists(aWindowID, aSampleRate, aPrimaryOutputDeviceID);
graphs->lookupForAdd({aWindowID, aSampleRate, aPrimaryOutputDeviceID}); if (graph) { // graph already exists
if (addPtr) { // graph already exists return graph;
return *addPtr;
} }
GraphRunType runType = DIRECT_DRIVER; GraphRunType runType = DIRECT_DRIVER;
@ -3586,10 +3585,11 @@ MediaTrackGraphImpl* MediaTrackGraphImpl::GetInstance(
// In a real time graph, the number of output channels is determined by // In a real time graph, the number of output channels is determined by
// the underlying number of channel of the default audio output device. // the underlying number of channel of the default audio output device.
uint32_t channelCount = CubebUtils::MaxNumberOfChannels(); uint32_t channelCount = CubebUtils::MaxNumberOfChannels();
MediaTrackGraphImpl* graph = new MediaTrackGraphImpl( graph = new MediaTrackGraphImpl(aWindowID, aSampleRate,
aWindowID, aSampleRate, aPrimaryOutputDeviceID, aMainThread); aPrimaryOutputDeviceID, aMainThread);
graph->Init(aGraphDriverRequested, runType, channelCount); graph->Init(aGraphDriverRequested, runType, channelCount);
MOZ_ALWAYS_TRUE(graphs->add(addPtr, graph)); MOZ_ALWAYS_TRUE(Graphs()->putNew(
{aWindowID, aSampleRate, aPrimaryOutputDeviceID}, graph));
LOG(LogLevel::Debug, ("Starting up MediaTrackGraph %p for window 0x%" PRIx64, LOG(LogLevel::Debug, ("Starting up MediaTrackGraph %p for window 0x%" PRIx64,
graph, aWindowID)); graph, aWindowID));

View file

@ -256,7 +256,7 @@ void RDDProcessHost::DestroyProcess() {
void RDDProcessHost::ResolvePromise() { void RDDProcessHost::ResolvePromise() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (!mLaunchPromiseSettled) { if (mLaunchPromise && !mLaunchPromiseSettled) {
mLaunchPromise->Resolve(true, __func__); mLaunchPromise->Resolve(true, __func__);
mLaunchPromiseSettled = true; mLaunchPromiseSettled = true;
} }
@ -268,7 +268,7 @@ void RDDProcessHost::ResolvePromise() {
void RDDProcessHost::RejectPromise() { void RDDProcessHost::RejectPromise() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (!mLaunchPromiseSettled) { if (mLaunchPromise && !mLaunchPromiseSettled) {
mLaunchPromise->Reject(NS_ERROR_FAILURE, __func__); mLaunchPromise->Reject(NS_ERROR_FAILURE, __func__);
mLaunchPromiseSettled = true; mLaunchPromiseSettled = true;
} }

View file

@ -129,7 +129,8 @@ RefPtr<GenericNonExclusivePromise> RDDProcessManager::LaunchRDDProcess() {
__func__); __func__);
} }
if (mLaunchRDDPromise && mProcess) { if (mProcess) {
MOZ_DIAGNOSTIC_ASSERT(mLaunchRDDPromise);
return mLaunchRDDPromise; return mLaunchRDDPromise;
} }
@ -154,7 +155,7 @@ RefPtr<GenericNonExclusivePromise> RDDProcessManager::LaunchRDDProcess() {
NS_ERROR_NOT_AVAILABLE, __func__); NS_ERROR_NOT_AVAILABLE, __func__);
} }
if (IsRDDProcessDestroyed()) { if (NS_WARN_IF(!IsRDDProcessLaunching())) {
return GenericNonExclusivePromise::CreateAndReject( return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_NOT_AVAILABLE, __func__); NS_ERROR_NOT_AVAILABLE, __func__);
} }
@ -219,14 +220,14 @@ auto RDDProcessManager::EnsureRDDProcessAndCreateBridge(
}); });
} }
bool RDDProcessManager::IsRDDProcessLaunching() { bool RDDProcessManager::IsRDDProcessLaunching() const {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
return !!mProcess && !mRDDChild; return !!mProcess && !mRDDChild;
} }
bool RDDProcessManager::IsRDDProcessDestroyed() const { bool RDDProcessManager::IsRDDProcessAlive() const {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
return !mRDDChild && !mProcess; return mRDDChild && mRDDChild->CanSend() && mProcess;
} }
void RDDProcessManager::OnProcessUnexpectedShutdown(RDDProcessHost* aHost) { void RDDProcessManager::OnProcessUnexpectedShutdown(RDDProcessHost* aHost) {
@ -261,14 +262,20 @@ void RDDProcessManager::NotifyRemoteActorDestroyed(
void RDDProcessManager::DestroyProcess() { void RDDProcessManager::DestroyProcess() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (!mProcess) { if (!mProcess) {
return; return;
} }
mProcess->Shutdown(); // Move onto the stack to ensure we don't re-enter from a chained promise
mProcessToken = 0; // rejection on the process shutdown.
RDDProcessHost* process = mProcess;
mProcess = nullptr; mProcess = nullptr;
process->Shutdown();
mProcessToken = 0;
mRDDChild = nullptr; mRDDChild = nullptr;
mLaunchRDDPromise = nullptr;
mQueuedPrefs.Clear(); mQueuedPrefs.Clear();
CrashReporter::RecordAnnotationCString( CrashReporter::RecordAnnotationCString(
@ -280,7 +287,7 @@ bool RDDProcessManager::CreateContentBridge(
ipc::Endpoint<PRemoteDecoderManagerChild>* aOutRemoteDecoderManager) { ipc::Endpoint<PRemoteDecoderManagerChild>* aOutRemoteDecoderManager) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (IsRDDProcessDestroyed()) { if (NS_WARN_IF(!IsRDDProcessAlive())) {
MOZ_LOG(sPDMLog, LogLevel::Debug, MOZ_LOG(sPDMLog, LogLevel::Debug,
("RDD shutdown before creating content bridge")); ("RDD shutdown before creating content bridge"));
return false; return false;
@ -310,6 +317,12 @@ bool RDDProcessManager::CreateVideoBridge() {
ipc::Endpoint<PVideoBridgeParent> parentPipe; ipc::Endpoint<PVideoBridgeParent> parentPipe;
ipc::Endpoint<PVideoBridgeChild> childPipe; ipc::Endpoint<PVideoBridgeChild> childPipe;
if (NS_WARN_IF(!IsRDDProcessAlive())) {
MOZ_LOG(sPDMLog, LogLevel::Debug,
("RDD shutdown before creating video bridge"));
return false;
}
GPUProcessManager* gpuManager = GPUProcessManager::Get(); GPUProcessManager* gpuManager = GPUProcessManager::Get();
ipc::EndpointProcInfo gpuProcessInfo = gpuManager ipc::EndpointProcInfo gpuProcessInfo = gpuManager
? gpuManager->GPUEndpointProcInfo() ? gpuManager->GPUEndpointProcInfo()

View file

@ -74,8 +74,8 @@ class RDDProcessManager final : public RDDProcessHost::Listener {
RefPtr<PRDDChild::TestTriggerMetricsPromise> TestTriggerMetrics(); RefPtr<PRDDChild::TestTriggerMetricsPromise> TestTriggerMetrics();
private: private:
bool IsRDDProcessLaunching(); bool IsRDDProcessLaunching() const;
bool IsRDDProcessDestroyed() const; bool IsRDDProcessAlive() const;
bool CreateVideoBridge(); bool CreateVideoBridge();
// Called from our xpcom-shutdown observer. // Called from our xpcom-shutdown observer.

View file

@ -1245,7 +1245,7 @@ already_AddRefed<mozilla::MediaByteBuffer> H265::ExtractHVCCExtraData(
// If we encounter SPS with the same id but different content, we will stop // If we encounter SPS with the same id but different content, we will stop
// attempting to detect duplicates. // attempting to detect duplicates.
bool checkDuplicate = true; bool checkDuplicate = true;
const H265SPS* firstSPS = nullptr; Maybe<uint8_t> firstSPSId;
RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer; RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer;
while (reader.Remaining() > nalLenSize) { while (reader.Remaining() > nalLenSize) {
@ -1305,8 +1305,8 @@ already_AddRefed<mozilla::MediaByteBuffer> H265::ExtractHVCCExtraData(
} else { } else {
spsRefTable[spsId] = Some(sps); spsRefTable[spsId] = Some(sps);
nalusMap.LookupOrInsert(nalu.mNalUnitType).AppendElement(nalu); nalusMap.LookupOrInsert(nalu.mNalUnitType).AppendElement(nalu);
if (!firstSPS) { if (!firstSPSId) {
firstSPS = spsRefTable[spsId].ptr(); firstSPSId.emplace(spsId);
} }
} }
} else if (nalu.IsVPS() || nalu.IsPPS()) { } else if (nalu.IsVPS() || nalu.IsPPS()) {
@ -1322,8 +1322,10 @@ already_AddRefed<mozilla::MediaByteBuffer> H265::ExtractHVCCExtraData(
spsEntry ? spsEntry.Data().Length() : 0, spsEntry ? spsEntry.Data().Length() : 0,
vpsEntry ? vpsEntry.Data().Length() : 0, vpsEntry ? vpsEntry.Data().Length() : 0,
ppsEntry ? ppsEntry.Data().Length() : 0); ppsEntry ? ppsEntry.Data().Length() : 0);
if (firstSPS) { if (firstSPSId) {
BitWriter writer(extradata); BitWriter writer(extradata);
const H265SPS* firstSPS = spsRefTable[*firstSPSId].ptr();
MOZ_ASSERT(firstSPS);
// ISO/IEC 14496-15, HEVCDecoderConfigurationRecord. // ISO/IEC 14496-15, HEVCDecoderConfigurationRecord.
writer.WriteBits(1, 8); // version writer.WriteBits(1, 8); // version

View file

@ -336,7 +336,9 @@ void CallbackHelper::OnCaptureEnded() {
nsIEventTarget* target = mParent->GetBackgroundEventTarget(); nsIEventTarget* target = mParent->GetBackgroundEventTarget();
MOZ_ALWAYS_SUCCEEDS(target->Dispatch(NS_NewRunnableFunction( MOZ_ALWAYS_SUCCEEDS(target->Dispatch(NS_NewRunnableFunction(
__func__, [&] { Unused << mParent->SendCaptureEnded(mStreamId); }))); __func__, [parent = RefPtr(mParent), id = mStreamId] {
Unused << parent->SendCaptureEnded(id);
})));
} }
void CallbackHelper::OnFrame(const webrtc::VideoFrame& aVideoFrame) { void CallbackHelper::OnFrame(const webrtc::VideoFrame& aVideoFrame) {

View file

@ -313,7 +313,7 @@ def main():
args = parser.parse_args() args = parser.parse_args()
if args.plugin == "openh264": if args.plugin == "openh264":
url_base = "http://ciscobinary.openh264.org" url_base = "https://ciscobinary.openh264.org"
if args.version is None or args.revision is None: if args.version is None or args.revision is None:
parser.error("openh264 requires version and revision") parser.error("openh264 requires version and revision")
elif args.plugin == "widevine": elif args.plugin == "widevine":

View file

@ -12,8 +12,21 @@
#include "js/ArrayBuffer.h" #include "js/ArrayBuffer.h"
namespace mozilla::dom { namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_WITH_JS_MEMBERS(RTCEncodedFrameBase, (mGlobal),
(mData)) NS_IMPL_CYCLE_COLLECTION_CLASS(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(RTCEncodedFrameBase)
using ::ImplCycleCollectionUnlink;
tmp->DetachData();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBERS(mData)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(RTCEncodedFrameBase) NS_IMPL_CYCLE_COLLECTING_ADDREF(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(RTCEncodedFrameBase) NS_IMPL_CYCLE_COLLECTING_RELEASE(RTCEncodedFrameBase)
@ -39,11 +52,27 @@ RTCEncodedFrameBase::RTCEncodedFrameBase(
jsapi.cx(), mFrame->GetData().size(), (void*)(mFrame->GetData().data())); jsapi.cx(), mFrame->GetData().size(), (void*)(mFrame->GetData().data()));
} }
RTCEncodedFrameBase::~RTCEncodedFrameBase() = default; RTCEncodedFrameBase::~RTCEncodedFrameBase() { DetachData(); }
void RTCEncodedFrameBase::DetachData() {
// We might have handled this in unlink already
if (mGlobal) {
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
return;
}
JS::Rooted<JSObject*> rootedData(jsapi.cx(), mData);
if (rootedData) {
JS::DetachArrayBuffer(jsapi.cx(), rootedData);
}
}
}
unsigned long RTCEncodedFrameBase::Timestamp() const { return mTimestamp; } unsigned long RTCEncodedFrameBase::Timestamp() const { return mTimestamp; }
void RTCEncodedFrameBase::SetData(const ArrayBuffer& aData) { void RTCEncodedFrameBase::SetData(const ArrayBuffer& aData) {
DetachData();
mData.set(aData.Obj()); mData.set(aData.Obj());
if (mFrame) { if (mFrame) {
aData.ProcessData([&](const Span<uint8_t>& aData, JS::AutoCheckCannotGC&&) { aData.ProcessData([&](const Span<uint8_t>& aData, JS::AutoCheckCannotGC&&) {
@ -61,12 +90,7 @@ uint64_t RTCEncodedFrameBase::GetCounter() const { return mCounter; }
std::unique_ptr<webrtc::TransformableFrameInterface> std::unique_ptr<webrtc::TransformableFrameInterface>
RTCEncodedFrameBase::TakeFrame() { RTCEncodedFrameBase::TakeFrame() {
AutoJSAPI jsapi; DetachData();
if (!jsapi.Init(mGlobal)) {
MOZ_CRASH("Could not init JSAPI!");
}
JS::Rooted<JSObject*> rootedData(jsapi.cx(), mData);
JS::DetachArrayBuffer(jsapi.cx(), rootedData);
return std::move(mFrame); return std::move(mFrame);
} }

View file

@ -47,6 +47,8 @@ class RTCEncodedFrameBase : public nsISupports, public nsWrapperCache {
protected: protected:
virtual ~RTCEncodedFrameBase(); virtual ~RTCEncodedFrameBase();
void DetachData();
RefPtr<nsIGlobalObject> mGlobal; RefPtr<nsIGlobalObject> mGlobal;
std::unique_ptr<webrtc::TransformableFrameInterface> mFrame; std::unique_ptr<webrtc::TransformableFrameInterface> mFrame;
const uint64_t mCounter = 0; const uint64_t mCounter = 0;

View file

@ -145,6 +145,9 @@ NotificationPermissionRequest::Run() {
PermissionCheckPurpose::PermissionRequest, PermissionCheckPurpose::PermissionRequest,
mWindow->GetExtantDoc())) { mWindow->GetExtantDoc())) {
mPermission = NotificationPermission::Denied; mPermission = NotificationPermission::Denied;
} else if (!StaticPrefs::dom_webnotifications_allowcrossoriginiframe() &&
!mPrincipal->Subsumes(mTopLevelPrincipal)) {
mPermission = NotificationPermission::Denied;
} }
// We can't call ShowPrompt() directly here since our logic for determining // We can't call ShowPrompt() directly here since our logic for determining

View file

@ -95,7 +95,8 @@ bool IsNotificationForbiddenFor(nsIPrincipal* aPrincipal,
if (outForeignByAncestorContext) { if (outForeignByAncestorContext) {
// nested first party // nested first party
ReportTelemetry(GleanLabel::eNestedFirstParty, aPurpose); ReportTelemetry(GleanLabel::eNestedFirstParty, aPurpose);
return false; return StaticPrefs::
dom_webnotifications_forbid_nested_first_party_enabled();
} }
// third party // third party

View file

@ -50,10 +50,26 @@ PermissionStatusSink::Init() {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
mWorkerRef = WeakWorkerRef::Create( RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
workerPrivate, [self = RefPtr(this)] { self->Disentangle(); }); workerPrivate, "PermissionStatusSink",
[self = RefPtr(this)]() { self->Disentangle(); });
if (NS_WARN_IF(!workerRef)) {
// If WorkerRef creation fails, the Worker has started shutting down. But
// we are on the Worker thread, promise handlers in
// PermissionStatus::Init()/Permissions::Query() can still be dispatched
// to the Worker thread for outer promise rejection.
return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
;
}
mWorkerRef = new ThreadSafeWorkerRef(workerRef);
} }
// On the Worker thread, so the below async function must be executed before
// WorkerRef callback which should also be on the Worker thread. So the above
// created WorkerRef should protect the outer promise handling can be
// dispatched on the Worker thread.
return InvokeAsync(GetMainThreadSerialEventTarget(), __func__, return InvokeAsync(GetMainThreadSerialEventTarget(), __func__,
[self = RefPtr(this)] { [self = RefPtr(this)] {
MOZ_ASSERT(!self->mObserver); MOZ_ASSERT(!self->mObserver);
@ -101,6 +117,17 @@ bool PermissionStatusSink::MaybeUpdatedByNotifyOnlyOnMainThread(
void PermissionStatusSink::PermissionChangedOnMainThread() { void PermissionStatusSink::PermissionChangedOnMainThread() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
// Nothing to do if Worker had shutted down.
if (!mSerialEventTarget->IsOnCurrentThread()) {
MutexAutoLock lock(mMutex);
if (!mWorkerRef) {
return;
}
}
// mWorkerRef is not nullptr, it will protect the promise handling can be
// dispatched to the Worker thread, even though the Worker starts shutdown,
// because mWorkerRef is nullify on the main thread.
ComputeStateOnMainThread()->Then( ComputeStateOnMainThread()->Then(
mSerialEventTarget, __func__, mSerialEventTarget, __func__,
[self = RefPtr(this)]( [self = RefPtr(this)](
@ -116,17 +143,16 @@ void PermissionStatusSink::Disentangle() {
mPermissionStatus = nullptr; mPermissionStatus = nullptr;
{
MutexAutoLock lock(mMutex);
mWorkerRef = nullptr;
}
NS_DispatchToMainThread( NS_DispatchToMainThread(
NS_NewRunnableFunction(__func__, [self = RefPtr(this)] { NS_NewRunnableFunction(__func__, [self = RefPtr(this)] {
if (self->mObserver) { if (self->mObserver) {
self->mObserver->RemoveSink(self); self->mObserver->RemoveSink(self);
self->mObserver = nullptr; self->mObserver = nullptr;
} }
{
MutexAutoLock lock(self->mMutex);
self->mWorkerRef = nullptr;
}
})); }));
} }
@ -166,7 +192,7 @@ PermissionStatusSink::ComputeStateOnMainThread() {
// If we have mWorkerRef, we haven't received the WorkerRef notification // If we have mWorkerRef, we haven't received the WorkerRef notification
// yet. // yet.
WorkerPrivate* workerPrivate = mWorkerRef->GetUnsafePrivate(); WorkerPrivate* workerPrivate = mWorkerRef->Private();
MOZ_ASSERT(workerPrivate); MOZ_ASSERT(workerPrivate);
ancestorWindow = workerPrivate->GetAncestorWindow(); ancestorWindow = workerPrivate->GetAncestorWindow();

View file

@ -19,7 +19,7 @@ namespace mozilla::dom {
class PermissionObserver; class PermissionObserver;
class PermissionStatus; class PermissionStatus;
class WeakWorkerRef; class ThreadSafeWorkerRef;
class PermissionStatusSink { class PermissionStatusSink {
public: public:
@ -70,7 +70,7 @@ class PermissionStatusSink {
// Protected by mutex. // Protected by mutex.
// Created and released on worker-thread. Used also on main-thread. // Created and released on worker-thread. Used also on main-thread.
RefPtr<WeakWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex); RefPtr<ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex);
PermissionName mPermissionName; PermissionName mPermissionName;
nsCString mPermissionType; nsCString mPermissionType;

View file

@ -4018,6 +4018,10 @@ void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
return; return;
} }
if (!mDocument) {
return;
}
bool isScript = !aRequest->IsModuleRequest(); bool isScript = !aRequest->IsModuleRequest();
const char* message; const char* message;
if (aResult == NS_ERROR_MALFORMED_URI) { if (aResult == NS_ERROR_MALFORMED_URI) {
@ -4066,6 +4070,9 @@ void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
void ScriptLoader::ReportWarningToConsole( void ScriptLoader::ReportWarningToConsole(
ScriptLoadRequest* aRequest, const char* aMessageName, ScriptLoadRequest* aRequest, const char* aMessageName,
const nsTArray<nsString>& aParams) const { const nsTArray<nsString>& aParams) const {
if (!mDocument) {
return;
}
uint32_t lineNo = aRequest->GetScriptLoadContext()->GetScriptLineNumber(); uint32_t lineNo = aRequest->GetScriptLoadContext()->GetScriptLineNumber();
JS::ColumnNumberOneOrigin columnNo = JS::ColumnNumberOneOrigin columnNo =
aRequest->GetScriptLoadContext()->GetScriptColumnNumber(); aRequest->GetScriptLoadContext()->GetScriptColumnNumber();

View file

@ -236,6 +236,8 @@ bool IsSameSite(nsIChannel* aHTTPChannel) {
// Helper function to determine whether a request was triggered // Helper function to determine whether a request was triggered
// by the end user in the context of SecFetch. // by the end user in the context of SecFetch.
// The more secure/closed state to return for this function is "false".
// A user triggered action is less restricted because it is not cross-origin.
bool IsUserTriggeredForSecFetchSite(nsIHttpChannel* aHTTPChannel) { bool IsUserTriggeredForSecFetchSite(nsIHttpChannel* aHTTPChannel) {
/* /*
* The goal is to distinguish between "webby" navigations that are controlled * The goal is to distinguish between "webby" navigations that are controlled
@ -247,8 +249,7 @@ bool IsUserTriggeredForSecFetchSite(nsIHttpChannel* aHTTPChannel) {
ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType(); ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
// A request issued by the browser is always user initiated. // A request issued by the browser is always user initiated.
if (loadInfo->TriggeringPrincipal()->IsSystemPrincipal() && if (loadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
contentType == ExtContentPolicy::TYPE_OTHER) {
return true; return true;
} }
@ -283,12 +284,12 @@ bool IsUserTriggeredForSecFetchSite(nsIHttpChannel* aHTTPChannel) {
if (referrerInfo) { if (referrerInfo) {
nsCOMPtr<nsIURI> originalReferrer; nsCOMPtr<nsIURI> originalReferrer;
referrerInfo->GetOriginalReferrer(getter_AddRefs(originalReferrer)); referrerInfo->GetOriginalReferrer(getter_AddRefs(originalReferrer));
if (originalReferrer) { if (!originalReferrer) {
return false; return true;
} }
} }
return true; return false;
} }
void mozilla::dom::SecFetch::AddSecFetchDest(nsIHttpChannel* aHTTPChannel) { void mozilla::dom::SecFetch::AddSecFetchDest(nsIHttpChannel* aHTTPChannel) {

View file

@ -54,6 +54,13 @@ WebAuthnRegisterResult::GetAttestationObject(
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
WebAuthnRegisterResult::GetAttestationConsentPromptShown(
bool* aAttestationConsentPromptShown) {
*aAttestationConsentPromptShown = mAttestationConsentPromptShown;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
WebAuthnRegisterResult::GetCredentialId(nsTArray<uint8_t>& aCredentialId) { WebAuthnRegisterResult::GetCredentialId(nsTArray<uint8_t>& aCredentialId) {
aCredentialId.Assign(mCredentialId); aCredentialId.Assign(mCredentialId);

View file

@ -38,7 +38,8 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
const Maybe<bool>& aPrfSupported, const Maybe<bool>& aPrfSupported,
const Maybe<nsTArray<uint8_t>>& aPrfFirst, const Maybe<nsTArray<uint8_t>>& aPrfFirst,
const Maybe<nsTArray<uint8_t>>& aPrfSecond) const Maybe<nsTArray<uint8_t>>& aPrfSecond)
: mClientDataJSON(aClientDataJSON), : mAttestationConsentPromptShown(false),
mClientDataJSON(aClientDataJSON),
mCredPropsRk(Nothing()), mCredPropsRk(Nothing()),
mAuthenticatorAttachment(aAuthenticatorAttachment), mAuthenticatorAttachment(aAuthenticatorAttachment),
mLargeBlobSupported(aLargeBlobSupported), mLargeBlobSupported(aLargeBlobSupported),
@ -63,6 +64,7 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
reinterpret_cast<uint8_t*>( reinterpret_cast<uint8_t*>(
aResponse->AttestationObject()->GetElements().Elements()), aResponse->AttestationObject()->GetElements().Elements()),
aResponse->AttestationObject()->Length()); aResponse->AttestationObject()->Length());
mAttestationConsentPromptShown = false;
if (aResponse->ClientDataJson()) { if (aResponse->ClientDataJson()) {
mClientDataJSON = Some(nsAutoCString( mClientDataJSON = Some(nsAutoCString(
reinterpret_cast<const char*>( reinterpret_cast<const char*>(
@ -92,6 +94,7 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
mAttestationObject.AppendElements(aResponse->pbAttestationObject, mAttestationObject.AppendElements(aResponse->pbAttestationObject,
aResponse->cbAttestationObject); aResponse->cbAttestationObject);
mAttestationConsentPromptShown = true;
nsTArray<WebAuthnExtensionResult> extensions; nsTArray<WebAuthnExtensionResult> extensions;
if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2) { if (aResponse->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2) {
@ -166,6 +169,7 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
~WebAuthnRegisterResult() = default; ~WebAuthnRegisterResult() = default;
nsTArray<uint8_t> mAttestationObject; nsTArray<uint8_t> mAttestationObject;
bool mAttestationConsentPromptShown;
nsTArray<uint8_t> mCredentialId; nsTArray<uint8_t> mCredentialId;
nsTArray<nsString> mTransports; nsTArray<nsString> mTransports;
Maybe<nsCString> mClientDataJSON; Maybe<nsCString> mClientDataJSON;

View file

@ -31,14 +31,12 @@ void WebAuthnService::ShowAttestationConsentPrompt(
NS_NewRunnableFunction(__func__, [self, aTransactionId]() { NS_NewRunnableFunction(__func__, [self, aTransactionId]() {
self->SetHasAttestationConsent( self->SetHasAttestationConsent(
aTransactionId, aTransactionId,
StaticPrefs:: StaticPrefs::security_webauthn_always_allow_direct_attestation());
security_webauth_webauthn_testing_allow_direct_attestation());
})); }));
#else #else
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction( nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
__func__, [self, aOrigin, aTransactionId, aBrowsingContextId]() { __func__, [self, aOrigin, aTransactionId, aBrowsingContextId]() {
if (StaticPrefs:: if (StaticPrefs::security_webauthn_always_allow_direct_attestation()) {
security_webauth_webauthn_testing_allow_direct_attestation()) {
self->SetHasAttestationConsent(aTransactionId, true); self->SetHasAttestationConsent(aTransactionId, true);
return; return;
} }
@ -115,10 +113,18 @@ WebAuthnService::MakeCredential(uint64_t aTransactionId,
} }
nsIWebAuthnRegisterResult* result = aValue.ResolveValue(); nsIWebAuthnRegisterResult* result = aValue.ResolveValue();
// If the RP requested attestation, we need to show a consent prompt // We can return whatever result we have if the authenticator
// before returning any identifying information. The platform may // handled attestation consent for us.
// have already done this for us, so we need to inspect the bool attestationConsentPromptShown = false;
// attestation object at this point. Unused << result->GetAttestationConsentPromptShown(
&attestationConsentPromptShown);
if (attestationConsentPromptShown) {
guard->ref().parentRegisterPromise.ref()->Resolve(result);
guard->reset();
return;
}
// If the RP requested attestation and the response contains
// identifying information, then we need to show a consent prompt.
bool resultIsIdentifying = true; bool resultIsIdentifying = true;
Unused << result->HasIdentifyingAttestation(&resultIsIdentifying); Unused << result->HasIdentifyingAttestation(&resultIsIdentifying);
if (attestationRequested && resultIsIdentifying) { if (attestationRequested && resultIsIdentifying) {
@ -127,6 +133,7 @@ WebAuthnService::MakeCredential(uint64_t aTransactionId,
aBrowsingContextId); aBrowsingContextId);
return; return;
} }
// In all other cases we strip out identifying information.
result->Anonymize(); result->Anonymize();
guard->ref().parentRegisterPromise.ref()->Resolve(result); guard->ref().parentRegisterPromise.ref()->Resolve(result);
guard->reset(); guard->reset();

View file

@ -185,6 +185,11 @@ impl WebAuthnRegisterResult {
Ok(out) Ok(out)
} }
xpcom_method!(get_attestation_consent_prompt_shown => GetAttestationConsentPromptShown() -> bool);
fn get_attestation_consent_prompt_shown(&self) -> Result<bool, nsresult> {
Ok(false)
}
xpcom_method!(get_credential_id => GetCredentialId() -> ThinVec<u8>); xpcom_method!(get_credential_id => GetCredentialId() -> ThinVec<u8>);
fn get_credential_id(&self) -> Result<ThinVec<u8>, nsresult> { fn get_credential_id(&self) -> Result<ThinVec<u8>, nsresult> {
let Some(credential_data) = &self.result.borrow().att_obj.auth_data.credential_data else { let Some(credential_data) = &self.result.borrow().att_obj.auth_data.credential_data else {

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