Update On Fri Apr 18 20:22:15 CEST 2025
This commit is contained in:
parent
9c69112ad3
commit
a4d062ffa7
3571 changed files with 182119 additions and 66740 deletions
187
Cargo.lock
generated
187
Cargo.lock
generated
|
@ -1792,7 +1792,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "error-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"error-support-macros",
|
||||
"lazy_static",
|
||||
|
@ -1804,7 +1804,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "error-support-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1921,7 +1921,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "firefox-versioning"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"thiserror 1.999.999",
|
||||
|
@ -2501,7 +2501,7 @@ dependencies = [
|
|||
"qcms",
|
||||
"rsdparsa_capi",
|
||||
"rure",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"rust_minidump_writer_linux",
|
||||
"signature_cache",
|
||||
"static_prefs",
|
||||
|
@ -2524,7 +2524,6 @@ dependencies = [
|
|||
name = "gkrust-uniffi-components"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.2",
|
||||
"relevancy",
|
||||
"search",
|
||||
"suggest",
|
||||
|
@ -2829,11 +2828,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
|
||||
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
|
||||
dependencies = [
|
||||
"hashbrown 0.14.999",
|
||||
"hashbrown 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3234,11 +3233,11 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "interrupt-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"uniffi",
|
||||
]
|
||||
|
||||
|
@ -3424,7 +3423,7 @@ dependencies = [
|
|||
"nserror",
|
||||
"nsstring",
|
||||
"rkv",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"storage_variant",
|
||||
|
@ -3440,7 +3439,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"kvstore",
|
||||
"moz_task",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
|
@ -3563,9 +3562,9 @@ checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
|
|||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.28.0"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
|
||||
checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
|
@ -4205,7 +4204,7 @@ dependencies = [
|
|||
"maybe-async",
|
||||
"mls-rs-core",
|
||||
"rand",
|
||||
"rusqlite",
|
||||
"rusqlite 0.31.999",
|
||||
"thiserror 1.999.999",
|
||||
"zeroize",
|
||||
]
|
||||
|
@ -4220,7 +4219,7 @@ dependencies = [
|
|||
"nserror",
|
||||
"nss-gk-api",
|
||||
"nsstring",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"static_prefs",
|
||||
"thin-vec",
|
||||
"xpcom",
|
||||
|
@ -4497,8 +4496,8 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
|||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "24.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109#a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=f1c496523ff0aa10c162fd01ad606960e925a5a4#f1c496523ff0aa10c162fd01ad606960e925a5a4"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
|
@ -4511,18 +4510,19 @@ dependencies = [
|
|||
"indexmap",
|
||||
"log",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"rustc-hash 1.999.999",
|
||||
"serde",
|
||||
"spirv",
|
||||
"strum",
|
||||
"strum 0.26.999",
|
||||
"thiserror 2.0.9",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "neqo-bin"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
|
@ -4543,35 +4543,38 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-common"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"env_logger",
|
||||
"log",
|
||||
"qlog",
|
||||
"strum 0.26.999",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "neqo-crypto"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"bindgen 0.69.4",
|
||||
"enum-map",
|
||||
"log",
|
||||
"mozbuild",
|
||||
"neqo-common",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"strum 0.26.999",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "neqo-http3"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"enumset",
|
||||
"log",
|
||||
|
@ -4581,13 +4584,14 @@ dependencies = [
|
|||
"neqo-transport",
|
||||
"qlog",
|
||||
"sfv",
|
||||
"strum 0.26.999",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "neqo-qpack"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"log",
|
||||
"neqo-common",
|
||||
|
@ -4598,10 +4602,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "neqo-transport"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"enumset",
|
||||
"indexmap",
|
||||
"log",
|
||||
"mtu",
|
||||
|
@ -4610,12 +4615,13 @@ dependencies = [
|
|||
"qlog",
|
||||
"smallvec",
|
||||
"static_assertions",
|
||||
"strum 0.26.999",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "neqo-udp"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.12.2#f8946d5187271b3e63e8d0209343510bdeac1451"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/mozilla/neqo?tag=v0.13.1#0a356afeb45631036df6b3028951a02d16fa8d27"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"log",
|
||||
|
@ -4874,13 +4880,11 @@ dependencies = [
|
|||
"android_logger",
|
||||
"byteorder",
|
||||
"core-foundation 0.9.999",
|
||||
"digest",
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
"libloading",
|
||||
"log",
|
||||
"pkcs11-bindings",
|
||||
"rand",
|
||||
"rsclientcerts",
|
||||
"sha2",
|
||||
"static_prefs",
|
||||
|
@ -4940,7 +4944,7 @@ checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
|||
[[package]]
|
||||
name = "payload-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
@ -5283,12 +5287,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "qlog"
|
||||
version = "0.13.0"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b5f65b920fa913ce92267bb3c4ed3b9c2f81d05f8e1376c3bbc95455eedb7df"
|
||||
checksum = "0f15b83c59e6b945f2261c95a1dd9faf239187f32ff0a96af1d1d28c4557f919"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"smallvec",
|
||||
|
@ -5302,9 +5305,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|||
|
||||
[[package]]
|
||||
name = "quinn-udp"
|
||||
version = "0.5.10"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944"
|
||||
checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
|
@ -5444,7 +5447,7 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|||
[[package]]
|
||||
name = "relevancy"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.21.999",
|
||||
|
@ -5456,7 +5459,7 @@ dependencies = [
|
|||
"rand",
|
||||
"rand_distr",
|
||||
"remote_settings",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
|
@ -5469,7 +5472,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "remote_settings"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
|
@ -5479,7 +5482,7 @@ dependencies = [
|
|||
"log",
|
||||
"parking_lot",
|
||||
"regex",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
|
@ -5600,9 +5603,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.9.0"
|
||||
version = "0.9.999"
|
||||
dependencies = [
|
||||
"ron 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63f3aa105dea217ef30d89581b65a4d527a19afc95ef5750be3890e8d3c5b837"
|
||||
checksum = "beceb6f7bf81c73e73aeef6dd1356d9a1b2b4909e1f0fc3e59b034f9572d7b7f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.9.0",
|
||||
|
@ -5616,8 +5626,11 @@ name = "rsclientcerts"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"digest",
|
||||
"gecko-profiler",
|
||||
"pkcs11-bindings",
|
||||
"rand",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5646,9 +5659,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.31.0"
|
||||
version = "0.31.999"
|
||||
dependencies = [
|
||||
"rusqlite 0.33.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
|
||||
checksum = "1c6d5e5acb6f6129fe3f7ba0a7fc77bca1942cb568535e18e7bc40262baf3110"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"fallible-iterator",
|
||||
|
@ -5800,7 +5820,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "search"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"error-support",
|
||||
"firefox-versioning",
|
||||
|
@ -6091,13 +6111,13 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sql-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"interrupt-support",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"parking_lot",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"tempfile",
|
||||
"thiserror 1.999.999",
|
||||
]
|
||||
|
@ -6167,18 +6187,25 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.3"
|
||||
version = "0.26.999"
|
||||
dependencies = [
|
||||
"strum 0.27.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.26.4"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||
checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
@ -6290,7 +6317,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
|||
[[package]]
|
||||
name = "suggest"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
@ -6302,7 +6329,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"remote_settings",
|
||||
"rmp-serde",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sql-support",
|
||||
|
@ -6342,18 +6369,18 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sync-guid"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"base64 0.21.999",
|
||||
"rand",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync15"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
@ -6393,7 +6420,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "tabs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
@ -6401,7 +6428,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"log",
|
||||
"payload-support",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
@ -6737,9 +6764,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
|||
[[package]]
|
||||
name = "types"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
@ -7119,7 +7146,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
[[package]]
|
||||
name = "viaduct"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"log",
|
||||
|
@ -7289,7 +7316,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webext-storage"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8e84c588a5cc2686973c5026ecd240d6275d7e94#8e84c588a5cc2686973c5026ecd240d6275d7e94"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6a007c98292fa72965d36389ce32d7609e399217#6a007c98292fa72965d36389ce32d7609e399217"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
@ -7298,7 +7325,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"log",
|
||||
"parking_lot",
|
||||
"rusqlite",
|
||||
"rusqlite 0.33.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
@ -7334,7 +7361,7 @@ dependencies = [
|
|||
"peek-poke",
|
||||
"plane-split",
|
||||
"rayon",
|
||||
"ron",
|
||||
"ron 0.10.1",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"svg_fmt",
|
||||
|
@ -7427,8 +7454,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "24.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109#a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=f1c496523ff0aa10c162fd01ad606960e925a5a4#f1c496523ff0aa10c162fd01ad606960e925a5a4"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
|
@ -7444,7 +7471,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"ron",
|
||||
"ron 0.9.999",
|
||||
"rustc-hash 1.999.999",
|
||||
"serde",
|
||||
"smallvec",
|
||||
|
@ -7457,24 +7484,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-core-deps-apple"
|
||||
version = "24.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109#a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=f1c496523ff0aa10c162fd01ad606960e925a5a4#f1c496523ff0aa10c162fd01ad606960e925a5a4"
|
||||
dependencies = [
|
||||
"wgpu-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core-deps-windows-linux-android"
|
||||
version = "24.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109#a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=f1c496523ff0aa10c162fd01ad606960e925a5a4#f1c496523ff0aa10c162fd01ad606960e925a5a4"
|
||||
dependencies = [
|
||||
"wgpu-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "24.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109#a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=f1c496523ff0aa10c162fd01ad606960e925a5a4#f1c496523ff0aa10c162fd01ad606960e925a5a4"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"arrayvec",
|
||||
|
@ -7509,8 +7536,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "24.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109#a0dbe5ebc6fa24422fb84b2e0fea1cc94dee5109"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=f1c496523ff0aa10c162fd01ad606960e925a5a4#f1c496523ff0aa10c162fd01ad606960e925a5a4"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bytemuck",
|
||||
|
|
30
Cargo.toml
30
Cargo.toml
|
@ -65,7 +65,7 @@ rust-version = "1.82.0"
|
|||
uniffi = "0.29.1"
|
||||
uniffi_bindgen = "0.29.1"
|
||||
# Shared across multiple application-services consumers.
|
||||
rusqlite = "0.31.0"
|
||||
rusqlite = "0.33.0"
|
||||
# Shared across multiple glean consumers.
|
||||
glean = "=64.0.1"
|
||||
|
||||
|
@ -204,13 +204,21 @@ web-sys = { path = "build/rust/dummy-web/web-sys" }
|
|||
|
||||
# Upgrade `core-foundation` 0.9.* to 0.10.
|
||||
core-foundation = { path = "build/rust/core-foundation" }
|
||||
|
||||
# Patch `core-graphics-types` 0.1.* to 0.2.
|
||||
core-graphics-types = { path = "build/rust/core-graphics-types" }
|
||||
|
||||
# Patch `half` 1.* to 2.
|
||||
half = { path = "build/rust/half" }
|
||||
|
||||
# Upgrade `rusqlite` 0.31 to 0.33.
|
||||
rusqlite = { path = "build/rust/rusqlite" }
|
||||
|
||||
# Patch `ron` 0.9.* to 0.10.
|
||||
ron = { path = "build/rust/ron" }
|
||||
|
||||
# Patch `strum` 0.26.* to 0.27.
|
||||
strum = { path = "build/rust/strum" }
|
||||
|
||||
# Overrides to allow easier use of common internal crates.
|
||||
moz_asserts = { path = "mozglue/static/rust/moz_asserts" }
|
||||
|
||||
|
@ -251,14 +259,14 @@ malloc_size_of_derive = { path = "xpcom/rust/malloc_size_of_derive" }
|
|||
objc = { git = "https://github.com/glandium/rust-objc", rev = "4de89f5aa9851ceca4d40e7ac1e2759410c04324" }
|
||||
|
||||
# application-services overrides to make updating them all simpler.
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
relevancy = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
search = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
suggest = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "8e84c588a5cc2686973c5026ecd240d6275d7e94" }
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
relevancy = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
search = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
suggest = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "6a007c98292fa72965d36389ce32d7609e399217" }
|
||||
|
||||
allocator-api2 = { path = "third_party/rust/allocator-api2" }
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
#include "States.h"
|
||||
|
||||
#include "nsAttrName.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
|
||||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#include "nsUnicharUtils.h"
|
||||
|
@ -1602,11 +1604,27 @@ uint8_t aria::AttrCharacteristicsFor(nsAtom* aAtom) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool aria::HasDefinedARIAHidden(nsIContent* aContent) {
|
||||
bool aria::IsValidARIAHidden(nsIContent* aContent) {
|
||||
return aContent && aContent->IsElement() &&
|
||||
nsAccUtils::ARIAAttrValueIs(aContent->AsElement(),
|
||||
nsGkAtoms::aria_hidden, nsGkAtoms::_true,
|
||||
eCaseMatters);
|
||||
eCaseMatters) &&
|
||||
!ShouldIgnoreARIAHidden(aContent);
|
||||
}
|
||||
|
||||
bool aria::ShouldIgnoreARIAHidden(nsIContent* aContent) {
|
||||
if (!aContent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dom::Document* doc = aContent->OwnerDoc();
|
||||
bool isValidElementType = (aContent == doc->GetDocumentElement());
|
||||
|
||||
if (auto docBody = doc->GetBody()) {
|
||||
isValidElementType |= (aContent == docBody->AsContent());
|
||||
}
|
||||
|
||||
return isValidElementType && doc->IsTopLevelContentDocument();
|
||||
}
|
||||
|
||||
const nsRoleMapEntry* aria::GetRoleMap(const nsStaticAtom* aAriaRole) {
|
||||
|
|
|
@ -305,9 +305,16 @@ uint64_t UniversalStatesFor(dom::Element* aElement);
|
|||
uint8_t AttrCharacteristicsFor(nsAtom* aAtom);
|
||||
|
||||
/**
|
||||
* Return true if the element has defined aria-hidden.
|
||||
* Return true if the element has defined aria-hidden
|
||||
* and should not be ignored per ShouldIgnoreARIAHidden.
|
||||
*/
|
||||
bool HasDefinedARIAHidden(nsIContent* aContent);
|
||||
bool IsValidARIAHidden(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Return true if the element should render its subtree
|
||||
* regardless of the presence of aria-hidden.
|
||||
*/
|
||||
bool ShouldIgnoreARIAHidden(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Get the role map entry for a given ARIA role.
|
||||
|
|
|
@ -43,6 +43,11 @@ bool RequestDomainsIfInactive(uint64_t aRequiredCacheDomains) {
|
|||
const bool isMissingRequiredCacheDomain =
|
||||
(aRequiredCacheDomains & ~activeCacheDomains) != 0;
|
||||
if (isMissingRequiredCacheDomain) {
|
||||
if (!accService->ShouldAllowNewCacheDomains()) {
|
||||
// Return true to indicate that the domain is not active, but don't
|
||||
// actually request it.
|
||||
return true;
|
||||
}
|
||||
aRequiredCacheDomains = GetCacheDomainSuperset(aRequiredCacheDomains);
|
||||
|
||||
const uint64_t cacheDomains = aRequiredCacheDomains | activeCacheDomains;
|
||||
|
|
|
@ -271,9 +271,11 @@ bool DomainsAreActive(uint64_t aRequiredCacheDomains);
|
|||
// false if all required domains are already active.
|
||||
bool RequestDomainsIfInactive(uint64_t aRequiredCacheDomains);
|
||||
|
||||
#define ASSERT_DOMAINS_ACTIVE(aCacheDomains) \
|
||||
MOZ_ASSERT(DomainsAreActive(aCacheDomains), \
|
||||
"Required domain(s) are not currently active.")
|
||||
#define ASSERT_DOMAINS_ACTIVE(aCacheDomains) \
|
||||
MOZ_ASSERT( \
|
||||
(GetAccService() && !GetAccService()->ShouldAllowNewCacheDomains()) || \
|
||||
DomainsAreActive(aCacheDomains), \
|
||||
"Required domain(s) are not currently active.")
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -493,7 +493,7 @@ void NotificationController::ScheduleProcessing() {
|
|||
// NotificationCollector: protected
|
||||
|
||||
bool NotificationController::IsUpdatePending() {
|
||||
return mPresShell->ObservingStyleFlushes() ||
|
||||
return mPresShell->NeedStyleFlush() || mPresShell->NeedLayoutFlush() ||
|
||||
mObservingState == eRefreshProcessingForUpdate || WaitingForParent() ||
|
||||
mContentInsertions.Count() != 0 || mNotifications.Length() != 0 ||
|
||||
!mTextArray.IsEmpty() ||
|
||||
|
|
|
@ -8,7 +8,7 @@ import re
|
|||
|
||||
|
||||
def generate(relH, relIdl):
|
||||
input = open(relIdl, "rt").read()
|
||||
input = open(relIdl).read()
|
||||
relations = re.findall(
|
||||
r"const unsigned long RELATION_([A-Z_]+) = ([x0-9a-f]+);", input
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ import re
|
|||
|
||||
|
||||
def generate(roleH, roleIdl):
|
||||
input = open(roleIdl, "rt").read()
|
||||
input = open(roleIdl).read()
|
||||
roles = re.findall(r"const unsigned long ROLE_([A-Z_]+) = (\d+);", input)
|
||||
|
||||
roleH.write(
|
||||
|
|
|
@ -1184,7 +1184,7 @@ LocalAccessible* nsAccessibilityService::CreateAccessible(
|
|||
if (!aNode->IsContent()) return nullptr;
|
||||
|
||||
nsIContent* content = aNode->AsContent();
|
||||
if (aria::HasDefinedARIAHidden(content)) {
|
||||
if (aria::IsValidARIAHidden(content)) {
|
||||
if (aIsSubtreeHidden) {
|
||||
*aIsSubtreeHidden = true;
|
||||
}
|
||||
|
@ -2096,5 +2096,34 @@ void PrefChanged(const char* aPref, void* aClosure) {
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t CacheDomainActivationBlocker::sEntryCount = 0;
|
||||
|
||||
CacheDomainActivationBlocker::CacheDomainActivationBlocker() {
|
||||
AssertIsOnMainThread();
|
||||
if (sEntryCount++ != 0) {
|
||||
// We're re-entering. This can happen if an earlier event (even in a
|
||||
// different document) ends up calling an XUL method, since that can run
|
||||
// script which can cause other events to fire. Only the outermost usage
|
||||
// should change the flag.
|
||||
return;
|
||||
}
|
||||
if (nsAccessibilityService* service = GetAccService()) {
|
||||
MOZ_ASSERT(service->mShouldAllowNewCacheDomains);
|
||||
service->mShouldAllowNewCacheDomains = false;
|
||||
}
|
||||
}
|
||||
|
||||
CacheDomainActivationBlocker::~CacheDomainActivationBlocker() {
|
||||
AssertIsOnMainThread();
|
||||
if (--sEntryCount != 0) {
|
||||
// Only the outermost usage should change the flag.
|
||||
return;
|
||||
}
|
||||
if (nsAccessibilityService* service = GetAccService()) {
|
||||
MOZ_ASSERT(!service->mShouldAllowNewCacheDomains);
|
||||
service->mShouldAllowNewCacheDomains = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -92,6 +92,23 @@ void PrefChanged(const char* aPref, void* aClosure);
|
|||
*/
|
||||
EPlatformDisabledState ReadPlatformDisabledState();
|
||||
|
||||
/**
|
||||
* RAII class to prevent new cache domains from being requested. This is
|
||||
* necessary in some cases when code for an OS accessibility API requires
|
||||
* information in order to fire an event. We don't necessarily know that a
|
||||
* client is even interested in that event, so requesting data that the client
|
||||
* may never query doesn't make sense.
|
||||
*/
|
||||
class MOZ_RAII CacheDomainActivationBlocker {
|
||||
public:
|
||||
CacheDomainActivationBlocker();
|
||||
~CacheDomainActivationBlocker();
|
||||
|
||||
private:
|
||||
// Used to manage re-entry.
|
||||
static uint32_t sEntryCount;
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -346,6 +363,7 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
|||
};
|
||||
|
||||
static uint64_t GetActiveCacheDomains() { return gCacheDomains; }
|
||||
bool ShouldAllowNewCacheDomains() { return mShouldAllowNewCacheDomains; }
|
||||
|
||||
#if defined(ANDROID)
|
||||
static mozilla::Monitor& GetAndroidMonitor();
|
||||
|
@ -415,6 +433,10 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
|||
* Contains the currently active cache domains.
|
||||
*/
|
||||
static uint64_t gCacheDomains;
|
||||
// True if requesting new cache domains should be allowed, false if this
|
||||
// should be disallowed. This should only be changed by
|
||||
// CacheDomainActivationBlocker.
|
||||
bool mShouldAllowNewCacheDomains = true;
|
||||
|
||||
// Can be weak because all atoms are known static
|
||||
using MarkupMap = nsTHashMap<nsAtom*, const mozilla::a11y::MarkupMapInfo*>;
|
||||
|
@ -450,6 +472,7 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
|||
friend mozilla::a11y::xpcAccessibleApplication*
|
||||
mozilla::a11y::XPCApplicationAcc();
|
||||
friend class xpcAccessibilityService;
|
||||
friend class mozilla::a11y::CacheDomainActivationBlocker;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -862,7 +862,7 @@ void DocAccessible::AttributeChanged(dom::Element* aElement,
|
|||
// Update the accessible tree on aria-hidden change. Make sure to not create
|
||||
// a tree under aria-hidden='true'.
|
||||
if (aAttribute == nsGkAtoms::aria_hidden) {
|
||||
if (aria::HasDefinedARIAHidden(aElement)) {
|
||||
if (aria::IsValidARIAHidden(aElement)) {
|
||||
ContentRemoved(aElement);
|
||||
} else {
|
||||
ContentInserted(aElement, aElement->GetNextSibling());
|
||||
|
@ -1206,7 +1206,7 @@ LocalAccessible* DocAccessible::GetAccessibleOrContainer(
|
|||
for (nsINode* currNode : dom::InclusiveFlatTreeAncestors(*start)) {
|
||||
// No container if is inside of aria-hidden subtree.
|
||||
if (aNoContainerIfPruned && currNode->IsElement() &&
|
||||
aria::HasDefinedARIAHidden(currNode->AsElement())) {
|
||||
aria::IsValidARIAHidden(currNode->AsElement())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,11 @@ prefs = [
|
|||
]
|
||||
|
||||
["browser_atspi_interfaces.js"]
|
||||
|
||||
["browser_groupPosition.js"]
|
||||
|
||||
["browser_prune_children.js"]
|
||||
|
||||
["browser_role.js"]
|
||||
|
||||
["browser_table.js"]
|
||||
|
|
|
@ -31,8 +31,6 @@ skip-if = ["os != 'win'"]
|
|||
|
||||
["browser_scroll_position_domain.js"]
|
||||
|
||||
["browser_text_offset_attributes_domain.js"]
|
||||
|
||||
["browser_state_domain.js"]
|
||||
|
||||
["browser_style_domain.js"]
|
||||
|
@ -43,6 +41,8 @@ skip-if = ["os != 'win'"]
|
|||
|
||||
["browser_text_domain.js"]
|
||||
|
||||
["browser_text_offset_attributes_domain.js"]
|
||||
|
||||
["browser_transform_matrix_domain.js"]
|
||||
|
||||
["browser_value_domain.js"]
|
||||
|
|
|
@ -20,6 +20,7 @@ support-files = [
|
|||
["browser_aria_activedescendant.js"]
|
||||
|
||||
# Caching tests
|
||||
|
||||
["browser_caching_actions.js"]
|
||||
|
||||
["browser_caching_attributes.js"]
|
||||
|
@ -59,6 +60,7 @@ skip-if = ["os != 'win'"]
|
|||
["browser_caching_value.js"]
|
||||
|
||||
# Events tests
|
||||
|
||||
["browser_events_announcement.js"]
|
||||
skip-if = ["os == 'win'"] # Bug 1288839
|
||||
|
||||
|
@ -81,6 +83,7 @@ skip-if = ["os == 'win'"] # Bug 1288839
|
|||
["browser_obj_group_002.js"]
|
||||
|
||||
# Tree update tests
|
||||
|
||||
["browser_treeupdate_ariadialog.js"]
|
||||
|
||||
["browser_treeupdate_ariaowns.js"]
|
||||
|
|
|
@ -6,5 +6,7 @@ support-files = [
|
|||
"!/accessible/tests/mochitest/*.js",
|
||||
"!/accessible/tests/browser/*.mjs",
|
||||
]
|
||||
|
||||
["browser_computedARIARole.js"]
|
||||
|
||||
["browser_minimumRole.js"]
|
||||
|
|
|
@ -351,8 +351,10 @@ function wrapWithIFrame(doc, options = {}) {
|
|||
if (options.contentSetup) {
|
||||
// Hide the body initially so we can ensure that any changes made by
|
||||
// contentSetup are included when the body's content is initially added to
|
||||
// the accessibility tree.
|
||||
iframeDocBodyAttrs["aria-hidden"] = "true";
|
||||
// the accessibility tree. Use `hidden` instead of `aria-hidden` because the
|
||||
// latter is ignored when applied to top level docs/<body> elements and we
|
||||
// want to remain consistent with our handling for non-iframe docs.
|
||||
iframeDocBodyAttrs.hidden = true;
|
||||
}
|
||||
if (options.remoteIframe) {
|
||||
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
||||
|
@ -427,8 +429,9 @@ function snippetToURL(doc, options = {}) {
|
|||
} else if (options.contentSetup) {
|
||||
// Hide the body initially so we can ensure that any changes made by
|
||||
// contentSetup are included when the body's content is initially added to
|
||||
// the accessibility tree.
|
||||
attrs["aria-hidden"] = "true";
|
||||
// the accessibility tree. Use `hidden` instead of `aria-hidden` because the
|
||||
// latter is ignored when applied to top level docs/<body> elements.
|
||||
attrs.hidden = true;
|
||||
}
|
||||
|
||||
const encodedDoc = encodeURIComponent(
|
||||
|
@ -614,13 +617,13 @@ function accessibleTask(doc, task, options = {}) {
|
|||
info("Executing contentSetup");
|
||||
const ready = waitForEvent(EVENT_REORDER, currentContentDoc());
|
||||
await invokeContentTask(browser, [], options.contentSetup);
|
||||
// snippetToURL set aria-hidden on the body. We now Remove aria-hidden
|
||||
// snippetToURL set hidden on the body. We now Remove hidden
|
||||
// and wait for a reorder on the body. This guarantees that any
|
||||
// changes made by contentSetup are included when the body's content
|
||||
// is initially added to the accessibility tree and that the
|
||||
// accessibility tree is up to date.
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document.body.removeAttribute("aria-hidden");
|
||||
content.document.body.removeAttribute("hidden");
|
||||
});
|
||||
await ready;
|
||||
info("contentSetup done");
|
||||
|
|
|
@ -188,13 +188,8 @@ addAccessibleTask(
|
|||
{ chrome: true, topLevel: false /* bug 1834129 */ }
|
||||
);
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"dom.element.contenteditable.plaintext-only.enabled"
|
||||
)
|
||||
) {
|
||||
addAccessibleTask(
|
||||
`<style>
|
||||
addAccessibleTask(
|
||||
`<style>
|
||||
#input {
|
||||
white-space: pre;
|
||||
}
|
||||
|
@ -206,17 +201,16 @@ if (
|
|||
}
|
||||
</style>
|
||||
<div id="input" contenteditable="plaintext-only" role="textbox"></div>`,
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(
|
||||
browser,
|
||||
findAccessibleChildByID(docAcc, "input"),
|
||||
"before",
|
||||
"after"
|
||||
);
|
||||
},
|
||||
{ chrome: true, topLevel: false /* bug 1834129 */ }
|
||||
);
|
||||
}
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(
|
||||
browser,
|
||||
findAccessibleChildByID(docAcc, "input"),
|
||||
"before",
|
||||
"after"
|
||||
);
|
||||
},
|
||||
{ chrome: true, topLevel: false /* bug 1834129 */ }
|
||||
);
|
||||
|
||||
addAccessibleTask(
|
||||
``,
|
||||
|
|
|
@ -28,6 +28,8 @@ skip-if = [
|
|||
|
||||
["browser_link.js"]
|
||||
|
||||
["browser_test_aria_hidden.js"]
|
||||
|
||||
["browser_searchbar.js"]
|
||||
|
||||
["browser_select.js"]
|
||||
|
|
329
accessible/tests/browser/tree/browser_test_aria_hidden.js
Normal file
329
accessible/tests/browser/tree/browser_test_aria_hidden.js
Normal file
|
@ -0,0 +1,329 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* import-globals-from ../../mochitest/role.js */
|
||||
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
|
||||
|
||||
/**
|
||||
* Verify loading a root doc with aria-hidden renders the document.
|
||||
* Non-root doc elements, like embedded iframes, should continue
|
||||
* to respect aria-hidden when present. This test ONLY tests
|
||||
* tab documents, it should not run in iframes. There is a separate
|
||||
* test for iframes below.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="content">I am some content in a document</p>
|
||||
`,
|
||||
async function testTabDocument(browser, docAcc) {
|
||||
const originalTree = { DOCUMENT: [{ PARAGRAPH: [{ TEXT_LEAF: [] }] }] };
|
||||
testAccessibleTree(docAcc, originalTree);
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: true,
|
||||
iframe: false,
|
||||
remoteIframe: false,
|
||||
contentDocBodyAttrs: { "aria-hidden": "true" },
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify adding aria-hidden to root doc elements has no effect.
|
||||
* Non-root doc elements, like embedded iframes, should continue
|
||||
* to respect aria-hidden when applied. This test ONLY tests
|
||||
* tab documents, it should not run in iframes. There is a separate
|
||||
* test for iframes below.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="content">I am some content in a document</p>
|
||||
`,
|
||||
async function testTabDocumentMutation(browser, docAcc) {
|
||||
const originalTree = { DOCUMENT: [{ PARAGRAPH: [{ TEXT_LEAF: [] }] }] };
|
||||
|
||||
testAccessibleTree(docAcc, originalTree);
|
||||
info("Adding aria-hidden=true to content doc");
|
||||
const unexpectedEvents = { unexpected: [[EVENT_REORDER, docAcc]] };
|
||||
await contentSpawnMutation(browser, unexpectedEvents, function () {
|
||||
const b = content.document.body;
|
||||
b.setAttribute("aria-hidden", "true");
|
||||
});
|
||||
|
||||
testAccessibleTree(docAcc, originalTree);
|
||||
},
|
||||
{ chrome: true, topLevel: true, iframe: false, remoteIframe: false }
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify loading an iframe doc with aria-hidden doesn't render the document.
|
||||
* This test ONLY tests iframe documents, it should not run in tab docs.
|
||||
* There is a separate test for tab docs above.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="content">I am some content in a document</p>
|
||||
`,
|
||||
async function testIframeDocument(browser, docAcc, topLevel) {
|
||||
const originalTree = { DOCUMENT: [{ INTERNAL_FRAME: [{ DOCUMENT: [] }] }] };
|
||||
testAccessibleTree(topLevel, originalTree);
|
||||
},
|
||||
{
|
||||
chrome: false,
|
||||
topLevel: false,
|
||||
iframe: true,
|
||||
remoteIframe: true,
|
||||
iframeDocBodyAttrs: { "aria-hidden": "true" },
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify adding aria-hidden to iframe doc elements removes
|
||||
* their subtree. This test ONLY tests iframe documents, it
|
||||
* should not run in tab documents. There is a separate test for
|
||||
* tab documents above.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="content">I am some content in a document</p>
|
||||
`,
|
||||
async function testIframeDocumentMutation(browser, docAcc, topLevel) {
|
||||
const originalTree = {
|
||||
DOCUMENT: [
|
||||
{
|
||||
INTERNAL_FRAME: [
|
||||
{
|
||||
DOCUMENT: [
|
||||
{
|
||||
PARAGRAPH: [
|
||||
{
|
||||
TEXT_LEAF: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
testAccessibleTree(topLevel, originalTree);
|
||||
info("Adding aria-hidden=true to content doc");
|
||||
await contentSpawnMutation(
|
||||
browser,
|
||||
{ expected: [[EVENT_REORDER, docAcc]] },
|
||||
function () {
|
||||
const b = content.document.body;
|
||||
b.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
);
|
||||
const newTree = {
|
||||
DOCUMENT: [
|
||||
{
|
||||
INTERNAL_FRAME: [
|
||||
{
|
||||
DOCUMENT: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
testAccessibleTree(topLevel, newTree);
|
||||
},
|
||||
{ chrome: false, topLevel: false, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
||||
// // ///////////////////////////////
|
||||
// // //////////////////// SVG Tests
|
||||
// // //////////////////////////////
|
||||
|
||||
const SVG_DOCUMENT_ID = "rootSVG";
|
||||
const HIDDEN_SVG_URI =
|
||||
"data:image/svg+xml,%3Csvg%20id%3D%22rootSVG%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20aria-hidden%3D%22true%22%3E%3Ctext%20x%3D%2210%22%20y%3D%2250%22%20font-size%3D%2230%22%20id%3D%22textSVG%22%3EMy%20SVG%3C%2Ftext%3E%3C%2Fsvg%3E";
|
||||
const SVG_URI =
|
||||
"data:image/svg+xml,%3Csvg%20id%3D%22rootSVG%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ctext%20x%3D%2210%22%20y%3D%2250%22%20font-size%3D%2230%22%20id%3D%22textSVG%22%3EMy%20SVG%3C%2Ftext%3E%3C%2Fsvg%3E";
|
||||
|
||||
/**
|
||||
* Verify loading an SVG document with aria-hidden=true renders the
|
||||
* entire document subtree.
|
||||
* Non-root svg elements, like those in embedded iframes, should
|
||||
* continue to respect aria-hidden when applied.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`hello world`,
|
||||
async function testSVGDocument(browser) {
|
||||
let loaded = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, SVG_DOCUMENT_ID);
|
||||
info("Loading SVG");
|
||||
browser.loadURI(Services.io.newURI(HIDDEN_SVG_URI), {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await loaded;
|
||||
|
||||
const tree = {
|
||||
DOCUMENT: [
|
||||
{
|
||||
TEXT_CONTAINER: [
|
||||
{
|
||||
TEXT_LEAF: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const root = getRootAccessible(document);
|
||||
const svgRoot = findAccessibleChildByID(root, SVG_DOCUMENT_ID);
|
||||
testAccessibleTree(svgRoot, tree);
|
||||
},
|
||||
{ chrome: true, topLevel: true, iframe: false, remoteIframe: false }
|
||||
);
|
||||
|
||||
///////////
|
||||
///// TODO: Bug 1960416
|
||||
//////////
|
||||
// /**
|
||||
// * Verify loading an SVG document with aria-hidden=true
|
||||
// * in an iframe does not render the document subtree.
|
||||
// */
|
||||
// addAccessibleTask(
|
||||
// `hello world`,
|
||||
// async function testSVGIframeDocument(browser) {
|
||||
// info("Loading SVG");
|
||||
// const loaded = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, SVG_DOCUMENT_ID);
|
||||
// await SpecialPowers.spawn(browser, [DEFAULT_IFRAME_ID, HIDDEN_SVG_URI], (_id,_uri) => {
|
||||
// content.document.getElementById(_id).src = _uri;
|
||||
// });
|
||||
// await loaded;
|
||||
|
||||
// const tree = {
|
||||
// DOCUMENT: [],
|
||||
// };
|
||||
// const root = getRootAccessible(document);
|
||||
// const svgRoot = findAccessibleChildByID(root, SVG_DOCUMENT_ID);
|
||||
// testAccessibleTree(svgRoot, tree);
|
||||
// },
|
||||
// { chrome: false, topLevel: false, iframe: true, remoteIframe: true }
|
||||
// );
|
||||
|
||||
/**
|
||||
* Verify adding aria-hidden to root svg elements has no effect.
|
||||
* Non-root svg elements, like those in embedded iframes, should
|
||||
* continue to respect aria-hidden when applied.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`hello world`,
|
||||
async function testSVGDocumentMutation(browser) {
|
||||
let loaded = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, SVG_DOCUMENT_ID);
|
||||
info("Loading SVG");
|
||||
browser.loadURI(Services.io.newURI(SVG_URI), {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await loaded;
|
||||
|
||||
const originalTree = {
|
||||
DOCUMENT: [
|
||||
{
|
||||
TEXT_CONTAINER: [
|
||||
{
|
||||
TEXT_LEAF: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const root = getRootAccessible(document);
|
||||
const svgRoot = findAccessibleChildByID(root, SVG_DOCUMENT_ID);
|
||||
testAccessibleTree(svgRoot, originalTree);
|
||||
info("Adding aria-hidden=true to svg");
|
||||
// XXX Bug 1959547: We incorrectly get a reorder
|
||||
// here. The tree should be unaffected by this attribute,
|
||||
// but it seems like it isn't! Below we'll verify that
|
||||
// the tree isn't removed, despite this reorder.
|
||||
const unexpectedEvents = { expected: [[EVENT_REORDER, SVG_DOCUMENT_ID]] };
|
||||
info("Adding aria-hidden");
|
||||
await contentSpawnMutation(
|
||||
browser,
|
||||
unexpectedEvents,
|
||||
function (_id) {
|
||||
const d = content.document.getElementById(_id);
|
||||
d.setAttribute("aria-hidden", "true");
|
||||
},
|
||||
[SVG_DOCUMENT_ID]
|
||||
);
|
||||
// XXX Bug 1959547: We end up with an extra node in the
|
||||
// tree after adding aria-hidden. It seems like SVG root
|
||||
// element is splitting off / no longer behaves as the
|
||||
// document...?
|
||||
const newTree = {
|
||||
DOCUMENT: [
|
||||
{
|
||||
DIAGRAM: [
|
||||
{
|
||||
TEXT_CONTAINER: [
|
||||
{
|
||||
TEXT_LEAF: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
testAccessibleTree(svgRoot, newTree);
|
||||
},
|
||||
{ chrome: true, topLevel: true, iframe: false, remoteIframe: false }
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify adding aria-hidden to root svg elements in iframes removes
|
||||
* the svg subtree.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`hello world`,
|
||||
async function testSVGIframeDocumentMutation(browser) {
|
||||
info("Loading SVG");
|
||||
const loaded = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, SVG_DOCUMENT_ID);
|
||||
await SpecialPowers.spawn(
|
||||
browser,
|
||||
[DEFAULT_IFRAME_ID, SVG_URI],
|
||||
(contentId, _uri) => {
|
||||
content.document.getElementById(contentId).src = _uri;
|
||||
}
|
||||
);
|
||||
await loaded;
|
||||
const originalTree = {
|
||||
DOCUMENT: [
|
||||
{
|
||||
TEXT_CONTAINER: [
|
||||
{
|
||||
TEXT_LEAF: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const svgRoot = findAccessibleChildByID(
|
||||
getRootAccessible(document),
|
||||
SVG_DOCUMENT_ID
|
||||
);
|
||||
testAccessibleTree(svgRoot, originalTree);
|
||||
|
||||
info("Adding aria-hidden=true to svg");
|
||||
const events = { expected: [[EVENT_REORDER, SVG_DOCUMENT_ID]] };
|
||||
await contentSpawnMutation(
|
||||
browser,
|
||||
events,
|
||||
function (_id) {
|
||||
const d = content.document.getElementById(_id);
|
||||
d.setAttribute("aria-hidden", "true");
|
||||
},
|
||||
[SVG_DOCUMENT_ID]
|
||||
);
|
||||
|
||||
const newTree = { DOCUMENT: [] };
|
||||
testAccessibleTree(svgRoot, newTree);
|
||||
},
|
||||
{ chrome: false, topLevel: false, iframe: true, remoteIframe: true }
|
||||
);
|
|
@ -240,7 +240,7 @@ class WaitForWinEvent:
|
|||
ctypes.oledll.ole32.CoWaitForMultipleHandles(
|
||||
COWAIT_DEFAULT, TIMEOUT, 1, handles, ctypes.byref(index)
|
||||
)
|
||||
except WindowsError as e:
|
||||
except OSError as e:
|
||||
if e.winerror == RPC_S_CALLPENDING:
|
||||
raise TimeoutError("Timeout before desired event received")
|
||||
raise
|
||||
|
@ -382,7 +382,7 @@ class WaitForUiaEvent(comtypes.COMObject):
|
|||
ctypes.oledll.ole32.CoWaitForMultipleHandles(
|
||||
COWAIT_DEFAULT, TIMEOUT, 1, handles, ctypes.byref(index)
|
||||
)
|
||||
except WindowsError as e:
|
||||
except OSError as e:
|
||||
if e.winerror == RPC_S_CALLPENDING:
|
||||
raise TimeoutError("Timeout before desired event received")
|
||||
raise
|
||||
|
|
|
@ -447,6 +447,29 @@ addUiaTask(
|
|||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Test the Value pattern on a document.
|
||||
*/
|
||||
addUiaTask(``, async function testValueDoc(browser) {
|
||||
// A test snippet is a data: URI. The accessibility engine won't return these.
|
||||
let url = new URL("https://example.net/document-builder.sjs");
|
||||
url.searchParams.append("html", `<body id=${DEFAULT_CONTENT_DOC_BODY_ID}>`);
|
||||
let loaded = waitForEvent(
|
||||
EVENT_DOCUMENT_LOAD_COMPLETE,
|
||||
DEFAULT_CONTENT_DOC_BODY_ID
|
||||
);
|
||||
BrowserTestUtils.startLoadingURIString(browser, url.href);
|
||||
await loaded;
|
||||
await definePyVar("doc", `getDocUia()`);
|
||||
await definePyVar("pattern", `getUiaPattern(doc, "Value")`);
|
||||
ok(await runPython(`bool(pattern)`), "doc has Value pattern");
|
||||
is(
|
||||
await runPython(`pattern.CurrentValue`),
|
||||
url.href,
|
||||
"doc has correct Value"
|
||||
);
|
||||
});
|
||||
|
||||
async function testRangeValueProps(id, ro, val, min, max, small, large) {
|
||||
await assignPyVarToUiaWithId(id);
|
||||
await definePyVar("pattern", `getUiaPattern(${id}, "RangeValue")`);
|
||||
|
|
|
@ -91,9 +91,6 @@ class LabelTextLeafRule : public PivotRule {
|
|||
|
||||
static void MaybeRaiseUiaLiveRegionEvent(Accessible* aAcc,
|
||||
uint32_t aGeckoEvent) {
|
||||
if (!::UiaClientsAreListening()) {
|
||||
return;
|
||||
}
|
||||
if (Accessible* live = nsAccUtils::GetLiveRegionRoot(aAcc)) {
|
||||
auto* uia = MsaaAccessible::GetFrom(live);
|
||||
::UiaRaiseAutomationEvent(uia, UIA_LiveRegionChangedEventId);
|
||||
|
@ -140,13 +137,18 @@ Accessible* uiaRawElmProvider::Acc() const {
|
|||
/* static */
|
||||
void uiaRawElmProvider::RaiseUiaEventForGeckoEvent(Accessible* aAcc,
|
||||
uint32_t aGeckoEvent) {
|
||||
if (!Compatibility::IsUiaEnabled()) {
|
||||
if (!Compatibility::IsUiaEnabled() || !::UiaClientsAreListening()) {
|
||||
return;
|
||||
}
|
||||
auto* uia = MsaaAccessible::GetFrom(aAcc);
|
||||
if (!uia) {
|
||||
return;
|
||||
}
|
||||
// Some UIA events include or depend on data that might not be cached yet. We
|
||||
// shouldn't request additional cache domains in this case because a client
|
||||
// might not even care about these events. Instead, we use explicit client
|
||||
// queries as a signal to request domains.
|
||||
CacheDomainActivationBlocker cacheBlocker;
|
||||
PROPERTYID property = 0;
|
||||
_variant_t newVal;
|
||||
bool gotNewVal = false;
|
||||
|
@ -205,7 +207,7 @@ void uiaRawElmProvider::RaiseUiaEventForGeckoEvent(Accessible* aAcc,
|
|||
gotNewVal = true;
|
||||
break;
|
||||
}
|
||||
if (property && ::UiaClientsAreListening()) {
|
||||
if (property) {
|
||||
// We can't get the old value. Thankfully, clients don't seem to need it.
|
||||
_variant_t oldVal;
|
||||
if (!gotNewVal) {
|
||||
|
@ -220,7 +222,7 @@ void uiaRawElmProvider::RaiseUiaEventForGeckoEvent(Accessible* aAcc,
|
|||
void uiaRawElmProvider::RaiseUiaEventForStateChange(Accessible* aAcc,
|
||||
uint64_t aState,
|
||||
bool aEnabled) {
|
||||
if (!Compatibility::IsUiaEnabled()) {
|
||||
if (!Compatibility::IsUiaEnabled() || !::UiaClientsAreListening()) {
|
||||
return;
|
||||
}
|
||||
auto* uia = MsaaAccessible::GetFrom(aAcc);
|
||||
|
@ -260,11 +262,9 @@ void uiaRawElmProvider::RaiseUiaEventForStateChange(Accessible* aAcc,
|
|||
return;
|
||||
}
|
||||
MOZ_ASSERT(property);
|
||||
if (::UiaClientsAreListening()) {
|
||||
// We can't get the old value. Thankfully, clients don't seem to need it.
|
||||
_variant_t oldVal;
|
||||
::UiaRaiseAutomationPropertyChangedEvent(uia, property, oldVal, newVal);
|
||||
}
|
||||
// We can't get the old value. Thankfully, clients don't seem to need it.
|
||||
_variant_t oldVal;
|
||||
::UiaRaiseAutomationPropertyChangedEvent(uia, property, oldVal, newVal);
|
||||
}
|
||||
|
||||
// IUnknown
|
||||
|
@ -1009,6 +1009,11 @@ uiaRawElmProvider::get_Value(__RPC__deref_out_opt BSTR* aRetVal) {
|
|||
}
|
||||
nsAutoString value;
|
||||
acc->Value(value);
|
||||
if (value.IsEmpty() && acc->IsDoc()) {
|
||||
// Exposing the URl via the Value pattern doesn't seem to be documented
|
||||
// anywhere. However, Chromium does it, as does the IA2 -> UIA proxy.
|
||||
nsAccUtils::DocumentURL(acc, value);
|
||||
}
|
||||
*aRetVal = ::SysAllocStringLen(value.get(), value.Length());
|
||||
if (!*aRetVal) {
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -1391,7 +1396,7 @@ bool uiaRawElmProvider::HasValuePattern() const {
|
|||
Accessible* acc = Acc();
|
||||
MOZ_ASSERT(acc);
|
||||
if (acc->HasNumericValue() || acc->IsCombobox() || acc->IsHTMLLink() ||
|
||||
acc->IsTextField()) {
|
||||
acc->IsTextField() || acc->IsDoc()) {
|
||||
return true;
|
||||
}
|
||||
const nsRoleMapEntry* roleMapEntry = acc->ARIARoleMap();
|
||||
|
|
|
@ -132,7 +132,7 @@ def print_cpp_file(fd, conf, incdirs):
|
|||
includes = []
|
||||
for e in conf.simple_events:
|
||||
if e not in includes:
|
||||
includes.append(("nsIAccessible%s" % e))
|
||||
includes.append("nsIAccessible%s" % e)
|
||||
|
||||
types = []
|
||||
for e in conf.simple_events:
|
||||
|
|
|
@ -172,7 +172,13 @@ Accessible* XULContentSelectDropdownAccessible::Parent() const {
|
|||
|
||||
DocAccessibleParent* focusedDoc =
|
||||
DocAccessibleParent::GetFrom(focusedContext);
|
||||
MOZ_ASSERT(focusedDoc && focusedDoc->IsDoc(), "No focused document found");
|
||||
if (NS_WARN_IF(!focusedDoc)) {
|
||||
// We can fail to get a document here if a user is
|
||||
// performing a drag-and-drop selection with mouse. See
|
||||
// `browser/base/content/tests/browser_selectpopup_large.js`
|
||||
return LocalParent();
|
||||
}
|
||||
MOZ_ASSERT(focusedDoc->IsDoc(), "Got non-document?");
|
||||
focusedAcc = focusedDoc->AsDoc()->GetFocusedAcc();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# 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/.
|
||||
|
||||
import io
|
||||
import re
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
@ -28,9 +27,7 @@ if not options.version:
|
|||
# builds), but also so that newly-built older versions (e.g. beta build) aren't
|
||||
# considered "newer" than previously-built newer versions (e.g. a trunk nightly)
|
||||
|
||||
define, MOZ_BUILDID, buildid = (
|
||||
io.open(options.buildid, "r", encoding="utf-8").read().split()
|
||||
)
|
||||
define, MOZ_BUILDID, buildid = open(options.buildid, encoding="utf-8").read().split()
|
||||
|
||||
# extract only the major version (i.e. "14" from "14.0b1")
|
||||
majorVersion = re.match(r"^(\d+)[^\d].*", options.version).group(1)
|
||||
|
|
|
@ -71,6 +71,13 @@ pref("extensions.webextensions.remote", true);
|
|||
pref("extensions.langpacks.signatures.required", true);
|
||||
pref("xpinstall.signatures.required", true);
|
||||
|
||||
// Enable data collection permissions.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("extensions.dataCollectionPermissions.enabled", true);
|
||||
#else
|
||||
pref("extensions.dataCollectionPermissions.enabled", false);
|
||||
#endif
|
||||
|
||||
// Dictionary download preference
|
||||
pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/firefox/language-tools/");
|
||||
|
||||
|
@ -480,11 +487,7 @@ pref("browser.urlbar.richSuggestions.featureGate", true);
|
|||
pref("browser.search.param.search_rich_suggestions", "fen");
|
||||
|
||||
// Feature gate pref for weather suggestions in the urlbar.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("browser.urlbar.weather.featureGate", true);
|
||||
#else
|
||||
pref("browser.urlbar.weather.featureGate", false);
|
||||
#endif
|
||||
|
||||
// Enable clipboard suggestions feature, the pref should be removed once stable.
|
||||
pref("browser.urlbar.clipboard.featureGate", false);
|
||||
|
@ -578,10 +581,8 @@ pref("browser.urlbar.quicksuggest.impressionCaps.sponsoredEnabled", false);
|
|||
|
||||
// When non-zero, this is the character-count threshold (inclusive) for showing
|
||||
// AMP suggestions as top picks. If an AMP suggestion is triggered by a keyword
|
||||
// at least this many characters long, it will be shown as a top pick. Full
|
||||
// keywords will also show AMP suggestions as top picks even if they have fewer
|
||||
// characters than this threshold.
|
||||
pref("browser.urlbar.quicksuggest.ampTopPickCharThreshold", 0);
|
||||
// at least this many characters long, it will be shown as a top pick.
|
||||
pref("browser.urlbar.quicksuggest.ampTopPickCharThreshold", 5);
|
||||
|
||||
// The matching strategy for AMP suggestions. Zero is the usual default
|
||||
// exact-keyword strategy. Other values are the integers defined on
|
||||
|
@ -907,6 +908,9 @@ pref("browser.spin_cursor_while_busy", false);
|
|||
// Enable display of contextual-password-manager option in browser sidebar
|
||||
pref("browser.contextual-password-manager.enabled", false);
|
||||
|
||||
// Add the "Passwords" tool to the sidebar if contextual-password-manager is enabled.
|
||||
pref("sidebar.newTool.migration.passwords", '{ "visibilityPref": "browser.contextual-password-manager.enabled"}');
|
||||
|
||||
// Enables the display of the Mozilla VPN banner in private browsing windows
|
||||
pref("browser.privatebrowsing.vpnpromourl", "https://vpn.mozilla.org/?utm_source=firefox-browser&utm_medium=firefox-%CHANNEL%-browser&utm_campaign=private-browsing-vpn-link");
|
||||
|
||||
|
@ -1054,11 +1058,7 @@ pref("browser.tabs.tooltipsShowPidAndActiveness", false);
|
|||
pref("browser.tabs.hoverPreview.enabled", true);
|
||||
pref("browser.tabs.hoverPreview.showThumbnails", true);
|
||||
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
pref("browser.tabs.groups.enabled", true);
|
||||
#else
|
||||
pref("browser.tabs.groups.enabled", false);
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("browser.tabs.groups.smart.enabled", true);
|
||||
|
@ -1815,6 +1815,12 @@ pref("browser.newtab.preload", true);
|
|||
// population (2500 / 10000).
|
||||
pref("browser.preonboarding.onTrainRolloutPopulation", 2500);
|
||||
|
||||
// Show "Download Firefox for mobile" QR code modal on newtab
|
||||
pref("browser.newtabpage.activity-stream.mobileDownloadModal.enabled", false);
|
||||
pref("browser.newtabpage.activity-stream.mobileDownloadModal.variant-a", false);
|
||||
pref("browser.newtabpage.activity-stream.mobileDownloadModal.variant-b", false);
|
||||
pref("browser.newtabpage.activity-stream.mobileDownloadModal.variant-c", false);
|
||||
|
||||
// Mozilla Ad Routing Service (MARS) unified ads service
|
||||
pref("browser.newtabpage.activity-stream.unifiedAds.tiles.enabled", true);
|
||||
pref("browser.newtabpage.activity-stream.unifiedAds.spocs.enabled", true);
|
||||
|
@ -1990,6 +1996,7 @@ pref("browser.newtabpage.activity-stream.discoverystream.sections.region-content
|
|||
pref("browser.newtabpage.activity-stream.discoverystream.sections.cards.enabled", true);
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.sections.personalization.inferred.enabled", false);
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.sections.personalization.inferred.user.enabled", true);
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.sections.personalization.inferred.blocked", false);
|
||||
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.sections.interestPicker.enabled", false);
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.sections.interestPicker.visibleSections", "");
|
||||
|
@ -2023,6 +2030,11 @@ pref("browser.newtabpage.activity-stream.discoverystream.onboardingExperience.en
|
|||
// List of locales that get thumbs up/down on recommended stories by default.
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.thumbsUpDown.locale-thumbs-config", "en-US, en-GB, en-CA");
|
||||
|
||||
pref("browser.newtabpage.activity-stream.telemetry.privatePing.enabled", false);
|
||||
|
||||
// surface ID sent from merino to the client from the curated-recommendations request
|
||||
pref("browser.newtabpage.activity-stream.telemetry.surfaceId", "");
|
||||
|
||||
// List of regions that get thumbs up/down on recommended stories by default.
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
pref("browser.newtabpage.activity-stream.discoverystream.thumbsUpDown.region-thumbs-config", "US, CA");
|
||||
|
@ -2554,20 +2566,24 @@ pref("browser.tabs.crashReporting.sendReport", true);
|
|||
pref("browser.tabs.crashReporting.includeURL", false);
|
||||
|
||||
// Enables the "Unload Tab" context menu item
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
pref("browser.tabs.unloadTabInContextMenu", true);
|
||||
#else
|
||||
pref("browser.tabs.unloadTabInContextMenu", false);
|
||||
#endif
|
||||
|
||||
// Whether tabs that have been explicitly unloaded
|
||||
// are faded out in the tab bar.
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
pref("browser.tabs.fadeOutExplicitlyUnloadedTabs", true);
|
||||
#else
|
||||
pref("browser.tabs.fadeOutExplicitlyUnloadedTabs", false);
|
||||
#endif
|
||||
|
||||
// Whether unloaded tabs (either from session restore or because
|
||||
// they are explicitly unloaded) are faded out in the tab bar.
|
||||
pref("browser.tabs.fadeOutUnloadedTabs", false);
|
||||
|
||||
// Whether tabs that have been explicitly unloaded
|
||||
// are faded out in the tab bar.
|
||||
pref("browser.tabs.fadeOutExplicitlyUnloadedTabs", false);
|
||||
|
||||
// If true, unprivileged extensions may use experimental APIs on
|
||||
// nightly and developer edition.
|
||||
pref("extensions.experiments.enabled", false);
|
||||
|
@ -2823,7 +2839,6 @@ pref("identity.fxaccounts.toolbar.pxiToolbarEnabled.vpnEnabled", true);
|
|||
|
||||
// Prefs to control Mozilla account panels that shows an updated flow
|
||||
// for users who don't have sync enabled
|
||||
pref("identity.fxaccounts.toolbar.syncSetup.enabled", false);
|
||||
pref("identity.fxaccounts.toolbar.syncSetup.panelAccessed", false);
|
||||
|
||||
// Toolbox preferences
|
||||
|
@ -2985,6 +3000,7 @@ pref("devtools.netmonitor.panes-network-details-height", 450);
|
|||
pref("devtools.netmonitor.panes-search-width", 550);
|
||||
pref("devtools.netmonitor.panes-search-height", 450);
|
||||
pref("devtools.netmonitor.filters", "[\"all\"]");
|
||||
pref("devtools.netmonitor.requestfilter", "");
|
||||
pref("devtools.netmonitor.visibleColumns",
|
||||
"[\"override\",\"status\",\"method\",\"domain\",\"file\",\"initiator\",\"type\",\"transferred\",\"contentSize\",\"waterfall\"]"
|
||||
);
|
||||
|
|
|
@ -614,37 +614,32 @@
|
|||
</hbox>
|
||||
</toolbarbutton>
|
||||
<vbox id="PanelUI-signedin-panel" hidden="true">
|
||||
<toolbarbutton id="PanelUI-fxa-menu-setup-sync-button"
|
||||
class="subviewbutton"
|
||||
data-l10n-id="appmenu-fxa-setup-sync"
|
||||
hidden="true"
|
||||
/>
|
||||
<vbox id="PanelUI-fxa-menu-setup-sync-container" hidden="true">
|
||||
<vbox class="PanelUI-fxa-menu-setup-sync" flex="1">
|
||||
<hbox class="sync-status-container" align="center">
|
||||
<image class="sync-status-indicator" role="presentation"/>
|
||||
<image class="sync-setup-icon" alt="Sync Status Icon" />
|
||||
<label id="sync-status-text"
|
||||
class="sync-setup-title"
|
||||
data-l10n-id="appmenuitem-fxa-sync-off-title"
|
||||
crop="end" />
|
||||
</hbox>
|
||||
<label id="sync-description-text"
|
||||
class="sync-setup-description"
|
||||
data-l10n-id="appmenuitem-fxa-sync-off-description"
|
||||
crop="end"/>
|
||||
<toolbarbutton id="PanelUI-fxa-menu-setup-sync-button"
|
||||
class="subviewbutton"
|
||||
data-l10n-id="appmenu-fxa-setup-sync-new"/>
|
||||
</vbox>
|
||||
<toolbarseparator id="PanelUI-set-up-sync-separator" />
|
||||
</vbox>
|
||||
<!-- The `Connect Another Device` button is disabled by default until the user logs into Sync. -->
|
||||
<toolbarbutton id="PanelUI-fxa-menu-connect-device-button"
|
||||
class="subviewbutton"
|
||||
data-l10n-id="fxa-menu-connect-another-device"
|
||||
disabled="true"
|
||||
/>
|
||||
<vbox id="PanelUI-fxa-menu-setup-sync-container" hidden="true">
|
||||
<toolbarseparator id="PanelUI-set-up-sync-separator" />
|
||||
<vbox class="PanelUI-fxa-menu-setup-sync" flex="1">
|
||||
<hbox class="sync-status-container" align="center">
|
||||
<image class="sync-status-indicator" role="presentation"/>
|
||||
<image class="sync-setup-icon" alt="Sync Status Icon" />
|
||||
<label id="sync-status-text"
|
||||
class="sync-setup-title"
|
||||
data-l10n-id="appmenuitem-fxa-sync-off-title"
|
||||
crop="end" />
|
||||
</hbox>
|
||||
<label id="sync-description-text"
|
||||
class="sync-setup-description"
|
||||
data-l10n-id="appmenuitem-fxa-sync-off-description"
|
||||
crop="end"/>
|
||||
<toolbarbutton id="PanelUI-fxa-menu-setup-sync-button-new"
|
||||
class="subviewbutton"
|
||||
data-l10n-id="appmenu-fxa-setup-sync-new"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<toolbarbutton id="PanelUI-fxa-menu-sendtab-button"
|
||||
class="subviewbutton subviewbutton-nav"
|
||||
data-l10n-id="fxa-menu-send-tab-to-device"
|
||||
|
|
|
@ -410,7 +410,7 @@ customElements.define(
|
|||
});
|
||||
doc.l10n.setAttributes(
|
||||
checkboxEl,
|
||||
"popup-notification-addon-privatebrowsing-checkbox"
|
||||
"popup-notification-addon-privatebrowsing-checkbox2"
|
||||
);
|
||||
return checkboxEl;
|
||||
}
|
||||
|
@ -419,9 +419,14 @@ customElements.define(
|
|||
const { grantTechnicalAndInteractionDataCollection } =
|
||||
this.notification.options.customElementOptions;
|
||||
|
||||
MozXULElement.insertFTLIfNeeded(
|
||||
"locales-preview/dataCollectionPermissions.ftl"
|
||||
);
|
||||
|
||||
const checkboxEl = this.ownerDocument.createXULElement("checkbox");
|
||||
checkboxEl.label = lazy.PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-description-data-long-technicalAndInteraction"
|
||||
this.ownerDocument.l10n.setAttributes(
|
||||
checkboxEl,
|
||||
"popup-notification-addon-technicalAndInteraction-checkbox"
|
||||
);
|
||||
checkboxEl.checked = grantTechnicalAndInteractionDataCollection;
|
||||
checkboxEl.addEventListener("CheckboxStateChange", () => {
|
||||
|
|
|
@ -134,7 +134,7 @@ var gBrowserInit = {
|
|||
|
||||
// Call this after we set attributes that might change toolbars' computed
|
||||
// text color.
|
||||
ToolbarIconColor.init();
|
||||
ToolbarIconColor.init(window);
|
||||
},
|
||||
|
||||
onDOMContentLoaded() {
|
||||
|
@ -274,6 +274,9 @@ var gBrowserInit = {
|
|||
gBrowser.adoptTabGroup(tabToAdopt.group, 0);
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
} else {
|
||||
if (tabToAdopt.group) {
|
||||
Glean.tabgroup.tabInteractions.remove_new_window.add();
|
||||
}
|
||||
gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToAdopt);
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1003,7 @@ var gBrowserInit = {
|
|||
|
||||
CustomTitlebar.uninit();
|
||||
|
||||
ToolbarIconColor.uninit();
|
||||
ToolbarIconColor.uninit(window);
|
||||
|
||||
// In certain scenarios it's possible for unload to be fired before onload,
|
||||
// (e.g. if the window is being closed after browser.js loads but before the
|
||||
|
|
|
@ -787,12 +787,6 @@ var gSync = {
|
|||
if (ctaCopyVariant) {
|
||||
NimbusFeatures.fxaAvatarMenuItem.recordExposureEvent();
|
||||
}
|
||||
|
||||
// We want to record exposure if the user has sync disabled and has
|
||||
// clicked to open the FxA panel
|
||||
if (this.isSignedIn && !UIState.get().syncEnabled) {
|
||||
NimbusFeatures.syncSetupFlow.recordExposureEvent();
|
||||
}
|
||||
},
|
||||
|
||||
onFxAPanelViewHiding(panelview) {
|
||||
|
@ -804,11 +798,9 @@ var gSync = {
|
|||
onCommand(button) {
|
||||
switch (button.id) {
|
||||
case "PanelUI-fxa-menu-sync-prefs-button":
|
||||
// fall through
|
||||
case "PanelUI-fxa-menu-setup-sync-button":
|
||||
this.openPrefsFromFxaMenu("sync_settings", button);
|
||||
break;
|
||||
case "PanelUI-fxa-menu-setup-sync-button-new":
|
||||
case "PanelUI-fxa-menu-setup-sync-button":
|
||||
this.openChooseWhatToSync("sync_settings", button);
|
||||
break;
|
||||
|
||||
|
@ -1136,16 +1128,9 @@ var gSync = {
|
|||
},
|
||||
|
||||
_disableSyncOffIndicator() {
|
||||
const newSyncSetupEnabled =
|
||||
NimbusFeatures.syncSetupFlow.getVariable("enabled");
|
||||
const SYNC_PANEL_ACCESSED_PREF =
|
||||
"identity.fxaccounts.toolbar.syncSetup.panelAccessed";
|
||||
// If the user was enrolled in the experiment and hasn't previously accessed
|
||||
// the panel, we disable the sync off indicator
|
||||
if (
|
||||
newSyncSetupEnabled &&
|
||||
!Services.prefs.getBoolPref(SYNC_PANEL_ACCESSED_PREF, false)
|
||||
) {
|
||||
if (!Services.prefs.getBoolPref(SYNC_PANEL_ACCESSED_PREF, false)) {
|
||||
// Turn off the indicator so the user doesn't see it in subsequent openings
|
||||
Services.prefs.setBoolPref(SYNC_PANEL_ACCESSED_PREF, true);
|
||||
}
|
||||
|
@ -1154,20 +1139,15 @@ var gSync = {
|
|||
_shouldShowSyncOffIndicator() {
|
||||
// We only ever want to show the user the dot once, once they've clicked into the panel
|
||||
// we do not show them the dot anymore
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"identity.fxaccounts.toolbar.syncSetup.panelAccessed",
|
||||
false
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return NimbusFeatures.syncSetupFlow.getVariable("enabled");
|
||||
return !Services.prefs.getBoolPref(
|
||||
"identity.fxaccounts.toolbar.syncSetup.panelAccessed",
|
||||
false
|
||||
);
|
||||
},
|
||||
|
||||
updateFxAPanel(state = {}) {
|
||||
const isNewSyncSetupFlowEnabled =
|
||||
NimbusFeatures.syncSetupFlow.getVariable("enabled");
|
||||
const expandedSignInCopy =
|
||||
NimbusFeatures.expandSignInButton.getVariable("ctaCopyVariant");
|
||||
const mainWindowEl = document.documentElement;
|
||||
|
||||
const menuHeaderTitleEl = PanelMultiView.getViewNode(
|
||||
|
@ -1206,16 +1186,51 @@ var gSync = {
|
|||
document,
|
||||
"PanelUI-fxa-menu-profiles-separator"
|
||||
);
|
||||
const syncSetupEl = PanelMultiView.getViewNode(
|
||||
document,
|
||||
"PanelUI-fxa-menu-setup-sync-container"
|
||||
);
|
||||
|
||||
const fxaToolbarMenuButton = document.getElementById(
|
||||
"fxa-toolbar-menu-button"
|
||||
);
|
||||
let fxaAvatarLabelEl = document.getElementById("fxa-avatar-label");
|
||||
|
||||
// Reset FxA/Sync UI elements to default, which is signed out
|
||||
cadButtonEl.setAttribute("disabled", true);
|
||||
cadButtonEl.hidden = isNewSyncSetupFlowEnabled;
|
||||
syncNowButtonEl.hidden = true;
|
||||
signedInContainer.hidden = true;
|
||||
fxaMenuAccountButtonEl.classList.remove("subviewbutton-nav");
|
||||
fxaMenuAccountButtonEl.removeAttribute("closemenu");
|
||||
menuHeaderDescriptionEl.hidden = false;
|
||||
|
||||
// Expanded sign in copy experiment is only for signed out users
|
||||
// so if a text variant has been provided then we show the expanded label
|
||||
// otherwise it'll be the default avatar icon
|
||||
// fxaToolbarMenuButton can be null in certain testing scenarios
|
||||
if (fxaToolbarMenuButton) {
|
||||
if (
|
||||
state.status === UIState.STATUS_NOT_CONFIGURED &&
|
||||
expandedSignInCopy
|
||||
) {
|
||||
fxaAvatarLabelEl.setAttribute(
|
||||
"value",
|
||||
this.fluentStrings.formatValueSync(expandedSignInCopy)
|
||||
);
|
||||
fxaAvatarLabelEl.removeAttribute("hidden");
|
||||
fxaToolbarMenuButton.setAttribute("data-l10n-id", "fxa-avatar-tooltip");
|
||||
fxaToolbarMenuButton.classList.add("avatar-button-background");
|
||||
} else {
|
||||
// Either signed in, or experiment not enabled
|
||||
fxaToolbarMenuButton.setAttribute(
|
||||
"data-l10n-id",
|
||||
"toolbar-button-account"
|
||||
);
|
||||
fxaToolbarMenuButton.classList.remove("avatar-button-background");
|
||||
fxaAvatarLabelEl.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The Firefox Account toolbar currently handles 3 different states for
|
||||
// users. The default `not_configured` state shows an empty avatar, `unverified`
|
||||
// state shows an avatar with an email icon, `login-failed` state shows an avatar
|
||||
|
@ -1282,34 +1297,17 @@ var gSync = {
|
|||
signedInContainer.hidden = false;
|
||||
cadButtonEl.removeAttribute("disabled");
|
||||
|
||||
// Due to bug 1951719, we toggle both old and new sync setup
|
||||
// elements as some platforms had a delay during sign-in/out
|
||||
// that there were some scenarios where both showed up or the
|
||||
// incorrect one
|
||||
const oldSyncSetupEl = PanelMultiView.getViewNode(
|
||||
document,
|
||||
"PanelUI-fxa-menu-setup-sync-button"
|
||||
);
|
||||
const newSyncSetupEl = PanelMultiView.getViewNode(
|
||||
document,
|
||||
"PanelUI-fxa-menu-setup-sync-container"
|
||||
);
|
||||
|
||||
if (state.syncEnabled) {
|
||||
// Always show sync now and connect another device button when sync is enabled
|
||||
syncNowButtonEl.removeAttribute("hidden");
|
||||
cadButtonEl.removeAttribute("hidden");
|
||||
oldSyncSetupEl.setAttribute("hidden", "true");
|
||||
newSyncSetupEl.setAttribute("hidden", "true");
|
||||
syncSetupEl.setAttribute("hidden", "true");
|
||||
} else {
|
||||
if (this._shouldShowSyncOffIndicator()) {
|
||||
let fxaButton = document.getElementById("fxa-toolbar-menu-button");
|
||||
fxaButton?.setAttribute("badge-status", "sync-disabled");
|
||||
fxaToolbarMenuButton?.setAttribute("badge-status", "sync-disabled");
|
||||
}
|
||||
// Show the sync element depending on if the user is enrolled or not
|
||||
isNewSyncSetupFlowEnabled
|
||||
? newSyncSetupEl.removeAttribute("hidden")
|
||||
: oldSyncSetupEl.removeAttribute("hidden");
|
||||
syncSetupEl.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
// Reposition profiles elements
|
||||
|
|
|
@ -92,6 +92,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
|||
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs",
|
||||
ToolbarContextMenu: "resource:///modules/ToolbarContextMenu.sys.mjs",
|
||||
ToolbarDropHandler: "resource:///modules/ToolbarDropHandler.sys.mjs",
|
||||
ToolbarIconColor: "moz-src:///browser/themes/ToolbarIconColor.sys.mjs",
|
||||
TranslationsParent: "resource://gre/actors/TranslationsParent.sys.mjs",
|
||||
UITour: "moz-src:///browser/components/uitour/UITour.sys.mjs",
|
||||
UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
|
||||
|
@ -5039,6 +5040,9 @@ function duplicateTabIn(aTab, where, delta) {
|
|||
});
|
||||
break;
|
||||
}
|
||||
if (aTab.group) {
|
||||
Glean.tabgroup.tabInteractions.duplicate.add();
|
||||
}
|
||||
}
|
||||
|
||||
var MousePosTracker = {
|
||||
|
@ -5124,120 +5128,6 @@ var MousePosTracker = {
|
|||
},
|
||||
};
|
||||
|
||||
var ToolbarIconColor = {
|
||||
_windowState: {
|
||||
active: false,
|
||||
fullscreen: false,
|
||||
customtitlebar: false,
|
||||
},
|
||||
init() {
|
||||
this._initialized = true;
|
||||
|
||||
window.addEventListener("nativethemechange", this);
|
||||
window.addEventListener("activate", this);
|
||||
window.addEventListener("deactivate", this);
|
||||
window.addEventListener("toolbarvisibilitychange", this);
|
||||
window.addEventListener("windowlwthemeupdate", this);
|
||||
|
||||
// If the window isn't active now, we assume that it has never been active
|
||||
// before and will soon become active such that inferFromText will be
|
||||
// called from the initial activate event.
|
||||
if (Services.focus.activeWindow == window) {
|
||||
this.inferFromText("activate");
|
||||
}
|
||||
},
|
||||
|
||||
uninit() {
|
||||
this._initialized = false;
|
||||
|
||||
window.removeEventListener("nativethemechange", this);
|
||||
window.removeEventListener("activate", this);
|
||||
window.removeEventListener("deactivate", this);
|
||||
window.removeEventListener("toolbarvisibilitychange", this);
|
||||
window.removeEventListener("windowlwthemeupdate", this);
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "activate":
|
||||
case "deactivate":
|
||||
case "nativethemechange":
|
||||
case "windowlwthemeupdate":
|
||||
this.inferFromText(event.type);
|
||||
break;
|
||||
case "toolbarvisibilitychange":
|
||||
this.inferFromText(event.type, event.visible);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// a cache of luminance values for each toolbar
|
||||
// to avoid unnecessary calls to getComputedStyle
|
||||
_toolbarLuminanceCache: new Map(),
|
||||
|
||||
inferFromText(reason, reasonValue) {
|
||||
if (!this._initialized) {
|
||||
return;
|
||||
}
|
||||
switch (reason) {
|
||||
case "activate": // falls through
|
||||
case "deactivate":
|
||||
this._windowState.active = reason === "activate";
|
||||
break;
|
||||
case "fullscreen":
|
||||
this._windowState.fullscreen = reasonValue;
|
||||
break;
|
||||
case "nativethemechange":
|
||||
case "windowlwthemeupdate":
|
||||
// theme change, we'll need to recalculate all color values
|
||||
this._toolbarLuminanceCache.clear();
|
||||
break;
|
||||
case "toolbarvisibilitychange":
|
||||
// toolbar changes dont require reset of the cached color values
|
||||
break;
|
||||
case "customtitlebar":
|
||||
this._windowState.customtitlebar = reasonValue;
|
||||
break;
|
||||
}
|
||||
|
||||
let toolbarSelector = ".browser-toolbar:not([collapsed=true])";
|
||||
if (AppConstants.platform == "macosx") {
|
||||
toolbarSelector += ":not([type=menubar])";
|
||||
}
|
||||
|
||||
// The getComputedStyle calls and setting the brighttext are separated in
|
||||
// two loops to avoid flushing layout and making it dirty repeatedly.
|
||||
let cachedLuminances = this._toolbarLuminanceCache;
|
||||
let luminances = new Map();
|
||||
for (let toolbar of document.querySelectorAll(toolbarSelector)) {
|
||||
// toolbars *should* all have ids, but guard anyway to avoid blowing up
|
||||
let cacheKey =
|
||||
toolbar.id && toolbar.id + JSON.stringify(this._windowState);
|
||||
// lookup cached luminance value for this toolbar in this window state
|
||||
let luminance = cacheKey && cachedLuminances.get(cacheKey);
|
||||
if (isNaN(luminance)) {
|
||||
let { r, g, b } = InspectorUtils.colorToRGBA(
|
||||
getComputedStyle(toolbar).color
|
||||
);
|
||||
luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
|
||||
if (cacheKey) {
|
||||
cachedLuminances.set(cacheKey, luminance);
|
||||
}
|
||||
}
|
||||
luminances.set(toolbar, luminance);
|
||||
}
|
||||
|
||||
const luminanceThreshold = 127; // In between 0 and 255
|
||||
for (let [toolbar, luminance] of luminances) {
|
||||
if (luminance <= luminanceThreshold) {
|
||||
toolbar.removeAttribute("brighttext");
|
||||
} else {
|
||||
toolbar.setAttribute("brighttext", "true");
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var PanicButtonNotifier = {
|
||||
init() {
|
||||
this._initialized = true;
|
||||
|
|
|
@ -30,11 +30,7 @@
|
|||
data-l10n-sync="true">
|
||||
<head>
|
||||
<!-- CSP might be disabled by C++ code. -->
|
||||
#if defined(EARLY_BETA_OR_EARLIER)
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src chrome: moz-src: resource: 'report-sample'" />
|
||||
#else
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src-attr 'none' 'report-sample'" />
|
||||
#endif
|
||||
|
||||
<!-- The "global.css" stylesheet is imported first to allow other stylesheets to
|
||||
override rules using selectors with the same specificity. This applies to
|
||||
|
|
|
@ -339,16 +339,31 @@
|
|||
</menupopup>
|
||||
|
||||
<menupopup id="sidebar-history-context-menu">
|
||||
<menuitem data-l10n-id="sidebar-history-context-menu-delete-page"
|
||||
id="sidebar-history-context-delete-page"/>
|
||||
<menuseparator/>
|
||||
<menuitem data-l10n-id="sidebar-context-menu-open-in-tab"
|
||||
id="sidebar-history-context-open-in-tab"/>
|
||||
<menu id="sidebar-history-context-menu-container-tab"
|
||||
data-l10n-id="sidebar-context-menu-open-in-container-tab"
|
||||
selection-type="single"
|
||||
node-type="link"
|
||||
hide-if-private-browsing="true"
|
||||
hide-if-usercontext-disabled="true">
|
||||
<menupopup id="sidebar-history-context-menu-container-popup"/>
|
||||
</menu>
|
||||
<menuitem data-l10n-id="sidebar-context-menu-open-in-window"
|
||||
id="sidebar-history-context-open-in-window"/>
|
||||
<menuitem data-l10n-id="sidebar-context-menu-open-in-private-window"
|
||||
id="sidebar-history-context-open-in-private-window"/>
|
||||
<menuseparator/>
|
||||
<menuitem data-l10n-id="sidebar-history-context-menu-delete-page-2"
|
||||
id="sidebar-history-context-delete-page"/>
|
||||
<menuitem data-l10n-id="sidebar-context-menu-forget-site"
|
||||
id="sidebar-history-context-forget-site"/>
|
||||
<menuseparator/>
|
||||
<menuitem data-l10n-id="sidebar-context-menu-copy-link"
|
||||
id="sidebar-history-context-copy-link"/>
|
||||
<menuseparator/>
|
||||
<menuitem data-l10n-id="sidebar-history-context-menu-bookmark-page"
|
||||
id="sidebar-history-context-bookmark-page"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="sidebar-synced-tabs-context-menu">
|
||||
|
|
|
@ -385,6 +385,16 @@ document.addEventListener(
|
|||
}
|
||||
});
|
||||
|
||||
const containerHistoryPopup = document.getElementById(
|
||||
"sidebar-history-context-menu-container-popup"
|
||||
);
|
||||
containerHistoryPopup.addEventListener("command", event =>
|
||||
PlacesUIUtils.openInContainerTab(event)
|
||||
);
|
||||
containerHistoryPopup.addEventListener("popupshowing", event =>
|
||||
PlacesUIUtils.createContainerTabMenu(event)
|
||||
);
|
||||
|
||||
document
|
||||
.getElementById("context_reopenInContainerPopupMenu")
|
||||
.addEventListener("command", event => {
|
||||
|
|
|
@ -463,9 +463,10 @@
|
|||
data-l10n-id="toolbar-button-account"
|
||||
cui-areatype="toolbar"
|
||||
removable="true">
|
||||
<vbox>
|
||||
<hbox>
|
||||
<image id="fxa-avatar-image"/>
|
||||
</vbox>
|
||||
<label id="fxa-avatar-label" hidden="true"/>
|
||||
</hbox>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbarbutton id="unified-extensions-button"
|
||||
|
|
|
@ -176,8 +176,6 @@ export class nsContextMenu {
|
|||
nsContextMenu.contentData = null;
|
||||
}
|
||||
|
||||
this.remoteType = this.actor?.domProcess?.remoteType;
|
||||
|
||||
const { gBrowser } = this.window;
|
||||
|
||||
this.shouldDisplay = context.shouldDisplay;
|
||||
|
@ -276,6 +274,8 @@ export class nsContextMenu {
|
|||
);
|
||||
}
|
||||
|
||||
this.remoteType = this.actor.manager.domProcess.remoteType;
|
||||
|
||||
this.selectedText = this.selectionInfo.text;
|
||||
this.isTextSelected = !!this.selectedText.length;
|
||||
this.webExtBrowserType = this.browser.getAttribute(
|
||||
|
|
|
@ -15,7 +15,7 @@ add_task(async function test_shortcut_key_label_in_fullscreen_menu_item() {
|
|||
const shortCutKeyLabel = isMac ? "\u2303\u2318F" : "F11";
|
||||
const enterMenuItemId = isMac ? "enterFullScreenItem" : "fullScreenItem";
|
||||
const exitMenuItemId = isMac ? "exitFullScreenItem" : "fullScreenItem";
|
||||
const accelKeyLabelSelector = ".menu-accel-container > label";
|
||||
const accelKeyLabelSelector = ".menu-accel";
|
||||
|
||||
const tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
|
|
|
@ -20,6 +20,10 @@ const PREF_ACCEPTED_POLICY_VERSION =
|
|||
PREF_BRANCH + "dataSubmissionPolicyAcceptedVersion";
|
||||
const PREF_ACCEPTED_POLICY_DATE =
|
||||
PREF_BRANCH + "dataSubmissionPolicyNotifiedTime";
|
||||
const PREF_TOS_ROLLOUT_POPULATION =
|
||||
"browser.preonboarding.onTrainRolloutPopulation";
|
||||
const PREF_TOS_ROLLOUT_ENROLLED =
|
||||
"browser.preonboarding.enrolledInOnTrainRollout";
|
||||
|
||||
const PREF_TELEMETRY_LOG_LEVEL = "toolkit.telemetry.log.level";
|
||||
|
||||
|
@ -127,6 +131,8 @@ add_setup(async function () {
|
|||
Preferences.set(PREF_BYPASS_NOTIFICATION, bypassNotification);
|
||||
Preferences.set(PREF_CURRENT_POLICY_VERSION, currentPolicyVersion);
|
||||
Preferences.reset(PREF_TELEMETRY_LOG_LEVEL);
|
||||
Preferences.reset(PREF_TOS_ROLLOUT_ENROLLED);
|
||||
Preferences.reset(PREF_TOS_ROLLOUT_POPULATION);
|
||||
|
||||
return closeAllNotifications();
|
||||
});
|
||||
|
@ -138,6 +144,9 @@ add_setup(async function () {
|
|||
// Ensure this isn't the first run, because then we open the first run page.
|
||||
Preferences.set(PREF_FIRST_RUN, false);
|
||||
TelemetryReportingPolicy.testUpdateFirstRun();
|
||||
// Do not trigger ToS modal for Linux, Mac, and MSIX builds
|
||||
Preferences.set(PREF_TOS_ROLLOUT_ENROLLED, false);
|
||||
Preferences.set(PREF_TOS_ROLLOUT_POPULATION, 0);
|
||||
});
|
||||
|
||||
function clearAcceptedPolicy() {
|
||||
|
|
|
@ -29,6 +29,7 @@ const startupPhases = {
|
|||
allowlist: {
|
||||
modules: new Set([
|
||||
"resource:///modules/BrowserGlue.sys.mjs",
|
||||
"moz-src:///browser/components/DesktopActorRegistry.sys.mjs",
|
||||
"resource:///modules/StartupRecorder.sys.mjs",
|
||||
"resource://gre/modules/AppConstants.sys.mjs",
|
||||
"resource://gre/modules/ActorManagerParent.sys.mjs",
|
||||
|
|
|
@ -20,6 +20,8 @@ add_task(async function () {
|
|||
|
||||
let unexpectedRects = 0;
|
||||
let alreadyFocused = false;
|
||||
let inRange = (val, min, max) => min <= val && val <= max;
|
||||
let tabBoundingRect = undefined;
|
||||
for (let i = 1; i < frames.length; ++i) {
|
||||
let frame = frames[i],
|
||||
previousFrame = frames[i - 1];
|
||||
|
@ -41,6 +43,22 @@ add_task(async function () {
|
|||
/**
|
||||
* Please don't add anything new unless justified!
|
||||
*/
|
||||
{
|
||||
name: "Shadow around active tab should not flicker on macOS (bug 1960967)",
|
||||
condition(r) {
|
||||
const tabRect = tabBoundingRect
|
||||
? tabBoundingRect
|
||||
: (tabBoundingRect = gBrowser.tabContainer
|
||||
.querySelector("tab[selected=true] .tab-background")
|
||||
.getBoundingClientRect());
|
||||
return (
|
||||
inRange(r.x1, tabRect.x - 2, tabRect.x + 2) &&
|
||||
inRange(r.y1, tabRect.y - 2, tabRect.y + 2) &&
|
||||
inRange(r.w, tabRect.width - 4, tabRect.width + 4) &&
|
||||
inRange(r.h, tabRect.height - 4, tabRect.height + 4)
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let rectText = `${rect.toSource()}, window width: ${width}`;
|
||||
|
|
|
@ -42,6 +42,8 @@ add_task(async function () {
|
|||
"We shouldn't have added any new expected reflows for window close."
|
||||
);
|
||||
|
||||
let inRange = (val, min, max) => min <= val && val <= max;
|
||||
let tabBoundingRect = undefined;
|
||||
await withPerfObserver(
|
||||
async function () {
|
||||
let promiseOrigBrowserFocused = TestUtils.waitForCondition(() => {
|
||||
|
@ -60,6 +62,24 @@ add_task(async function () {
|
|||
}
|
||||
return rects;
|
||||
},
|
||||
exceptions: [
|
||||
{
|
||||
name: "Shadow around active tab should not flicker on macOS (bug 1960967)",
|
||||
condition(r) {
|
||||
const tabRect = tabBoundingRect
|
||||
? tabBoundingRect
|
||||
: (tabBoundingRect = win.gBrowser.tabContainer
|
||||
.querySelector("tab[selected=true] .tab-background")
|
||||
.getBoundingClientRect());
|
||||
return (
|
||||
inRange(r.x1, tabRect.x - 2, tabRect.x + 2) &&
|
||||
inRange(r.y1, tabRect.y - 2, tabRect.y + 2) &&
|
||||
inRange(r.w, tabRect.width - 4, tabRect.width + 4) &&
|
||||
inRange(r.h, tabRect.height - 4, tabRect.height + 4)
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
win
|
||||
|
|
|
@ -41,6 +41,7 @@ add_task(async function () {
|
|||
|
||||
let alreadyFocused = false;
|
||||
let inRange = (val, min, max) => min <= val && val <= max;
|
||||
let tabBoundingRect = undefined;
|
||||
let expectations = {
|
||||
expectedReflows: EXPECTED_REFLOWS,
|
||||
frames: {
|
||||
|
@ -108,6 +109,22 @@ add_task(async function () {
|
|||
) && // in the toolbar
|
||||
inRange(r.x1, 30, 90), // close to the left of the screen
|
||||
},
|
||||
{
|
||||
name: "Shadow around active tab should not flicker on macOS (bug 1960967)",
|
||||
condition(r) {
|
||||
const tabRect = tabBoundingRect
|
||||
? tabBoundingRect
|
||||
: (tabBoundingRect = gBrowser.tabContainer
|
||||
.querySelector("tab[selected=true] .tab-background")
|
||||
.getBoundingClientRect());
|
||||
return (
|
||||
inRange(r.x1, tabRect.x - 2, tabRect.x + 2) &&
|
||||
inRange(r.y1, tabRect.y - 2, tabRect.y + 2) &&
|
||||
inRange(r.w, tabRect.width - 4, tabRect.width + 4) &&
|
||||
inRange(r.h, tabRect.height - 4, tabRect.height + 4)
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ function dirtyFrame(win) {
|
|||
* @param win (browser window, optional)
|
||||
* The browser window to monitor. Defaults to the current window.
|
||||
*
|
||||
* @return An array of reflow stacks
|
||||
* @return An array of reflow stacks and paths
|
||||
*/
|
||||
async function recordReflows(testPromise, win = window) {
|
||||
// Collect all reflow stacks, we'll process them later.
|
||||
|
@ -44,7 +44,33 @@ async function recordReflows(testPromise, win = window) {
|
|||
let observer = {
|
||||
reflow() {
|
||||
// Gather information about the current code path.
|
||||
reflows.push(new Error().stack);
|
||||
let stack = new Error().stack;
|
||||
let path = stack
|
||||
.trim()
|
||||
.split("\n")
|
||||
.slice(1) // the first frame which is our test code.
|
||||
.map(line => line.replace(/:\d+:\d+$/, "")); // strip line numbers.
|
||||
|
||||
// Stack trace is empty. Reflow was triggered by native code, which
|
||||
// we ignore.
|
||||
if (path.length === 0) {
|
||||
ChromeUtils.addProfilerMarker(
|
||||
"ignoredNativeReflow",
|
||||
{ category: "Test" },
|
||||
"Intentionally ignoring reflow without JS stack"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
path[0] ===
|
||||
"forceRefreshDriverTick@chrome://mochikit/content/tests/SimpleTest/AccessibilityUtils.js"
|
||||
) {
|
||||
// a11y-checks fake a refresh driver tick.
|
||||
return;
|
||||
}
|
||||
|
||||
reflows.push({ stack, path: path.join("|") });
|
||||
|
||||
// Just in case, dirty the frame now that we've reflowed. This will
|
||||
// allow us to detect additional reflows that occur in this same tick
|
||||
|
@ -59,8 +85,8 @@ async function recordReflows(testPromise, win = window) {
|
|||
},
|
||||
|
||||
reflowInterruptible() {
|
||||
// Interruptible reflows are the reflows caused by the refresh
|
||||
// driver ticking. These are fine.
|
||||
// Interruptible reflows are always triggered by native code, like the
|
||||
// refresh driver. These are fine.
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
|
@ -152,19 +178,7 @@ function reportUnexpectedReflows(reflows, expectedReflows = []) {
|
|||
);
|
||||
}
|
||||
|
||||
for (let stack of reflows) {
|
||||
let path = stack
|
||||
.split("\n")
|
||||
.slice(1) // the first frame which is our test code.
|
||||
.map(line => line.replace(/:\d+:\d+$/, "")) // strip line numbers.
|
||||
.join("|");
|
||||
|
||||
// Stack trace is empty. Reflow was triggered by native code, which
|
||||
// we ignore.
|
||||
if (path === "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let { stack, path } of reflows) {
|
||||
// Functions from EventUtils.js calculate coordinates and
|
||||
// dimensions, causing us to reflow. That's the test
|
||||
// harness and we don't care about that, so we'll filter that out.
|
||||
|
|
|
@ -13,6 +13,8 @@ support-files = ["head.js"]
|
|||
["browser_all_files_referenced.js"]
|
||||
skip-if = ["verify && bits == 32"] # Causes OOMs when run repeatedly
|
||||
|
||||
["browser_glean_metrics_exist.js"]
|
||||
|
||||
["browser_misused_characters_in_strings.js"]
|
||||
support-files = ["bug1262648_string_with_newlines.dtd"]
|
||||
skip-if = ["os == 'win' && msix"] # Permafail on MSIX packages due to it running on files it shouldn't.
|
||||
|
@ -24,8 +26,6 @@ skip-if = ["os == 'win' && msix"] # Permafail on MSIX packages due to it running
|
|||
["browser_parsable_script.js"]
|
||||
skip-if = ["ccov && os == 'linux'"] # https://bugzilla.mozilla.org/show_bug.cgi?id=1608081
|
||||
|
||||
["browser_glean_metrics_exist.js"]
|
||||
|
||||
["browser_sentence_case_strings.js"]
|
||||
|
||||
["browser_title_case_menus.js"]
|
||||
|
|
|
@ -214,7 +214,8 @@ add_task(async function test_ui_state_signedin() {
|
|||
"PanelUI-fxa-menu-account-signout-button",
|
||||
],
|
||||
disabledItems: [],
|
||||
hiddenItems: ["PanelUI-fxa-menu-setup-sync-button"],
|
||||
hiddenItems: ["PanelUI-fxa-menu-setup-sync-container"],
|
||||
visibleItems: [],
|
||||
});
|
||||
|
||||
await checkProfilesButtons(
|
||||
|
@ -431,7 +432,6 @@ add_task(async function test_ui_state_signed_in() {
|
|||
enabledItems: [
|
||||
"PanelUI-fxa-menu-sendtab-button",
|
||||
"PanelUI-fxa-menu-connect-device-button",
|
||||
"PanelUI-fxa-menu-setup-sync-button",
|
||||
"PanelUI-fxa-menu-account-signout-button",
|
||||
],
|
||||
disabledItems: [],
|
||||
|
@ -439,6 +439,7 @@ add_task(async function test_ui_state_signed_in() {
|
|||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
],
|
||||
visibleItems: ["PanelUI-fxa-menu-setup-sync-container"],
|
||||
});
|
||||
checkFxAAvatar("signedin");
|
||||
await closeFxaPanel();
|
||||
|
@ -476,7 +477,6 @@ add_task(async function test_ui_state_signed_in_no_display_name() {
|
|||
enabledItems: [
|
||||
"PanelUI-fxa-menu-sendtab-button",
|
||||
"PanelUI-fxa-menu-connect-device-button",
|
||||
"PanelUI-fxa-menu-setup-sync-button",
|
||||
"PanelUI-fxa-menu-account-signout-button",
|
||||
],
|
||||
disabledItems: [],
|
||||
|
@ -484,6 +484,7 @@ add_task(async function test_ui_state_signed_in_no_display_name() {
|
|||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
],
|
||||
visibleItems: ["PanelUI-fxa-menu-setup-sync-container"],
|
||||
});
|
||||
checkFxAAvatar("signedin");
|
||||
await closeFxaPanel();
|
||||
|
@ -523,7 +524,6 @@ add_task(async function test_ui_state_unverified() {
|
|||
headerDescription: state.email,
|
||||
enabledItems: [
|
||||
"PanelUI-fxa-menu-sendtab-button",
|
||||
"PanelUI-fxa-menu-setup-sync-button",
|
||||
"PanelUI-fxa-menu-account-signout-button",
|
||||
],
|
||||
disabledItems: ["PanelUI-fxa-menu-connect-device-button"],
|
||||
|
@ -531,6 +531,7 @@ add_task(async function test_ui_state_unverified() {
|
|||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
],
|
||||
visibleItems: ["PanelUI-fxa-menu-setup-sync-container"],
|
||||
});
|
||||
checkFxAAvatar("unverified");
|
||||
await closeFxaPanel();
|
||||
|
@ -570,7 +571,6 @@ add_task(async function test_ui_state_loginFailed() {
|
|||
headerDescription: state.displayName,
|
||||
enabledItems: [
|
||||
"PanelUI-fxa-menu-sendtab-button",
|
||||
"PanelUI-fxa-menu-setup-sync-button",
|
||||
"PanelUI-fxa-menu-account-signout-button",
|
||||
],
|
||||
disabledItems: ["PanelUI-fxa-menu-connect-device-button"],
|
||||
|
@ -578,6 +578,7 @@ add_task(async function test_ui_state_loginFailed() {
|
|||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
],
|
||||
visibleItems: ["PanelUI-fxa-menu-setup-sync-container"],
|
||||
});
|
||||
checkFxAAvatar("login-failed");
|
||||
await closeFxaPanel();
|
||||
|
@ -691,6 +692,7 @@ add_task(async function test_experiment_ui_state_unconfigured() {
|
|||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
],
|
||||
visibleItems: [],
|
||||
});
|
||||
|
||||
// Revert the pref at the end of the test
|
||||
|
@ -759,7 +761,8 @@ add_task(async function test_experiment_ui_state_signedin() {
|
|||
"PanelUI-fxa-menu-vpn-button",
|
||||
],
|
||||
disabledItems: [],
|
||||
hiddenItems: ["PanelUI-fxa-menu-setup-sync-button"],
|
||||
hiddenItems: ["PanelUI-fxa-menu-setup-sync-container"],
|
||||
visibleItems: [],
|
||||
});
|
||||
checkFxAAvatar("signedin");
|
||||
gSync.relativeTimeFormat = origRelativeTimeFormat;
|
||||
|
@ -781,16 +784,7 @@ add_task(async function test_experiment_ui_state_signedin() {
|
|||
await closeTabAndMainPanel();
|
||||
});
|
||||
|
||||
add_task(async function test_new_sync_setup_ui_exp_enabled() {
|
||||
// Enroll in the experiment with the feature enabled
|
||||
await ExperimentAPI.ready();
|
||||
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: NimbusFeatures.syncSetupFlow.featureId,
|
||||
value: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
add_task(async function test_new_sync_setup_ui() {
|
||||
let state = {
|
||||
status: UIState.STATUS_SIGNED_IN,
|
||||
syncEnabled: false,
|
||||
|
@ -811,20 +805,21 @@ add_task(async function test_new_sync_setup_ui_exp_enabled() {
|
|||
headerDescription: "Foo Bar",
|
||||
enabledItems: [
|
||||
"PanelUI-fxa-menu-sendtab-button",
|
||||
"PanelUI-fxa-menu-setup-sync-container", // New set-up element should be visible
|
||||
"PanelUI-fxa-menu-account-signout-button",
|
||||
"PanelUI-fxa-menu-connect-device-button",
|
||||
],
|
||||
disabledItems: [],
|
||||
hiddenItems: [
|
||||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
"PanelUI-fxa-menu-connect-device-button", // CAD should also be hidden
|
||||
"PanelUI-fxa-menu-setup-sync-button", // Old button should be hidden
|
||||
],
|
||||
visibleItems: [
|
||||
"PanelUI-fxa-menu-setup-sync-container",
|
||||
"PanelUI-fxa-menu-connect-device-button",
|
||||
],
|
||||
});
|
||||
|
||||
await closeFxaPanel();
|
||||
await doCleanup();
|
||||
|
||||
// We need to reset the panel back to hidden since in the code we flip between the old and new sync setup ids
|
||||
// so subsequent tests will fail if checking this new container
|
||||
|
@ -834,52 +829,6 @@ add_task(async function test_new_sync_setup_ui_exp_enabled() {
|
|||
newSyncSetup.setAttribute("hidden", true);
|
||||
});
|
||||
|
||||
add_task(async function test_new_sync_setup_ui_no_exp() {
|
||||
// Enroll in the experiment with the feature disabled
|
||||
await ExperimentAPI.ready();
|
||||
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: NimbusFeatures.syncSetupFlow.featureId,
|
||||
value: {
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
let state = {
|
||||
status: UIState.STATUS_SIGNED_IN,
|
||||
syncEnabled: false,
|
||||
email: "foo@bar.com",
|
||||
displayName: "Foo Bar",
|
||||
avatarURL: "https://foo.bar",
|
||||
};
|
||||
|
||||
gSync.updateAllUI(state);
|
||||
|
||||
await openFxaPanel();
|
||||
|
||||
checkMenuBarItem("sync-enable");
|
||||
checkPanelHeader();
|
||||
|
||||
checkFxaToolbarButtonPanel({
|
||||
headerTitle: "Manage account",
|
||||
headerDescription: "Foo Bar",
|
||||
enabledItems: [
|
||||
"PanelUI-fxa-menu-sendtab-button",
|
||||
"PanelUI-fxa-menu-connect-device-button",
|
||||
"PanelUI-fxa-menu-setup-sync-button", // Old setup button should be visible
|
||||
"PanelUI-fxa-menu-account-signout-button",
|
||||
],
|
||||
disabledItems: [],
|
||||
hiddenItems: [
|
||||
"PanelUI-fxa-menu-syncnow-button",
|
||||
"PanelUI-fxa-menu-sync-prefs-button",
|
||||
"PanelUI-fxa-menu-setup-sync-container", // New setup container should be hidden
|
||||
],
|
||||
});
|
||||
|
||||
await doCleanup();
|
||||
await closeFxaPanel();
|
||||
});
|
||||
|
||||
// Ensure we can see the new "My services" section if the user has enabled relay on their account
|
||||
add_task(async function test_ui_my_services_signedin() {
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com/");
|
||||
|
@ -938,9 +887,10 @@ add_task(async function test_ui_my_services_signedin() {
|
|||
],
|
||||
disabledItems: [],
|
||||
hiddenItems: [
|
||||
"PanelUI-fxa-menu-setup-sync-button",
|
||||
"PanelUI-fxa-menu-setup-sync-container",
|
||||
"PanelUI-fxa-menu-relay-button", // the relay button in the "other protections" side should be hidden
|
||||
],
|
||||
visibleItems: [],
|
||||
});
|
||||
checkFxAAvatar("signedin");
|
||||
gSync.relativeTimeFormat = origRelativeTimeFormat;
|
||||
|
@ -962,6 +912,91 @@ add_task(async function test_ui_my_services_signedin() {
|
|||
await closeTabAndMainPanel();
|
||||
});
|
||||
|
||||
add_task(async function test_experiment_signin_button_signed_out() {
|
||||
// Enroll in Nimbus experiment
|
||||
await ExperimentAPI.ready();
|
||||
let cleanupNimbus = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: NimbusFeatures.expandSignInButton.featureId,
|
||||
value: {
|
||||
ctaCopyVariant: "fxa-avatar-sign-in",
|
||||
},
|
||||
});
|
||||
|
||||
// Set UI state to STATUS_NOT_CONFIGURED (signed out)
|
||||
let state = { status: UIState.STATUS_NOT_CONFIGURED };
|
||||
gSync.updateAllUI(state);
|
||||
|
||||
const fxaAvatarLabel = document.getElementById("fxa-avatar-label");
|
||||
ok(fxaAvatarLabel, "Avatar label element should exist");
|
||||
is(
|
||||
fxaAvatarLabel.hidden,
|
||||
false,
|
||||
"Avatar label should be visible when Nimbus experiment is enabled"
|
||||
);
|
||||
|
||||
const expectedLabel =
|
||||
gSync.fluentStrings.formatValueSync("fxa-avatar-sign-in");
|
||||
|
||||
is(
|
||||
fxaAvatarLabel.getAttribute("value"),
|
||||
expectedLabel,
|
||||
`Avatar label should have the expected localized value: ${expectedLabel}`
|
||||
);
|
||||
|
||||
// Clean up experiment
|
||||
await cleanupNimbus();
|
||||
|
||||
// Reset UI state after experiment cleanup
|
||||
gSync.updateAllUI(state);
|
||||
|
||||
is(
|
||||
fxaAvatarLabel.hidden,
|
||||
true,
|
||||
"Avatar label should be hidden after Nimbus experiment is cleaned up"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_experiment_signin_button_signed_in() {
|
||||
// Enroll in Nimbus experiment
|
||||
await ExperimentAPI.ready();
|
||||
let cleanupNimbus = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: NimbusFeatures.expandSignInButton.featureId,
|
||||
value: {
|
||||
ctaCopyVariant: "fxa-avatar-sign-in",
|
||||
},
|
||||
});
|
||||
|
||||
let state = {
|
||||
status: UIState.STATUS_SIGNED_IN,
|
||||
syncEnabled: true,
|
||||
email: "foo@bar.com",
|
||||
displayName: "Foo Bar",
|
||||
avatarURL: "https://foo.bar",
|
||||
lastSync: new Date(),
|
||||
syncing: false,
|
||||
};
|
||||
gSync.updateAllUI(state);
|
||||
|
||||
const fxaAvatarLabel = document.getElementById("fxa-avatar-label");
|
||||
is(
|
||||
fxaAvatarLabel.hidden,
|
||||
true,
|
||||
"Avatar label should never be visible when signed in"
|
||||
);
|
||||
|
||||
// Clean up experiment
|
||||
await cleanupNimbus();
|
||||
|
||||
// Reset UI state after experiment cleanup
|
||||
gSync.updateAllUI(state);
|
||||
|
||||
is(
|
||||
fxaAvatarLabel.hidden,
|
||||
true,
|
||||
"Avatar label should still be hidden when signed in without experiment"
|
||||
);
|
||||
});
|
||||
|
||||
function checkPanelUIStatusBar({
|
||||
description,
|
||||
title,
|
||||
|
@ -1053,6 +1088,7 @@ async function checkFxaToolbarButtonPanel({
|
|||
enabledItems,
|
||||
disabledItems,
|
||||
hiddenItems,
|
||||
visibleItems,
|
||||
}) {
|
||||
is(
|
||||
document.getElementById("fxa-menu-header-title").value,
|
||||
|
@ -1079,6 +1115,25 @@ async function checkFxaToolbarButtonPanel({
|
|||
const el = document.getElementById(id);
|
||||
is(el.getAttribute("hidden"), "true", id + " is hidden");
|
||||
}
|
||||
|
||||
for (const id of visibleItems) {
|
||||
const el = document.getElementById(id);
|
||||
ok(isElementVisible(el), `${id} is visible`);
|
||||
}
|
||||
}
|
||||
|
||||
function isElementVisible(el) {
|
||||
if (!el) {
|
||||
return false;
|
||||
}
|
||||
let style = window.getComputedStyle(el);
|
||||
// The “hidden” property on the element itself
|
||||
// might not exist or might be false, so we also
|
||||
// check that the computed style is not hiding it
|
||||
// (display: none or visibility: hidden).
|
||||
return (
|
||||
!el.hidden && style.display !== "none" && style.visibility !== "hidden"
|
||||
);
|
||||
}
|
||||
|
||||
async function checkProfilesButtons(
|
||||
|
|
|
@ -43,14 +43,14 @@ support-files = ["openPromptOffTimeout.html"]
|
|||
|
||||
["browser_promptFocus.js"]
|
||||
|
||||
["browser_prompt_close_event.js"]
|
||||
|
||||
["browser_prompt_close_groups.js"]
|
||||
support-files = ["file_beforeunload_stop.html"]
|
||||
fail-if = [
|
||||
"a11y_checks",
|
||||
] # Bug 1953248 a11y_checks fails when testing multiple tab prompts
|
||||
|
||||
["browser_prompt_close_event.js"]
|
||||
|
||||
["browser_prompt_closed_window.js"]
|
||||
|
||||
["browser_switchTabPermissionPrompt.js"]
|
||||
|
|
|
@ -54,6 +54,11 @@ category browser-idle-startup resource://gre/modules/UpdateListener.sys.mjs Upda
|
|||
category browser-idle-startup resource:///modules/WindowsJumpLists.sys.mjs WinTaskbarJumpList.startup
|
||||
#endif
|
||||
|
||||
# Note that these telemetry entries schedule their own idle tasks,
|
||||
# so they are guaranteed to run after everything else.
|
||||
category browser-idle-startup moz-src:///browser/components/StartupTelemetry.sys.mjs StartupTelemetry.browserIdleStartup
|
||||
category browser-best-effort-idle-startup moz-src:///browser/components/StartupTelemetry.sys.mjs StartupTelemetry.bestEffortIdleStartup
|
||||
|
||||
# App shutdown consumers
|
||||
category browser-quit-application-granted resource:///modules/BrowserUsageTelemetry.sys.mjs BrowserUsageTelemetry.uninit
|
||||
category browser-quit-application-granted resource:///modules/Interactions.sys.mjs Interactions.uninit
|
||||
|
|
File diff suppressed because it is too large
Load diff
232
browser/components/DefaultBrowserCheck.sys.mjs
Normal file
232
browser/components/DefaultBrowserCheck.sys.mjs
Normal file
|
@ -0,0 +1,232 @@
|
|||
/* 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/. */
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
let lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
|
||||
CommonDialog: "resource://gre/modules/CommonDialog.sys.mjs",
|
||||
SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
|
||||
});
|
||||
|
||||
export var DefaultBrowserCheck = {
|
||||
async prompt(win) {
|
||||
const shellService = win.getShellService();
|
||||
const needPin =
|
||||
(await shellService.doesAppNeedPin()) ||
|
||||
(await shellService.doesAppNeedStartMenuPin());
|
||||
|
||||
win.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
|
||||
win.MozXULElement.insertFTLIfNeeded(
|
||||
"browser/defaultBrowserNotification.ftl"
|
||||
);
|
||||
// Record default prompt impression
|
||||
let now = Math.floor(Date.now() / 1000).toString();
|
||||
Services.prefs.setCharPref(
|
||||
"browser.shell.mostRecentDefaultPromptSeen",
|
||||
now
|
||||
);
|
||||
|
||||
// Resolve the translations for the prompt elements and return only the
|
||||
// string values
|
||||
|
||||
let pinMessage;
|
||||
if (AppConstants.platform == "macosx") {
|
||||
pinMessage = "default-browser-prompt-message-pin-mac";
|
||||
} else if (
|
||||
AppConstants.platform == "win" &&
|
||||
Services.sysinfo.getProperty("hasWinPackageId", false)
|
||||
) {
|
||||
pinMessage = "default-browser-prompt-message-pin-msix";
|
||||
} else {
|
||||
pinMessage = "default-browser-prompt-message-pin";
|
||||
}
|
||||
let [promptTitle, promptMessage, askLabel, yesButton, notNowButton] = (
|
||||
await win.document.l10n.formatMessages([
|
||||
{
|
||||
id: needPin
|
||||
? "default-browser-prompt-title-pin"
|
||||
: "default-browser-prompt-title-alt",
|
||||
},
|
||||
{
|
||||
id: needPin ? pinMessage : "default-browser-prompt-message-alt",
|
||||
},
|
||||
{ id: "default-browser-prompt-checkbox-not-again-label" },
|
||||
{
|
||||
id: needPin
|
||||
? "default-browser-prompt-button-primary-set"
|
||||
: "default-browser-prompt-button-primary-alt",
|
||||
},
|
||||
{ id: "default-browser-prompt-button-secondary" },
|
||||
])
|
||||
).map(({ value }) => value);
|
||||
|
||||
let ps = Services.prompt;
|
||||
let buttonFlags =
|
||||
ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0 +
|
||||
ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_1 +
|
||||
ps.BUTTON_POS_0_DEFAULT;
|
||||
let rv = await ps.asyncConfirmEx(
|
||||
win.browsingContext,
|
||||
ps.MODAL_TYPE_INTERNAL_WINDOW,
|
||||
promptTitle,
|
||||
promptMessage,
|
||||
buttonFlags,
|
||||
yesButton,
|
||||
notNowButton,
|
||||
null,
|
||||
askLabel,
|
||||
false, // checkbox state
|
||||
{
|
||||
headerIconCSSValue: lazy.CommonDialog.DEFAULT_APP_ICON_CSS,
|
||||
}
|
||||
);
|
||||
let buttonNumClicked = rv.get("buttonNumClicked");
|
||||
let checkboxState = rv.get("checked");
|
||||
if (buttonNumClicked == 0) {
|
||||
// We must explicitly await pinning to the taskbar before
|
||||
// trying to set as default. If we fall back to setting
|
||||
// as default through the Windows Settings menu that interferes
|
||||
// with showing the pinning notification as we no longer have
|
||||
// window focus.
|
||||
try {
|
||||
await shellService.pinToTaskbar();
|
||||
} catch (e) {
|
||||
this.log.error("Failed to pin to taskbar", e);
|
||||
}
|
||||
try {
|
||||
await shellService.pinToStartMenu();
|
||||
} catch (e) {
|
||||
this.log.error("Failed to pin to Start Menu", e);
|
||||
}
|
||||
try {
|
||||
await shellService.setAsDefault();
|
||||
} catch (e) {
|
||||
this.log.error("Failed to set the default browser", e);
|
||||
}
|
||||
}
|
||||
if (checkboxState) {
|
||||
shellService.shouldCheckDefaultBrowser = false;
|
||||
Services.prefs.setCharPref("browser.shell.userDisabledDefaultCheck", now);
|
||||
}
|
||||
|
||||
try {
|
||||
let resultEnum = buttonNumClicked * 2 + !checkboxState;
|
||||
Glean.browser.setDefaultResult.accumulateSingleSample(resultEnum);
|
||||
} catch (ex) {
|
||||
/* Don't break if Telemetry is acting up. */
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the default browser check prompt will be shown.
|
||||
*
|
||||
* @param {boolean} isStartupCheck
|
||||
* If true, prefs will be set and telemetry will be recorded.
|
||||
* @returns {boolean} True if the default browser check prompt will be shown.
|
||||
*/
|
||||
async willCheckDefaultBrowser(isStartupCheck) {
|
||||
let win = lazy.BrowserWindowTracker.getTopWindow();
|
||||
let shellService = win.getShellService();
|
||||
|
||||
// Perform default browser checking.
|
||||
if (!shellService) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let shouldCheck =
|
||||
!AppConstants.DEBUG && shellService.shouldCheckDefaultBrowser;
|
||||
|
||||
// Even if we shouldn't check the default browser, we still continue when
|
||||
// isStartupCheck = true to set prefs and telemetry.
|
||||
if (!shouldCheck && !isStartupCheck) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip the "Set Default Browser" check during first-run or after the
|
||||
// browser has been run a few times.
|
||||
const skipDefaultBrowserCheck =
|
||||
Services.prefs.getBoolPref(
|
||||
"browser.shell.skipDefaultBrowserCheckOnFirstRun"
|
||||
) &&
|
||||
!Services.prefs.getBoolPref(
|
||||
"browser.shell.didSkipDefaultBrowserCheckOnFirstRun"
|
||||
);
|
||||
|
||||
let promptCount = Services.prefs.getIntPref(
|
||||
"browser.shell.defaultBrowserCheckCount",
|
||||
0
|
||||
);
|
||||
|
||||
// If SessionStartup's state is not initialized, checking sessionType will set
|
||||
// its internal state to "do not restore".
|
||||
await lazy.SessionStartup.onceInitialized;
|
||||
let willRecoverSession =
|
||||
lazy.SessionStartup.sessionType == lazy.SessionStartup.RECOVER_SESSION;
|
||||
|
||||
// Don't show the prompt if we're already the default browser.
|
||||
let isDefault = false;
|
||||
let isDefaultError = false;
|
||||
try {
|
||||
isDefault = shellService.isDefaultBrowser(isStartupCheck, false);
|
||||
} catch (ex) {
|
||||
isDefaultError = true;
|
||||
}
|
||||
|
||||
if (isDefault && isStartupCheck) {
|
||||
let now = Math.floor(Date.now() / 1000).toString();
|
||||
Services.prefs.setCharPref(
|
||||
"browser.shell.mostRecentDateSetAsDefault",
|
||||
now
|
||||
);
|
||||
}
|
||||
|
||||
let willPrompt = shouldCheck && !isDefault && !willRecoverSession;
|
||||
|
||||
if (willPrompt) {
|
||||
if (skipDefaultBrowserCheck) {
|
||||
if (isStartupCheck) {
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.shell.didSkipDefaultBrowserCheckOnFirstRun",
|
||||
true
|
||||
);
|
||||
}
|
||||
willPrompt = false;
|
||||
} else {
|
||||
promptCount++;
|
||||
if (isStartupCheck) {
|
||||
Services.prefs.setIntPref(
|
||||
"browser.shell.defaultBrowserCheckCount",
|
||||
promptCount
|
||||
);
|
||||
}
|
||||
if (!AppConstants.RELEASE_OR_BETA && promptCount > 3) {
|
||||
willPrompt = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isStartupCheck) {
|
||||
try {
|
||||
// Report default browser status on startup to telemetry
|
||||
// so we can track whether we are the default.
|
||||
Glean.browser.isUserDefault[isDefault ? "true" : "false"].add();
|
||||
Glean.browser.isUserDefaultError[
|
||||
isDefaultError ? "true" : "false"
|
||||
].add();
|
||||
Glean.browser.setDefaultAlwaysCheck[
|
||||
shouldCheck ? "true" : "false"
|
||||
].add();
|
||||
Glean.browser.setDefaultDialogPromptRawcount.accumulateSingleSample(
|
||||
promptCount
|
||||
);
|
||||
} catch (ex) {
|
||||
/* Don't break the default prompt if telemetry is broken. */
|
||||
}
|
||||
}
|
||||
|
||||
return willPrompt;
|
||||
},
|
||||
};
|
831
browser/components/DesktopActorRegistry.sys.mjs
Normal file
831
browser/components/DesktopActorRegistry.sys.mjs
Normal file
|
@ -0,0 +1,831 @@
|
|||
/* 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/. */
|
||||
|
||||
import { ActorManagerParent } from "resource://gre/modules/ActorManagerParent.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
|
||||
SelectableProfileService:
|
||||
"resource:///modules/profiles/SelectableProfileService.sys.mjs",
|
||||
});
|
||||
|
||||
/**
|
||||
* Fission-compatible JSProcess implementations.
|
||||
* Each actor options object takes the form of a ProcessActorOptions dictionary.
|
||||
* Detailed documentation of these options is in dom/docs/ipc/jsactors.rst,
|
||||
* available at https://firefox-source-docs.mozilla.org/dom/ipc/jsactors.html
|
||||
*/
|
||||
let JSPROCESSACTORS = {
|
||||
// Miscellaneous stuff that needs to be initialized per process.
|
||||
BrowserProcess: {
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/BrowserProcessChild.sys.mjs",
|
||||
observers: [
|
||||
// WebRTC related notifications. They are here to avoid loading WebRTC
|
||||
// components when not needed.
|
||||
"getUserMedia:request",
|
||||
"recording-device-stopped",
|
||||
"PeerConnection:request",
|
||||
"recording-device-events",
|
||||
"recording-window-ended",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
RefreshBlockerObserver: {
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/RefreshBlockerChild.sys.mjs",
|
||||
observers: [
|
||||
"webnavigation-create",
|
||||
"chrome-webnavigation-create",
|
||||
"webnavigation-destroy",
|
||||
"chrome-webnavigation-destroy",
|
||||
],
|
||||
},
|
||||
|
||||
enablePreference: "accessibility.blockautorefresh",
|
||||
onPreferenceChanged: isEnabled => {
|
||||
lazy.BrowserWindowTracker.orderedWindows.forEach(win => {
|
||||
for (let browser of win.gBrowser.browsers) {
|
||||
try {
|
||||
browser.sendMessageToActor(
|
||||
"PreferenceChanged",
|
||||
{ isEnabled },
|
||||
"RefreshBlocker",
|
||||
"all"
|
||||
);
|
||||
} catch (ex) {}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Fission-compatible JSWindowActor implementations.
|
||||
* Detailed documentation of these options is in dom/docs/ipc/jsactors.rst,
|
||||
* available at https://firefox-source-docs.mozilla.org/dom/ipc/jsactors.html
|
||||
*/
|
||||
let JSWINDOWACTORS = {
|
||||
Megalist: {
|
||||
parent: {
|
||||
esModuleURI: "resource://gre/actors/MegalistParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource://gre/actors/MegalistChild.sys.mjs",
|
||||
events: {
|
||||
DOMContentLoaded: {},
|
||||
},
|
||||
},
|
||||
includeChrome: true,
|
||||
matches: ["chrome://global/content/megalist/megalist.html"],
|
||||
allFrames: true,
|
||||
enablePreference: "browser.contextual-password-manager.enabled",
|
||||
},
|
||||
|
||||
AboutLogins: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutLoginsParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutLoginsChild.sys.mjs",
|
||||
events: {
|
||||
AboutLoginsCopyLoginDetail: { wantUntrusted: true },
|
||||
AboutLoginsCreateLogin: { wantUntrusted: true },
|
||||
AboutLoginsDeleteLogin: { wantUntrusted: true },
|
||||
AboutLoginsDismissBreachAlert: { wantUntrusted: true },
|
||||
AboutLoginsImportFromBrowser: { wantUntrusted: true },
|
||||
AboutLoginsImportFromFile: { wantUntrusted: true },
|
||||
AboutLoginsImportReportInit: { wantUntrusted: true },
|
||||
AboutLoginsImportReportReady: { wantUntrusted: true },
|
||||
AboutLoginsInit: { wantUntrusted: true },
|
||||
AboutLoginsGetHelp: { wantUntrusted: true },
|
||||
AboutLoginsOpenPreferences: { wantUntrusted: true },
|
||||
AboutLoginsOpenSite: { wantUntrusted: true },
|
||||
AboutLoginsRecordTelemetryEvent: { wantUntrusted: true },
|
||||
AboutLoginsRemoveAllLogins: { wantUntrusted: true },
|
||||
AboutLoginsSortChanged: { wantUntrusted: true },
|
||||
AboutLoginsSyncEnable: { wantUntrusted: true },
|
||||
AboutLoginsUpdateLogin: { wantUntrusted: true },
|
||||
AboutLoginsExportPasswords: { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:logins", "about:logins?*", "about:loginsimportreport"],
|
||||
allFrames: true,
|
||||
remoteTypes: ["privilegedabout"],
|
||||
},
|
||||
|
||||
AboutMessagePreview: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutMessagePreviewParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutMessagePreviewChild.sys.mjs",
|
||||
events: {
|
||||
DOMDocElementInserted: { capture: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:messagepreview", "about:messagepreview?*"],
|
||||
},
|
||||
|
||||
AboutPocket: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutPocketParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutPocketChild.sys.mjs",
|
||||
|
||||
events: {
|
||||
DOMDocElementInserted: { capture: true },
|
||||
},
|
||||
},
|
||||
|
||||
remoteTypes: ["privilegedabout"],
|
||||
matches: [
|
||||
"about:pocket-saved*",
|
||||
"about:pocket-signup*",
|
||||
"about:pocket-home*",
|
||||
"about:pocket-style-guide*",
|
||||
],
|
||||
},
|
||||
|
||||
AboutPrivateBrowsing: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutPrivateBrowsingParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutPrivateBrowsingChild.sys.mjs",
|
||||
|
||||
events: {
|
||||
DOMDocElementInserted: { capture: true },
|
||||
},
|
||||
},
|
||||
|
||||
matches: ["about:privatebrowsing*"],
|
||||
},
|
||||
|
||||
AboutProtections: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutProtectionsParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutProtectionsChild.sys.mjs",
|
||||
|
||||
events: {
|
||||
DOMDocElementInserted: { capture: true },
|
||||
},
|
||||
},
|
||||
|
||||
matches: ["about:protections", "about:protections?*"],
|
||||
},
|
||||
|
||||
AboutReader: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutReaderParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutReaderChild.sys.mjs",
|
||||
events: {
|
||||
DOMContentLoaded: {},
|
||||
pageshow: { mozSystemGroup: true },
|
||||
// Don't try to create the actor if only the pagehide event fires.
|
||||
// This can happen with the initial about:blank documents.
|
||||
pagehide: { mozSystemGroup: true, createActor: false },
|
||||
},
|
||||
},
|
||||
messageManagerGroups: ["browsers"],
|
||||
},
|
||||
|
||||
AboutTabCrashed: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutTabCrashedParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutTabCrashedChild.sys.mjs",
|
||||
events: {
|
||||
DOMDocElementInserted: { capture: true },
|
||||
},
|
||||
},
|
||||
|
||||
matches: ["about:tabcrashed*"],
|
||||
},
|
||||
|
||||
AboutWelcomeShopping: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutWelcomeParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutWelcomeChild.sys.mjs",
|
||||
events: {
|
||||
Update: {},
|
||||
},
|
||||
},
|
||||
matches: ["about:shoppingsidebar"],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
messageManagerGroups: ["shopping-sidebar", "browsers", "review-checker"],
|
||||
},
|
||||
|
||||
AboutWelcome: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/AboutWelcomeParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/AboutWelcomeChild.sys.mjs",
|
||||
events: {
|
||||
// This is added so the actor instantiates immediately and makes
|
||||
// methods available to the page js on load.
|
||||
DOMDocElementInserted: {},
|
||||
},
|
||||
},
|
||||
matches: ["about:welcome"],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
|
||||
// See Bug 1618306
|
||||
// Remove this preference check when we turn on separate about:welcome for all users.
|
||||
enablePreference: "browser.aboutwelcome.enabled",
|
||||
},
|
||||
|
||||
BackupUI: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/BackupUIParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/BackupUIChild.sys.mjs",
|
||||
events: {
|
||||
"BackupUI:InitWidget": { wantUntrusted: true },
|
||||
"BackupUI:EnableScheduledBackups": { wantUntrusted: true },
|
||||
"BackupUI:DisableScheduledBackups": { wantUntrusted: true },
|
||||
"BackupUI:ShowFilepicker": { wantUntrusted: true },
|
||||
"BackupUI:GetBackupFileInfo": { wantUntrusted: true },
|
||||
"BackupUI:RestoreFromBackupFile": { wantUntrusted: true },
|
||||
"BackupUI:RestoreFromBackupChooseFile": { wantUntrusted: true },
|
||||
"BackupUI:EnableEncryption": { wantUntrusted: true },
|
||||
"BackupUI:DisableEncryption": { wantUntrusted: true },
|
||||
"BackupUI:RerunEncryption": { wantUntrusted: true },
|
||||
"BackupUI:ShowBackupLocation": { wantUntrusted: true },
|
||||
"BackupUI:EditBackupLocation": { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:preferences*", "about:settings*"],
|
||||
enablePreference: "browser.backup.preferences.ui.enabled",
|
||||
},
|
||||
|
||||
BlockedSite: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/BlockedSiteParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/BlockedSiteChild.sys.mjs",
|
||||
events: {
|
||||
AboutBlockedLoaded: { wantUntrusted: true },
|
||||
click: {},
|
||||
},
|
||||
},
|
||||
matches: ["about:blocked?*"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
BrowserTab: {
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/BrowserTabChild.sys.mjs",
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
},
|
||||
|
||||
ClickHandler: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ClickHandlerParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ClickHandlerChild.sys.mjs",
|
||||
events: {
|
||||
chromelinkclick: { capture: true, mozSystemGroup: true },
|
||||
},
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
/* Note: this uses the same JSMs as ClickHandler, but because it
|
||||
* relies on "normal" click events anywhere on the page (not just
|
||||
* links) and is expensive, and only does something for the
|
||||
* small group of people who have the feature enabled, it is its
|
||||
* own actor which is only registered if the pref is enabled.
|
||||
*/
|
||||
MiddleMousePasteHandler: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ClickHandlerParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ClickHandlerChild.sys.mjs",
|
||||
events: {
|
||||
auxclick: { capture: true, mozSystemGroup: true },
|
||||
},
|
||||
},
|
||||
enablePreference: "middlemouse.contentLoadURL",
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
ContentSearch: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ContentSearchParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ContentSearchChild.sys.mjs",
|
||||
events: {
|
||||
ContentSearchClient: { capture: true, wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: [
|
||||
"about:home",
|
||||
"about:welcome",
|
||||
"about:newtab",
|
||||
"about:privatebrowsing",
|
||||
"about:test-about-content-search-ui",
|
||||
],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
},
|
||||
|
||||
ContextMenu: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ContextMenuParent.sys.mjs",
|
||||
},
|
||||
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ContextMenuChild.sys.mjs",
|
||||
events: {
|
||||
contextmenu: { mozSystemGroup: true },
|
||||
},
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
DecoderDoctor: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/DecoderDoctorParent.sys.mjs",
|
||||
},
|
||||
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/DecoderDoctorChild.sys.mjs",
|
||||
observers: ["decoder-doctor-notification"],
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
DOMFullscreen: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/DOMFullscreenParent.sys.mjs",
|
||||
},
|
||||
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/DOMFullscreenChild.sys.mjs",
|
||||
events: {
|
||||
"MozDOMFullscreen:Request": {},
|
||||
"MozDOMFullscreen:Entered": {},
|
||||
"MozDOMFullscreen:NewOrigin": {},
|
||||
"MozDOMFullscreen:Exit": {},
|
||||
"MozDOMFullscreen:Exited": {},
|
||||
},
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
EncryptedMedia: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/EncryptedMediaParent.sys.mjs",
|
||||
},
|
||||
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/EncryptedMediaChild.sys.mjs",
|
||||
observers: ["mediakeys-request"],
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
FormValidation: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/FormValidationParent.sys.mjs",
|
||||
},
|
||||
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/FormValidationChild.sys.mjs",
|
||||
events: {
|
||||
MozInvalidForm: {},
|
||||
// Listening to ‘pageshow’ event is only relevant if an invalid form
|
||||
// popup was open, so don't create the actor when fired.
|
||||
pageshow: { createActor: false },
|
||||
},
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
GenAI: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/GenAIParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/GenAIChild.sys.mjs",
|
||||
events: {
|
||||
mousedown: {},
|
||||
mouseup: {},
|
||||
},
|
||||
},
|
||||
allFrames: true,
|
||||
onAddActor(register, unregister) {
|
||||
let isRegistered = false;
|
||||
|
||||
// Register the actor if we have a provider set and not yet registered
|
||||
const maybeRegister = () => {
|
||||
if (Services.prefs.getCharPref("browser.ml.chat.provider", "")) {
|
||||
if (!isRegistered) {
|
||||
register();
|
||||
isRegistered = true;
|
||||
}
|
||||
} else if (isRegistered) {
|
||||
unregister();
|
||||
isRegistered = false;
|
||||
}
|
||||
};
|
||||
|
||||
Services.prefs.addObserver("browser.ml.chat.provider", maybeRegister);
|
||||
maybeRegister();
|
||||
},
|
||||
},
|
||||
|
||||
LightweightTheme: {
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/LightweightThemeChild.sys.mjs",
|
||||
events: {
|
||||
pageshow: { mozSystemGroup: true },
|
||||
DOMContentLoaded: {},
|
||||
},
|
||||
},
|
||||
includeChrome: true,
|
||||
allFrames: true,
|
||||
matches: [
|
||||
"about:asrouter",
|
||||
"about:home",
|
||||
"about:newtab",
|
||||
"about:welcome",
|
||||
"chrome://browser/content/syncedtabs/sidebar.xhtml",
|
||||
"chrome://browser/content/places/historySidebar.xhtml",
|
||||
"chrome://browser/content/places/bookmarksSidebar.xhtml",
|
||||
"about:firefoxview",
|
||||
"about:editprofile",
|
||||
"about:deleteprofile",
|
||||
"about:newprofile",
|
||||
],
|
||||
},
|
||||
|
||||
LinkHandler: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/LinkHandlerParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/LinkHandlerChild.sys.mjs",
|
||||
events: {
|
||||
DOMHeadElementParsed: {},
|
||||
DOMLinkAdded: {},
|
||||
DOMLinkChanged: {},
|
||||
pageshow: {},
|
||||
// The `pagehide` event is only used to clean up state which will not be
|
||||
// present if the actor hasn't been created.
|
||||
pagehide: { createActor: false },
|
||||
},
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
},
|
||||
|
||||
LinkPreview: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/LinkPreviewParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/LinkPreviewChild.sys.mjs",
|
||||
},
|
||||
includeChrome: true,
|
||||
enablePreference: "browser.ml.linkPreview.enabled",
|
||||
},
|
||||
|
||||
PageInfo: {
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/PageInfoChild.sys.mjs",
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
PageStyle: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/PageStyleParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/PageStyleChild.sys.mjs",
|
||||
events: {
|
||||
pageshow: { createActor: false },
|
||||
},
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
Pdfjs: {
|
||||
parent: {
|
||||
esModuleURI: "resource://pdf.js/PdfjsParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource://pdf.js/PdfjsChild.sys.mjs",
|
||||
},
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
// GMP crash reporting
|
||||
Plugin: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/PluginParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/PluginChild.sys.mjs",
|
||||
events: {
|
||||
PluginCrashed: { capture: true },
|
||||
},
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
PointerLock: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/PointerLockParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/PointerLockChild.sys.mjs",
|
||||
events: {
|
||||
"MozDOMPointerLock:Entered": {},
|
||||
"MozDOMPointerLock:Exited": {},
|
||||
},
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
Profiles: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ProfilesParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ProfilesChild.sys.mjs",
|
||||
events: {
|
||||
DOMDocElementInserted: { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:editprofile", "about:deleteprofile", "about:newprofile"],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
onAddActor(register, unregister) {
|
||||
let registered = false;
|
||||
|
||||
const maybeRegister = () => {
|
||||
let isEnabled = lazy.SelectableProfileService.isEnabled;
|
||||
|
||||
if (isEnabled && !registered) {
|
||||
register();
|
||||
} else if (!isEnabled && registered) {
|
||||
unregister();
|
||||
}
|
||||
|
||||
registered = isEnabled;
|
||||
};
|
||||
|
||||
// Defer all this logic until a little later in startup
|
||||
Services.obs.addObserver(() => {
|
||||
// Update when the pref changes
|
||||
lazy.SelectableProfileService.on("enableChanged", maybeRegister);
|
||||
|
||||
maybeRegister();
|
||||
}, "final-ui-startup");
|
||||
},
|
||||
},
|
||||
|
||||
Prompt: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/PromptParent.sys.mjs",
|
||||
},
|
||||
includeChrome: true,
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
RefreshBlocker: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/RefreshBlockerParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/RefreshBlockerChild.sys.mjs",
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
enablePreference: "accessibility.blockautorefresh",
|
||||
},
|
||||
|
||||
ReviewChecker: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ReviewCheckerParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ReviewCheckerChild.sys.mjs",
|
||||
events: {
|
||||
ContentReady: { wantUntrusted: true },
|
||||
PolledRequestMade: { wantUntrusted: true },
|
||||
// This is added so the actor instantiates immediately and makes
|
||||
// methods available to the page js on load.
|
||||
DOMDocElementInserted: {},
|
||||
ReportProductAvailable: { wantUntrusted: true },
|
||||
AdClicked: { wantUntrusted: true },
|
||||
AdImpression: { wantUntrusted: true },
|
||||
DisableShopping: { wantUntrusted: true },
|
||||
CloseShoppingSidebar: { wantUntrusted: true },
|
||||
MoveSidebarToLeft: { wantUntrusted: true },
|
||||
MoveSidebarToRight: { wantUntrusted: true },
|
||||
ShowSidebarSettings: { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:shoppingsidebar"],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
messageManagerGroups: ["review-checker", "browsers"],
|
||||
enablePreference: "browser.shopping.experience2023.integratedSidebar",
|
||||
},
|
||||
|
||||
ScreenshotsComponent: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///modules/ScreenshotsUtils.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ScreenshotsComponentChild.sys.mjs",
|
||||
events: {
|
||||
"Screenshots:Close": {},
|
||||
"Screenshots:Copy": {},
|
||||
"Screenshots:Download": {},
|
||||
"Screenshots:HidePanel": {},
|
||||
"Screenshots:OverlaySelection": {},
|
||||
"Screenshots:RecordEvent": {},
|
||||
"Screenshots:ShowPanel": {},
|
||||
"Screenshots:FocusPanel": {},
|
||||
},
|
||||
},
|
||||
enablePreference: "screenshots.browser.component.enabled",
|
||||
},
|
||||
|
||||
ScreenshotsHelper: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///modules/ScreenshotsUtils.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///modules/ScreenshotsHelperChild.sys.mjs",
|
||||
},
|
||||
allFrames: true,
|
||||
enablePreference: "screenshots.browser.component.enabled",
|
||||
},
|
||||
|
||||
SearchSERPTelemetry: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/SearchSERPTelemetryParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/SearchSERPTelemetryChild.sys.mjs",
|
||||
events: {
|
||||
DOMContentLoaded: {},
|
||||
pageshow: { mozSystemGroup: true },
|
||||
// The 'pagehide' event is only used to clean up state, and should not
|
||||
// force actor creation.
|
||||
pagehide: { createActor: false },
|
||||
load: { mozSystemGroup: true, capture: true },
|
||||
},
|
||||
},
|
||||
matches: ["https://*/*"],
|
||||
},
|
||||
|
||||
ShieldFrame: {
|
||||
parent: {
|
||||
esModuleURI: "resource://normandy-content/ShieldFrameParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource://normandy-content/ShieldFrameChild.sys.mjs",
|
||||
events: {
|
||||
pageshow: {},
|
||||
pagehide: {},
|
||||
ShieldPageEvent: { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:studies*"],
|
||||
},
|
||||
|
||||
ShoppingSidebar: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ShoppingSidebarParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ShoppingSidebarChild.sys.mjs",
|
||||
events: {
|
||||
ContentReady: { wantUntrusted: true },
|
||||
PolledRequestMade: { wantUntrusted: true },
|
||||
// This is added so the actor instantiates immediately and makes
|
||||
// methods available to the page js on load.
|
||||
DOMDocElementInserted: {},
|
||||
ReportProductAvailable: { wantUntrusted: true },
|
||||
AdClicked: { wantUntrusted: true },
|
||||
AdImpression: { wantUntrusted: true },
|
||||
DisableShopping: { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
matches: ["about:shoppingsidebar"],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
messageManagerGroups: ["shopping-sidebar", "browsers"],
|
||||
enablePreference: "browser.shopping.experience2023.enabled",
|
||||
},
|
||||
|
||||
SpeechDispatcher: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/SpeechDispatcherParent.sys.mjs",
|
||||
},
|
||||
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/SpeechDispatcherChild.sys.mjs",
|
||||
observers: ["chrome-synth-voices-error"],
|
||||
},
|
||||
|
||||
messageManagerGroups: ["browsers"],
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
ASRouter: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/ASRouterParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/ASRouterChild.sys.mjs",
|
||||
events: {
|
||||
// This is added so the actor instantiates immediately and makes
|
||||
// methods available to the page js on load.
|
||||
DOMDocElementInserted: {},
|
||||
},
|
||||
},
|
||||
matches: ["about:asrouter*", "about:welcome*", "about:privatebrowsing*"],
|
||||
remoteTypes: ["privilegedabout"],
|
||||
},
|
||||
|
||||
SwitchDocumentDirection: {
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/SwitchDocumentDirectionChild.sys.mjs",
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
UITour: {
|
||||
parent: {
|
||||
esModuleURI: "moz-src:///browser/components/uitour/UITourParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "moz-src:///browser/components/uitour/UITourChild.sys.mjs",
|
||||
events: {
|
||||
mozUITour: { wantUntrusted: true },
|
||||
},
|
||||
},
|
||||
|
||||
enablePreference: "browser.uitour.enabled",
|
||||
messageManagerGroups: ["browsers"],
|
||||
},
|
||||
|
||||
WebRTC: {
|
||||
parent: {
|
||||
esModuleURI: "resource:///actors/WebRTCParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI: "resource:///actors/WebRTCChild.sys.mjs",
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
};
|
||||
|
||||
export let DesktopActorRegistry = {
|
||||
init() {
|
||||
ActorManagerParent.addJSProcessActors(JSPROCESSACTORS);
|
||||
ActorManagerParent.addJSWindowActors(JSWINDOWACTORS);
|
||||
},
|
||||
};
|
891
browser/components/ProfileDataUpgrader.sys.mjs
Normal file
891
browser/components/ProfileDataUpgrader.sys.mjs
Normal file
|
@ -0,0 +1,891 @@
|
|||
/* 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/. */
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
|
||||
FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
|
||||
FirefoxBridgeExtensionUtils:
|
||||
"resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs",
|
||||
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
|
||||
PlacesUIUtils: "resource:///modules/PlacesUIUtils.sys.mjs",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
|
||||
UsageReporting: "resource://gre/modules/UsageReporting.sys.mjs",
|
||||
});
|
||||
|
||||
export let ProfileDataUpgrader = {
|
||||
_migrateXULStoreForDocument(fromURL, toURL) {
|
||||
Array.from(Services.xulStore.getIDsEnumerator(fromURL)).forEach(id => {
|
||||
Array.from(Services.xulStore.getAttributeEnumerator(fromURL, id)).forEach(
|
||||
attr => {
|
||||
let value = Services.xulStore.getValue(fromURL, id, attr);
|
||||
Services.xulStore.setValue(toURL, id, attr, value);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
_migrateHashedKeysForXULStoreForDocument(docUrl) {
|
||||
Array.from(Services.xulStore.getIDsEnumerator(docUrl))
|
||||
.filter(id => id.startsWith("place:"))
|
||||
.forEach(id => {
|
||||
Services.xulStore.removeValue(docUrl, id, "open");
|
||||
let hashedId = lazy.PlacesUIUtils.obfuscateUrlForXulStore(id);
|
||||
Services.xulStore.setValue(docUrl, hashedId, "open", "true");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* This method transforms data in the profile directory so that it can be
|
||||
* used in the current version of Firefox. It is organized similar to
|
||||
* typical database version upgrades: we are invoked with the version of the
|
||||
* profile data on disk (`existingDataVersion`) and the version we expect/need
|
||||
* (`newVersion`), and execute any necessary migrations.
|
||||
*
|
||||
* In practice, most of the migrations move user choices from one preference
|
||||
* to another, or ensure that other mechanical file moves (e.g. of document
|
||||
* URLs like browser.xhtml).
|
||||
*
|
||||
* If you're adding a new migration, you will need to increment
|
||||
* APP_DATA_VERSION in BrowserGlue.sys.mjs' _migrateUI. That version is not
|
||||
* in this module so that we can avoid loading this module entirely in common
|
||||
* cases (Firefox startups where a profile is not upgraded).
|
||||
*
|
||||
* Note that this is invoked very early on startup and should try to avoid
|
||||
* doing very expensive things immediately unless absolutely necessary. Some
|
||||
* of the migrations will therefore set a pref or otherwise flag that their
|
||||
* component needs to do more work later, perhaps during idle tasks or
|
||||
* similar, to avoid front-loading the component initialization into this
|
||||
* early part of startup. Of course, some of these migrations (e.g. to ensure
|
||||
* that browser windows remember their sizes if the URL to browser.xhtml has
|
||||
* changed) _need_ to run very early, and that is OK.
|
||||
*
|
||||
* @param {integer} existingDataVersion
|
||||
* The version of the data in the profile.
|
||||
* @param {integer} newVersion
|
||||
* The version that the application expects/needs.
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
upgrade(existingDataVersion, newVersion) {
|
||||
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
|
||||
|
||||
let xulStore = Services.xulStore;
|
||||
|
||||
if (existingDataVersion < 90) {
|
||||
this._migrateXULStoreForDocument(
|
||||
"chrome://browser/content/places/historySidebar.xul",
|
||||
"chrome://browser/content/places/historySidebar.xhtml"
|
||||
);
|
||||
this._migrateXULStoreForDocument(
|
||||
"chrome://browser/content/places/places.xul",
|
||||
"chrome://browser/content/places/places.xhtml"
|
||||
);
|
||||
this._migrateXULStoreForDocument(
|
||||
"chrome://browser/content/places/bookmarksSidebar.xul",
|
||||
"chrome://browser/content/places/bookmarksSidebar.xhtml"
|
||||
);
|
||||
}
|
||||
|
||||
// Clear socks proxy values if they were shared from http, to prevent
|
||||
// websocket breakage after bug 1577862 (see bug 969282).
|
||||
if (
|
||||
existingDataVersion < 91 &&
|
||||
Services.prefs.getBoolPref("network.proxy.share_proxy_settings", false) &&
|
||||
Services.prefs.getIntPref("network.proxy.type", 0) == 1
|
||||
) {
|
||||
let httpProxy = Services.prefs.getCharPref("network.proxy.http", "");
|
||||
let httpPort = Services.prefs.getIntPref("network.proxy.http_port", 0);
|
||||
let socksProxy = Services.prefs.getCharPref("network.proxy.socks", "");
|
||||
let socksPort = Services.prefs.getIntPref("network.proxy.socks_port", 0);
|
||||
if (httpProxy && httpProxy == socksProxy && httpPort == socksPort) {
|
||||
Services.prefs.setCharPref(
|
||||
"network.proxy.socks",
|
||||
Services.prefs.getCharPref("network.proxy.backup.socks", "")
|
||||
);
|
||||
Services.prefs.setIntPref(
|
||||
"network.proxy.socks_port",
|
||||
Services.prefs.getIntPref("network.proxy.backup.socks_port", 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 92) {
|
||||
// privacy.userContext.longPressBehavior pref was renamed and changed to a boolean
|
||||
let longpress = Services.prefs.getIntPref(
|
||||
"privacy.userContext.longPressBehavior",
|
||||
0
|
||||
);
|
||||
if (longpress == 1) {
|
||||
Services.prefs.setBoolPref(
|
||||
"privacy.userContext.newTabContainerOnLeftClick.enabled",
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 93) {
|
||||
// The Gecko Profiler Addon is now an internal component. Remove the old
|
||||
// addon, and enable the new UI.
|
||||
|
||||
function enableProfilerButton(wasAddonActive) {
|
||||
// Enable the feature pref. This will add it to the customization palette,
|
||||
// but not to the the navbar.
|
||||
Services.prefs.setBoolPref(
|
||||
"devtools.performance.popup.feature-flag",
|
||||
true
|
||||
);
|
||||
|
||||
if (wasAddonActive) {
|
||||
const { ProfilerMenuButton } = ChromeUtils.importESModule(
|
||||
"resource://devtools/client/performance-new/popup/menu-button.sys.mjs"
|
||||
);
|
||||
if (!ProfilerMenuButton.isInNavbar()) {
|
||||
ProfilerMenuButton.addToNavbar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let addonPromise;
|
||||
try {
|
||||
addonPromise = lazy.AddonManager.getAddonByID(
|
||||
"geckoprofiler@mozilla.com"
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Could not access the AddonManager to upgrade the profile. This is most " +
|
||||
"likely because the upgrader is being run from an xpcshell test where " +
|
||||
"the AddonManager is not initialized."
|
||||
);
|
||||
}
|
||||
Promise.resolve(addonPromise).then(addon => {
|
||||
if (!addon) {
|
||||
// Either the addon wasn't installed, or the call to getAddonByID failed.
|
||||
return;
|
||||
}
|
||||
// Remove the old addon.
|
||||
const wasAddonActive = addon.isActive;
|
||||
addon
|
||||
.uninstall()
|
||||
.catch(console.error)
|
||||
.then(() => enableProfilerButton(wasAddonActive))
|
||||
.catch(console.error);
|
||||
}, console.error);
|
||||
}
|
||||
|
||||
// Clear unused socks proxy backup values - see bug 1625773.
|
||||
if (existingDataVersion < 94) {
|
||||
let backup = Services.prefs.getCharPref("network.proxy.backup.socks", "");
|
||||
let backupPort = Services.prefs.getIntPref(
|
||||
"network.proxy.backup.socks_port",
|
||||
0
|
||||
);
|
||||
let socksProxy = Services.prefs.getCharPref("network.proxy.socks", "");
|
||||
let socksPort = Services.prefs.getIntPref("network.proxy.socks_port", 0);
|
||||
if (backup == socksProxy) {
|
||||
Services.prefs.clearUserPref("network.proxy.backup.socks");
|
||||
}
|
||||
if (backupPort == socksPort) {
|
||||
Services.prefs.clearUserPref("network.proxy.backup.socks_port");
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 95) {
|
||||
const oldPrefName = "media.autoplay.enabled.user-gestures-needed";
|
||||
const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
|
||||
const newPrefValue = oldPrefValue ? 0 : 1;
|
||||
Services.prefs.setIntPref("media.autoplay.blocking_policy", newPrefValue);
|
||||
Services.prefs.clearUserPref(oldPrefName);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 96) {
|
||||
const oldPrefName = "browser.urlbar.openViewOnFocus";
|
||||
const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.urlbar.suggest.topsites",
|
||||
oldPrefValue
|
||||
);
|
||||
Services.prefs.clearUserPref(oldPrefName);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 97) {
|
||||
let userCustomizedWheelMax = Services.prefs.prefHasUserValue(
|
||||
"general.smoothScroll.mouseWheel.durationMaxMS"
|
||||
);
|
||||
let userCustomizedWheelMin = Services.prefs.prefHasUserValue(
|
||||
"general.smoothScroll.mouseWheel.durationMinMS"
|
||||
);
|
||||
|
||||
if (!userCustomizedWheelMin && !userCustomizedWheelMax) {
|
||||
// If the user has an existing profile but hasn't customized the wheel
|
||||
// animation duration, they will now get the new default values. This
|
||||
// condition used to set a migrationPercent pref to 0, so that users
|
||||
// upgrading an older profile would gradually have their wheel animation
|
||||
// speed migrated to the new values. However, that "gradual migration"
|
||||
// was phased out by FF 86, so we don't need to set that pref anymore.
|
||||
} else if (userCustomizedWheelMin && !userCustomizedWheelMax) {
|
||||
// If they customized just one of the two, save the old value for the
|
||||
// other one as well, because the two values go hand-in-hand and we
|
||||
// don't want to move just one to a new value and leave the other one
|
||||
// at a customized value. In both of these cases, we leave the "migration
|
||||
// complete" percentage at 100, because they have customized this and
|
||||
// don't need any further migration.
|
||||
Services.prefs.setIntPref(
|
||||
"general.smoothScroll.mouseWheel.durationMaxMS",
|
||||
400
|
||||
);
|
||||
} else if (!userCustomizedWheelMin && userCustomizedWheelMax) {
|
||||
// Same as above case, but for the other pref.
|
||||
Services.prefs.setIntPref(
|
||||
"general.smoothScroll.mouseWheel.durationMinMS",
|
||||
200
|
||||
);
|
||||
} else {
|
||||
// The last remaining case is if they customized both values, in which
|
||||
// case also don't need to do anything; the user's customized values
|
||||
// will be retained and respected.
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 98) {
|
||||
Services.prefs.clearUserPref("browser.search.cohort");
|
||||
}
|
||||
|
||||
if (existingDataVersion < 99) {
|
||||
Services.prefs.clearUserPref("security.tls.version.enable-deprecated");
|
||||
}
|
||||
|
||||
if (existingDataVersion < 102) {
|
||||
// In Firefox 83, we moved to a dynamic button, so it needs to be removed
|
||||
// from default placement. This is done early enough that it doesn't
|
||||
// impact adding new managed bookmarks.
|
||||
const { CustomizableUI } = ChromeUtils.importESModule(
|
||||
"resource:///modules/CustomizableUI.sys.mjs"
|
||||
);
|
||||
CustomizableUI.removeWidgetFromArea("managed-bookmarks");
|
||||
}
|
||||
|
||||
// We have to rerun these because we had to use 102 on beta.
|
||||
// They were 101 and 102 before.
|
||||
if (existingDataVersion < 103) {
|
||||
// Set a pref if the bookmarks toolbar was already visible,
|
||||
// so we can keep it visible when navigating away from newtab
|
||||
let bookmarksToolbarWasVisible =
|
||||
Services.xulStore.getValue(
|
||||
BROWSER_DOCURL,
|
||||
"PersonalToolbar",
|
||||
"collapsed"
|
||||
) == "false";
|
||||
if (bookmarksToolbarWasVisible) {
|
||||
// Migrate the user to the "always visible" value. See firefox.js for
|
||||
// the other possible states.
|
||||
Services.prefs.setCharPref(
|
||||
"browser.toolbars.bookmarks.visibility",
|
||||
"always"
|
||||
);
|
||||
}
|
||||
Services.xulStore.removeValue(
|
||||
BROWSER_DOCURL,
|
||||
"PersonalToolbar",
|
||||
"collapsed"
|
||||
);
|
||||
|
||||
Services.prefs.clearUserPref(
|
||||
"browser.livebookmarks.migrationAttemptsLeft"
|
||||
);
|
||||
}
|
||||
|
||||
// For existing profiles, continue putting bookmarks in the
|
||||
// "other bookmarks" folder.
|
||||
if (existingDataVersion < 104) {
|
||||
Services.prefs.setCharPref(
|
||||
"browser.bookmarks.defaultLocation",
|
||||
"unfiled"
|
||||
);
|
||||
}
|
||||
|
||||
// Renamed and flipped the logic of a pref to make its purpose more clear.
|
||||
if (existingDataVersion < 105) {
|
||||
const oldPrefName = "browser.urlbar.imeCompositionClosesPanel";
|
||||
const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.urlbar.keepPanelOpenDuringImeComposition",
|
||||
!oldPrefValue
|
||||
);
|
||||
Services.prefs.clearUserPref(oldPrefName);
|
||||
}
|
||||
|
||||
// Initialize the new browser.urlbar.showSuggestionsBeforeGeneral pref.
|
||||
if (existingDataVersion < 106) {
|
||||
lazy.UrlbarPrefs.initializeShowSearchSuggestionsFirstPref();
|
||||
}
|
||||
|
||||
if (existingDataVersion < 107) {
|
||||
// Migrate old http URIs for mailto handlers to their https equivalents.
|
||||
// The handler service will do this. We need to wait with migrating
|
||||
// until the handler service has started up, so just set a pref here.
|
||||
const kPref = "browser.handlers.migrations";
|
||||
// We might have set up another migration further up. Create an array,
|
||||
// and drop empty strings resulting from the `split`:
|
||||
let migrations = Services.prefs
|
||||
.getCharPref(kPref, "")
|
||||
.split(",")
|
||||
.filter(x => !!x);
|
||||
migrations.push("secure-mail");
|
||||
Services.prefs.setCharPref(kPref, migrations.join(","));
|
||||
}
|
||||
|
||||
if (existingDataVersion < 108) {
|
||||
// Migrate old ctrlTab pref to new ctrlTab pref
|
||||
let defaultValue = false;
|
||||
let oldPrefName = "browser.ctrlTab.recentlyUsedOrder";
|
||||
let oldPrefDefault = true;
|
||||
// Use old pref value if the user used Ctrl+Tab before, elsewise use new default value
|
||||
if (Services.prefs.getBoolPref("browser.engagement.ctrlTab.has-used")) {
|
||||
let newPrefValue = Services.prefs.getBoolPref(
|
||||
oldPrefName,
|
||||
oldPrefDefault
|
||||
);
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.ctrlTab.sortByRecentlyUsed",
|
||||
newPrefValue
|
||||
);
|
||||
} else {
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.ctrlTab.sortByRecentlyUsed",
|
||||
defaultValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 109) {
|
||||
// Migrate old pref to new pref
|
||||
if (
|
||||
Services.prefs.prefHasUserValue("signon.recipes.remoteRecipesEnabled")
|
||||
) {
|
||||
// Fetch the previous value of signon.recipes.remoteRecipesEnabled and assign it to signon.recipes.remoteRecipes.enabled.
|
||||
Services.prefs.setBoolPref(
|
||||
"signon.recipes.remoteRecipes.enabled",
|
||||
Services.prefs.getBoolPref(
|
||||
"signon.recipes.remoteRecipesEnabled",
|
||||
true
|
||||
)
|
||||
);
|
||||
//Then clear user pref
|
||||
Services.prefs.clearUserPref("signon.recipes.remoteRecipesEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 120) {
|
||||
// Migrate old titlebar bool pref to new int-based one.
|
||||
const oldPref = "browser.tabs.drawInTitlebar";
|
||||
const newPref = "browser.tabs.inTitlebar";
|
||||
if (Services.prefs.prefHasUserValue(oldPref)) {
|
||||
// We may have int prefs for builds between bug 1736518 and bug 1739539.
|
||||
const oldPrefType = Services.prefs.getPrefType(oldPref);
|
||||
if (oldPrefType == Services.prefs.PREF_BOOL) {
|
||||
Services.prefs.setIntPref(
|
||||
newPref,
|
||||
Services.prefs.getBoolPref(oldPref) ? 1 : 0
|
||||
);
|
||||
} else {
|
||||
Services.prefs.setIntPref(
|
||||
newPref,
|
||||
Services.prefs.getIntPref(oldPref)
|
||||
);
|
||||
}
|
||||
Services.prefs.clearUserPref(oldPref);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 121) {
|
||||
// Migrate stored uris and convert them to use hashed keys
|
||||
this._migrateHashedKeysForXULStoreForDocument(BROWSER_DOCURL);
|
||||
this._migrateHashedKeysForXULStoreForDocument(
|
||||
"chrome://browser/content/places/bookmarksSidebar.xhtml"
|
||||
);
|
||||
this._migrateHashedKeysForXULStoreForDocument(
|
||||
"chrome://browser/content/places/historySidebar.xhtml"
|
||||
);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 122) {
|
||||
// Migrate xdg-desktop-portal pref from old to new prefs.
|
||||
try {
|
||||
const oldPref = "widget.use-xdg-desktop-portal";
|
||||
if (Services.prefs.getBoolPref(oldPref)) {
|
||||
Services.prefs.setIntPref(
|
||||
"widget.use-xdg-desktop-portal.file-picker",
|
||||
1
|
||||
);
|
||||
Services.prefs.setIntPref(
|
||||
"widget.use-xdg-desktop-portal.mime-handler",
|
||||
1
|
||||
);
|
||||
}
|
||||
Services.prefs.clearUserPref(oldPref);
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
// Bug 1745248: Due to multiple backouts, do not use UI Version 123
|
||||
// as this version is most likely set for the Nightly channel
|
||||
|
||||
if (existingDataVersion < 124) {
|
||||
// Migrate "extensions.formautofill.available" and
|
||||
// "extensions.formautofill.creditCards.available" from old to new prefs
|
||||
const oldFormAutofillModule = "extensions.formautofill.available";
|
||||
const oldCreditCardsAvailable =
|
||||
"extensions.formautofill.creditCards.available";
|
||||
const newCreditCardsAvailable =
|
||||
"extensions.formautofill.creditCards.supported";
|
||||
const newAddressesAvailable =
|
||||
"extensions.formautofill.addresses.supported";
|
||||
if (Services.prefs.prefHasUserValue(oldFormAutofillModule)) {
|
||||
let moduleAvailability = Services.prefs.getCharPref(
|
||||
oldFormAutofillModule
|
||||
);
|
||||
if (moduleAvailability == "on") {
|
||||
Services.prefs.setCharPref(newAddressesAvailable, moduleAvailability);
|
||||
Services.prefs.setCharPref(
|
||||
newCreditCardsAvailable,
|
||||
Services.prefs.getBoolPref(oldCreditCardsAvailable) ? "on" : "off"
|
||||
);
|
||||
}
|
||||
|
||||
if (moduleAvailability == "off") {
|
||||
Services.prefs.setCharPref(
|
||||
newCreditCardsAvailable,
|
||||
moduleAvailability
|
||||
);
|
||||
Services.prefs.setCharPref(newAddressesAvailable, moduleAvailability);
|
||||
}
|
||||
}
|
||||
|
||||
// after migrating, clear old prefs so we can remove them later.
|
||||
Services.prefs.clearUserPref(oldFormAutofillModule);
|
||||
Services.prefs.clearUserPref(oldCreditCardsAvailable);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 125) {
|
||||
// Bug 1756243 - Clear PiP cached coordinates since we changed their
|
||||
// coordinate space.
|
||||
const PIP_PLAYER_URI =
|
||||
"chrome://global/content/pictureinpicture/player.xhtml";
|
||||
try {
|
||||
for (let value of ["left", "top", "width", "height"]) {
|
||||
Services.xulStore.removeValue(
|
||||
PIP_PLAYER_URI,
|
||||
"picture-in-picture",
|
||||
value
|
||||
);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error("Failed to clear XULStore PiP values: ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
function migrateXULAttributeToStyle(url, id, attr) {
|
||||
try {
|
||||
let value = Services.xulStore.getValue(url, id, attr);
|
||||
if (value) {
|
||||
Services.xulStore.setValue(url, id, "style", `${attr}: ${value}px;`);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(`Error migrating ${id}'s ${attr} value: `, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Bug 1792748 used version 129 with a buggy variant of the sidebar width
|
||||
// migration. This version is already in use in the nightly channel, so it
|
||||
// shouldn't be used.
|
||||
|
||||
// Bug 1793366: migrate sidebar persisted attribute from width to style.
|
||||
if (existingDataVersion < 130) {
|
||||
migrateXULAttributeToStyle(BROWSER_DOCURL, "sidebar-box", "width");
|
||||
}
|
||||
|
||||
// Migration 131 was moved to 133 to allow for an uplift.
|
||||
|
||||
if (existingDataVersion < 132) {
|
||||
// These attributes are no longer persisted, thus remove them from xulstore.
|
||||
for (let url of [
|
||||
"chrome://browser/content/places/bookmarkProperties.xhtml",
|
||||
"chrome://browser/content/places/bookmarkProperties2.xhtml",
|
||||
]) {
|
||||
for (let attr of ["width", "screenX", "screenY"]) {
|
||||
xulStore.removeValue(url, "bookmarkproperties", attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 133) {
|
||||
xulStore.removeValue(BROWSER_DOCURL, "urlbar-container", "width");
|
||||
}
|
||||
|
||||
// Migration 134 was removed because it was no longer necessary.
|
||||
|
||||
if (existingDataVersion < 135 && AppConstants.platform == "linux") {
|
||||
// Avoid changing titlebar setting for users that used to had it off.
|
||||
try {
|
||||
if (!Services.prefs.prefHasUserValue("browser.tabs.inTitlebar")) {
|
||||
let de = Services.appinfo.desktopEnvironment;
|
||||
let oldDefault = de.includes("gnome") || de.includes("pantheon");
|
||||
if (!oldDefault) {
|
||||
Services.prefs.setIntPref("browser.tabs.inTitlebar", 0);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error migrating tabsInTitlebar setting", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 136) {
|
||||
migrateXULAttributeToStyle(
|
||||
"chrome://browser/content/places/places.xhtml",
|
||||
"placesList",
|
||||
"width"
|
||||
);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 137) {
|
||||
// The default value for enabling smooth scrolls is now false if the
|
||||
// user prefers reduced motion. If the value was previously set, do
|
||||
// not reset it, but if it was not explicitly set preserve the old
|
||||
// default value.
|
||||
if (
|
||||
!Services.prefs.prefHasUserValue("general.smoothScroll") &&
|
||||
Services.appinfo.prefersReducedMotion
|
||||
) {
|
||||
Services.prefs.setBoolPref("general.smoothScroll", true);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 138) {
|
||||
// Bug 1757297: Change scheme of all existing 'https-only-load-insecure'
|
||||
// permissions with https scheme to http scheme.
|
||||
try {
|
||||
Services.perms
|
||||
.getAllByTypes(["https-only-load-insecure"])
|
||||
.filter(permission => permission.principal.schemeIs("https"))
|
||||
.forEach(permission => {
|
||||
const capability = permission.capability;
|
||||
const uri = permission.principal.URI.mutate()
|
||||
.setScheme("http")
|
||||
.finalize();
|
||||
const principal =
|
||||
Services.scriptSecurityManager.createContentPrincipal(uri, {});
|
||||
Services.perms.removePermission(permission);
|
||||
Services.perms.addFromPrincipal(
|
||||
principal,
|
||||
"https-only-load-insecure",
|
||||
capability
|
||||
);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Error migrating https-only-load-insecure permission", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 139) {
|
||||
// Reset the default permissions to ALLOW_ACTION to rollback issues for
|
||||
// affected users, see Bug 1579517
|
||||
// originInfo in the format [origin, type]
|
||||
[
|
||||
["https://www.mozilla.org", "uitour"],
|
||||
["https://support.mozilla.org", "uitour"],
|
||||
["about:home", "uitour"],
|
||||
["about:newtab", "uitour"],
|
||||
["https://addons.mozilla.org", "install"],
|
||||
["https://support.mozilla.org", "remote-troubleshooting"],
|
||||
["about:welcome", "autoplay-media"],
|
||||
].forEach(originInfo => {
|
||||
// Reset permission on the condition that it is set to
|
||||
// UNKNOWN_ACTION, we want to prevent resetting user
|
||||
// manipulated permissions
|
||||
if (
|
||||
Services.perms.UNKNOWN_ACTION ==
|
||||
Services.perms.testPermissionFromPrincipal(
|
||||
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
originInfo[0]
|
||||
),
|
||||
originInfo[1]
|
||||
)
|
||||
) {
|
||||
// Adding permissions which have default values does not create
|
||||
// new permissions, but rather remove the UNKNOWN_ACTION permission
|
||||
// overrides. User's not affected by Bug 1579517 will not be affected by this addition.
|
||||
Services.perms.addFromPrincipal(
|
||||
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
originInfo[0]
|
||||
),
|
||||
originInfo[1],
|
||||
Services.perms.ALLOW_ACTION
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (existingDataVersion < 140) {
|
||||
// Remove browser.fixup.alternate.enabled pref in Bug 1850902.
|
||||
Services.prefs.clearUserPref("browser.fixup.alternate.enabled");
|
||||
}
|
||||
|
||||
if (existingDataVersion < 141) {
|
||||
for (const filename of ["signons.sqlite", "signons.sqlite.corrupt"]) {
|
||||
const filePath = PathUtils.join(PathUtils.profileDir, filename);
|
||||
IOUtils.remove(filePath, { ignoreAbsent: true }).catch(console.error);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 142) {
|
||||
// Bug 1860392 - Remove incorrectly persisted theming values from sidebar style.
|
||||
try {
|
||||
let value = xulStore.getValue(BROWSER_DOCURL, "sidebar-box", "style");
|
||||
if (value) {
|
||||
// Remove custom properties.
|
||||
value = value
|
||||
.split(";")
|
||||
.filter(v => !v.trim().startsWith("--"))
|
||||
.join(";");
|
||||
xulStore.setValue(BROWSER_DOCURL, "sidebar-box", "style", value);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 143) {
|
||||
// Version 143 has been superseded by version 145 below.
|
||||
}
|
||||
|
||||
if (existingDataVersion < 144) {
|
||||
// TerminatorTelemetry was removed in bug 1879136. Before it was removed,
|
||||
// the ShutdownDuration.json file would be written to disk at shutdown
|
||||
// so that the next launch of the browser could read it in and send
|
||||
// shutdown performance measurements.
|
||||
//
|
||||
// Unfortunately, this mechanism and its measurements were fairly
|
||||
// unreliable, so they were removed.
|
||||
for (const filename of [
|
||||
"ShutdownDuration.json",
|
||||
"ShutdownDuration.json.tmp",
|
||||
]) {
|
||||
const filePath = PathUtils.join(PathUtils.profileDir, filename);
|
||||
IOUtils.remove(filePath, { ignoreAbsent: true }).catch(console.error);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingDataVersion < 145) {
|
||||
if (AppConstants.platform == "win") {
|
||||
// In Firefox 122, we enabled the firefox and firefox-private protocols.
|
||||
// We switched over to using firefox-bridge and firefox-private-bridge,
|
||||
// but we want to clean up the use of the other protocols.
|
||||
lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
|
||||
lazy.FirefoxBridgeExtensionUtils.OLD_PUBLIC_PROTOCOL,
|
||||
lazy.FirefoxBridgeExtensionUtils.OLD_PRIVATE_PROTOCOL
|
||||
);
|
||||
|
||||
// Clean up the old user prefs from FX 122
|
||||
Services.prefs.clearUserPref(
|
||||
"network.protocol-handler.external.firefox"
|
||||
);
|
||||
Services.prefs.clearUserPref(
|
||||
"network.protocol-handler.external.firefox-private"
|
||||
);
|
||||
|
||||
// In Firefox 126, we switched over to using native messaging so the
|
||||
// protocols are no longer necessary even in firefox-bridge and
|
||||
// firefox-private-bridge form
|
||||
lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
|
||||
lazy.FirefoxBridgeExtensionUtils.PUBLIC_PROTOCOL,
|
||||
lazy.FirefoxBridgeExtensionUtils.PRIVATE_PROTOCOL
|
||||
);
|
||||
Services.prefs.clearUserPref(
|
||||
"network.protocol-handler.external.firefox-bridge"
|
||||
);
|
||||
Services.prefs.clearUserPref(
|
||||
"network.protocol-handler.external.firefox-private-bridge"
|
||||
);
|
||||
Services.prefs.clearUserPref("browser.shell.customProtocolsRegistered");
|
||||
}
|
||||
}
|
||||
|
||||
// Version 146 had a typo issue and thus it has been replaced by 147.
|
||||
|
||||
if (existingDataVersion < 147) {
|
||||
// We're securing the boolean prefs for OS Authentication.
|
||||
// This is achieved by converting them into a string pref and encrypting the values
|
||||
// stored inside it.
|
||||
|
||||
// Note: we don't run this on nightly builds and we also do not run this
|
||||
// for users with primary password enabled. That means both these sets of
|
||||
// users will have the features turned on by default. For Nightly this is
|
||||
// an intentional product decision; for primary password this is because
|
||||
// we cannot encrypt the opt-out value without asking for the primary
|
||||
// password, which in turn means we cannot migrate without doing so. It
|
||||
// is also very difficult to postpone this migration because there is no
|
||||
// way to know when the user has put in the primary password. We will
|
||||
// probably reconsider some of this architecture in future, but for now
|
||||
// this is the least-painful method considering the alternatives, cf.
|
||||
// bug 1901899.
|
||||
if (
|
||||
!AppConstants.NIGHTLY_BUILD &&
|
||||
!lazy.LoginHelper.isPrimaryPasswordSet()
|
||||
) {
|
||||
const hasRunBetaMigration = Services.prefs
|
||||
.getCharPref("browser.startup.homepage_override.mstone", "")
|
||||
.startsWith("127.0");
|
||||
|
||||
// Version 146 UI migration wrote to a wrong `creditcards` pref when
|
||||
// the feature was disabled, instead it should have used `creditCards`.
|
||||
// The correct pref name is in AUTOFILL_CREDITCARDS_REAUTH_PREF.
|
||||
// Note that we only wrote prefs if the feature was disabled.
|
||||
let ccTypoDisabled = !lazy.FormAutofillUtils.getOSAuthEnabled(
|
||||
"extensions.formautofill.creditcards.reauth.optout"
|
||||
);
|
||||
let ccCorrectPrefDisabled = !lazy.FormAutofillUtils.getOSAuthEnabled(
|
||||
lazy.FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF
|
||||
);
|
||||
let ccPrevReauthPrefValue = Services.prefs.getBoolPref(
|
||||
"extensions.formautofill.reauth.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
let userHadEnabledCreditCardReauth =
|
||||
// If we've run beta migration, and neither typo nor correct pref
|
||||
// indicate disablement, the user enabled the pref:
|
||||
(hasRunBetaMigration && !ccTypoDisabled && !ccCorrectPrefDisabled) ||
|
||||
// Or if we never ran beta migration and the bool pref is set:
|
||||
ccPrevReauthPrefValue;
|
||||
|
||||
lazy.FormAutofillUtils.setOSAuthEnabled(
|
||||
lazy.FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF,
|
||||
userHadEnabledCreditCardReauth
|
||||
);
|
||||
|
||||
if (!hasRunBetaMigration) {
|
||||
const passwordsPrevReauthPrefValue = Services.prefs.getBoolPref(
|
||||
"signon.management.page.os-auth.enabled",
|
||||
false
|
||||
);
|
||||
lazy.LoginHelper.setOSAuthEnabled(
|
||||
lazy.LoginHelper.OS_AUTH_FOR_PASSWORDS_PREF,
|
||||
passwordsPrevReauthPrefValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Services.prefs.clearUserPref("extensions.formautofill.reauth.enabled");
|
||||
Services.prefs.clearUserPref("signon.management.page.os-auth.enabled");
|
||||
Services.prefs.clearUserPref(
|
||||
"extensions.formautofill.creditcards.reauth.optout"
|
||||
);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 148) {
|
||||
// The Firefox Translations addon is now a built-in Firefox feature.
|
||||
let addonPromise;
|
||||
try {
|
||||
addonPromise = lazy.AddonManager.getAddonByID(
|
||||
"firefox-translations-addon@mozilla.org"
|
||||
);
|
||||
} catch (error) {
|
||||
// This always throws in xpcshell as the AddonManager is not initialized.
|
||||
if (!Services.env.exists("XPCSHELL_TEST_PROFILE_DIR")) {
|
||||
console.error(
|
||||
"Could not access the AddonManager to upgrade the profile."
|
||||
);
|
||||
}
|
||||
}
|
||||
addonPromise?.then(addon => addon?.uninstall()).catch(console.error);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 149) {
|
||||
// remove permissions used by deleted nsContentManager
|
||||
[
|
||||
"other",
|
||||
"script",
|
||||
"image",
|
||||
"stylesheet",
|
||||
"object",
|
||||
"document",
|
||||
"subdocument",
|
||||
"refresh",
|
||||
"xbl",
|
||||
"ping",
|
||||
"xmlhttprequest",
|
||||
"objectsubrequest",
|
||||
"dtd",
|
||||
"font",
|
||||
"websocket",
|
||||
"csp_report",
|
||||
"xslt",
|
||||
"beacon",
|
||||
"fetch",
|
||||
"manifest",
|
||||
"speculative",
|
||||
].forEach(type => {
|
||||
Services.perms.removeByType(type);
|
||||
});
|
||||
}
|
||||
|
||||
if (existingDataVersion < 150) {
|
||||
Services.prefs.clearUserPref("toolkit.telemetry.pioneerId");
|
||||
}
|
||||
|
||||
if (existingDataVersion < 151) {
|
||||
// Existing Firefox users should have the usage reporting upload
|
||||
// preference "inherit" the general data reporting preference.
|
||||
lazy.UsageReporting.adoptDataReportingPreference();
|
||||
}
|
||||
|
||||
if (
|
||||
existingDataVersion < 152 &&
|
||||
Services.prefs.getBoolPref("sidebar.revamp") &&
|
||||
!Services.prefs.getBoolPref("browser.ml.chat.enabled")
|
||||
) {
|
||||
let tools = Services.prefs.getCharPref("sidebar.main.tools");
|
||||
if (tools?.includes("aichat")) {
|
||||
let updatedTools = tools
|
||||
.split(",")
|
||||
.filter(t => t != "aichat")
|
||||
.join(",");
|
||||
Services.prefs.setCharPref("sidebar.main.tools", updatedTools);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
existingDataVersion < 153 &&
|
||||
Services.prefs.getBoolPref("sidebar.revamp") &&
|
||||
!Services.prefs.prefHasUserValue("sidebar.main.tools")
|
||||
) {
|
||||
// This pref will now be a user set branch but we want to preserve the previous
|
||||
// default value for existing sidebar.revamp users who hadn't changed it.
|
||||
Services.prefs.setCharPref(
|
||||
"sidebar.main.tools",
|
||||
"aichat,syncedtabs,history"
|
||||
);
|
||||
}
|
||||
|
||||
if (existingDataVersion < 154) {
|
||||
// Remove mibbit handler.
|
||||
// The handler service will do this. We need to wait with migrating
|
||||
// until the handler service has started up, so just set a pref here.
|
||||
const kPref = "browser.handlers.migrations";
|
||||
// We might have set up another migration further up. Create an array,
|
||||
// and drop empty strings resulting from the `split`:
|
||||
let migrations = Services.prefs
|
||||
.getCharPref(kPref, "")
|
||||
.split(",")
|
||||
.filter(x => !!x);
|
||||
migrations.push("mibbit");
|
||||
Services.prefs.setCharPref(kPref, migrations.join(","));
|
||||
}
|
||||
|
||||
// Update the migration version.
|
||||
Services.prefs.setIntPref("browser.migration.version", newVersion);
|
||||
},
|
||||
};
|
495
browser/components/StartupTelemetry.sys.mjs
Normal file
495
browser/components/StartupTelemetry.sys.mjs
Normal file
|
@ -0,0 +1,495 @@
|
|||
/* 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/. */
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
let lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BrowserInitState: "resource:///modules/BrowserGlue.sys.mjs",
|
||||
BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.sys.mjs",
|
||||
FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
|
||||
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||
OsEnvironment: "resource://gre/modules/OsEnvironment.sys.mjs",
|
||||
PlacesDBUtils: "resource://gre/modules/PlacesDBUtils.sys.mjs",
|
||||
ShellService: "resource:///modules/ShellService.sys.mjs",
|
||||
TelemetryReportingPolicy:
|
||||
"resource://gre/modules/TelemetryReportingPolicy.sys.mjs",
|
||||
UsageReporting: "resource://gre/modules/UsageReporting.sys.mjs",
|
||||
});
|
||||
|
||||
/**
|
||||
* Used to collect various bits of telemetry during browser startup.
|
||||
*
|
||||
*/
|
||||
export let StartupTelemetry = {
|
||||
// Some tasks are expensive because they involve significant disk IO, and
|
||||
// may also write information to disk. If we submit the telemetry that may
|
||||
// happen anyway, but if we don't then this is undesirable, so those tasks are
|
||||
// only run if we will submit the results.
|
||||
// Why run any telemetry code at all if we don't submit the data? Because
|
||||
// local and autoland builds usually do not submit telemetry, but we still
|
||||
// want to be able to run automated tests to check the code _worked_.
|
||||
get _willUseExpensiveTelemetry() {
|
||||
return (
|
||||
AppConstants.MOZ_TELEMETRY_REPORTING &&
|
||||
Services.prefs.getBoolPref(
|
||||
"datareporting.healthreport.uploadEnabled",
|
||||
false
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
_runIdleTasks(tasks, profilerMarker) {
|
||||
for (let task of tasks) {
|
||||
ChromeUtils.idleDispatch(async () => {
|
||||
if (!Services.startup.shuttingDown) {
|
||||
let startTime = Cu.now();
|
||||
try {
|
||||
await task();
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
} finally {
|
||||
ChromeUtils.addProfilerMarker(
|
||||
profilerMarker,
|
||||
startTime,
|
||||
task.toSource()
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
browserIdleStartup() {
|
||||
let tasks = [
|
||||
// FOG doesn't need to be initialized _too_ early because it has a pre-init buffer.
|
||||
() => this.initFOG(),
|
||||
|
||||
() => this.contentBlocking(),
|
||||
() => this.dataSanitization(),
|
||||
() => this.pipEnabled(),
|
||||
() => this.sslKeylogFile(),
|
||||
() => this.osAuthEnabled(),
|
||||
() => this.startupConditions(),
|
||||
() => this.httpsOnlyState(),
|
||||
() => this.globalPrivacyControl(),
|
||||
];
|
||||
if (this._willUseExpensiveTelemetry) {
|
||||
tasks.push(() => lazy.PlacesDBUtils.telemetry());
|
||||
}
|
||||
if (AppConstants.platform == "win") {
|
||||
tasks.push(
|
||||
() => this.pinningStatus(),
|
||||
() => this.isDefaultHandler()
|
||||
);
|
||||
} else if (AppConstants.platform == "macosx") {
|
||||
tasks.push(() => this.macDockStatus());
|
||||
}
|
||||
|
||||
this._runIdleTasks(tasks, "startupTelemetryIdleTask");
|
||||
},
|
||||
|
||||
/**
|
||||
* Use this function as an entry point to collect telemetry that we hope
|
||||
* to collect once per session, at any arbitrary point in time, and
|
||||
*
|
||||
* **which we are okay with sometimes not running at all.**
|
||||
*
|
||||
* See BrowserGlue.sys.mjs's _scheduleBestEffortUserIdleTasks for more
|
||||
* details.
|
||||
*/
|
||||
bestEffortIdleStartup() {
|
||||
let tasks = [
|
||||
() => this.primaryPasswordEnabled(),
|
||||
() => this.trustObjectCount(),
|
||||
() => lazy.OsEnvironment.reportAllowedAppSources(),
|
||||
];
|
||||
if (AppConstants.platform == "win" && this._willUseExpensiveTelemetry) {
|
||||
tasks.push(
|
||||
() => lazy.BrowserUsageTelemetry.reportProfileCount(),
|
||||
() => lazy.BrowserUsageTelemetry.reportInstallationTelemetry()
|
||||
);
|
||||
}
|
||||
this._runIdleTasks(tasks, "startupTelemetryLateIdleTask");
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize Firefox-on-Glean.
|
||||
*
|
||||
* This is at the top because it's a bit different from the other code here
|
||||
* which is strictly collecting specific metrics.
|
||||
*/
|
||||
async initFOG() {
|
||||
// Handle Usage Profile ID. Similar logic to what's happening in
|
||||
// `TelemetryControllerParent` for the client ID. Must be done before
|
||||
// initializing FOG so that ping enabled/disabled states are correct
|
||||
// before Glean takes actions.
|
||||
await lazy.UsageReporting.ensureInitialized();
|
||||
|
||||
// If needed, delay initializing FOG until policy interaction is
|
||||
// completed. See comments in `TelemetryReportingPolicy`.
|
||||
await lazy.TelemetryReportingPolicy.ensureUserIsNotified();
|
||||
|
||||
Services.fog.initializeFOG();
|
||||
|
||||
// Register Glean to listen for experiment updates releated to the
|
||||
// "gleanInternalSdk" feature defined in the t/c/nimbus/FeatureManifest.yaml
|
||||
// This feature is intended for internal Glean use only. For features wishing
|
||||
// to set a remote metric configuration, please use the "glean" feature for
|
||||
// the purpose of setting the data-control-plane features via Server Knobs.
|
||||
lazy.NimbusFeatures.gleanInternalSdk.onUpdate(() => {
|
||||
let cfg = lazy.NimbusFeatures.gleanInternalSdk.getVariable(
|
||||
"gleanMetricConfiguration"
|
||||
);
|
||||
Services.fog.applyServerKnobsConfig(JSON.stringify(cfg));
|
||||
});
|
||||
|
||||
// Register Glean to listen for experiment updates releated to the
|
||||
// "glean" feature defined in the t/c/nimbus/FeatureManifest.yaml
|
||||
lazy.NimbusFeatures.glean.onUpdate(() => {
|
||||
let cfg = lazy.NimbusFeatures.glean.getVariable(
|
||||
"gleanMetricConfiguration"
|
||||
);
|
||||
Services.fog.applyServerKnobsConfig(JSON.stringify(cfg));
|
||||
});
|
||||
},
|
||||
|
||||
startupConditions() {
|
||||
let nowSeconds = Math.round(Date.now() / 1000);
|
||||
// Don't include cases where we don't have the pref. This rules out the first install
|
||||
// as well as the first run of a build since this was introduced. These could by some
|
||||
// definitions be referred to as "cold" startups, but probably not since we likely
|
||||
// just wrote many of the files we use to disk. This way we should approximate a lower
|
||||
// bound to the number of cold startups rather than an upper bound.
|
||||
let lastCheckSeconds = Services.prefs.getIntPref(
|
||||
"browser.startup.lastColdStartupCheck",
|
||||
nowSeconds
|
||||
);
|
||||
Services.prefs.setIntPref(
|
||||
"browser.startup.lastColdStartupCheck",
|
||||
nowSeconds
|
||||
);
|
||||
try {
|
||||
let secondsSinceLastOSRestart =
|
||||
Services.startup.secondsSinceLastOSRestart;
|
||||
let isColdStartup =
|
||||
nowSeconds - secondsSinceLastOSRestart > lastCheckSeconds;
|
||||
Glean.startup.isCold.set(isColdStartup);
|
||||
Glean.startup.secondsSinceLastOsRestart.set(secondsSinceLastOSRestart);
|
||||
} catch (ex) {
|
||||
if (ex.name !== "NS_ERROR_NOT_IMPLEMENTED") {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
contentBlocking() {
|
||||
let tpEnabled = Services.prefs.getBoolPref(
|
||||
"privacy.trackingprotection.enabled"
|
||||
);
|
||||
Glean.contentblocking.trackingProtectionEnabled[
|
||||
tpEnabled ? "true" : "false"
|
||||
].add();
|
||||
|
||||
let tpPBEnabled = Services.prefs.getBoolPref(
|
||||
"privacy.trackingprotection.pbmode.enabled"
|
||||
);
|
||||
Glean.contentblocking.trackingProtectionPbmDisabled[
|
||||
!tpPBEnabled ? "true" : "false"
|
||||
].add();
|
||||
|
||||
let cookieBehavior = Services.prefs.getIntPref(
|
||||
"network.cookie.cookieBehavior"
|
||||
);
|
||||
Glean.contentblocking.cookieBehavior.accumulateSingleSample(cookieBehavior);
|
||||
|
||||
let fpEnabled = Services.prefs.getBoolPref(
|
||||
"privacy.trackingprotection.fingerprinting.enabled"
|
||||
);
|
||||
let cmEnabled = Services.prefs.getBoolPref(
|
||||
"privacy.trackingprotection.cryptomining.enabled"
|
||||
);
|
||||
let categoryPref;
|
||||
switch (
|
||||
Services.prefs.getStringPref("browser.contentblocking.category", null)
|
||||
) {
|
||||
case "standard":
|
||||
categoryPref = 0;
|
||||
break;
|
||||
case "strict":
|
||||
categoryPref = 1;
|
||||
break;
|
||||
case "custom":
|
||||
categoryPref = 2;
|
||||
break;
|
||||
default:
|
||||
// Any other value is unsupported.
|
||||
categoryPref = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
Glean.contentblocking.fingerprintingBlockingEnabled.set(fpEnabled);
|
||||
Glean.contentblocking.cryptominingBlockingEnabled.set(cmEnabled);
|
||||
Glean.contentblocking.category.set(categoryPref);
|
||||
},
|
||||
|
||||
dataSanitization() {
|
||||
Glean.datasanitization.privacySanitizeSanitizeOnShutdown.set(
|
||||
Services.prefs.getBoolPref("privacy.sanitize.sanitizeOnShutdown")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownCookies.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.cookies")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownHistory.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.history")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownFormdata.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.formdata")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownDownloads.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.downloads")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownCache.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.cache")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownSessions.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.sessions")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownOfflineApps.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.offlineApps")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownSiteSettings.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.siteSettings")
|
||||
);
|
||||
Glean.datasanitization.privacyClearOnShutdownOpenWindows.set(
|
||||
Services.prefs.getBoolPref("privacy.clearOnShutdown.openWindows")
|
||||
);
|
||||
|
||||
let exceptions = 0;
|
||||
for (let permission of Services.perms.all) {
|
||||
// We consider just permissions set for http, https and file URLs.
|
||||
if (
|
||||
permission.type == "cookie" &&
|
||||
permission.capability == Ci.nsICookiePermission.ACCESS_SESSION &&
|
||||
["http", "https", "file"].some(scheme =>
|
||||
permission.principal.schemeIs(scheme)
|
||||
)
|
||||
) {
|
||||
exceptions++;
|
||||
}
|
||||
}
|
||||
Glean.datasanitization.sessionPermissionExceptions.set(exceptions);
|
||||
},
|
||||
|
||||
httpsOnlyState() {
|
||||
const PREF_ENABLED = "dom.security.https_only_mode";
|
||||
const PREF_WAS_ENABLED = "dom.security.https_only_mode_ever_enabled";
|
||||
const _checkHTTPSOnlyPref = async () => {
|
||||
const enabled = Services.prefs.getBoolPref(PREF_ENABLED, false);
|
||||
const was_enabled = Services.prefs.getBoolPref(PREF_WAS_ENABLED, false);
|
||||
let value = 0;
|
||||
if (enabled) {
|
||||
value = 1;
|
||||
Services.prefs.setBoolPref(PREF_WAS_ENABLED, true);
|
||||
} else if (was_enabled) {
|
||||
value = 2;
|
||||
}
|
||||
Glean.security.httpsOnlyModeEnabled.set(value);
|
||||
};
|
||||
|
||||
Services.prefs.addObserver(PREF_ENABLED, _checkHTTPSOnlyPref);
|
||||
_checkHTTPSOnlyPref();
|
||||
|
||||
const PREF_PBM_WAS_ENABLED =
|
||||
"dom.security.https_only_mode_ever_enabled_pbm";
|
||||
const PREF_PBM_ENABLED = "dom.security.https_only_mode_pbm";
|
||||
|
||||
const _checkHTTPSOnlyPBMPref = async () => {
|
||||
const enabledPBM = Services.prefs.getBoolPref(PREF_PBM_ENABLED, false);
|
||||
const was_enabledPBM = Services.prefs.getBoolPref(
|
||||
PREF_PBM_WAS_ENABLED,
|
||||
false
|
||||
);
|
||||
let valuePBM = 0;
|
||||
if (enabledPBM) {
|
||||
valuePBM = 1;
|
||||
Services.prefs.setBoolPref(PREF_PBM_WAS_ENABLED, true);
|
||||
} else if (was_enabledPBM) {
|
||||
valuePBM = 2;
|
||||
}
|
||||
Glean.security.httpsOnlyModeEnabledPbm.set(valuePBM);
|
||||
};
|
||||
|
||||
Services.prefs.addObserver(PREF_PBM_ENABLED, _checkHTTPSOnlyPBMPref);
|
||||
_checkHTTPSOnlyPBMPref();
|
||||
},
|
||||
|
||||
globalPrivacyControl() {
|
||||
const FEATURE_PREF_ENABLED = "privacy.globalprivacycontrol.enabled";
|
||||
const FUNCTIONALITY_PREF_ENABLED =
|
||||
"privacy.globalprivacycontrol.functionality.enabled";
|
||||
const PREF_WAS_ENABLED = "privacy.globalprivacycontrol.was_ever_enabled";
|
||||
const _checkGPCPref = async () => {
|
||||
const feature_enabled = Services.prefs.getBoolPref(
|
||||
FEATURE_PREF_ENABLED,
|
||||
false
|
||||
);
|
||||
const functionality_enabled = Services.prefs.getBoolPref(
|
||||
FUNCTIONALITY_PREF_ENABLED,
|
||||
false
|
||||
);
|
||||
const was_enabled = Services.prefs.getBoolPref(PREF_WAS_ENABLED, false);
|
||||
let value = 0;
|
||||
if (feature_enabled && functionality_enabled) {
|
||||
value = 1;
|
||||
Services.prefs.setBoolPref(PREF_WAS_ENABLED, true);
|
||||
} else if (was_enabled) {
|
||||
value = 2;
|
||||
}
|
||||
Glean.security.globalPrivacyControlEnabled.set(value);
|
||||
};
|
||||
|
||||
Services.prefs.addObserver(FEATURE_PREF_ENABLED, _checkGPCPref);
|
||||
Services.prefs.addObserver(FUNCTIONALITY_PREF_ENABLED, _checkGPCPref);
|
||||
_checkGPCPref();
|
||||
},
|
||||
|
||||
async pinningStatus() {
|
||||
let shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
|
||||
Ci.nsIWindowsShellService
|
||||
);
|
||||
let winTaskbar = Cc["@mozilla.org/windows-taskbar;1"].getService(
|
||||
Ci.nsIWinTaskbar
|
||||
);
|
||||
|
||||
try {
|
||||
Glean.osEnvironment.isTaskbarPinned.set(
|
||||
await shellService.isCurrentAppPinnedToTaskbarAsync(
|
||||
winTaskbar.defaultGroupId
|
||||
)
|
||||
);
|
||||
// Bug 1911343: Pinning regular browsing on MSIX
|
||||
// causes false positives when checking for private
|
||||
// browsing.
|
||||
if (
|
||||
AppConstants.platform === "win" &&
|
||||
!Services.sysinfo.getProperty("hasWinPackageId")
|
||||
) {
|
||||
Glean.osEnvironment.isTaskbarPinnedPrivate.set(
|
||||
await shellService.isCurrentAppPinnedToTaskbarAsync(
|
||||
winTaskbar.defaultPrivateGroupId
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
|
||||
let classification;
|
||||
let shortcut;
|
||||
try {
|
||||
shortcut = Services.appinfo.processStartupShortcut;
|
||||
classification = shellService.classifyShortcut(shortcut);
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
|
||||
if (!classification) {
|
||||
if (lazy.BrowserInitState.isLaunchOnLogin) {
|
||||
classification = "Autostart";
|
||||
} else if (shortcut) {
|
||||
classification = "OtherShortcut";
|
||||
} else {
|
||||
classification = "Other";
|
||||
}
|
||||
}
|
||||
// Because of how taskbar tabs work, it may be classifed as a taskbar
|
||||
// shortcut, in which case we want to overwrite it.
|
||||
if (lazy.BrowserInitState.isTaskbarTab) {
|
||||
classification = "TaskbarTab";
|
||||
}
|
||||
Glean.osEnvironment.launchMethod.set(classification);
|
||||
},
|
||||
|
||||
isDefaultHandler() {
|
||||
// Report whether Firefox is the default handler for various files types
|
||||
// and protocols, in particular, ".pdf" and "mailto"
|
||||
[".pdf", "mailto"].every(x => {
|
||||
Glean.osEnvironment.isDefaultHandler[x].set(
|
||||
lazy.ShellService.isDefaultHandlerFor(x)
|
||||
);
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
||||
macDockStatus() {
|
||||
// Report macOS Dock status
|
||||
Glean.osEnvironment.isKeptInDock.set(
|
||||
Cc["@mozilla.org/widget/macdocksupport;1"].getService(
|
||||
Ci.nsIMacDockSupport
|
||||
).isAppInDock
|
||||
);
|
||||
},
|
||||
|
||||
sslKeylogFile() {
|
||||
Glean.sslkeylogging.enabled.set(Services.env.exists("SSLKEYLOGFILE"));
|
||||
},
|
||||
|
||||
osAuthEnabled() {
|
||||
// Manually read these prefs. This treats any non-empty-string
|
||||
// value as "turned off", irrespective of whether it correctly
|
||||
// decrypts to the correct value, because we cannot do the
|
||||
// decryption if the primary password has not yet been provided,
|
||||
// and for telemetry treating that situation as "turned off"
|
||||
// seems reasonable.
|
||||
const osAuthForCc = !Services.prefs.getStringPref(
|
||||
lazy.FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF,
|
||||
""
|
||||
);
|
||||
const osAuthForPw = !Services.prefs.getStringPref(
|
||||
lazy.LoginHelper.OS_AUTH_FOR_PASSWORDS_PREF,
|
||||
""
|
||||
);
|
||||
|
||||
Glean.formautofill.osAuthEnabled.set(osAuthForCc);
|
||||
Glean.pwmgr.osAuthEnabled.set(osAuthForPw);
|
||||
},
|
||||
|
||||
primaryPasswordEnabled() {
|
||||
let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(
|
||||
Ci.nsIPK11TokenDB
|
||||
);
|
||||
let token = tokenDB.getInternalKeyToken();
|
||||
Glean.primaryPassword.enabled.set(token.hasPassword);
|
||||
},
|
||||
|
||||
trustObjectCount() {
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||
Ci.nsIX509CertDB
|
||||
);
|
||||
// countTrustObjects also logs the number of trust objects for telemetry purposes
|
||||
certdb.countTrustObjects();
|
||||
},
|
||||
|
||||
pipEnabled() {
|
||||
const TOGGLE_ENABLED_PREF =
|
||||
"media.videocontrols.picture-in-picture.video-toggle.enabled";
|
||||
|
||||
const observe = (subject, topic) => {
|
||||
const enabled = Services.prefs.getBoolPref(TOGGLE_ENABLED_PREF, false);
|
||||
Glean.pictureinpicture.toggleEnabled.set(enabled);
|
||||
|
||||
// Record events when preferences change
|
||||
if (topic === "nsPref:changed") {
|
||||
if (enabled) {
|
||||
Glean.pictureinpictureSettings.enableSettings.record();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Services.prefs.addObserver(TOGGLE_ENABLED_PREF, observe);
|
||||
observe();
|
||||
},
|
||||
};
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
head = ''
|
||||
# make the firefox services (eg newtab-service) available to xpcshell
|
||||
firefox-appdir = "browser"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
head = "head.js"
|
||||
firefox-appdir = "browser"
|
||||
|
||||
|
|
|
@ -855,8 +855,6 @@ const SHOPPING_MICROSURVEY = {
|
|||
};
|
||||
|
||||
const OPTED_IN_TIME_PREF = "browser.shopping.experience2023.survey.optedInTime";
|
||||
const ONBOARDING_FIRST_IMPRESSION_TIME_PREF =
|
||||
"browser.shopping.experience2023.firstImpressionTime";
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
|
@ -962,19 +960,6 @@ export class AboutWelcomeShoppingChild extends AboutWelcomeChild {
|
|||
});
|
||||
}
|
||||
|
||||
setOnBoardingImpressionTime() {
|
||||
const now = Date.now() / 1000;
|
||||
this.AWSendToParent("SPECIAL_ACTION", {
|
||||
type: "SET_PREF",
|
||||
data: {
|
||||
pref: {
|
||||
name: ONBOARDING_FIRST_IMPRESSION_TIME_PREF,
|
||||
value: now,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
// Decide when to show/hide onboarding and survey message
|
||||
const { productUrl, showOnboarding, data, isSupportedSite, isProductPage } =
|
||||
|
@ -1067,8 +1052,6 @@ export class AboutWelcomeShoppingChild extends AboutWelcomeChild {
|
|||
if (this.showMicroSurvey && !this.showOnboarding) {
|
||||
messageContent = SHOPPING_MICROSURVEY;
|
||||
this.setShoppingSurveySeen();
|
||||
} else {
|
||||
this.setOnBoardingImpressionTime();
|
||||
}
|
||||
return Cu.cloneInto(messageContent, this.contentWindow);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = ["os == 'android'"]
|
||||
firefox-appdir = "browser"
|
||||
|
||||
["test_AboutWelcomeAttribution.js"]
|
||||
|
|
|
@ -65,6 +65,7 @@ Please note that some targeting attributes require stricter controls on the tele
|
|||
* [primaryResolution](#primaryresolution)
|
||||
* [profileAgeCreated](#profileagecreated)
|
||||
* [profileAgeReset](#profileagereset)
|
||||
* [profileGroupId](#profilegroupid)
|
||||
* [profileRestartCount](#profilerestartcount)
|
||||
* [providerCohorts](#providercohorts)
|
||||
* [recentBookmarks](#recentbookmarks)
|
||||
|
@ -1092,3 +1093,8 @@ declare const systemArch: string | null;
|
|||
### `totalSearches`
|
||||
|
||||
Returns the number of times a user has completed a search in the URL Bar. The number is arbitrarily capped at 100.
|
||||
|
||||
|
||||
### `profileGroupId`
|
||||
|
||||
Returns the stable profile group ID used for data reporting.
|
||||
|
|
|
@ -34,6 +34,11 @@ const { ShellService } = ChromeUtils.importESModule(
|
|||
"resource:///modules/ShellService.sys.mjs"
|
||||
);
|
||||
|
||||
// eslint-disable-next-line mozilla/use-static-import
|
||||
const { ClientID } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/ClientID.sys.mjs"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
|
@ -388,6 +393,12 @@ export const QueryCache = {
|
|||
FRECENT_SITES_UPDATE_INTERVAL,
|
||||
ShellService
|
||||
),
|
||||
profileGroupId: new CachedTargetingGetter(
|
||||
"getCachedProfileGroupID",
|
||||
null,
|
||||
FRECENT_SITES_UPDATE_INTERVAL,
|
||||
ClientID
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1184,6 +1195,10 @@ const TargetingGetters = {
|
|||
get totalSearches() {
|
||||
return lazy.totalSearches;
|
||||
},
|
||||
|
||||
get profileGroupId() {
|
||||
return QueryCache.getters.profileGroupId.get();
|
||||
},
|
||||
};
|
||||
|
||||
export const ASRouterTargeting = {
|
||||
|
|
|
@ -1618,8 +1618,7 @@ const MESSAGES = () => {
|
|||
{
|
||||
type: "action",
|
||||
label: {
|
||||
string_id:
|
||||
"shopping-callout-not-opted-in-integrated-reminder-do-not-show",
|
||||
string_id: "split-dismiss-button-dont-show-option",
|
||||
},
|
||||
action: {
|
||||
type: "SET_PREF",
|
||||
|
@ -1631,13 +1630,12 @@ const MESSAGES = () => {
|
|||
},
|
||||
dismiss: true,
|
||||
},
|
||||
id: "shopping-callout-not-opted-in-integrated-reminder-do-not-show",
|
||||
id: "split-dismiss-button-dont-show-option",
|
||||
},
|
||||
{
|
||||
type: "action",
|
||||
label: {
|
||||
string_id:
|
||||
"shopping-callout-not-opted-in-integrated-reminder-show-fewer",
|
||||
string_id: "split-dismiss-button-show-fewer-option",
|
||||
},
|
||||
action: {
|
||||
type: "MULTI_ACTION",
|
||||
|
@ -1666,7 +1664,7 @@ const MESSAGES = () => {
|
|||
},
|
||||
dismiss: true,
|
||||
},
|
||||
id: "shopping-callout-not-opted-in-integrated-reminder-show-fewer",
|
||||
id: "split-dismiss-button-show-fewer-option",
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
|
@ -1674,8 +1672,7 @@ const MESSAGES = () => {
|
|||
{
|
||||
type: "action",
|
||||
label: {
|
||||
string_id:
|
||||
"shopping-callout-not-opted-in-integrated-reminder-manage-settings",
|
||||
string_id: "split-dismiss-button-manage-settings-option",
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_ABOUT_PAGE",
|
||||
|
@ -1685,7 +1682,7 @@ const MESSAGES = () => {
|
|||
},
|
||||
dismiss: true,
|
||||
},
|
||||
id: "shopping-callout-not-opted-in-integrated-reminder-manage-settings",
|
||||
id: "split-dismiss-button-manage-settings-option",
|
||||
},
|
||||
],
|
||||
attached_to: "additional_button",
|
||||
|
@ -1887,8 +1884,7 @@ const MESSAGES = () => {
|
|||
{
|
||||
type: "action",
|
||||
label: {
|
||||
string_id:
|
||||
"shopping-callout-not-opted-in-integrated-reminder-do-not-show",
|
||||
string_id: "split-dismiss-button-dont-show-option",
|
||||
},
|
||||
action: {
|
||||
type: "SET_PREF",
|
||||
|
@ -1900,13 +1896,12 @@ const MESSAGES = () => {
|
|||
},
|
||||
dismiss: true,
|
||||
},
|
||||
id: "shopping-callout-not-opted-in-integrated-reminder-do-not-show",
|
||||
id: "split-dismiss-button-dont-show-option",
|
||||
},
|
||||
{
|
||||
type: "action",
|
||||
label: {
|
||||
string_id:
|
||||
"shopping-callout-not-opted-in-integrated-reminder-show-fewer",
|
||||
string_id: "split-dismiss-button-show-fewer-option",
|
||||
},
|
||||
action: {
|
||||
type: "MULTI_ACTION",
|
||||
|
@ -1935,7 +1930,7 @@ const MESSAGES = () => {
|
|||
},
|
||||
dismiss: true,
|
||||
},
|
||||
id: "shopping-callout-not-opted-in-integrated-reminder-show-fewer",
|
||||
id: "split-dismiss-button-show-fewer-option",
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
|
@ -1943,8 +1938,7 @@ const MESSAGES = () => {
|
|||
{
|
||||
type: "action",
|
||||
label: {
|
||||
string_id:
|
||||
"shopping-callout-not-opted-in-integrated-reminder-manage-settings",
|
||||
string_id: "split-dismiss-button-manage-settings-option",
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_ABOUT_PAGE",
|
||||
|
@ -1954,7 +1948,7 @@ const MESSAGES = () => {
|
|||
},
|
||||
dismiss: true,
|
||||
},
|
||||
id: "shopping-callout-not-opted-in-integrated-reminder-manage-settings",
|
||||
id: "split-dismiss-button-manage-settings-option",
|
||||
},
|
||||
],
|
||||
attached_to: "additional_button",
|
||||
|
|
|
@ -1546,7 +1546,7 @@ const MESSAGES = () => [
|
|||
id: "TEST_NEWTAB_MESSAGE",
|
||||
template: "newtab_message",
|
||||
content: {
|
||||
messageType: "CustomWallpaperHighlight",
|
||||
messageType: "DownloadMobilePromoHighlight",
|
||||
},
|
||||
trigger: {
|
||||
id: "newtabMessageCheck",
|
||||
|
|
|
@ -8,6 +8,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
|||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
|
||||
BuiltInThemes: "resource:///modules/BuiltInThemes.sys.mjs",
|
||||
CFRMessageProvider: "resource:///modules/asrouter/CFRMessageProvider.sys.mjs",
|
||||
ClientID: "resource://gre/modules/ClientID.sys.mjs",
|
||||
ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||
ExperimentFakes: "resource://testing-common/NimbusTestUtils.sys.mjs",
|
||||
FxAccounts: "resource://gre/modules/FxAccounts.sys.mjs",
|
||||
|
@ -2000,3 +2001,22 @@ add_task(async function check_unhandledCampaignAction() {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function check_profileGroupIdTargeting() {
|
||||
const expected = await ClientID.getCachedProfileGroupID();
|
||||
const result = await ASRouterTargeting.Environment.profileGroupId;
|
||||
|
||||
is(typeof result, "string", "profileGroupId should be a string");
|
||||
|
||||
is(result, expected, "it should be equal to the profile group id");
|
||||
|
||||
const message = {
|
||||
id: "foo",
|
||||
targeting: `profileGroupId == "${expected.toString()}"`,
|
||||
};
|
||||
is(
|
||||
await ASRouterTargeting.findMatchingMessage({ messages: [message] }),
|
||||
message,
|
||||
"should select correct item by profile group id"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ const { CustomizableUITestUtils } = ChromeUtils.importESModule(
|
|||
"resource://testing-common/CustomizableUITestUtils.sys.mjs"
|
||||
);
|
||||
const { DefaultBrowserCheck } = ChromeUtils.importESModule(
|
||||
"resource:///modules/BrowserGlue.sys.mjs"
|
||||
"moz-src:///browser/components/DefaultBrowserCheck.sys.mjs"
|
||||
);
|
||||
|
||||
const PDF_TEST_URL =
|
||||
|
|
|
@ -96,10 +96,7 @@ add_task(async function test_messagesLoaded_reach_experiment() {
|
|||
],
|
||||
}
|
||||
);
|
||||
Assert.ok(
|
||||
await ExperimentTestUtils.validateExperiment(recipe),
|
||||
"Valid recipe"
|
||||
);
|
||||
await ExperimentTestUtils.validateExperiment(recipe);
|
||||
|
||||
await client.db.importChanges({}, Date.now(), [recipe], { clear: true });
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[DEFAULT]
|
||||
head = "head.js"
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os == 'android'"]
|
||||
prefs = [
|
||||
"browser.backup.log=true",
|
||||
]
|
||||
|
|
|
@ -47,12 +47,6 @@ Classes = [
|
|||
'esModule': 'resource:///modules/BrowserGlue.sys.mjs',
|
||||
'constructor': 'BrowserGlue',
|
||||
},
|
||||
{
|
||||
'cid': '{d8903bf6-68d5-4e97-bcd1-e4d3012f721a}',
|
||||
'contract_ids': ['@mozilla.org/content-permission/prompt;1'],
|
||||
'esModule': 'resource:///modules/BrowserGlue.sys.mjs',
|
||||
'constructor': 'ContentPermissionPrompt',
|
||||
},
|
||||
]
|
||||
|
||||
if (buildconfig.substs.get('MOZ_DEBUG') or
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
/* 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/. */
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* Contains elements of the Content Analysis UI, which are integrated into
|
||||
|
@ -99,7 +100,7 @@ export const ContentAnalysis = {
|
|||
|
||||
/**
|
||||
* @typedef {object} RequestInfo
|
||||
* @property {BrowsingContext} browsingContext - browsing context where the request was sent from
|
||||
* @property {CanonicalBrowsingContext} browsingContext - browsing context where the request was sent from
|
||||
* @property {ResourceNameOrOperationType} resourceNameOrOperationType - name of the operation
|
||||
*/
|
||||
|
||||
|
@ -162,6 +163,7 @@ export const ContentAnalysis = {
|
|||
Services.obs.addObserver(this, "dlp-request-made");
|
||||
Services.obs.addObserver(this, "dlp-response");
|
||||
Services.obs.addObserver(this, "quit-application");
|
||||
Services.obs.addObserver(this, "quit-application-granted");
|
||||
Services.obs.addObserver(this, "quit-application-requested");
|
||||
},
|
||||
|
||||
|
@ -204,7 +206,7 @@ export const ContentAnalysis = {
|
|||
null,
|
||||
null,
|
||||
null,
|
||||
{ value: 0 }
|
||||
{ value: false }
|
||||
);
|
||||
if (buttonSelected === 1) {
|
||||
// Cancel the quit operation
|
||||
|
@ -218,7 +220,10 @@ export const ContentAnalysis = {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "quit-application": {
|
||||
// Note that we do this in quit-application-granted instead of quit-application
|
||||
// because otherwise we can get a shutdownhang if WARN dialogs are showing and
|
||||
// the user quits via keyboard or the hamburger menu (bug 1959966)
|
||||
case "quit-application-granted": {
|
||||
// We're quitting, so respond false to all WARN dialogs.
|
||||
let requestTokensToCancel = this.warnDialogRequestTokens;
|
||||
// Clear this first so the handler showing the dialog will know not
|
||||
|
@ -230,6 +235,9 @@ export const ContentAnalysis = {
|
|||
false
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "quit-application": {
|
||||
this.uninitialize();
|
||||
break;
|
||||
}
|
||||
|
@ -310,7 +318,7 @@ export const ContentAnalysis = {
|
|||
* Shows the panel that indicates that DLP is active.
|
||||
*
|
||||
* @param {Element} element The toolbarbutton the user has clicked on
|
||||
* @param {panelUI} panelUI Maintains state for the main menu panel
|
||||
* @param {*} panelUI Maintains state for the main menu panel
|
||||
*/
|
||||
async showPanel(element, panelUI) {
|
||||
element.ownerDocument.l10n.setAttributes(
|
||||
|
@ -367,7 +375,7 @@ export const ContentAnalysis = {
|
|||
* _SHOW_DIALOGS and _SHOW_NOTIFICATIONS.
|
||||
*
|
||||
* @param {string} aMessage - Message to show
|
||||
* @param {BrowsingContext} aBrowsingContext - BrowsingContext to show the dialog in.
|
||||
* @param {CanonicalBrowsingContext} aBrowsingContext - BrowsingContext to show the dialog in.
|
||||
* @param {number} aTimeout - timeout for closing the native notification. 0 indicates it is
|
||||
* not automatically closed.
|
||||
* @returns {NotificationInfo?} - information about the native notification, if it has been shown.
|
||||
|
@ -405,7 +413,7 @@ export const ContentAnalysis = {
|
|||
/**
|
||||
* Whether the notification should block browser interaction.
|
||||
*
|
||||
* @param {number} aAnalysisType The type of DLP analysis being done.
|
||||
* @param {nsIContentAnalysisRequest.AnalysisType} aAnalysisType The type of DLP analysis being done.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_shouldShowBlockingNotification(aAnalysisType) {
|
||||
|
@ -451,7 +459,7 @@ export const ContentAnalysis = {
|
|||
/**
|
||||
* Gets a name or operation type from a request
|
||||
*
|
||||
* @param {object} aRequest The nsIContentAnalysisRequest
|
||||
* @param {nsIContentAnalysisRequest} aRequest The nsIContentAnalysisRequest
|
||||
* @param {boolean} aStandalone Whether the message is going to be used on its own
|
||||
* line. This is used to add more context to the message
|
||||
* if a file is being uploaded rather than just the name
|
||||
|
@ -482,7 +490,7 @@ export const ContentAnalysis = {
|
|||
*
|
||||
* @param {nsIContentAnalysisRequest} aRequest
|
||||
* @param {ResourceNameOrOperationType} aResourceNameOrOperationType
|
||||
* @param {BrowsingContext} aBrowsingContext
|
||||
* @param {CanonicalBrowsingContext} aBrowsingContext
|
||||
*/
|
||||
_queueSlowCAMessage(
|
||||
aRequest,
|
||||
|
@ -553,7 +561,7 @@ export const ContentAnalysis = {
|
|||
/**
|
||||
* Gets all the requests that are still in progress.
|
||||
*
|
||||
* @returns {Iterable<RequestInfo>} Information about the requests that are still in progress
|
||||
* @returns {IteratorObject<RequestInfo>} Information about the requests that are still in progress
|
||||
*/
|
||||
_getAllSlowCARequestInfos() {
|
||||
return this.userActionToBusyDialogMap
|
||||
|
@ -566,10 +574,10 @@ export const ContentAnalysis = {
|
|||
* Show a message to the user to indicate that a CA request is taking
|
||||
* a long time.
|
||||
*
|
||||
* @param {string} aOperation Name of the operation
|
||||
* @param {nsIContentAnalysisRequest.AnalysisType} aOperation The operation
|
||||
* @param {nsIContentAnalysisRequest} aRequest The request that is taking a long time
|
||||
* @param {string} aBodyMessage Message to show in the body of the alert
|
||||
* @param {BrowsingContext} aBrowsingContext BrowsingContext to show the alert in
|
||||
* @param {CanonicalBrowsingContext} aBrowsingContext BrowsingContext to show the alert in
|
||||
*/
|
||||
_showSlowCAMessage(aOperation, aRequest, aBodyMessage, aBrowsingContext) {
|
||||
if (!this._shouldShowBlockingNotification(aOperation)) {
|
||||
|
@ -712,8 +720,6 @@ export const ContentAnalysis = {
|
|||
// This is also be called if the tab/window is closed while a request is in progress,
|
||||
// in which case we need to cancel the request.
|
||||
if (this.requestTokenToRequestInfo.delete(aRequestToken)) {
|
||||
// TODO: Is this useful? I think no.
|
||||
this._removeSlowCAMessage({}, aRequestToken);
|
||||
this._removeSlowCAMessage(aUserActionId, aRequestToken);
|
||||
lazy.gContentAnalysis.cancelRequestsByRequestToken(aRequestToken);
|
||||
}
|
||||
|
@ -726,14 +732,14 @@ export const ContentAnalysis = {
|
|||
/**
|
||||
* Show a message to the user to indicate the result of a CA request.
|
||||
*
|
||||
* @param {object} aResourceNameOrOperationType
|
||||
* @param {BrowsingContext} aBrowsingContext
|
||||
* @param {ResourceNameOrOperationType} aResourceNameOrOperationType
|
||||
* @param {CanonicalBrowsingContext} aBrowsingContext
|
||||
* @param {string} aRequestToken
|
||||
* @param {string} aUserActionId
|
||||
* @param {number} aCAResult
|
||||
* @param {bool} aIsAgentResponse
|
||||
* @param {boolean} aIsAgentResponse
|
||||
* @param {number} aRequestCancelError
|
||||
* @returns {NotificationInfo?} a notification object (if shown)
|
||||
* @returns {Promise<NotificationInfo?>} a notification object (if shown)
|
||||
*/
|
||||
async _showCAResult(
|
||||
aResourceNameOrOperationType,
|
||||
|
@ -785,7 +791,7 @@ export const ContentAnalysis = {
|
|||
),
|
||||
null,
|
||||
null,
|
||||
{}
|
||||
false
|
||||
);
|
||||
allow = result.get("buttonNumClicked") === 0;
|
||||
} catch {
|
||||
|
|
14
browser/components/contentanalysis/content/tsconfig.json
Normal file
14
browser/components/contentanalysis/content/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../../../tools/@types/tsconfig.json",
|
||||
"include": ["*.mjs", "types/*.ts"],
|
||||
|
||||
"compilerOptions": {
|
||||
"checkJs": true,
|
||||
"plugins": [
|
||||
{
|
||||
"transform": "../../../../tools/ts/plugins/checkRootOnly.js",
|
||||
"transformProgram": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
[DEFAULT]
|
||||
head = ''
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
firefox-appdir = "browser"
|
||||
|
||||
["test_unified_extensions_migration.js"]
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
[DEFAULT]
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
head = "head.js"
|
||||
firefox-appdir = "browser"
|
||||
support-files = ["../../../../../netwerk/test/unit/http2-ca.pem"]
|
||||
|
||||
["test_DNSLookup.js"]
|
||||
skip-if = ["debug"] # Bug 1617845
|
||||
|
||||
["test_LookupAggregator.js"]
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[DEFAULT]
|
||||
head = "head.js"
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
|
||||
["test_DownloadLastDir_basics.js"]
|
||||
|
||||
|
|
|
@ -1987,7 +1987,6 @@ export var Policies = {
|
|||
"security.mixed_content.block_active_content",
|
||||
"security.mixed_content.block_display_content",
|
||||
"security.mixed_content.upgrade_display_content",
|
||||
"security.osclientcerts.assume_rsa_pss_support",
|
||||
"security.osclientcerts.autoload",
|
||||
"security.OCSP.enabled",
|
||||
"security.OCSP.require",
|
||||
|
@ -2642,9 +2641,22 @@ export var Policies = {
|
|||
param.FeatureRecommendations,
|
||||
param.Locked
|
||||
);
|
||||
|
||||
// We use the mostRecentTargetLanguages pref to control the
|
||||
// translations panel intro. Setting a language value simulates a
|
||||
// first translation, which skips the intro panel for users with
|
||||
// FeatureRecommendations disabled.
|
||||
const topWebPreferredLanguage = Services.prefs
|
||||
.getComplexValue("intl.accept_languages", Ci.nsIPrefLocalizedString)
|
||||
.data.split(/\s*,\s*/g)[0];
|
||||
|
||||
const preferredLanguage = topWebPreferredLanguage.length
|
||||
? topWebPreferredLanguage
|
||||
: Services.locale.appLocaleAsBCP47;
|
||||
|
||||
PoliciesUtils.setDefaultPref(
|
||||
"browser.translations.panelShown",
|
||||
!param.FeatureRecommendations,
|
||||
"browser.translations.mostRecentTargetLanguages",
|
||||
param.FeatureRecommendations ? "" : preferredLanguage,
|
||||
param.Locked
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
firefox-appdir = "browser"
|
||||
head = "head.js"
|
||||
support-files = [
|
||||
|
|
|
@ -309,3 +309,353 @@ add_task(async function testOptionalPermissionsDialogShowsFullDomainsList() {
|
|||
await extension.unload();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function testOptionalPermissionsDialogWithDataCollection() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.dataCollectionPermissions.enabled", true]],
|
||||
});
|
||||
|
||||
const createTestExtension = ({
|
||||
id,
|
||||
optional_permissions = undefined,
|
||||
data_collection_permissions = undefined,
|
||||
}) => {
|
||||
return ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
// Set the generated id as a name to make it easier to recognize the
|
||||
// test case from dialog screenshots (e.g. in the screenshot captured
|
||||
// when the test hits a failure).
|
||||
name: id,
|
||||
version: "1.0",
|
||||
optional_permissions,
|
||||
browser_specific_settings: {
|
||||
gecko: { id, data_collection_permissions },
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"extpage.html": `<!DOCTYPE html><script src="extpage.js"></script>`,
|
||||
"extpage.js"() {
|
||||
browser.test.onMessage.addListener(async msg => {
|
||||
if (msg !== "request-perms") {
|
||||
browser.test.fail(`Got unexpected test message ${msg}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
browser_specific_settings: {
|
||||
gecko: { data_collection_permissions },
|
||||
},
|
||||
optional_permissions,
|
||||
} = browser.runtime.getManifest();
|
||||
|
||||
let perms = {
|
||||
data_collection: data_collection_permissions.optional,
|
||||
};
|
||||
if (optional_permissions.length) {
|
||||
perms.permissions = optional_permissions;
|
||||
}
|
||||
|
||||
browser.test.withHandlingUserInput(() => {
|
||||
browser.permissions.request(perms);
|
||||
browser.test.sendMessage("perms-requested");
|
||||
});
|
||||
});
|
||||
|
||||
browser.test.sendMessage("ready");
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const TEST_CASES = [
|
||||
{
|
||||
title: "With an optional data collection permission",
|
||||
data_collection_permissions: {
|
||||
optional: ["healthInfo"],
|
||||
},
|
||||
verifyDialog(popupContentEl, { extensionId }) {
|
||||
Assert.equal(
|
||||
popupContentEl.querySelector(".popup-notification-description")
|
||||
.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-optional-data-collection-only-text",
|
||||
{ extension: extensionId }
|
||||
),
|
||||
"Expected header string without perms"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.childElementCount,
|
||||
1,
|
||||
"Expected a single entry in the list"
|
||||
);
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-description-data-some-optional",
|
||||
{
|
||||
permissions: "health information",
|
||||
}
|
||||
),
|
||||
"Expected formatted data collection permission string"
|
||||
);
|
||||
Assert.ok(
|
||||
popupContentEl.hasAttribute("learnmoreurl"),
|
||||
"Expected a learn more link"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "With multiple optional data collection permissions",
|
||||
data_collection_permissions: {
|
||||
optional: ["healthInfo", "bookmarksInfo"],
|
||||
},
|
||||
verifyDialog(popupContentEl, { extensionId }) {
|
||||
Assert.equal(
|
||||
popupContentEl.querySelector(".popup-notification-description")
|
||||
.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-optional-data-collection-only-text",
|
||||
{ extension: extensionId }
|
||||
),
|
||||
"Expected header string without perms"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.childElementCount,
|
||||
1,
|
||||
"Expected a single entry in the list"
|
||||
);
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-description-data-some-optional",
|
||||
{
|
||||
permissions: "health information, bookmarks",
|
||||
}
|
||||
),
|
||||
"Expected formatted data collection permission string"
|
||||
);
|
||||
Assert.ok(
|
||||
popupContentEl.hasAttribute("learnmoreurl"),
|
||||
"Expected a learn more link"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "With technical and interaction data",
|
||||
data_collection_permissions: {
|
||||
optional: ["technicalAndInteraction"],
|
||||
},
|
||||
verifyDialog(popupContentEl, { extensionId }) {
|
||||
Assert.equal(
|
||||
popupContentEl.querySelector(".popup-notification-description")
|
||||
.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-optional-data-collection-only-text",
|
||||
{ extension: extensionId }
|
||||
),
|
||||
"Expected header string without perms"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.childElementCount,
|
||||
1,
|
||||
"Expected a single entry in the list"
|
||||
);
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-description-data-some-optional",
|
||||
{
|
||||
permissions: "technical and interaction data",
|
||||
}
|
||||
),
|
||||
"Expected formatted data collection permission string"
|
||||
);
|
||||
Assert.ok(
|
||||
popupContentEl.hasAttribute("learnmoreurl"),
|
||||
"Expected a learn more link"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "With optional API and data collection permissions",
|
||||
optional_permissions: ["bookmarks"],
|
||||
data_collection_permissions: {
|
||||
optional: ["bookmarksInfo"],
|
||||
},
|
||||
verifyDialog(popupContentEl, { extensionId }) {
|
||||
Assert.equal(
|
||||
popupContentEl.querySelector(".popup-notification-description")
|
||||
.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-optional-data-collection-text",
|
||||
{ extension: extensionId }
|
||||
),
|
||||
"Expected header string with perms"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.childElementCount,
|
||||
2,
|
||||
"Expected two entries in the list"
|
||||
);
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.firstChild.textContent,
|
||||
PERMISSION_L10N.formatValueSync("webext-perms-description-bookmarks"),
|
||||
"Expected formatted data collection permission string"
|
||||
);
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.lastChild.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-description-data-some-optional",
|
||||
{
|
||||
permissions: "bookmarks",
|
||||
}
|
||||
),
|
||||
"Expected formatted data collection permission string"
|
||||
);
|
||||
Assert.ok(
|
||||
popupContentEl.hasAttribute("learnmoreurl"),
|
||||
"Expected a learn more link"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "With non-promptable API and optional data collection permission",
|
||||
optional_permissions: ["webRequest"],
|
||||
data_collection_permissions: {
|
||||
optional: ["healthInfo"],
|
||||
},
|
||||
verifyDialog(popupContentEl, { extensionId }) {
|
||||
Assert.equal(
|
||||
popupContentEl.querySelector(".popup-notification-description")
|
||||
.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-optional-data-collection-only-text",
|
||||
{ extension: extensionId }
|
||||
),
|
||||
"Expected header string without perms"
|
||||
);
|
||||
|
||||
// We expect a single entry because `webRequest` is non-promptable.
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.childElementCount,
|
||||
1,
|
||||
"Expected a single entry in the list"
|
||||
);
|
||||
Assert.equal(
|
||||
popupContentEl.permsListEl.textContent,
|
||||
PERMISSION_L10N.formatValueSync(
|
||||
"webext-perms-description-data-some-optional",
|
||||
{
|
||||
permissions: "health information",
|
||||
}
|
||||
),
|
||||
"Expected formatted data collection permission string"
|
||||
);
|
||||
Assert.ok(
|
||||
popupContentEl.hasAttribute("learnmoreurl"),
|
||||
"Expected a learn more link"
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (const {
|
||||
title,
|
||||
optional_permissions,
|
||||
data_collection_permissions,
|
||||
verifyDialog,
|
||||
} of TEST_CASES) {
|
||||
info(title);
|
||||
|
||||
const extensionId = `@${title.toLowerCase().replaceAll(/[^\w]+/g, "-")}`;
|
||||
const extension = createTestExtension({
|
||||
id: extensionId,
|
||||
optional_permissions,
|
||||
data_collection_permissions,
|
||||
});
|
||||
await extension.startup();
|
||||
|
||||
let extPageURL = `moz-extension://${extension.uuid}/extpage.html`;
|
||||
await BrowserTestUtils.withNewTab(extPageURL, async () => {
|
||||
let promiseRequestDisalog = promisePopupNotificationShown(
|
||||
"addon-webext-permissions"
|
||||
);
|
||||
await extension.awaitMessage("ready");
|
||||
extension.sendMessage("request-perms");
|
||||
await extension.awaitMessage("perms-requested");
|
||||
const popupContentEl = await promiseRequestDisalog;
|
||||
verifyDialog(popupContentEl, { extensionId });
|
||||
});
|
||||
|
||||
await extension.unload();
|
||||
}
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(
|
||||
async function testOptionalPermissionsDialogWithDataCollectionAlreadyGranted() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.dataCollectionPermissions.enabled", true]],
|
||||
});
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: "1.0",
|
||||
browser_specific_settings: {
|
||||
gecko: {
|
||||
data_collection_permissions: {
|
||||
optional: ["healthInfo"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"extpage.html": `<!DOCTYPE html><script src="extpage.js"></script>`,
|
||||
"extpage.js"() {
|
||||
browser.test.onMessage.addListener(async msg => {
|
||||
if (msg !== "request-perms") {
|
||||
browser.test.fail(`Got unexpected test message ${msg}`);
|
||||
return;
|
||||
}
|
||||
|
||||
browser.test.withHandlingUserInput(async () => {
|
||||
await browser.permissions.request({
|
||||
data_collection: ["healthInfo"],
|
||||
});
|
||||
browser.test.sendMessage("perms-requested");
|
||||
});
|
||||
});
|
||||
|
||||
browser.test.sendMessage("ready");
|
||||
},
|
||||
},
|
||||
});
|
||||
await extension.startup();
|
||||
|
||||
let extPageURL = `moz-extension://${extension.uuid}/extpage.html`;
|
||||
await BrowserTestUtils.withNewTab(extPageURL, async () => {
|
||||
let promiseRequestDisalog = promisePopupNotificationShown(
|
||||
"addon-webext-permissions"
|
||||
).then(panel => {
|
||||
// Grant the permission.
|
||||
panel.button.click();
|
||||
});
|
||||
|
||||
await extension.awaitMessage("ready");
|
||||
extension.sendMessage("request-perms");
|
||||
await extension.awaitMessage("perms-requested");
|
||||
await promiseRequestDisalog;
|
||||
|
||||
extension.sendMessage("request-perms");
|
||||
await extension.awaitMessage("perms-requested");
|
||||
});
|
||||
|
||||
await extension.unload();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -99,7 +99,7 @@ async function checkTelemetry(source, prevEngine, newEngine) {
|
|||
category: "search.engine.default",
|
||||
name: "changed",
|
||||
extra: {
|
||||
change_source: source,
|
||||
change_reason: source,
|
||||
previous_engine_id: prevEngine.id,
|
||||
new_engine_id: newEngine.id,
|
||||
new_display_name: newEngine.name,
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
[DEFAULT]
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
head = "head.js"
|
||||
firefox-appdir = "browser"
|
||||
tags = "webextensions"
|
||||
dupe-manifest = ""
|
||||
|
||||
["test_ext_bookmarks.js"]
|
||||
skip-if = ["condprof"] # Bug 1769184 - by design for now
|
||||
|
||||
["test_ext_browsingData_downloads.js"]
|
||||
|
||||
["test_ext_browsingData_passwords.js"]
|
||||
skip-if = ["tsan"] # Times out, bug 1612707
|
||||
|
||||
["test_ext_browsingData_settings.js"]
|
||||
|
||||
|
@ -44,7 +41,6 @@ skip-if = ["tsan"] # Times out, bug 1612707
|
|||
["test_ext_pkcs11_management.js"]
|
||||
|
||||
["test_ext_settings_overrides_defaults.js"]
|
||||
skip-if = ["condprof"] # Bug 1776135 - by design, modifies search settings at start of test
|
||||
|
||||
["test_ext_settings_overrides_search.js"]
|
||||
|
||||
|
@ -53,7 +49,6 @@ skip-if = ["condprof"] # Bug 1776135 - by design, modifies search settings at st
|
|||
["test_ext_settings_validate.js"]
|
||||
|
||||
["test_ext_topSites.js"]
|
||||
skip-if = ["condprof"] # Bug 1769184 - by design for now
|
||||
|
||||
["test_ext_url_overrides_newtab.js"]
|
||||
|
||||
|
|
|
@ -400,6 +400,7 @@ export class FxviewTabRowBase extends MozLitElement {
|
|||
title: { type: String },
|
||||
timeMsPref: { type: Number },
|
||||
url: { type: String },
|
||||
uri: { type: String },
|
||||
searchQuery: { type: String },
|
||||
};
|
||||
|
||||
|
@ -423,6 +424,11 @@ export class FxviewTabRowBase extends MozLitElement {
|
|||
return focusItem;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.uri = this.url;
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.currentFocusable.focus();
|
||||
}
|
||||
|
|
|
@ -6,12 +6,19 @@ prefs = [
|
|||
]
|
||||
|
||||
["browser_chat_contextmenu.js"]
|
||||
|
||||
["browser_chat_nimbus.js"]
|
||||
|
||||
["browser_chat_request.js"]
|
||||
|
||||
["browser_chat_shortcuts.js"]
|
||||
|
||||
["browser_chat_sidebar.js"]
|
||||
|
||||
["browser_chat_telemetry.js"]
|
||||
|
||||
["browser_genai_actors.js"]
|
||||
|
||||
["browser_genai_init.js"]
|
||||
|
||||
["browser_link_preview.js"]
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
firefox-appdir = "browser"
|
||||
|
||||
["test_build_chat_prompt.js"]
|
||||
|
||||
["test_contextual_prompts.js"]
|
||||
|
||||
["test_link_preview_text.js"]
|
||||
|
||||
["test_provider_id.js"]
|
||||
|
||||
["test_show_chat_entrypoint.js"]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[DEFAULT]
|
||||
head = "head.js"
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os != 'win'"]
|
||||
run-if = ["os == 'win'"]
|
||||
|
||||
# These tests must all run sequentially because they use the same registry key.
|
||||
# It might be possible to get around this requirement by overriding the install
|
||||
|
@ -10,7 +10,9 @@ skip-if = ["os != 'win'"]
|
|||
|
||||
["test_empty_prefs_list.js"]
|
||||
run-sequentially = "Uses the Windows registry"
|
||||
skip-if = ["os == 'win' && msix"] # https://bugzilla.mozilla.org/show_bug.cgi?id=1807932
|
||||
skip-if = [
|
||||
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && msix", # Bug 1807932
|
||||
]
|
||||
|
||||
["test_invalid_name.js"]
|
||||
run-sequentially = "Uses the Windows registry"
|
||||
|
|
|
@ -286,7 +286,7 @@ add_task(async function test_show_happy_feature_callout_message() {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
win.gBrowser,
|
||||
"about:messagepreview",
|
||||
false
|
||||
true
|
||||
);
|
||||
|
||||
let aboutMessagePreviewActor = await getAboutMessagePreviewParent(
|
||||
|
@ -330,7 +330,7 @@ add_task(async function test_show_feature_callout_without_trigger() {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
win.gBrowser,
|
||||
"about:messagepreview",
|
||||
false
|
||||
true
|
||||
);
|
||||
|
||||
let aboutMessagePreviewActor = await getAboutMessagePreviewParent(
|
||||
|
@ -374,7 +374,7 @@ add_task(async function test_show_feature_callout_anchors() {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
win.gBrowser,
|
||||
"about:messagepreview",
|
||||
false
|
||||
true
|
||||
);
|
||||
|
||||
let aboutMessagePreviewActor = await getAboutMessagePreviewParent(
|
||||
|
@ -418,7 +418,7 @@ add_task(async function test_show_bad_feature_callout_message() {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
win.gBrowser,
|
||||
"about:messagepreview",
|
||||
false
|
||||
true
|
||||
);
|
||||
|
||||
let aboutMessagePreviewActor = await getAboutMessagePreviewParent(
|
||||
|
|
|
@ -985,3 +985,21 @@ browser:
|
|||
- aoprea@mozilla.com
|
||||
expires: never
|
||||
telemetry_mirror: h#BROWSER_ATTRIBUTION_ERRORS
|
||||
|
||||
default_at_launch:
|
||||
type: boolean
|
||||
lifetime: application
|
||||
description: |
|
||||
Whether the shell service identified this app as the default browser.
|
||||
Checked once near startup.
|
||||
On Windows, this is operationalized as whether Firefox is the default
|
||||
HTTP protocol handler and the default HTML file handler.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1950389
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1950389
|
||||
notification_emails:
|
||||
- application-update-telemetry-alerts@mozilla.com
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
head = "head_migration.js"
|
||||
tags = "condprof os_integration"
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
prefs = ["browser.migrate.showBookmarksToolbarAfterMigration=true"]
|
||||
support-files = [
|
||||
"Library/**",
|
||||
|
@ -32,33 +31,21 @@ run-if = ["os == 'linux'"]
|
|||
["test_Chrome_corrupt_history.js"]
|
||||
|
||||
["test_Chrome_credit_cards.js"]
|
||||
skip-if = [
|
||||
"os == 'linux'",
|
||||
"os == 'android'",
|
||||
"condprof", # bug 1769154 - not realistic for condprof
|
||||
]
|
||||
skip-if = ["os == 'linux' && os_version == '18.04' && processor == 'x86_64'"]
|
||||
|
||||
["test_Chrome_extensions.js"]
|
||||
|
||||
["test_Chrome_formdata.js"]
|
||||
|
||||
["test_Chrome_history.js"]
|
||||
skip-if = ["os != 'mac'"] # Relies on ULibDir
|
||||
run-if = ["os == 'mac'"] # Relies on ULibDir
|
||||
|
||||
["test_Chrome_passwords.js"]
|
||||
skip-if = [
|
||||
"os == 'linux'",
|
||||
"os == 'android'",
|
||||
"condprof", # bug 1769154 - not realistic for condprof
|
||||
]
|
||||
skip-if = ["os == 'linux' && os_version == '18.04' && processor == 'x86_64'"]
|
||||
|
||||
["test_Chrome_passwords_emptySource.js"]
|
||||
skip-if = [
|
||||
"os == 'linux'",
|
||||
"os == 'android'",
|
||||
"condprof", # bug 1769154 - not realistic for condprof
|
||||
]
|
||||
support-files = ["LibraryWithNoData/**"]
|
||||
skip-if = ["os == 'linux' && os_version == '18.04' && processor == 'x86_64'"]
|
||||
|
||||
["test_Chrome_permissions.js"]
|
||||
|
||||
|
@ -73,10 +60,11 @@ run-if = ["os == 'win' && bits == 64"] # bug 1392396
|
|||
|
||||
["test_IE_history.js"]
|
||||
run-if = ["os == 'win'"]
|
||||
skip-if = ["os == 'win' && msix"] # https://bugzilla.mozilla.org/show_bug.cgi?id=1807928
|
||||
skip-if = [
|
||||
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && msix", # Bug 1807928
|
||||
]
|
||||
|
||||
["test_MigrationUtils_timedRetry.js"]
|
||||
skip-if = ["os == 'mac' && !debug"] #Bug 1558330
|
||||
|
||||
["test_PasswordFileMigrator.js"]
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ DIRS += [
|
|||
"newtab",
|
||||
"originattributes",
|
||||
"pagedata",
|
||||
"permissions",
|
||||
"places",
|
||||
"pocket",
|
||||
"preferences",
|
||||
|
@ -104,6 +105,13 @@ EXTRA_JS_MODULES += [
|
|||
"distribution.sys.mjs",
|
||||
]
|
||||
|
||||
MOZ_SRC_FILES += [
|
||||
"DefaultBrowserCheck.sys.mjs",
|
||||
"DesktopActorRegistry.sys.mjs",
|
||||
"ProfileDataUpgrader.sys.mjs",
|
||||
"StartupTelemetry.sys.mjs",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_DEBUG"] or CONFIG["MOZ_DEV_EDITION"] or CONFIG["NIGHTLY_BUILD"]:
|
||||
EXTRA_JS_MODULES += [
|
||||
"StartupRecorder.sys.mjs",
|
||||
|
|
|
@ -1503,6 +1503,22 @@ pocket:
|
|||
description: >
|
||||
If click belongs in a section, the numeric position of the section
|
||||
type: string
|
||||
title: &title
|
||||
description: >
|
||||
Title of the article
|
||||
type: string
|
||||
url: &url
|
||||
description: >
|
||||
Url of the article
|
||||
type: string
|
||||
time_sensitive: &time_sensitive
|
||||
description: >
|
||||
Indicates whether the article is time sensitive. This is passed down from merino
|
||||
type: boolean
|
||||
publisher: &publisher
|
||||
description: >
|
||||
derived publisher name of article
|
||||
type: string
|
||||
is_section_followed: *is_section_followed
|
||||
send_in_pings:
|
||||
- newtab
|
||||
|
@ -1570,6 +1586,10 @@ pocket:
|
|||
If click belongs in a section, the numeric position of the section
|
||||
type: string
|
||||
is_section_followed: *is_section_followed
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab
|
||||
|
||||
|
@ -1612,6 +1632,10 @@ pocket:
|
|||
If click belongs in a section, the numeric position of the section
|
||||
type: string
|
||||
is_section_followed: *is_section_followed
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab
|
||||
|
||||
|
@ -1822,9 +1846,556 @@ pocket:
|
|||
If event belongs in a section, the numeric position of the section
|
||||
type: string
|
||||
is_section_followed: *is_section_followed
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab
|
||||
|
||||
newtab_content:
|
||||
|
||||
coarse_os:
|
||||
type: string
|
||||
description: >
|
||||
The name of the operating system. Possible values:
|
||||
Android, iOS, Linux, Windows, or macOS
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
expires: never
|
||||
lifetime: application
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
coarse_os_version:
|
||||
type: string
|
||||
description: |
|
||||
The user-visible version of the operating system (e.g. "1.2.3").
|
||||
If the version detection fails, this metric gets set to 0.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
expires: never
|
||||
lifetime: application
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
utc_offset:
|
||||
type: quantity
|
||||
description: >
|
||||
<0-24> positive UTC offset, rounded to the nearest integer number greater than 0.
|
||||
(If less than 0, then add 24.)
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
lifetime: application
|
||||
unit: utc offset
|
||||
|
||||
surface_id:
|
||||
type: string
|
||||
description: >
|
||||
Surface id sent to the client from merino api
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
- newtab
|
||||
lifetime: application
|
||||
|
||||
followed_sections:
|
||||
type: string_list
|
||||
description: >
|
||||
Optional metric: section ids followed by user in alphabetical order, if possible,
|
||||
ordered by most recently followed. Max 2 sections
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
lifetime: application
|
||||
|
||||
# The `newtab-content` ping does not include any info sections, and
|
||||
# therefore needs to capture experiments and rollouts independently. This
|
||||
# data layout agrees with the `nimbus-targeting-context` ping for ease of
|
||||
# analysis.
|
||||
active_experiments:
|
||||
type: object
|
||||
description: >
|
||||
slugs of actively enrolled experiments
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
expires: never
|
||||
structure:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
active_rollouts:
|
||||
type: object
|
||||
description: >
|
||||
slugs of actively enrolled rollouts
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
expires: never
|
||||
structure:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
enrollments_map:
|
||||
type: object
|
||||
description: >
|
||||
Information about historic enrollments, including the branches enrolled.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
expires: never
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
data_sensitivity:
|
||||
- technical
|
||||
structure:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
experimentSlug:
|
||||
type: string
|
||||
branchSlug:
|
||||
type: string
|
||||
|
||||
impression:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a pocket tile is visible to the user.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1786612
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1817105
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1854245
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1862670
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1937200
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1786612
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1817105#c11
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1854245
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- anicholson@mozilla.com
|
||||
- chutten@mozilla.com
|
||||
- mmccorquodale@mozilla.com
|
||||
- najiang@mozilla.com
|
||||
- lina@mozilla.com
|
||||
- sdowne@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
is_sponsored: *is_sponsored_pocket
|
||||
format: *format
|
||||
position: *pocket_position
|
||||
recommendation_id: *recommendation_id
|
||||
tile_id: *pocket_tile_id
|
||||
scheduled_corpus_item_id: *scheduled_corpus_item_id
|
||||
corpus_item_id: *corpus_item_id
|
||||
received_rank: *received_rank
|
||||
recommended_at: *recommended_at
|
||||
topic:
|
||||
description: The topic of the recommendation. Like "entertainment".
|
||||
type: string
|
||||
selected_topics:
|
||||
description: >
|
||||
The list of topics the user selected
|
||||
type: string
|
||||
is_list_card:
|
||||
description: >
|
||||
Where the article card is in the list component
|
||||
type: boolean
|
||||
section:
|
||||
description: >
|
||||
If click belongs in a section, the name of the section
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
If click belongs in a section, the numberic position of the section
|
||||
type: string
|
||||
is_section_followed:
|
||||
description: >
|
||||
If click belongs in a section, if that section is followed
|
||||
type: boolean
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
click:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a pocket tile is clicked.
|
||||
Only happens on click. Not on middle-click. Not on "Open in new Tab"-like
|
||||
options in the context menu.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- mcrawford@mozilla.cocm
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
is_sponsored: *is_sponsored_pocket
|
||||
format: *format
|
||||
position: *pocket_position
|
||||
recommendation_id: *recommendation_id
|
||||
tile_id: *pocket_tile_id
|
||||
scheduled_corpus_item_id: *scheduled_corpus_item_id
|
||||
corpus_item_id: *corpus_item_id
|
||||
received_rank: *received_rank
|
||||
recommended_at: *recommended_at
|
||||
matches_selected_topic:
|
||||
description: >
|
||||
Returns value based on if a the topic of the pocket recommendation matches one
|
||||
of the user-selected topic categories
|
||||
type: string
|
||||
topic:
|
||||
description: The topic of the recommendation. Like "entertainment".
|
||||
type: string
|
||||
selected_topics:
|
||||
description: >
|
||||
The list of topics the user selected
|
||||
type: string
|
||||
is_list_card:
|
||||
description: >
|
||||
Where the article card is in the list component
|
||||
type: boolean
|
||||
section:
|
||||
description: >
|
||||
If click belongs in a section, the name of the section
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
If click belongs in a section, the numberic position of the section
|
||||
type: string
|
||||
is_section_followed:
|
||||
description: >
|
||||
If click belongs in a section, if that section is followed
|
||||
type: boolean
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
dismiss:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a pocket tile is dismissed.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1786612
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1937200
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1786612
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- sdowne@mozilla.com
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
is_sponsored: *is_sponsored_pocket
|
||||
format: *format
|
||||
position: *pocket_position
|
||||
recommendation_id: *recommendation_id
|
||||
tile_id: *pocket_tile_id
|
||||
scheduled_corpus_item_id: *scheduled_corpus_item_id
|
||||
corpus_item_id: *corpus_item_id
|
||||
received_rank: *received_rank
|
||||
recommended_at: *recommended_at
|
||||
section:
|
||||
description: >
|
||||
If click belongs in a section, the name of the section
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
If click belongs in a section, the numberic position of the section
|
||||
type: string
|
||||
is_section_followed:
|
||||
description: >
|
||||
If click belongs in a section, if that section is followed
|
||||
type: boolean
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
thumb_voting_interaction:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a thumbs up/down on a tile is clicked.
|
||||
Only happens on click. Not on middle-click. Not on "Open in new Tab"-like
|
||||
options in the context menu.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1902099
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1937200
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1902099
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
recommendation_id: *recommendation_id
|
||||
tile_id: *pocket_tile_id
|
||||
thumbs_up:
|
||||
description: >
|
||||
If the user clicked thumbs up.
|
||||
type: boolean
|
||||
thumbs_down:
|
||||
description: >
|
||||
If the user clicked thumbs down.
|
||||
type: boolean
|
||||
scheduled_corpus_item_id: *scheduled_corpus_item_id
|
||||
corpus_item_id: *corpus_item_id
|
||||
received_rank: *received_rank
|
||||
recommended_at: *recommended_at
|
||||
topic:
|
||||
description: The topic of the recommendation. Like "entertainment".
|
||||
type: string
|
||||
is_list_card:
|
||||
description: >
|
||||
Where the article card is in the list component
|
||||
type: boolean
|
||||
section:
|
||||
description: >
|
||||
If event belongs in a section, the name of the section
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
If event belongs in a section, the numberic position of the section
|
||||
type: string
|
||||
is_section_followed:
|
||||
description: >
|
||||
If event belongs in a section, if that section is followed
|
||||
type: boolean
|
||||
title: *title
|
||||
url: *url
|
||||
time_sensitive: *time_sensitive
|
||||
publisher: *publisher
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
sections_impression:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a section is viewport and triggers an impression event
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1927916
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1938215
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1927916
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
section:
|
||||
description: >
|
||||
section that had impression event
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
position of section on newtab
|
||||
type: string
|
||||
is_section_followed:
|
||||
description: >
|
||||
If click belongs in a section, if that section is followed
|
||||
type: boolean
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
sections_follow_section:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a section is followed
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1932191
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1932191
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
section:
|
||||
description: >
|
||||
section that had impression event
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
position of section on newtab
|
||||
type: string
|
||||
event_source:
|
||||
description: >
|
||||
Where the source of the event originated ("button", "context menu", etc.)
|
||||
type: string
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
sections_unfollow_section:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a section is unfollowed
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1932191
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1932191
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
section:
|
||||
description: >
|
||||
section that had impression event
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
position of section on newtab
|
||||
type: string
|
||||
event_source:
|
||||
description: >
|
||||
Where the source of the event originated ("button", "context menu", etc.)
|
||||
type: string
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
sections_block_section:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a section is blocked
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1932191
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1932191
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
section:
|
||||
description: >
|
||||
section that had impression event
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
position of section on newtab
|
||||
type: string
|
||||
event_source:
|
||||
description: >
|
||||
Where the source of the event originated ("button", "context menu", etc.)
|
||||
type: string
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
sections_unblock_section:
|
||||
type: event
|
||||
description: >
|
||||
Recorded when a section is unblocked
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1940566
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1940566
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- mcrawford@mozilla.com
|
||||
expires: never
|
||||
extra_keys:
|
||||
newtab_visit_id: *newtab_visit_id
|
||||
section:
|
||||
description: >
|
||||
section that had unblock event
|
||||
type: string
|
||||
section_position:
|
||||
description: >
|
||||
position of section on newtab
|
||||
type: string
|
||||
event_source:
|
||||
description: >
|
||||
Where the source of the event originated ("button", "context menu", etc.)
|
||||
type: string
|
||||
send_in_pings:
|
||||
- newtab-content
|
||||
|
||||
top_sites: # Replacement for PingCentre "topsites-impression|click" pings.
|
||||
ping_type:
|
||||
type: string
|
||||
|
|
|
@ -30,6 +30,32 @@ newtab:
|
|||
- anicholson@mozilla.com
|
||||
- najiang@mozilla.com
|
||||
|
||||
newtab-content:
|
||||
description: |
|
||||
Private Newtab-related instrumentation sent over OHTTP
|
||||
Can be disabled via the `newtabPingEnabled` variable of the `glean` Nimbus
|
||||
feature, or the `browser.newtabpage.ping.enabled` pref.
|
||||
metadata:
|
||||
include_info_sections: false
|
||||
include_client_id: false
|
||||
uploader_capabilities:
|
||||
- ohttp
|
||||
reasons:
|
||||
newtab_session_end: |
|
||||
The newtab visit ended.
|
||||
Could be by navigation, being closed, etc.
|
||||
component_init: |
|
||||
The newtab component init'd,
|
||||
and the newtab and homepage settings have been categorized.
|
||||
This is mostly to ensure we hear at least once from clients configured to
|
||||
not show a newtab UI.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1956331
|
||||
notification_emails:
|
||||
- nbarrett@mozilla.com
|
||||
|
||||
top-sites:
|
||||
description: |
|
||||
A ping representing a single event happening with or to a TopSite.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[DEFAULT]
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
head = "../../../../extensions/newtab/test/xpcshell/head.js"
|
||||
|
||||
["test_AboutNewTab.js"]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[DEFAULT]
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
support-files = ["head.js"]
|
||||
head = "head.js"
|
||||
|
||||
|
|
133
browser/components/permissions/ContentPermissionPrompt.sys.mjs
Normal file
133
browser/components/permissions/ContentPermissionPrompt.sys.mjs
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* 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/. */
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
Integration: "resource://gre/modules/Integration.sys.mjs",
|
||||
PermissionUI: "resource:///modules/PermissionUI.sys.mjs",
|
||||
});
|
||||
/**
|
||||
* ContentPermissionIntegration is responsible for showing the user
|
||||
* simple permission prompts when content requests additional
|
||||
* capabilities.
|
||||
*
|
||||
* While there are some built-in permission prompts, createPermissionPrompt
|
||||
* can also be overridden by system add-ons or tests to provide new ones.
|
||||
*
|
||||
* This override ability is provided by Integration.sys.mjs. See
|
||||
* PermissionUI.sys.mjs for an example of how to provide a new prompt
|
||||
* from an add-on.
|
||||
*/
|
||||
const ContentPermissionIntegration = {
|
||||
/**
|
||||
* Creates a PermissionPrompt for a given permission type and
|
||||
* nsIContentPermissionRequest.
|
||||
*
|
||||
* @param {string} type
|
||||
* The type of the permission request from content. This normally
|
||||
* matches the "type" field of an nsIContentPermissionType, but it
|
||||
* can be something else if the permission does not use the
|
||||
* nsIContentPermissionRequest model. Note that this type might also
|
||||
* be different from the permission key used in the permissions
|
||||
* database.
|
||||
* Example: "geolocation"
|
||||
* @param {nsIContentPermissionRequest} request
|
||||
* The request for a permission from content.
|
||||
* @returns {PermissionPrompt?} (see PermissionUI.sys.mjs),
|
||||
* or undefined if the type cannot be handled.
|
||||
*/
|
||||
createPermissionPrompt(type, request) {
|
||||
switch (type) {
|
||||
case "geolocation": {
|
||||
return new lazy.PermissionUI.GeolocationPermissionPrompt(request);
|
||||
}
|
||||
case "xr": {
|
||||
return new lazy.PermissionUI.XRPermissionPrompt(request);
|
||||
}
|
||||
case "desktop-notification": {
|
||||
return new lazy.PermissionUI.DesktopNotificationPermissionPrompt(
|
||||
request
|
||||
);
|
||||
}
|
||||
case "persistent-storage": {
|
||||
return new lazy.PermissionUI.PersistentStoragePermissionPrompt(request);
|
||||
}
|
||||
case "midi": {
|
||||
return new lazy.PermissionUI.MIDIPermissionPrompt(request);
|
||||
}
|
||||
case "storage-access": {
|
||||
return new lazy.PermissionUI.StorageAccessPermissionPrompt(request);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
export function ContentPermissionPrompt() {}
|
||||
|
||||
ContentPermissionPrompt.prototype = {
|
||||
classID: Components.ID("{d8903bf6-68d5-4e97-bcd1-e4d3012f721a}"),
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIContentPermissionPrompt"]),
|
||||
|
||||
/**
|
||||
* This implementation of nsIContentPermissionPrompt.prompt ensures
|
||||
* that there's only one nsIContentPermissionType in the request,
|
||||
* and that it's of type nsIContentPermissionType. Failing to
|
||||
* satisfy either of these conditions will result in this method
|
||||
* throwing NS_ERRORs. If the combined ContentPermissionIntegration
|
||||
* cannot construct a prompt for this particular request, an
|
||||
* NS_ERROR_FAILURE will be thrown.
|
||||
*
|
||||
* Any time an error is thrown, the nsIContentPermissionRequest is
|
||||
* cancelled automatically.
|
||||
*
|
||||
* @param {nsIContentPermissionRequest} request
|
||||
* The request that we're to show a prompt for.
|
||||
*/
|
||||
prompt(request) {
|
||||
if (request.element && request.element.fxrPermissionPrompt) {
|
||||
// For Firefox Reality on Desktop, switch to a different mechanism to
|
||||
// prompt the user since fewer permissions are available and since many
|
||||
// UI dependencies are not availabe.
|
||||
request.element.fxrPermissionPrompt(request);
|
||||
return;
|
||||
}
|
||||
|
||||
let type;
|
||||
try {
|
||||
// Only allow exactly one permission request here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
throw Components.Exception(
|
||||
"Expected an nsIContentPermissionRequest with only 1 type.",
|
||||
Cr.NS_ERROR_UNEXPECTED
|
||||
);
|
||||
}
|
||||
|
||||
type = types.queryElementAt(0, Ci.nsIContentPermissionType).type;
|
||||
let combinedIntegration = lazy.Integration.contentPermission.getCombined(
|
||||
ContentPermissionIntegration
|
||||
);
|
||||
|
||||
let permissionPrompt = combinedIntegration.createPermissionPrompt(
|
||||
type,
|
||||
request
|
||||
);
|
||||
if (!permissionPrompt) {
|
||||
throw Components.Exception(
|
||||
`Failed to handle permission of type ${type}`,
|
||||
Cr.NS_ERROR_FAILURE
|
||||
);
|
||||
}
|
||||
|
||||
permissionPrompt.prompt();
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
request.cancel();
|
||||
throw ex;
|
||||
}
|
||||
},
|
||||
};
|
14
browser/components/permissions/components.conf
Normal file
14
browser/components/permissions/components.conf
Normal file
|
@ -0,0 +1,14 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Classes = [
|
||||
{
|
||||
'cid': '{d8903bf6-68d5-4e97-bcd1-e4d3012f721a}',
|
||||
'contract_ids': ['@mozilla.org/content-permission/prompt;1'],
|
||||
'esModule': 'moz-src:///browser/components/permissions/ContentPermissionPrompt.sys.mjs',
|
||||
'constructor': 'ContentPermissionPrompt',
|
||||
},
|
||||
]
|
16
browser/components/permissions/moz.build
Normal file
16
browser/components/permissions/moz.build
Normal file
|
@ -0,0 +1,16 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPCOM_MANIFESTS += [
|
||||
"components.conf",
|
||||
]
|
||||
|
||||
MOZ_SRC_FILES += [
|
||||
"ContentPermissionPrompt.sys.mjs",
|
||||
]
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Site Permissions")
|
|
@ -907,8 +907,8 @@ export var PlacesUIUtils = {
|
|||
) {
|
||||
if (
|
||||
aNode &&
|
||||
lazy.PlacesUtils.nodeIsURI(aNode) &&
|
||||
this.checkURLSecurity(aNode, aWindow)
|
||||
this.checkURLSecurity(aNode, aWindow) &&
|
||||
this.isURILike(aNode)
|
||||
) {
|
||||
let isBookmark = lazy.PlacesUtils.nodeIsBookmark(aNode);
|
||||
|
||||
|
@ -940,6 +940,16 @@ export var PlacesUIUtils = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines whether a node contains a uri
|
||||
*
|
||||
* @param {nsINavHistoryResultNode | DOMElement} aNode A result node.
|
||||
* @returns {boolean} whether the node contains a uri
|
||||
*/
|
||||
isURILike(aNode) {
|
||||
return lazy.PlacesUtils.nodeIsURI(aNode) || !!aNode.uri;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper for guessing scheme from an url string.
|
||||
* Used to avoid nsIURI overhead in frequently called UI functions. This is not
|
||||
|
@ -1391,11 +1401,19 @@ export var PlacesUIUtils = {
|
|||
|
||||
placesContextShowing(event) {
|
||||
let menupopup = event.target;
|
||||
if (menupopup.id != "placesContext") {
|
||||
if (
|
||||
!["placesContext", "sidebar-history-context-menu"].includes(menupopup.id)
|
||||
) {
|
||||
// Ignore any popupshowing events from submenus
|
||||
return;
|
||||
}
|
||||
|
||||
if (menupopup.id == "sidebar-history-context-menu") {
|
||||
PlacesUIUtils.lastContextMenuTriggerNode =
|
||||
menupopup.triggerNode.triggerNode;
|
||||
return;
|
||||
}
|
||||
|
||||
PlacesUIUtils.lastContextMenuTriggerNode = menupopup.triggerNode;
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.tabs.loadBookmarksInTabs", false)) {
|
||||
|
@ -1443,7 +1461,13 @@ export var PlacesUIUtils = {
|
|||
menupopup._view.destroyContextMenu();
|
||||
}
|
||||
|
||||
if (menupopup.id == "placesContext") {
|
||||
if (
|
||||
[
|
||||
"sidebar-history-context-menu",
|
||||
"placesContext",
|
||||
"sidebar-synced-tabs-context-menu",
|
||||
].includes(menupopup.id)
|
||||
) {
|
||||
PlacesUIUtils.lastContextMenuTriggerNode = null;
|
||||
PlacesUIUtils.lastContextMenuCommand = null;
|
||||
}
|
||||
|
@ -1467,9 +1491,14 @@ export var PlacesUIUtils = {
|
|||
return;
|
||||
}
|
||||
let view = this.getViewForNode(triggerNode);
|
||||
this._openNodeIn(view.selectedNode, "tab", view.ownerWindow, {
|
||||
userContextId,
|
||||
});
|
||||
this._openNodeIn(
|
||||
view?.selectedNode || triggerNode,
|
||||
"tab",
|
||||
view?.ownerWindow || triggerNode.ownerGlobal.top,
|
||||
{
|
||||
userContextId,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
openSelectionInTabs(event) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[DEFAULT]
|
||||
head = "head_bookmarks.js"
|
||||
firefox-appdir = "browser"
|
||||
skip-if = ["os == 'android'"] # bug 1730213
|
||||
support-files = [
|
||||
"bookmarks.glue.html",
|
||||
"bookmarks.glue.json",
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
* Note: we display the icon box for every item whether or not it has an icon
|
||||
* so the labels of all the items align vertically.
|
||||
*/
|
||||
.actionsMenu > menupopup > menuitem > .menu-iconic-left {
|
||||
.actionsMenu > menupopup > menuitem > .menu-icon {
|
||||
display: flex;
|
||||
min-width: 16px;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
<link rel="localization" href="preview/translations.ftl"/>
|
||||
<link rel="localization" href="preview/enUS-searchFeatures.ftl"/>
|
||||
<link rel="localization" href="preview/backupSettings.ftl"/>
|
||||
<link rel="localization" href="preview/reportContentTemporary.ftl"/>
|
||||
<link rel="localization" href="security/certificates/certManager.ftl"/>
|
||||
<link rel="localization" href="security/certificates/deviceManager.ftl"/>
|
||||
<link rel="localization" href="toolkit/updates/history.ftl"/>
|
||||
|
|
|
@ -272,7 +272,7 @@ add_task(async function test_setDefaultEngine() {
|
|||
category: "search.engine.default",
|
||||
name: "changed",
|
||||
extra: {
|
||||
change_source: "user",
|
||||
change_reason: "user",
|
||||
previous_engine_id: engine1.telemetryId,
|
||||
new_engine_id: "other-engine2",
|
||||
new_display_name: "engine2",
|
||||
|
@ -319,7 +319,7 @@ add_task(async function test_setPrivateDefaultEngine() {
|
|||
category: "search.engine.private",
|
||||
name: "changed",
|
||||
extra: {
|
||||
change_source: "user",
|
||||
change_reason: "user",
|
||||
previous_engine_id: engine2.telemetryId,
|
||||
new_engine_id: "other-engine1",
|
||||
new_display_name: "engine1",
|
||||
|
|
|
@ -97,6 +97,8 @@ skip-if = ["verify"]
|
|||
|
||||
["browser_privatebrowsing_opendir.js"]
|
||||
|
||||
["browser_privatebrowsing_permissions.js"]
|
||||
|
||||
["browser_privatebrowsing_placesTitleNoUpdate.js"]
|
||||
|
||||
["browser_privatebrowsing_placestitle.js"]
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that permissions don't persist across private browsing sessions by
|
||||
// opening a new pbm window, gaining a notification permission, reopening the
|
||||
// pbm window, and then checking the notification permission.
|
||||
|
||||
const TEST_URL = "https://example.com";
|
||||
const TEST_PRINCIPAL = Services.scriptSecurityManager.createContentPrincipal(
|
||||
Services.io.newURI(TEST_URL),
|
||||
{ privateBrowsingId: 1 }
|
||||
);
|
||||
|
||||
async function checkNotificationPermission(tab, isAllowExpected) {
|
||||
// Check permission manager
|
||||
let permission = Services.perms.testExactPermissionFromPrincipal(
|
||||
TEST_PRINCIPAL,
|
||||
"desktop-notification"
|
||||
);
|
||||
is(
|
||||
permission,
|
||||
isAllowExpected
|
||||
? Services.perms.ALLOW_ACTION
|
||||
: Services.perms.UNKNOWN_ACTION,
|
||||
`Permission ${isAllowExpected ? "should" : "should not"} exist in permission manager`
|
||||
);
|
||||
|
||||
// Check Notification API directly
|
||||
await SpecialPowers.spawn(tab, [isAllowExpected], _isAllowExpected => {
|
||||
is(
|
||||
content.Notification.permission,
|
||||
_isAllowExpected ? "granted" : "default",
|
||||
`The notification API ${_isAllowExpected ? "should" : "should not"} allow notification`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async () => {
|
||||
// Explicit user interaction would make this test more complicated than
|
||||
// nescessary
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.webnotifications.requireuserinteraction", false]],
|
||||
});
|
||||
|
||||
// Create a private browsing window
|
||||
let privateWindow = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
let privateTab = privateWindow.gBrowser.selectedBrowser;
|
||||
|
||||
info("Checking permissions before test");
|
||||
await checkNotificationPermission(privateTab, false);
|
||||
|
||||
// Open test site
|
||||
BrowserTestUtils.startLoadingURIString(privateTab, TEST_URL);
|
||||
await BrowserTestUtils.browserLoaded(privateTab);
|
||||
|
||||
// Gain "notification" permission on test site in private tab
|
||||
let popupShown = BrowserTestUtils.waitForEvent(
|
||||
privateWindow.PopupNotifications.panel,
|
||||
"popupshown"
|
||||
);
|
||||
await SpecialPowers.spawn(privateTab, [], () => {
|
||||
content.Notification.requestPermission();
|
||||
});
|
||||
await popupShown;
|
||||
|
||||
let notification = privateWindow.PopupNotifications.panel.firstElementChild;
|
||||
let popupHidden = BrowserTestUtils.waitForEvent(
|
||||
privateWindow.PopupNotifications.panel,
|
||||
"popuphidden"
|
||||
);
|
||||
notification.button.click();
|
||||
await popupHidden;
|
||||
|
||||
info("Checking permissions after permission was granted");
|
||||
await checkNotificationPermission(privateTab, true);
|
||||
|
||||
// Close private window
|
||||
await BrowserTestUtils.closeWindow(privateWindow);
|
||||
|
||||
// Open new private window
|
||||
privateWindow = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
privateTab = privateWindow.gBrowser.selectedBrowser;
|
||||
|
||||
// Open example site again
|
||||
BrowserTestUtils.startLoadingURIString(privateTab, TEST_URL);
|
||||
await BrowserTestUtils.browserLoaded(privateTab);
|
||||
|
||||
info("Checking permissions after pbm window got reopened");
|
||||
await checkNotificationPermission(privateTab, false);
|
||||
|
||||
// Close private window again
|
||||
await BrowserTestUtils.closeWindow(privateWindow);
|
||||
});
|
|
@ -17,5 +17,9 @@ prefs = [
|
|||
["test_selectable_profile_service_exists.js"]
|
||||
|
||||
["test_selectable_profiles_lifecycle.js"]
|
||||
skip-if = [
|
||||
"os == 'mac' && os_version == '10.15' && processor == 'x86_64'", # Bug 1952514
|
||||
"os == 'mac' && os_version == '14.70' && processor == 'x86_64'", # Bug 1952514
|
||||
]
|
||||
|
||||
["test_shared_prefs_lifecycles_methods.js"]
|
||||
|
|
483
browser/components/protections/ContentBlockingPrefs.sys.mjs
Normal file
483
browser/components/protections/ContentBlockingPrefs.sys.mjs
Normal file
|
@ -0,0 +1,483 @@
|
|||
/* 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/. */
|
||||
|
||||
const PREFS_CHANGING_CATEGORY = new Set([
|
||||
"network.cookie.cookieBehavior",
|
||||
"network.cookie.cookieBehavior.pbmode",
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault",
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation",
|
||||
"privacy.partition.network_state.ocsp_cache",
|
||||
"privacy.query_stripping.enabled",
|
||||
"privacy.query_stripping.enabled.pbmode",
|
||||
"privacy.fingerprintingProtection",
|
||||
"privacy.fingerprintingProtection.pbmode",
|
||||
]);
|
||||
|
||||
/**
|
||||
* @class ContentBlockingPrefs
|
||||
*
|
||||
* Manages how the content blocking and anti-tracking preferences relate to the
|
||||
* broad Tracking Protection categories (standard, strict and custom).
|
||||
*
|
||||
* @typedef {"standard"|"strict"|"custom"} CBCategory
|
||||
*/
|
||||
export let ContentBlockingPrefs = {
|
||||
PREF_CB_CATEGORY: "browser.contentblocking.category",
|
||||
PREF_STRICT_DEF: "browser.contentblocking.features.strict",
|
||||
switchingCategory: false,
|
||||
|
||||
setPrefExpectations() {
|
||||
// The prefs inside CATEGORY_PREFS are initial values.
|
||||
// If the pref remains null, then it will expect the default value.
|
||||
// The "standard" category is defined as expecting default values of the
|
||||
// listed prefs. The "strict" category lists all prefs that will be set
|
||||
// according to the strict feature pref.
|
||||
this.CATEGORY_PREFS = {
|
||||
strict: {
|
||||
"network.cookie.cookieBehavior": null,
|
||||
"network.cookie.cookieBehavior.pbmode": null,
|
||||
"privacy.trackingprotection.pbmode.enabled": null,
|
||||
"privacy.trackingprotection.enabled": null,
|
||||
"privacy.trackingprotection.socialtracking.enabled": null,
|
||||
"privacy.trackingprotection.fingerprinting.enabled": null,
|
||||
"privacy.trackingprotection.cryptomining.enabled": null,
|
||||
"privacy.trackingprotection.emailtracking.enabled": null,
|
||||
"privacy.trackingprotection.emailtracking.pbmode.enabled": null,
|
||||
"privacy.trackingprotection.consentmanager.skip.enabled": null,
|
||||
"privacy.trackingprotection.consentmanager.skip.pbmode.enabled": null,
|
||||
"privacy.annotate_channels.strict_list.enabled": null,
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault": null,
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation":
|
||||
null,
|
||||
"privacy.partition.network_state.ocsp_cache": null,
|
||||
"privacy.query_stripping.enabled": null,
|
||||
"privacy.query_stripping.enabled.pbmode": null,
|
||||
"privacy.fingerprintingProtection": null,
|
||||
"privacy.fingerprintingProtection.pbmode": null,
|
||||
"network.cookie.cookieBehavior.optInPartitioning": null,
|
||||
"privacy.bounceTrackingProtection.mode": null,
|
||||
},
|
||||
standard: {
|
||||
"network.cookie.cookieBehavior": null,
|
||||
"network.cookie.cookieBehavior.pbmode": null,
|
||||
"privacy.trackingprotection.pbmode.enabled": null,
|
||||
"privacy.trackingprotection.enabled": null,
|
||||
"privacy.trackingprotection.socialtracking.enabled": null,
|
||||
"privacy.trackingprotection.fingerprinting.enabled": null,
|
||||
"privacy.trackingprotection.cryptomining.enabled": null,
|
||||
"privacy.trackingprotection.emailtracking.enabled": null,
|
||||
"privacy.trackingprotection.emailtracking.pbmode.enabled": null,
|
||||
"privacy.trackingprotection.consentmanager.skip.enabled": null,
|
||||
"privacy.trackingprotection.consentmanager.skip.pbmode.enabled": null,
|
||||
"privacy.annotate_channels.strict_list.enabled": null,
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault": null,
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation":
|
||||
null,
|
||||
"privacy.partition.network_state.ocsp_cache": null,
|
||||
"privacy.query_stripping.enabled": null,
|
||||
"privacy.query_stripping.enabled.pbmode": null,
|
||||
"privacy.fingerprintingProtection": null,
|
||||
"privacy.fingerprintingProtection.pbmode": null,
|
||||
"network.cookie.cookieBehavior.optInPartitioning": null,
|
||||
"privacy.bounceTrackingProtection.mode": null,
|
||||
},
|
||||
};
|
||||
let type = "strict";
|
||||
let rulesArray = Services.prefs
|
||||
.getStringPref(this.PREF_STRICT_DEF)
|
||||
.split(",");
|
||||
for (let item of rulesArray) {
|
||||
switch (item) {
|
||||
case "tp":
|
||||
this.CATEGORY_PREFS[type]["privacy.trackingprotection.enabled"] =
|
||||
true;
|
||||
break;
|
||||
case "-tp":
|
||||
this.CATEGORY_PREFS[type]["privacy.trackingprotection.enabled"] =
|
||||
false;
|
||||
break;
|
||||
case "tpPrivate":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.pbmode.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-tpPrivate":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.pbmode.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "fp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.fingerprinting.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-fp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.fingerprinting.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "cryptoTP":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.cryptomining.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-cryptoTP":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.cryptomining.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "stp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.socialtracking.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-stp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.socialtracking.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "emailTP":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.emailtracking.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-emailTP":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.emailtracking.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "emailTPPrivate":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.emailtracking.pbmode.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-emailTPPrivate":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.emailtracking.pbmode.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "consentmanagerSkip":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.consentmanager.skip.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-consentmanagerSkip":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.consentmanager.skip.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "consentmanagerSkipPrivate":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.consentmanager.skip.pbmode.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-consentmanagerSkipPrivate":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.trackingprotection.consentmanager.skip.pbmode.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "lvl2":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.annotate_channels.strict_list.enabled"
|
||||
] = true;
|
||||
break;
|
||||
case "-lvl2":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.annotate_channels.strict_list.enabled"
|
||||
] = false;
|
||||
break;
|
||||
case "rp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault"
|
||||
] = true;
|
||||
break;
|
||||
case "-rp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault"
|
||||
] = false;
|
||||
break;
|
||||
case "rpTop":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation"
|
||||
] = true;
|
||||
break;
|
||||
case "-rpTop":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation"
|
||||
] = false;
|
||||
break;
|
||||
case "ocsp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.partition.network_state.ocsp_cache"
|
||||
] = true;
|
||||
break;
|
||||
case "-ocsp":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"privacy.partition.network_state.ocsp_cache"
|
||||
] = false;
|
||||
break;
|
||||
case "qps":
|
||||
this.CATEGORY_PREFS[type]["privacy.query_stripping.enabled"] = true;
|
||||
break;
|
||||
case "-qps":
|
||||
this.CATEGORY_PREFS[type]["privacy.query_stripping.enabled"] = false;
|
||||
break;
|
||||
case "qpsPBM":
|
||||
this.CATEGORY_PREFS[type]["privacy.query_stripping.enabled.pbmode"] =
|
||||
true;
|
||||
break;
|
||||
case "-qpsPBM":
|
||||
this.CATEGORY_PREFS[type]["privacy.query_stripping.enabled.pbmode"] =
|
||||
false;
|
||||
break;
|
||||
case "fpp":
|
||||
this.CATEGORY_PREFS[type]["privacy.fingerprintingProtection"] = true;
|
||||
break;
|
||||
case "-fpp":
|
||||
this.CATEGORY_PREFS[type]["privacy.fingerprintingProtection"] = false;
|
||||
break;
|
||||
case "fppPrivate":
|
||||
this.CATEGORY_PREFS[type]["privacy.fingerprintingProtection.pbmode"] =
|
||||
true;
|
||||
break;
|
||||
case "-fppPrivate":
|
||||
this.CATEGORY_PREFS[type]["privacy.fingerprintingProtection.pbmode"] =
|
||||
false;
|
||||
break;
|
||||
case "cookieBehavior0":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior"] =
|
||||
Ci.nsICookieService.BEHAVIOR_ACCEPT;
|
||||
break;
|
||||
case "cookieBehavior1":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN;
|
||||
break;
|
||||
case "cookieBehavior2":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT;
|
||||
break;
|
||||
case "cookieBehavior3":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior"] =
|
||||
Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN;
|
||||
break;
|
||||
case "cookieBehavior4":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
|
||||
break;
|
||||
case "cookieBehavior5":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
|
||||
break;
|
||||
case "cookieBehaviorPBM0":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior.pbmode"] =
|
||||
Ci.nsICookieService.BEHAVIOR_ACCEPT;
|
||||
break;
|
||||
case "cookieBehaviorPBM1":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior.pbmode"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN;
|
||||
break;
|
||||
case "cookieBehaviorPBM2":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior.pbmode"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT;
|
||||
break;
|
||||
case "cookieBehaviorPBM3":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior.pbmode"] =
|
||||
Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN;
|
||||
break;
|
||||
case "cookieBehaviorPBM4":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior.pbmode"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
|
||||
break;
|
||||
case "cookieBehaviorPBM5":
|
||||
this.CATEGORY_PREFS[type]["network.cookie.cookieBehavior.pbmode"] =
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
|
||||
break;
|
||||
case "3pcd":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"network.cookie.cookieBehavior.optInPartitioning"
|
||||
] = true;
|
||||
break;
|
||||
case "-3pcd":
|
||||
this.CATEGORY_PREFS[type][
|
||||
"network.cookie.cookieBehavior.optInPartitioning"
|
||||
] = false;
|
||||
break;
|
||||
case "btp":
|
||||
this.CATEGORY_PREFS[type]["privacy.bounceTrackingProtection.mode"] =
|
||||
Ci.nsIBounceTrackingProtection.MODE_ENABLED;
|
||||
break;
|
||||
case "-btp":
|
||||
// We currently consider MODE_ENABLED_DRY_RUN the "off" state. See
|
||||
// nsIBounceTrackingProtection.idl for details.
|
||||
this.CATEGORY_PREFS[type]["privacy.bounceTrackingProtection.mode"] =
|
||||
Ci.nsIBounceTrackingProtection.MODE_ENABLED_DRY_RUN;
|
||||
break;
|
||||
default:
|
||||
console.error(`Error: Unknown rule observed ${item}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if CB prefs match perfectly with one of our pre-defined categories.
|
||||
*
|
||||
* @param {CBCategory} category
|
||||
*/
|
||||
prefsMatch(category) {
|
||||
// The category pref must be either unset, or match.
|
||||
if (
|
||||
Services.prefs.prefHasUserValue(this.PREF_CB_CATEGORY) &&
|
||||
Services.prefs.getStringPref(this.PREF_CB_CATEGORY) != category
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
for (let pref in this.CATEGORY_PREFS[category]) {
|
||||
let value = this.CATEGORY_PREFS[category][pref];
|
||||
if (value == null) {
|
||||
if (Services.prefs.prefHasUserValue(pref)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
let prefType = Services.prefs.getPrefType(pref);
|
||||
if (
|
||||
(prefType == Services.prefs.PREF_BOOL &&
|
||||
Services.prefs.getBoolPref(pref) != value) ||
|
||||
(prefType == Services.prefs.PREF_INT &&
|
||||
Services.prefs.getIntPref(pref) != value) ||
|
||||
(prefType == Services.prefs.PREF_STRING &&
|
||||
Services.prefs.getStringPref(pref) != value)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
matchCBCategory() {
|
||||
if (this.switchingCategory) {
|
||||
return;
|
||||
}
|
||||
// If PREF_CB_CATEGORY is not set match users to a Content Blocking category. Check if prefs fit
|
||||
// perfectly into strict or standard, otherwise match with custom. If PREF_CB_CATEGORY has previously been set,
|
||||
// a change of one of these prefs necessarily puts us in "custom".
|
||||
if (this.prefsMatch("standard")) {
|
||||
Services.prefs.setStringPref(this.PREF_CB_CATEGORY, "standard");
|
||||
} else if (this.prefsMatch("strict")) {
|
||||
Services.prefs.setStringPref(this.PREF_CB_CATEGORY, "strict");
|
||||
} else {
|
||||
Services.prefs.setStringPref(this.PREF_CB_CATEGORY, "custom");
|
||||
}
|
||||
|
||||
// If there is a custom policy which changes a related pref, then put the user in custom so
|
||||
// they still have access to other content blocking prefs, and to keep our default definitions
|
||||
// from changing.
|
||||
let policy = Services.policies.getActivePolicies();
|
||||
if (policy && (policy.EnableTrackingProtection || policy.Cookies)) {
|
||||
Services.prefs.setStringPref(this.PREF_CB_CATEGORY, "custom");
|
||||
}
|
||||
},
|
||||
|
||||
updateCBCategory() {
|
||||
if (
|
||||
this.switchingCategory ||
|
||||
!Services.prefs.prefHasUserValue(this.PREF_CB_CATEGORY)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// Turn on switchingCategory flag, to ensure that when the individual prefs that change as a result
|
||||
// of the category change do not trigger yet another category change.
|
||||
this.switchingCategory = true;
|
||||
let value = Services.prefs.getStringPref(this.PREF_CB_CATEGORY);
|
||||
this.setPrefsToCategory(value);
|
||||
this.switchingCategory = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets all user-exposed content blocking preferences to values that match the selected category.
|
||||
*
|
||||
* @param {CBCategory} category
|
||||
*/
|
||||
setPrefsToCategory(category) {
|
||||
// Leave prefs as they were if we are switching to "custom" category.
|
||||
if (category == "custom") {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let pref in this.CATEGORY_PREFS[category]) {
|
||||
let value = this.CATEGORY_PREFS[category][pref];
|
||||
if (!Services.prefs.prefIsLocked(pref)) {
|
||||
if (value == null) {
|
||||
Services.prefs.clearUserPref(pref);
|
||||
} else {
|
||||
switch (Services.prefs.getPrefType(pref)) {
|
||||
case Services.prefs.PREF_BOOL:
|
||||
Services.prefs.setBoolPref(pref, value);
|
||||
break;
|
||||
case Services.prefs.PREF_INT:
|
||||
Services.prefs.setIntPref(pref, value);
|
||||
break;
|
||||
case Services.prefs.PREF_STRING:
|
||||
Services.prefs.setStringPref(pref, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setPrefExpectationsAndUpdate() {
|
||||
this.setPrefExpectations();
|
||||
this.updateCBCategory();
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic != "nsPref:changed") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
data.startsWith("privacy.trackingprotection") ||
|
||||
PREFS_CHANGING_CATEGORY.has(data)
|
||||
) {
|
||||
this.matchCBCategory();
|
||||
}
|
||||
|
||||
if (data.startsWith("privacy.trackingprotection")) {
|
||||
this.setPrefExpectations();
|
||||
} else if (data == this.PREF_CB_CATEGORY) {
|
||||
this.updateCBCategory();
|
||||
} else if (data == "browser.contentblocking.features.strict") {
|
||||
this.setPrefExpectationsAndUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
this.setPrefExpectationsAndUpdate();
|
||||
this.matchCBCategory();
|
||||
|
||||
for (let prefix of PREF_PREFIXES_TO_OBSERVE) {
|
||||
Services.prefs.addObserver(prefix, this);
|
||||
}
|
||||
},
|
||||
|
||||
uninit() {
|
||||
for (let prefix of PREF_PREFIXES_TO_OBSERVE) {
|
||||
Services.prefs.removeObserver(prefix, this);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const PREF_PREFIXES_TO_OBSERVE = new Set([
|
||||
"privacy.trackingprotection",
|
||||
"network.cookie.cookieBehavior",
|
||||
"network.http.referer.disallowCrossSiteRelaxingDefault",
|
||||
"privacy.partition.network_state.ocsp_cache",
|
||||
"privacy.query_stripping.enabled",
|
||||
"privacy.fingerprintingProtection",
|
||||
ContentBlockingPrefs.PREF_CB_CATEGORY,
|
||||
ContentBlockingPrefs.PREF_STRICT_DEF,
|
||||
]);
|
||||
|
||||
ContentBlockingPrefs.QueryInterface = ChromeUtils.generateQI([Ci.nsIObserver]);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue