Update On Tue Jul 16 20:49:23 CEST 2024
This commit is contained in:
parent
286baec8ee
commit
776d6ead9e
892 changed files with 16976 additions and 34974 deletions
40
Cargo.lock
generated
40
Cargo.lock
generated
|
@ -1715,7 +1715,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "error-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"error-support-macros",
|
||||
"lazy_static",
|
||||
|
@ -1727,7 +1727,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "error-support-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3048,7 +3048,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "interrupt-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot",
|
||||
|
@ -4246,7 +4246,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "nss_build_common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
|
||||
[[package]]
|
||||
name = "nsstring"
|
||||
|
@ -4456,6 +4456,16 @@ version = "1.0.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
||||
|
||||
[[package]]
|
||||
name = "payload-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke"
|
||||
version = "0.3.0"
|
||||
|
@ -4921,7 +4931,7 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|||
[[package]]
|
||||
name = "relevancy"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.21.3",
|
||||
|
@ -4944,7 +4954,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "remote_settings"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"parking_lot",
|
||||
"serde",
|
||||
|
@ -5479,7 +5489,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sql-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"interrupt-support",
|
||||
|
@ -5661,7 +5671,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
|||
[[package]]
|
||||
name = "suggest"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
@ -5712,7 +5722,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sync-guid"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"base64 0.21.3",
|
||||
"rand",
|
||||
|
@ -5723,7 +5733,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sync15"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
@ -5731,6 +5741,7 @@ dependencies = [
|
|||
"interrupt-support",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"payload-support",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
@ -5754,13 +5765,14 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "tabs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
"interrupt-support",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"payload-support",
|
||||
"rusqlite",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
@ -6081,7 +6093,7 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
|||
[[package]]
|
||||
name = "types"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"rusqlite",
|
||||
"serde",
|
||||
|
@ -6448,7 +6460,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
[[package]]
|
||||
name = "viaduct"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"log",
|
||||
|
@ -6596,7 +6608,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webext-storage"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151#46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=8fd08c6f2f8acd38579bd3142fecda9272957b72#8fd08c6f2f8acd38579bd3142fecda9272957b72"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
|
16
Cargo.toml
16
Cargo.toml
|
@ -217,14 +217,14 @@ warp = { git = "https://github.com/seanmonstar/warp", rev = "9d081461ae1167eb321
|
|||
malloc_size_of_derive = { path = "xpcom/rust/malloc_size_of_derive" }
|
||||
|
||||
# application-services overrides to make updating them all simpler.
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
relevancy = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
suggest = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "46acbeb2cee2fb7f024b6ff5943bdfdb6cc53151" }
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
relevancy = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
suggest = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
|
||||
# Patch mio 0.8.8 to use windows-sys 0.52 (backport https://github.com/tokio-rs/mio/commit/eea9e3e0c469480e5c59c01e6c3c7e5fd88f0848)
|
||||
mio_0_8 = { package = "mio", git = "https://github.com/glandium/mio", rev = "9a2ef335c366044ffe73b1c4acabe50a1daefe05" }
|
||||
|
|
|
@ -27,18 +27,7 @@
|
|||
<h1 data-l10n-id="default-bookmarks-heading">default-bookmarks-heading</h1>
|
||||
|
||||
<dl><p>
|
||||
<dt><h3 personal_toolbar_folder="true" data-l10n-id="default-bookmarks-toolbarfolder">default-bookmarks-toolbarfolder</h3></dt>
|
||||
<dd data-l10n-id="default-bookmarks-toolbarfolder-description">default-bookmarks-toolbarfolder-description</dd>
|
||||
#ifndef NIGHTLY_BUILD
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
<dl><p>
|
||||
<dt><a href="https://www.mozilla.org/firefox/central/" icon="@firefox_icon@" data-l10n-id="default-bookmarks-getting-started">default-bookmarks-getting-started</a></dt>
|
||||
</dl><p>
|
||||
#else
|
||||
<dl><p>
|
||||
<dt><a href="https://www.mozilla.org/firefox/?utm_medium=firefox-desktop&utm_source=bookmarks-toolbar&utm_campaign=new-users&utm_content=-global" icon="@firefox_icon@" data-l10n-id="default-bookmarks-getting-started">default-bookmarks-getting-started</a></dt>
|
||||
</dl><p>
|
||||
#endif
|
||||
<dt><h3 data-l10n-id="default-bookmarks-firefox-heading">default-bookmarks-firefox-heading</h3></dt>
|
||||
<dl><p>
|
||||
<dt><a href="https://support.mozilla.org/products/firefox" icon="@firefox_icon@" data-l10n-id="default-bookmarks-firefox-get-help">default-bookmarks-firefox-get-help</a></dt>
|
||||
|
@ -51,11 +40,9 @@
|
|||
<dt><a href="https://www.mozilla.org/about/" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-about">default-bookmarks-firefox-about</a></dt>
|
||||
</dl><p>
|
||||
#else
|
||||
<dl><p>
|
||||
<dt><a href="https://www.mozilla.org/contribute/?utm_medium=firefox-desktop&utm_source=bookmarks-toolbar&utm_campaign=new-users-nightly&utm_content=-global" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-community">default-bookmarks-firefox-community</a></dt>
|
||||
</dl><p>
|
||||
<dt><h3 data-l10n-id="default-bookmarks-nightly-heading">default-bookmarks-nightly-heading</h3></dt>
|
||||
<dl><p>
|
||||
<dt><a href="https://www.mozilla.org/contribute/?utm_medium=firefox-desktop&utm_source=bookmarks-toolbar&utm_campaign=new-users-nightly&utm_content=-global" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-firefox-community">default-bookmarks-firefox-community</a></dt>
|
||||
<dt><a href="https://blog.nightly.mozilla.org/" icon="@mozilla_icon@" data-l10n-id="default-bookmarks-nightly-blog">default-bookmarks-nightly-blog</a></dt>
|
||||
<dt><a href="https://bugzilla.mozilla.org/" icon="@bugzilla_icon@" shortcuturl="bz" data-l10n-id="default-bookmarks-bugzilla">default-bookmarks-bugzilla</a></dt>
|
||||
<dt><a href="https://developer.mozilla.org/" icon="@mdn_icon@" shortcuturl="mdn" data-l10n-id="default-bookmarks-mdn">default-bookmarks-mdn</a></dt>
|
||||
|
|
|
@ -41,6 +41,10 @@ function getBrowser(panel) {
|
|||
browser.setAttribute("tooltip", "aHTMLTooltip");
|
||||
browser.setAttribute("autocompletepopup", "PopupAutoComplete");
|
||||
|
||||
if (gAllowTransparentBrowser) {
|
||||
browser.setAttribute("transparent", "true");
|
||||
}
|
||||
|
||||
// Ensure that the browser is going to run in the same bc group as the other
|
||||
// extension pages from the same addon.
|
||||
browser.setAttribute(
|
||||
|
@ -175,3 +179,10 @@ function loadPanel(extensionId, extensionUrl, browserStyle) {
|
|||
browser.fixupAndLoadURIString(extensionUrl, { triggeringPrincipal });
|
||||
});
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"gAllowTransparentBrowser",
|
||||
"browser.tabs.allow_transparent_browser",
|
||||
false
|
||||
);
|
||||
|
|
|
@ -88,6 +88,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
ResetPBMPanel: "resource:///modules/ResetPBMPanel.sys.mjs",
|
||||
SafeBrowsing: "resource://gre/modules/SafeBrowsing.sys.mjs",
|
||||
Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
|
||||
SandboxUtils: "resource://gre/modules/SandboxUtils.sys.mjs",
|
||||
SaveToPocket: "chrome://pocket/content/SaveToPocket.sys.mjs",
|
||||
ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs",
|
||||
SearchSERPCategorization: "resource:///modules/SearchSERPTelemetry.sys.mjs",
|
||||
|
@ -1719,6 +1720,16 @@ BrowserGlue.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
_verifySandboxUserNamespaces: function BG_verifySandboxUserNamespaces(aWin) {
|
||||
if (!AppConstants.MOZ_SANDBOX) {
|
||||
return;
|
||||
}
|
||||
|
||||
lazy.SandboxUtils.maybeWarnAboutMissingUserNamespaces(
|
||||
aWin.gNotificationBox
|
||||
);
|
||||
},
|
||||
|
||||
_earlyBlankFirstPaint(cmdLine) {
|
||||
let startTime = Cu.now();
|
||||
if (
|
||||
|
@ -1981,6 +1992,8 @@ BrowserGlue.prototype = {
|
|||
"browser.contentblocking.features.strict",
|
||||
this._setPrefExpectationsAndUpdate
|
||||
);
|
||||
|
||||
this._verifySandboxUserNamespaces(aWindow);
|
||||
},
|
||||
|
||||
_maybeOfferProfileReset() {
|
||||
|
|
|
@ -570,6 +570,13 @@ export class BackupService extends EventTarget {
|
|||
this.dispatchEvent(new CustomEvent("BackupService:StateUpdate"));
|
||||
}
|
||||
|
||||
/**
|
||||
* True if a recovery is currently in progress.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
#recoveryInProgress = false;
|
||||
|
||||
/**
|
||||
* An object holding the current state of the BackupService instance, for
|
||||
* the purposes of representing it in the user interface. Ideally, this would
|
||||
|
@ -2280,75 +2287,85 @@ export class BackupService extends EventTarget {
|
|||
profilePath = PathUtils.profileDir,
|
||||
profileRootPath = null
|
||||
) {
|
||||
const RECOVERY_FILE_DEST_PATH = PathUtils.join(
|
||||
profilePath,
|
||||
BackupService.PROFILE_FOLDER_NAME,
|
||||
BackupService.RECOVERY_ZIP_FILE_NAME
|
||||
);
|
||||
await this.extractCompressedSnapshotFromArchive(
|
||||
archivePath,
|
||||
RECOVERY_FILE_DEST_PATH,
|
||||
recoveryCode
|
||||
);
|
||||
|
||||
let encState = null;
|
||||
if (recoveryCode) {
|
||||
// We were passed a recovery code and made it to this line. That implies
|
||||
// that the backup was encrypted, and the recovery code was the correct
|
||||
// one to decrypt it. We now generate a new ArchiveEncryptionState with
|
||||
// that recovery code to write into the recovered profile.
|
||||
({ instance: encState } = await lazy.ArchiveEncryptionState.initialize(
|
||||
recoveryCode
|
||||
));
|
||||
}
|
||||
|
||||
const RECOVERY_FOLDER_DEST_PATH = PathUtils.join(
|
||||
profilePath,
|
||||
BackupService.PROFILE_FOLDER_NAME,
|
||||
"recovery"
|
||||
);
|
||||
await this.decompressRecoveryFile(
|
||||
RECOVERY_FILE_DEST_PATH,
|
||||
RECOVERY_FOLDER_DEST_PATH
|
||||
);
|
||||
|
||||
// Now that we've decompressed it, reclaim some disk space by getting rid of
|
||||
// the ZIP file.
|
||||
try {
|
||||
await IOUtils.remove(RECOVERY_FILE_DEST_PATH);
|
||||
} catch (_) {
|
||||
lazy.logConsole.warn("Could not remove ", RECOVERY_FILE_DEST_PATH);
|
||||
// No concurrent recoveries.
|
||||
if (this.#recoveryInProgress) {
|
||||
lazy.logConsole.warn("Recovery attempt already in progress");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// We're using a try/finally here to clean up the temporary OSKeyStore.
|
||||
// We need to make sure that cleanup occurs _after_ the recovery has
|
||||
// either fully succeeded, or fully failed. We await the return value
|
||||
// of recoverFromSnapshotFolder so that the finally will not execute
|
||||
// until after recoverFromSnapshotFolder has finished resolving or
|
||||
// rejecting.
|
||||
let newProfile = await this.recoverFromSnapshotFolder(
|
||||
RECOVERY_FOLDER_DEST_PATH,
|
||||
shouldLaunch,
|
||||
profileRootPath,
|
||||
encState
|
||||
this.#recoveryInProgress = true;
|
||||
const RECOVERY_FILE_DEST_PATH = PathUtils.join(
|
||||
profilePath,
|
||||
BackupService.PROFILE_FOLDER_NAME,
|
||||
BackupService.RECOVERY_ZIP_FILE_NAME
|
||||
);
|
||||
return newProfile;
|
||||
} finally {
|
||||
// If we had decrypted a backup, we would have created the temporary
|
||||
// recovery OSKeyStore row with the label
|
||||
// BackupService.RECOVERY_OSKEYSTORE_LABEL, which we will now delete,
|
||||
// no matter if we succeeded or failed to recover.
|
||||
//
|
||||
// Note that according to nsIOSKeyStore, this is a no-op in the event that
|
||||
// no secret exists at BackupService.RECOVERY_OSKEYSTORE_LABEL, so we're
|
||||
// fine to do this even if we were recovering from an unencrypted
|
||||
// backup.
|
||||
await this.extractCompressedSnapshotFromArchive(
|
||||
archivePath,
|
||||
RECOVERY_FILE_DEST_PATH,
|
||||
recoveryCode
|
||||
);
|
||||
|
||||
let encState = null;
|
||||
if (recoveryCode) {
|
||||
await lazy.nativeOSKeyStore.asyncDeleteSecret(
|
||||
BackupService.RECOVERY_OSKEYSTORE_LABEL
|
||||
);
|
||||
// We were passed a recovery code and made it to this line. That implies
|
||||
// that the backup was encrypted, and the recovery code was the correct
|
||||
// one to decrypt it. We now generate a new ArchiveEncryptionState with
|
||||
// that recovery code to write into the recovered profile.
|
||||
({ instance: encState } = await lazy.ArchiveEncryptionState.initialize(
|
||||
recoveryCode
|
||||
));
|
||||
}
|
||||
|
||||
const RECOVERY_FOLDER_DEST_PATH = PathUtils.join(
|
||||
profilePath,
|
||||
BackupService.PROFILE_FOLDER_NAME,
|
||||
"recovery"
|
||||
);
|
||||
await this.decompressRecoveryFile(
|
||||
RECOVERY_FILE_DEST_PATH,
|
||||
RECOVERY_FOLDER_DEST_PATH
|
||||
);
|
||||
|
||||
// Now that we've decompressed it, reclaim some disk space by getting rid of
|
||||
// the ZIP file.
|
||||
try {
|
||||
await IOUtils.remove(RECOVERY_FILE_DEST_PATH);
|
||||
} catch (_) {
|
||||
lazy.logConsole.warn("Could not remove ", RECOVERY_FILE_DEST_PATH);
|
||||
}
|
||||
try {
|
||||
// We're using a try/finally here to clean up the temporary OSKeyStore.
|
||||
// We need to make sure that cleanup occurs _after_ the recovery has
|
||||
// either fully succeeded, or fully failed. We await the return value
|
||||
// of recoverFromSnapshotFolder so that the finally will not execute
|
||||
// until after recoverFromSnapshotFolder has finished resolving or
|
||||
// rejecting.
|
||||
let newProfile = await this.recoverFromSnapshotFolder(
|
||||
RECOVERY_FOLDER_DEST_PATH,
|
||||
shouldLaunch,
|
||||
profileRootPath,
|
||||
encState
|
||||
);
|
||||
return newProfile;
|
||||
} finally {
|
||||
// If we had decrypted a backup, we would have created the temporary
|
||||
// recovery OSKeyStore row with the label
|
||||
// BackupService.RECOVERY_OSKEYSTORE_LABEL, which we will now delete,
|
||||
// no matter if we succeeded or failed to recover.
|
||||
//
|
||||
// Note that according to nsIOSKeyStore, this is a no-op in the event that
|
||||
// no secret exists at BackupService.RECOVERY_OSKEYSTORE_LABEL, so we're
|
||||
// fine to do this even if we were recovering from an unencrypted
|
||||
// backup.
|
||||
if (recoveryCode) {
|
||||
await lazy.nativeOSKeyStore.asyncDeleteSecret(
|
||||
BackupService.RECOVERY_OSKEYSTORE_LABEL
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.#recoveryInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,10 +65,18 @@ export class BackupUIChild extends JSWindowActorChild {
|
|||
});
|
||||
} else if (event.type == "BackupUI:RestoreFromBackupFile") {
|
||||
let { backupFile, backupPassword } = event.detail;
|
||||
this.sendAsyncMessage("RestoreFromBackupFile", {
|
||||
event.target.recoveryInProgress = true;
|
||||
event.target.recoveryErrorCode = 0;
|
||||
let result = await this.sendQuery("RestoreFromBackupFile", {
|
||||
backupFile,
|
||||
backupPassword,
|
||||
});
|
||||
event.target.recoveryInProgress = false;
|
||||
if (result.success) {
|
||||
event.target.restoreFromBackupDialogEl?.close();
|
||||
} else {
|
||||
event.target.recoveryErrorCode = result.errorCode;
|
||||
}
|
||||
} else if (event.type == "BackupUI:RestoreFromBackupChooseFile") {
|
||||
this.sendAsyncMessage("RestoreFromBackupChooseFile");
|
||||
} else if (event.type == "BackupUI:ToggleEncryption") {
|
||||
|
|
|
@ -6,6 +6,16 @@ const lazy = {};
|
|||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BackupService: "resource:///modules/backup/BackupService.sys.mjs",
|
||||
ERRORS: "resource:///modules/backup/BackupConstants.mjs",
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "logConsole", function () {
|
||||
return console.createInstance({
|
||||
prefix: "BackupUIParent",
|
||||
maxLogLevel: Services.prefs.getBoolPref("browser.backup.log", false)
|
||||
? "Debug"
|
||||
: "Warn",
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -177,10 +187,10 @@ export class BackupUIParent extends JSWindowActorParent {
|
|||
true /* shouldLaunch */
|
||||
);
|
||||
} catch (e) {
|
||||
/**
|
||||
* TODO: (Bug 1905156) display a localized version of error in the restore dialog.
|
||||
*/
|
||||
lazy.logConsole.error(`Failed to restore file: ${backupFile}`, e);
|
||||
return { success: false, errorCode: e.cause || lazy.ERRORS.UNKNOWN };
|
||||
}
|
||||
return { success: true };
|
||||
} else if (message.name == "ToggleEncryption") {
|
||||
let { isEncryptionEnabled, password } = message.data;
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ export default class BackupSettings extends MozLitElement {
|
|||
|
||||
static properties = {
|
||||
backupServiceState: { type: Object },
|
||||
recoveryErrorCode: { type: Number },
|
||||
recoveryInProgress: { type: Boolean },
|
||||
_enableEncryptionTypeAttr: { type: String },
|
||||
};
|
||||
|
||||
|
@ -75,6 +77,8 @@ export default class BackupSettings extends MozLitElement {
|
|||
lastBackupDate: null,
|
||||
lastBackupFileName: "",
|
||||
};
|
||||
this.recoveryInProgress = false;
|
||||
this.recoveryErrorCode = 0;
|
||||
this._enableEncryptionTypeAttr = "";
|
||||
}
|
||||
|
||||
|
@ -140,7 +144,6 @@ export default class BackupSettings extends MozLitElement {
|
|||
}
|
||||
break;
|
||||
case "restoreFromBackupConfirm":
|
||||
this.restoreFromBackupDialogEl.close();
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("BackupUI:RestoreFromBackupFile", {
|
||||
bubbles: true,
|
||||
|
@ -290,6 +293,8 @@ export default class BackupSettings extends MozLitElement {
|
|||
.backupFilePath=${backupFilePath}
|
||||
.backupFileToRestore=${backupFileToRestore}
|
||||
.backupFileInfo=${backupFileInfo}
|
||||
.recoveryInProgress=${this.recoveryInProgress}
|
||||
.recoveryErrorCode=${this.recoveryErrorCode}
|
||||
></restore-from-backup>
|
||||
</dialog>`;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ export default class RestoreFromBackup extends MozLitElement {
|
|||
backupFileToRestore: { type: String, reflect: true },
|
||||
backupFileInfo: { type: Object },
|
||||
_fileIconURL: { type: String },
|
||||
recoveryInProgress: { type: Boolean },
|
||||
recoveryErrorCode: { type: Number },
|
||||
};
|
||||
|
||||
static get queries() {
|
||||
|
@ -106,7 +108,7 @@ export default class RestoreFromBackup extends MozLitElement {
|
|||
|
||||
handleConfirm() {
|
||||
let backupFile = this.backupFileToRestore;
|
||||
if (!backupFile) {
|
||||
if (!backupFile || this.recoveryInProgress) {
|
||||
return;
|
||||
}
|
||||
let backupPassword = this.passwordInput?.value;
|
||||
|
@ -177,6 +179,10 @@ export default class RestoreFromBackup extends MozLitElement {
|
|||
}
|
||||
|
||||
contentTemplate() {
|
||||
let buttonL10nId = !this.recoveryInProgress
|
||||
? "restore-from-backup-confirm-button"
|
||||
: "restore-from-backup-restoring-button";
|
||||
|
||||
return html`
|
||||
<div
|
||||
id="restore-from-backup-wrapper"
|
||||
|
@ -203,7 +209,8 @@ export default class RestoreFromBackup extends MozLitElement {
|
|||
id="restore-from-backup-confirm-button"
|
||||
@click=${this.handleConfirm}
|
||||
type="primary"
|
||||
data-l10n-id="restore-from-backup-confirm-button"
|
||||
data-l10n-id="${buttonL10nId}"
|
||||
?disabled=${!this.backupFileToRestore || this.recoveryInProgress}
|
||||
></moz-button>
|
||||
</moz-button-group>
|
||||
</div>
|
||||
|
|
|
@ -22,12 +22,16 @@ const Template = ({
|
|||
backupFilePath,
|
||||
backupFileToRestore,
|
||||
backupFileInfo,
|
||||
recoveryInProgress,
|
||||
recoveryErrorCode,
|
||||
}) => html`
|
||||
<moz-card style="width: fit-content;">
|
||||
<restore-from-backup
|
||||
.backupFilePath=${backupFilePath}
|
||||
.backupFileToRestore=${backupFileToRestore}
|
||||
.backupFileInfo=${backupFileInfo}
|
||||
.recoveryInProgress=${recoveryInProgress}
|
||||
.recoveryErrorCode=${recoveryErrorCode}
|
||||
></restore-from-backup>
|
||||
</moz-card>
|
||||
`;
|
||||
|
@ -46,4 +50,12 @@ EncryptedBackupFound.args = {
|
|||
backupFileInfo: { date: new Date(), isEncrypted: true },
|
||||
};
|
||||
|
||||
export const RecoveryInProgress = Template.bind({});
|
||||
RecoveryInProgress.args = {
|
||||
backupFilePath: "/Some/User/Documents",
|
||||
backupFileToRestore: "/Some/User/Documents/Firefox Backup/backup.html",
|
||||
backupFileInfo: { date: new Date() },
|
||||
recoveryInProgress: true,
|
||||
};
|
||||
|
||||
export const NoBackupFound = Template.bind({});
|
||||
|
|
|
@ -12,6 +12,8 @@ support-files = [
|
|||
|
||||
["browser_settings_enable_backup_encryption.js"]
|
||||
|
||||
["browser_settings_restore_from_backup.js"]
|
||||
|
||||
["browser_settings_turn_off_scheduled_backups.js"]
|
||||
|
||||
["browser_settings_turn_on_scheduled_backups.js"]
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_setup(async () => {
|
||||
MockFilePicker.init(window.browsingContext);
|
||||
registerCleanupFunction(() => {
|
||||
MockFilePicker.cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the a backup file can be restored from the settings page.
|
||||
*/
|
||||
add_task(async function test_restore_from_backup() {
|
||||
await BrowserTestUtils.withNewTab("about:preferences", async browser => {
|
||||
let sandbox = sinon.createSandbox();
|
||||
let recoverFromBackupArchiveStub = sandbox
|
||||
.stub(BackupService.prototype, "recoverFromBackupArchive")
|
||||
.resolves();
|
||||
|
||||
const mockBackupFilePath = await IOUtils.createUniqueFile(
|
||||
PathUtils.tempDir,
|
||||
"backup.html"
|
||||
);
|
||||
const mockBackupFile = Cc["@mozilla.org/file/local;1"].createInstance(
|
||||
Ci.nsIFile
|
||||
);
|
||||
mockBackupFile.initWithPath(mockBackupFilePath);
|
||||
|
||||
let filePickerShownPromise = new Promise(resolve => {
|
||||
MockFilePicker.showCallback = async () => {
|
||||
Assert.ok(true, "Filepicker shown");
|
||||
MockFilePicker.setFiles([mockBackupFile]);
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
|
||||
let settings = browser.contentDocument.querySelector("backup-settings");
|
||||
|
||||
await settings.updateComplete;
|
||||
|
||||
Assert.ok(
|
||||
settings.restoreFromBackupButtonEl,
|
||||
"Button to restore backups should be found"
|
||||
);
|
||||
|
||||
settings.restoreFromBackupButtonEl.click();
|
||||
|
||||
await settings.updateComplete;
|
||||
|
||||
let restoreFromBackup = settings.restoreFromBackupEl;
|
||||
|
||||
Assert.ok(restoreFromBackup, "restore-from-backup should be found");
|
||||
|
||||
let infoPromise = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"getBackupFileInfo"
|
||||
);
|
||||
|
||||
restoreFromBackup.chooseButtonEl.click();
|
||||
await filePickerShownPromise;
|
||||
|
||||
await infoPromise;
|
||||
// Set mock file info
|
||||
restoreFromBackup.backupFileInfo = {
|
||||
date: new Date(),
|
||||
isEncrypted: true,
|
||||
};
|
||||
await restoreFromBackup.updateComplete;
|
||||
|
||||
// Set password for file
|
||||
restoreFromBackup.passwordInput.value = "h-*@Vfge3_hGxdpwqr@w";
|
||||
|
||||
let restorePromise = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"restoreFromBackupConfirm"
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
restoreFromBackup.confirmButtonEl,
|
||||
"Confirm button should be found"
|
||||
);
|
||||
|
||||
await restoreFromBackup.updateComplete;
|
||||
restoreFromBackup.confirmButtonEl.click();
|
||||
|
||||
await restorePromise.then(e => {
|
||||
let mockEvent = {
|
||||
backupFile: mockBackupFile.path,
|
||||
backupPassword: "h-*@Vfge3_hGxdpwqr@w",
|
||||
};
|
||||
Assert.deepEqual(
|
||||
e.detail,
|
||||
mockEvent,
|
||||
"Event should contain the file and password"
|
||||
);
|
||||
});
|
||||
|
||||
Assert.ok(
|
||||
recoverFromBackupArchiveStub.calledOnce,
|
||||
"BackupService was called to start a recovery from a backup archive."
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the dialog stays open while restoring from the settings page.
|
||||
*/
|
||||
add_task(async function test_restore_in_progress() {
|
||||
await BrowserTestUtils.withNewTab("about:preferences", async browser => {
|
||||
let sandbox = sinon.createSandbox();
|
||||
let bs = BackupService.get();
|
||||
|
||||
let { promise: recoverPromise, resolve: recoverResolve } =
|
||||
Promise.withResolvers();
|
||||
let recoverFromBackupArchiveStub = sandbox
|
||||
.stub(bs, "recoverFromBackupArchive")
|
||||
.returns(recoverPromise);
|
||||
|
||||
let settings = browser.contentDocument.querySelector("backup-settings");
|
||||
|
||||
await settings.updateComplete;
|
||||
|
||||
Assert.ok(
|
||||
settings.restoreFromBackupButtonEl,
|
||||
"Button to restore backups should be found"
|
||||
);
|
||||
|
||||
settings.restoreFromBackupButtonEl.click();
|
||||
|
||||
await settings.updateComplete;
|
||||
|
||||
let restoreFromBackup = settings.restoreFromBackupEl;
|
||||
|
||||
Assert.ok(restoreFromBackup, "restore-from-backup should be found");
|
||||
Assert.ok(
|
||||
restoreFromBackup.confirmButtonEl.disabled,
|
||||
"Confirm button should be disabled."
|
||||
);
|
||||
|
||||
const mockBackupFilePath = await IOUtils.createUniqueFile(
|
||||
PathUtils.tempDir,
|
||||
"backup.html"
|
||||
);
|
||||
|
||||
// Set mock file
|
||||
restoreFromBackup.backupFileToRestore = mockBackupFilePath;
|
||||
await restoreFromBackup.updateComplete;
|
||||
|
||||
Assert.ok(
|
||||
!restoreFromBackup.confirmButtonEl.disabled,
|
||||
"Confirm button should not be disabled."
|
||||
);
|
||||
Assert.equal(
|
||||
restoreFromBackup.confirmButtonEl.getAttribute("data-l10n-id"),
|
||||
"restore-from-backup-confirm-button",
|
||||
"Confirm button should show confirm message."
|
||||
);
|
||||
|
||||
let restorePromise = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"restoreFromBackupConfirm"
|
||||
);
|
||||
|
||||
restoreFromBackup.confirmButtonEl.click();
|
||||
let currentState = bs.state;
|
||||
let recoveryInProgressState = Object.assign(
|
||||
{ recoveryInProgress: true },
|
||||
currentState
|
||||
);
|
||||
sandbox.stub(BackupService.prototype, "state").get(() => {
|
||||
return recoveryInProgressState;
|
||||
});
|
||||
bs.stateUpdate();
|
||||
|
||||
await restorePromise;
|
||||
|
||||
await settings.updateComplete;
|
||||
|
||||
Assert.ok(
|
||||
settings.restoreFromBackupDialogEl.open,
|
||||
"Restore dialog should still be open."
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
restoreFromBackup.confirmButtonEl.disabled,
|
||||
"Confirm button should be disabled."
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
restoreFromBackup.confirmButtonEl.getAttribute("data-l10n-id"),
|
||||
"restore-from-backup-restoring-button",
|
||||
"Confirm button should show restoring message."
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
recoverFromBackupArchiveStub.calledOnce,
|
||||
"BackupService was called to start a recovery from a backup archive."
|
||||
);
|
||||
|
||||
// Now cause recovery to resolve.
|
||||
recoverResolve();
|
||||
// Wait a tick of the event loop to let the BackupUIParent respond to
|
||||
// the promise resolution, and to send its message to the BackupUIChild.
|
||||
await new Promise(resolve => SimpleTest.executeSoon(resolve));
|
||||
// Wait a second tick to let the BackupUIChild respond to the message
|
||||
// from BackupUIParent.
|
||||
await new Promise(resolve => SimpleTest.executeSoon(resolve));
|
||||
|
||||
await settings.updateComplete;
|
||||
|
||||
Assert.ok(
|
||||
!settings.restoreFromBackupDialogEl.open,
|
||||
"Restore dialog should now be closed."
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
});
|
|
@ -123,6 +123,12 @@
|
|||
height: 2px;
|
||||
border-radius: 2px;
|
||||
margin: -3px 2px 0;
|
||||
|
||||
#tabbrowser-tabs[orient="vertical"] & {
|
||||
height: 100%;
|
||||
margin: 0 -2px;
|
||||
width: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.userContext-icon,
|
||||
|
|
|
@ -269,6 +269,17 @@ add_task(async function testOverflowingBookmarksButtonContextMenu() {
|
|||
* to the menu from the overflow panel, and then back to the toolbar.
|
||||
*/
|
||||
add_task(async function testOverflowingBookmarksItemsContextMenu() {
|
||||
info("Adding a bookmark to the bookmarks toolbar.");
|
||||
let addedBookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Test",
|
||||
url: "https://example.com",
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.remove(addedBookmark);
|
||||
});
|
||||
|
||||
info("Ensuring panel is ready.");
|
||||
await PanelUI.ensureReady();
|
||||
|
||||
|
|
|
@ -2021,6 +2021,26 @@ export var Policies = {
|
|||
},
|
||||
},
|
||||
|
||||
PrivateBrowsingModeAvailability: {
|
||||
onBeforeAddons(manager, param) {
|
||||
switch (param) {
|
||||
// Private Browsing mode disabled
|
||||
case 1:
|
||||
manager.disallowFeature("privatebrowsing");
|
||||
blockAboutPage(manager, "about:privatebrowsing", true);
|
||||
setAndLockPref("browser.privatebrowsing.autostart", false);
|
||||
break;
|
||||
// Private Browsing mode forced
|
||||
case 2:
|
||||
setAndLockPref("browser.privatebrowsing.autostart", true);
|
||||
break;
|
||||
// Private Browsing mode available
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
PromptForDownloadLocation: {
|
||||
onBeforeAddons(manager, param) {
|
||||
setAndLockPref("browser.download.useDownloadDir", !param);
|
||||
|
|
|
@ -1234,6 +1234,11 @@
|
|||
"type": "boolean"
|
||||
},
|
||||
|
||||
"PrivateBrowsingModeAvailability": {
|
||||
"type": "number",
|
||||
"enum": [0, 1, 2]
|
||||
},
|
||||
|
||||
"PromptForDownloadLocation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
|
|
@ -107,6 +107,8 @@ https_first_disabled = true
|
|||
|
||||
["browser_policy_passwordmanager.js"]
|
||||
|
||||
["browser_policy_privatebrowsingmodeavailability.js"]
|
||||
|
||||
["browser_policy_search_engine.js"]
|
||||
|
||||
["browser_policy_searchbar.js"]
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_privatebrowsing_disabled() {
|
||||
await setupPolicyEngineWithJson({
|
||||
policies: {
|
||||
PrivateBrowsingModeAvailability: 1,
|
||||
},
|
||||
});
|
||||
is(
|
||||
PrivateBrowsingUtils.enabled,
|
||||
false,
|
||||
"Private browsing should be disabled"
|
||||
);
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let privateBrowsingCommand = newWin.document.getElementById(
|
||||
"Tools:PrivateBrowsing"
|
||||
);
|
||||
is(
|
||||
privateBrowsingCommand.hidden,
|
||||
true,
|
||||
"The private browsing command should be hidden"
|
||||
);
|
||||
await BrowserTestUtils.withNewTab(
|
||||
"about:preferences#privacy",
|
||||
async browser => {
|
||||
ok(
|
||||
browser.contentDocument.querySelector("menuitem[value='dontremember']")
|
||||
.disabled,
|
||||
"Don't remember history should be disabled"
|
||||
);
|
||||
}
|
||||
);
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
|
||||
await testPageBlockedByPolicy("about:privatebrowsing");
|
||||
});
|
||||
|
||||
add_task(async function test_privatebrowsing_enabled() {
|
||||
await setupPolicyEngineWithJson({
|
||||
policies: {
|
||||
PrivateBrowsingModeAvailability: 2,
|
||||
},
|
||||
});
|
||||
|
||||
is(PrivateBrowsingUtils.enabled, true, "Private browsing should be true");
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await BrowserTestUtils.withNewTab(
|
||||
"about:preferences#privacy",
|
||||
async browser => {
|
||||
ok(
|
||||
browser.contentDocument.getElementById("historyMode").disabled,
|
||||
"History dropdown should be disabled"
|
||||
);
|
||||
}
|
||||
);
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
|
@ -693,6 +693,17 @@ function bookmarkContextMenuExtension() {
|
|||
}
|
||||
|
||||
add_task(async function test_bookmark_contextmenu() {
|
||||
info("Adding a bookmark to the bookmarks toolbar.");
|
||||
let addedBookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Test",
|
||||
url: "https://example.com",
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.remove(addedBookmark);
|
||||
});
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
|
||||
|
||||
await toggleBookmarksToolbar(true);
|
||||
|
|
|
@ -155,6 +155,17 @@ add_task(async function test_actionContextMenus() {
|
|||
});
|
||||
|
||||
add_task(async function test_bookmarkContextMenu() {
|
||||
info("Adding a bookmark to the bookmarks toolbar.");
|
||||
let addedBookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Test",
|
||||
url: "https://example.com",
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.remove(addedBookmark);
|
||||
});
|
||||
|
||||
const ext = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
permissions: ["menus", "bookmarks"],
|
||||
|
|
|
@ -7,7 +7,6 @@ ChromeUtils.defineESModuleGetters(this, {
|
|||
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
|
||||
AddonTestUtils: "resource://testing-common/AddonTestUtils.sys.mjs",
|
||||
SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs",
|
||||
SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs",
|
||||
TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
|
||||
});
|
||||
|
||||
|
@ -22,19 +21,14 @@ SearchTestUtils.init(this);
|
|||
const DEFAULT_ENGINE = {
|
||||
id: "basic",
|
||||
name: "basic",
|
||||
loadPath: SearchUtils.newSearchConfigEnabled
|
||||
? "[app]basic@search.mozilla.org"
|
||||
: "[addon]basic@search.mozilla.org",
|
||||
submissionUrl: SearchUtils.newSearchConfigEnabled
|
||||
? "https://mochi.test:8888/browser/browser/components/search/test/browser/?foo=1&search="
|
||||
: "https://mochi.test:8888/browser/browser/components/search/test/browser/?search=&foo=1",
|
||||
loadPath: "[app]basic@search.mozilla.org",
|
||||
submissionUrl:
|
||||
"https://mochi.test:8888/browser/browser/components/search/test/browser/?foo=1&search=",
|
||||
};
|
||||
const ALTERNATE_ENGINE = {
|
||||
id: "simple",
|
||||
name: "Simple Engine",
|
||||
loadPath: SearchUtils.newSearchConfigEnabled
|
||||
? "[app]simple@search.mozilla.org"
|
||||
: "[addon]simple@search.mozilla.org",
|
||||
loadPath: "[app]simple@search.mozilla.org",
|
||||
submissionUrl: "https://example.com/?sourceId=Mozilla-search&search=",
|
||||
};
|
||||
const ALTERNATE2_ENGINE = {
|
||||
|
@ -104,9 +98,7 @@ add_setup(async function () {
|
|||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
let response = await fetch(
|
||||
SearchUtils.newSearchConfigEnabled
|
||||
? `resource://search-extensions/search-config-v2.json`
|
||||
: `resource://search-extensions/engines.json`
|
||||
"resource://search-extensions/search-config-v2.json"
|
||||
);
|
||||
let json = await response.json();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(json.data);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name": "another",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"description": "another",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "another@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "another",
|
||||
"search_url": "https://mochi.test:8888/browser/browser/components/search/test/browser/?search={searchTerms}&bar=1",
|
||||
"suggest_url": "https://mochi.test:8888/browser/browser/modules/test/browser/usageTelemetrySearchSuggestions.sjs?{searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name": "basic",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"description": "basic",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "basic@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "basic",
|
||||
"search_url": "https://mochi.test:8888/browser/browser/components/search/test/browser/?search={searchTerms}&foo=1",
|
||||
"suggest_url": "https://mochi.test:8888/browser/browser/modules/test/browser/usageTelemetrySearchSuggestions.sjs?{searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"data": [
|
||||
{
|
||||
"webExtension": {
|
||||
"id": "basic@search.mozilla.org",
|
||||
"name": "basic",
|
||||
"search_url": "https://mochi.test:8888/browser/browser/components/search/test/browser/?search={searchTerms}&foo=1",
|
||||
"suggest_url": "https://mochi.test:8888/browser/browser/modules/test/browser/usageTelemetrySearchSuggestions.sjs?{searchTerms}"
|
||||
},
|
||||
"appliesTo": [
|
||||
{
|
||||
"included": { "everywhere": true },
|
||||
"default": "yes"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"webExtension": {
|
||||
"id": "simple@search.mozilla.org"
|
||||
},
|
||||
"appliesTo": [
|
||||
{
|
||||
"included": { "everywhere": true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"webExtension": {
|
||||
"id": "another@search.mozilla.org"
|
||||
},
|
||||
"appliesTo": [
|
||||
{
|
||||
"included": { "everywhere": true }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"name": "Simple Engine",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"description": "Simple engine with a different name from the WebExtension id prefix",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "simple@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "Simple Engine",
|
||||
"search_url": "https://example.com",
|
||||
"params": [
|
||||
{
|
||||
"name": "sourceId",
|
||||
"value": "Mozilla-search"
|
||||
},
|
||||
{
|
||||
"name": "search",
|
||||
"value": "{searchTerms}"
|
||||
}
|
||||
],
|
||||
"suggest_url": "https://example.com?search={searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
{
|
||||
"name": "MozParamsTest",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "test@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"description": "A test search engine (based on Google search)",
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "MozParamsTest",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
"params": [
|
||||
{
|
||||
"name": "test-0",
|
||||
"condition": "purpose",
|
||||
"purpose": "contextmenu",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"name": "test-1",
|
||||
"condition": "purpose",
|
||||
"purpose": "searchbar",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "test-2",
|
||||
"condition": "purpose",
|
||||
"purpose": "homepage",
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"name": "test-3",
|
||||
"condition": "purpose",
|
||||
"purpose": "keyword",
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"name": "test-4",
|
||||
"condition": "purpose",
|
||||
"purpose": "newtab",
|
||||
"value": "4"
|
||||
},
|
||||
{
|
||||
"name": "simple",
|
||||
"value": "5"
|
||||
},
|
||||
{
|
||||
"name": "term",
|
||||
"value": "{searchTerms}"
|
||||
},
|
||||
{
|
||||
"name": "lang",
|
||||
"value": "{language}"
|
||||
},
|
||||
{
|
||||
"name": "prefval",
|
||||
"condition": "pref",
|
||||
"pref": "code"
|
||||
},
|
||||
{
|
||||
"name": "experimenter-1",
|
||||
"condition": "pref",
|
||||
"pref": "nimbus-key-1"
|
||||
},
|
||||
{
|
||||
"name": "experimenter-2",
|
||||
"condition": "pref",
|
||||
"pref": "nimbus-key-2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"name": "MozParamsTest2",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "test2@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"description": "A second test search engine",
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "MozParamsTest2",
|
||||
"search_url": "https://example.com/2/?q={searchTerms}",
|
||||
"params": [
|
||||
{
|
||||
"name": "simple2",
|
||||
"value": "5"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -157,35 +157,7 @@ add_task(async function setup() {
|
|||
AddonTestUtils.usePrivilegedSignatures = false;
|
||||
AddonTestUtils.overrideCertDB();
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
await SearchTestUtils.useTestEngines(
|
||||
"data",
|
||||
null,
|
||||
SearchUtils.newSearchConfigEnabled
|
||||
? CONFIG_V2
|
||||
: [
|
||||
{
|
||||
webExtension: {
|
||||
id: "test@search.mozilla.org",
|
||||
},
|
||||
appliesTo: [
|
||||
{
|
||||
included: { everywhere: true },
|
||||
default: "yes",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
webExtension: {
|
||||
id: "test2@search.mozilla.org",
|
||||
},
|
||||
appliesTo: [
|
||||
{
|
||||
included: { everywhere: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
||||
await SearchTestUtils.useTestEngines("data", null, CONFIG_V2);
|
||||
await Services.search.init();
|
||||
registerCleanupFunction(async () => {
|
||||
await AddonTestUtils.promiseShutdownManager();
|
||||
|
@ -244,9 +216,7 @@ add_task(async function test_extension_changing_to_app_provided_default() {
|
|||
|
||||
assertEngineParameters({
|
||||
name: "MozParamsTest2",
|
||||
searchURL: SearchUtils.newSearchConfigEnabled
|
||||
? "https://example.com/2/?simple2=5&q={searchTerms}"
|
||||
: "https://example.com/2/?q={searchTerms}&simple2=5",
|
||||
searchURL: "https://example.com/2/?simple2=5&q={searchTerms}",
|
||||
messageSnippet: "left unchanged",
|
||||
});
|
||||
|
||||
|
@ -335,9 +305,7 @@ add_task(async function test_extension_overriding_app_provided_default() {
|
|||
);
|
||||
assertEngineParameters({
|
||||
name: "MozParamsTest2",
|
||||
searchURL: SearchUtils.newSearchConfigEnabled
|
||||
? "https://example.com/2/?simple2=5&q={searchTerms}"
|
||||
: "https://example.com/2/?q={searchTerms}&simple2=5",
|
||||
searchURL: "https://example.com/2/?simple2=5&q={searchTerms}",
|
||||
messageSnippet: "reverted",
|
||||
});
|
||||
|
||||
|
@ -380,9 +348,7 @@ add_task(async function test_extension_overriding_app_provided_default() {
|
|||
|
||||
assertEngineParameters({
|
||||
name: "MozParamsTest2",
|
||||
searchURL: SearchUtils.newSearchConfigEnabled
|
||||
? "https://example.com/2/?simple2=5&q={searchTerms}"
|
||||
: "https://example.com/2/?q={searchTerms}&simple2=5",
|
||||
searchURL: "https://example.com/2/?simple2=5&q={searchTerms}",
|
||||
messageSnippet: "reverted",
|
||||
});
|
||||
sinon.restore();
|
||||
|
|
|
@ -15,9 +15,6 @@ const { NimbusFeatures } = ChromeUtils.importESModule(
|
|||
const { sinon } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/Sinon.sys.mjs"
|
||||
);
|
||||
const { SearchUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/SearchUtils.sys.mjs"
|
||||
);
|
||||
|
||||
AddonTestUtils.init(this);
|
||||
AddonTestUtils.overrideCertDB();
|
||||
|
@ -53,19 +50,6 @@ const params = [
|
|||
{ name: "prefval", condition: "pref", pref: "code" },
|
||||
];
|
||||
|
||||
const CONFIG = [
|
||||
{
|
||||
webExtension: {
|
||||
id: "test@search.mozilla.org",
|
||||
},
|
||||
appliesTo: [
|
||||
{
|
||||
included: { everywhere: true },
|
||||
default: "yes",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const CONFIG_V2 = [
|
||||
{
|
||||
recordType: "engine",
|
||||
|
@ -156,11 +140,7 @@ add_task(async function setup() {
|
|||
let readyStub = sinon.stub(NimbusFeatures.search, "ready").resolves();
|
||||
let updateStub = sinon.stub(NimbusFeatures.search, "onUpdate");
|
||||
await promiseStartupManager();
|
||||
await SearchTestUtils.useTestEngines(
|
||||
"data",
|
||||
null,
|
||||
SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG
|
||||
);
|
||||
await SearchTestUtils.useTestEngines("data", null, CONFIG_V2);
|
||||
await Services.search.init();
|
||||
registerCleanupFunction(async () => {
|
||||
await promiseShutdownManager();
|
||||
|
@ -198,9 +178,7 @@ add_task(async function test_extension_setting_moz_params() {
|
|||
).uri.spec;
|
||||
equal(
|
||||
expectedURL,
|
||||
SearchUtils.newSearchConfigEnabled
|
||||
? `https://example.com/?${p.name}=${p.value}&${paramStr}&q=test`
|
||||
: `https://example.com/?q=test&${p.name}=${p.value}&${paramStr}`,
|
||||
`https://example.com/?${p.name}=${p.value}&${paramStr}&q=test`,
|
||||
"search url is expected"
|
||||
);
|
||||
}
|
||||
|
@ -271,9 +249,7 @@ add_task(async function test_nimbus_params() {
|
|||
).uri.spec;
|
||||
equal(
|
||||
expectedURL,
|
||||
SearchUtils.newSearchConfigEnabled
|
||||
? `https://example.com/?${p.name}=${p.value}&${paramStr}&q=test`
|
||||
: `https://example.com/?q=test&${p.name}=${p.value}&${paramStr}`,
|
||||
`https://example.com/?${p.name}=${p.value}&${paramStr}&q=test`,
|
||||
"search url is expected"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -46,16 +46,11 @@ run-sequentially = "very high failure rate in parallel"
|
|||
|
||||
["test_ext_settings_overrides_defaults.js"]
|
||||
skip-if = ["condprof"] # Bug 1776135 - by design, modifies search settings at start of test
|
||||
support-files = [
|
||||
"data/test/manifest.json",
|
||||
"data/test2/manifest.json",
|
||||
]
|
||||
|
||||
["test_ext_settings_overrides_search.js"]
|
||||
|
||||
["test_ext_settings_overrides_search_mozParam.js"]
|
||||
skip-if = ["condprof"] # Bug 1776652
|
||||
support-files = ["data/test/manifest.json"]
|
||||
|
||||
["test_ext_settings_overrides_shutdown.js"]
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ module.exports = {
|
|||
"content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx",
|
||||
"content-src/components/CustomizeMenu/**",
|
||||
"content-src/components/WallpapersSection/**",
|
||||
"content-src/components/DiscoveryStreamComponents/TopicSelection/TopicSelection.jsx",
|
||||
],
|
||||
rules: {
|
||||
"jsx-a11y/anchor-has-content": "off",
|
||||
|
|
|
@ -95,6 +95,16 @@ function templateHTML(options) {
|
|||
type="module"
|
||||
src="chrome://global/content/elements/moz-toggle.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button-group.mjs"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
`.trimLeft();
|
||||
|
|
|
@ -143,6 +143,7 @@ for (const type of [
|
|||
"SYSTEM_TICK",
|
||||
"TELEMETRY_IMPRESSION_STATS",
|
||||
"TELEMETRY_USER_EVENT",
|
||||
"TOPIC_SELECTION_SPOTLIGHT_TOGGLE",
|
||||
"TOP_SITES_CANCEL_EDIT",
|
||||
"TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL",
|
||||
"TOP_SITES_EDIT",
|
||||
|
|
|
@ -86,6 +86,7 @@ export const INITIAL_STATE = {
|
|||
recentSavesData: [],
|
||||
isUserLoggedIn: false,
|
||||
recentSavesEnabled: false,
|
||||
showTopicSelection: false,
|
||||
},
|
||||
Notifications: {
|
||||
showNotifications: false,
|
||||
|
@ -844,6 +845,11 @@ function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
|
|||
};
|
||||
}
|
||||
return prevState;
|
||||
case at.TOPIC_SELECTION_SPOTLIGHT_TOGGLE:
|
||||
return {
|
||||
...prevState,
|
||||
showTopicSelection: !prevState.showTopicSelection,
|
||||
};
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import { Search } from "content-src/components/Search/Search";
|
|||
import { Sections } from "content-src/components/Sections/Sections";
|
||||
import { Weather } from "content-src/components/Weather/Weather";
|
||||
import { Notifications } from "content-src/components/Notifications/Notifications";
|
||||
import { TopicSelection } from "content-src/components/DiscoveryStreamComponents/TopicSelection/TopicSelection";
|
||||
import { WallpaperFeatureHighlight } from "../DiscoveryStreamComponents/FeatureHighlight/WallpaperFeatureHighlight";
|
||||
|
||||
const VISIBLE = "visible";
|
||||
|
@ -385,7 +386,7 @@ export class BaseContent extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { App } = props;
|
||||
const { App, DiscoveryStream } = props;
|
||||
const { initialized, customizeMenuVisible } = App;
|
||||
const prefs = props.Prefs.values;
|
||||
|
||||
|
@ -394,6 +395,9 @@ export class BaseContent extends React.PureComponent {
|
|||
const wallpapersEnabled = prefs["newtabWallpapers.enabled"];
|
||||
const wallpapersV2Enabled = prefs["newtabWallpapers.v2.enabled"];
|
||||
const weatherEnabled = prefs.showWeather;
|
||||
const { showTopicSelection } = DiscoveryStream;
|
||||
const mayShowTopicSelection =
|
||||
showTopicSelection && prefs["discoverystream.topicSelection.enabled"];
|
||||
|
||||
const { pocketConfig } = prefs;
|
||||
|
||||
|
@ -535,6 +539,7 @@ export class BaseContent extends React.PureComponent {
|
|||
</ErrorBoundary>
|
||||
)}
|
||||
</aside>
|
||||
{mayShowTopicSelection && <TopicSelection />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -7,6 +7,7 @@ import { FluentOrText } from "content-src/components/FluentOrText/FluentOrText";
|
|||
import { SponsoredContentHighlight } from "../DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
|
||||
|
||||
/**
|
||||
* A section that can collapse. As of bug 1710937, it can no longer collapse.
|
||||
|
@ -19,11 +20,13 @@ export class _CollapsibleSection extends React.PureComponent {
|
|||
this.onMenuButtonMouseEnter = this.onMenuButtonMouseEnter.bind(this);
|
||||
this.onMenuButtonMouseLeave = this.onMenuButtonMouseLeave.bind(this);
|
||||
this.onMenuUpdate = this.onMenuUpdate.bind(this);
|
||||
this.setContextMenuButtonRef = this.setContextMenuButtonRef.bind(this);
|
||||
this.handleTopicSelectionButtonClick =
|
||||
this.handleTopicSelectionButtonClick.bind(this);
|
||||
this.state = {
|
||||
menuButtonHover: false,
|
||||
showContextMenu: false,
|
||||
};
|
||||
this.setContextMenuButtonRef = this.setContextMenuButtonRef.bind(this);
|
||||
}
|
||||
|
||||
setContextMenuButtonRef(element) {
|
||||
|
@ -46,6 +49,12 @@ export class _CollapsibleSection extends React.PureComponent {
|
|||
this.setState({ showContextMenu });
|
||||
}
|
||||
|
||||
handleTopicSelectionButtonClick() {
|
||||
this.props.dispatch(
|
||||
ac.AlsoToMain({ type: at.TOPIC_SELECTION_SPOTLIGHT_TOGGLE })
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isAnimating, maxHeight, menuButtonHover, showContextMenu } =
|
||||
this.state;
|
||||
|
@ -69,6 +78,8 @@ export class _CollapsibleSection extends React.PureComponent {
|
|||
titleStyle = { visibility: "hidden" };
|
||||
}
|
||||
const hasSubtitleClassName = subTitle ? `has-subtitle` : ``;
|
||||
const topicSelectionEnabled =
|
||||
this.props.Prefs.values["discoverystream.topicSelection.enabled"];
|
||||
return (
|
||||
<section
|
||||
className={`collapsible-section ${this.props.className}${
|
||||
|
@ -107,6 +118,13 @@ export class _CollapsibleSection extends React.PureComponent {
|
|||
/>
|
||||
)}
|
||||
</h3>
|
||||
{topicSelectionEnabled && (
|
||||
<moz-button
|
||||
label="Personalize my feed"
|
||||
type="primary"
|
||||
onClick={this.handleTopicSelectionButtonClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<ErrorBoundary className="section-body-fallback">
|
||||
<div ref={this.onBodyMount} style={bodyStyle}>
|
||||
|
|
|
@ -60,6 +60,15 @@
|
|||
min-height: 19px;
|
||||
margin-bottom: 13px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
@media (max-width: $break-point-medium - 1) {
|
||||
flex-direction: column;
|
||||
gap: var(--space-small);
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
|
|
@ -119,11 +119,5 @@
|
|||
// _TopSites.scss
|
||||
.top-site-outer {
|
||||
margin-block-end: 0;
|
||||
|
||||
.top-site-inner>a {
|
||||
// Setting individual properties to negative undefined variable reference ($half-base-gutter)
|
||||
padding-top: var(--space-xsmall);
|
||||
padding-bottom: var(--space-xsmall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
/* 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 React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { ModalOverlayWrapper } from "content-src/components/ModalOverlay/ModalOverlay";
|
||||
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
|
||||
|
||||
// TODO: move strings to newtab.ftl once strings have been approved
|
||||
const TOPIC_LABELS = {
|
||||
"newtab-topic-business": "Business",
|
||||
"newtab-topic-arts": "Entertainment",
|
||||
"newtab-topic-food": "Food",
|
||||
"newtab-topic-health": "Health",
|
||||
"newtab-topic-finance": "Money",
|
||||
"newtab-topic-government": "Politics",
|
||||
"newtab-topic-sports": "Sports",
|
||||
"newtab-topic-tech": "Tech",
|
||||
"newtab-topic-travel": "Travel",
|
||||
"newtab-topic-education": "Science",
|
||||
"newtab-topic-society": "Life Hacks",
|
||||
};
|
||||
|
||||
const EMOJI_LABELS = {
|
||||
business: "💼",
|
||||
arts: "🎭",
|
||||
food: "🍕",
|
||||
health: "🩺",
|
||||
finance: "💰",
|
||||
government: "🏛️",
|
||||
sports: "⚽️",
|
||||
tech: "💻",
|
||||
travel: "✈️",
|
||||
education: "🧪",
|
||||
society: "💡",
|
||||
};
|
||||
|
||||
function TopicSelection() {
|
||||
const dispatch = useDispatch();
|
||||
const inputRef = useRef(null);
|
||||
const modalRef = useRef(null);
|
||||
const checkboxWrapperRef = useRef(null);
|
||||
const topics = useSelector(
|
||||
state => state.Prefs.values["discoverystream.topicSelection.topics"]
|
||||
).split(", ");
|
||||
const selectedTopics = useSelector(
|
||||
state => state.Prefs.values["discoverystream.topicSelection.selectedTopics"]
|
||||
);
|
||||
const suggestedTopics = useSelector(
|
||||
state =>
|
||||
state.Prefs.values["discoverystream.topicSelection.suggestedTopics"]
|
||||
).split(", ");
|
||||
|
||||
// TODO: only show suggested topics during the first run
|
||||
// if selectedTopics is empty - default to using the suggestedTopics as a starting value
|
||||
const [topicsToSelect, setTopicsToSelect] = useState(
|
||||
selectedTopics ? selectedTopics.split(", ") : suggestedTopics
|
||||
);
|
||||
|
||||
function handleModalClose() {
|
||||
dispatch(ac.AlsoToMain({ type: at.TOPIC_SELECTION_SPOTLIGHT_TOGGLE }));
|
||||
}
|
||||
|
||||
// when component mounts, set focus to input
|
||||
useEffect(() => {
|
||||
inputRef?.current?.focus();
|
||||
}, [inputRef]);
|
||||
|
||||
const handleFocus = useCallback(e => {
|
||||
// this list will have to be updated with other reusable components that get used inside of this modal
|
||||
const tabbableElements = modalRef.current.querySelectorAll(
|
||||
'a[href], button, moz-button, input[tabindex="0"]'
|
||||
);
|
||||
const [firstTabableEl] = tabbableElements;
|
||||
const lastTabbableEl = tabbableElements[tabbableElements.length - 1];
|
||||
|
||||
let isTabPressed = e.key === "Tab" || e.keyCode === 9;
|
||||
let isArrowPressed = e.key === "ArrowUp" || e.key === "ArrowDown";
|
||||
|
||||
if (isTabPressed) {
|
||||
if (e.shiftKey) {
|
||||
if (document.activeElement === firstTabableEl) {
|
||||
lastTabbableEl.focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (document.activeElement === lastTabbableEl) {
|
||||
firstTabableEl.focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (
|
||||
isArrowPressed &&
|
||||
checkboxWrapperRef.current.contains(document.activeElement)
|
||||
) {
|
||||
const checkboxElements =
|
||||
checkboxWrapperRef.current.querySelectorAll("input");
|
||||
const [firstInput] = checkboxElements;
|
||||
const lastInput = checkboxElements[checkboxElements.length - 1];
|
||||
const inputArr = Array.from(checkboxElements);
|
||||
const currentIndex = inputArr.indexOf(document.activeElement);
|
||||
let nextEl;
|
||||
if (e.key === "ArrowUp") {
|
||||
nextEl =
|
||||
document.activeElement === firstInput
|
||||
? lastInput
|
||||
: checkboxElements[currentIndex - 1];
|
||||
} else if (e.key === "ArrowDown") {
|
||||
nextEl =
|
||||
document.activeElement === lastInput
|
||||
? firstInput
|
||||
: checkboxElements[currentIndex + 1];
|
||||
}
|
||||
nextEl.tabIndex = 0;
|
||||
document.activeElement.tabIndex = -1;
|
||||
nextEl.focus();
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const ref = modalRef.current;
|
||||
ref.addEventListener("keydown", handleFocus);
|
||||
|
||||
inputRef.current.tabIndex = 0;
|
||||
|
||||
return () => {
|
||||
ref.removeEventListener("keydown", handleFocus);
|
||||
};
|
||||
}, [handleFocus]);
|
||||
|
||||
function handleChange(e) {
|
||||
const topic = e.target.name;
|
||||
const isChecked = e.target.checked;
|
||||
if (isChecked) {
|
||||
setTopicsToSelect([...topicsToSelect, topic]);
|
||||
} else {
|
||||
const updatedTopics = topicsToSelect.filter(t => t !== topic);
|
||||
setTopicsToSelect(updatedTopics);
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
dispatch(
|
||||
ac.SetPref(
|
||||
"discoverystream.topicSelection.selectedTopics",
|
||||
topicsToSelect.join(", ")
|
||||
)
|
||||
);
|
||||
handleModalClose();
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalOverlayWrapper
|
||||
onClose={handleModalClose}
|
||||
innerClassName="topic-selection-container"
|
||||
>
|
||||
<div className="topic-selection-form" ref={modalRef}>
|
||||
<button
|
||||
className="dismiss-button"
|
||||
title="dismiss"
|
||||
onClick={handleModalClose}
|
||||
/>
|
||||
<h1 className="title">Select topics you care about</h1>
|
||||
<p className="subtitle">
|
||||
Tell us what you are interested in and we’ll recommend you great
|
||||
stories!
|
||||
</p>
|
||||
<div className="topic-list" ref={checkboxWrapperRef}>
|
||||
{topics.map((topic, i) => {
|
||||
const checked = topicsToSelect.includes(topic);
|
||||
return (
|
||||
<label className={`topic-item`} key={topic}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={topic}
|
||||
name={topic}
|
||||
ref={i === 0 ? inputRef : null}
|
||||
onChange={handleChange}
|
||||
checked={checked}
|
||||
aria-checked={checked}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
<div className={`topic-custom-checkbox`}>
|
||||
<span className="topic-icon">{EMOJI_LABELS[`${topic}`]}</span>
|
||||
<span className="topic-checked" />
|
||||
</div>
|
||||
<span className="topic-item-label">
|
||||
{TOPIC_LABELS[`newtab-topic-${topic}`]}
|
||||
</span>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<a href="https://support.mozilla.org/en-US/kb/pocket-recommendations-firefox-new-tab">
|
||||
How we protect your data and privacy
|
||||
</a>
|
||||
<moz-button-group className="button-group">
|
||||
<moz-button label="Remove topics" onClick={handleModalClose} />
|
||||
<moz-button
|
||||
label="Save topics"
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
</moz-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlayWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export { TopicSelection };
|
|
@ -0,0 +1,163 @@
|
|||
/* stylelint-disable max-nesting-depth */
|
||||
|
||||
.modalOverlayOuter.active:has(.topic-selection-container) {
|
||||
background-color: rgba(21, 20, 26, 50%);
|
||||
}
|
||||
|
||||
.topic-selection-container {
|
||||
--transition: 0.6s opacity, 0.6s scale, 0.6s rotate, 0.6s translate;
|
||||
|
||||
position: relative;
|
||||
border-radius: var(--space-small);
|
||||
box-shadow: $shadow-large;
|
||||
padding: var(--size-item-large);
|
||||
max-width: 745px;
|
||||
height: auto;
|
||||
|
||||
.dismiss-button {
|
||||
position: absolute;
|
||||
appearance: none;
|
||||
border: none;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
inset-inline: auto 0;
|
||||
border-radius: var(--border-radius-small);
|
||||
padding: 0;
|
||||
margin: var(--space-small);
|
||||
display: block;
|
||||
float: inline-end;
|
||||
background: url('chrome://global/skin/icons/close.svg') no-repeat center / 16px;
|
||||
height: var(--size-item-large);
|
||||
width: var(--size-item-large);
|
||||
align-self: end;
|
||||
// override default min-height and min-width for buttons
|
||||
min-height: var(--size-item-large);
|
||||
min-width: var(--size-item-large);
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
transition: var(--transition);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--button-background-color-hover);
|
||||
|
||||
&:active {
|
||||
background-color: var(--button-background-color-active)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: var(--font-size-xlarge);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-block-end: var(--space-small);
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
text-align: center;
|
||||
margin-block: 0 var(--space-xlarge);
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.button-group {
|
||||
gap: var(--space-medium);
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.topic-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--size-item-small);
|
||||
margin: var(--size-item-large) auto;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
|
||||
.topic-item {
|
||||
border-radius: 40px;
|
||||
padding-inline: 6px var(--size-item-small);
|
||||
padding-block: 6px;
|
||||
border: 1px solid var(--color-gray-60);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-self: center;
|
||||
max-width: fit-content;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
|
||||
&:has(input:checked) {
|
||||
border-color: var(--color-accent-primary);
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
outline-offset: 2px;
|
||||
outline: 2px solid var(--color-accent-primary);
|
||||
}
|
||||
|
||||
.topic-item-label {
|
||||
margin-inline-end: var(--space-small);
|
||||
}
|
||||
|
||||
.topic-custom-checkbox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 100%;
|
||||
background-color: var(--newtab-button-static-background);
|
||||
margin-inline-end: var(--space-large);
|
||||
|
||||
.topic-icon {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.topic-checked {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
opacity: 0;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: absolute;
|
||||
inset-inline-start: 0.5em;
|
||||
top: 0.4em;
|
||||
|
||||
&:checked~.topic-custom-checkbox {
|
||||
background-color: var(--color-accent-primary);
|
||||
position: relative;
|
||||
|
||||
.topic-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.topic-checked {
|
||||
color: var(--color-white);
|
||||
-moz-context-properties: fill;
|
||||
display: block;
|
||||
fill: currentColor;
|
||||
background: url('chrome://global/skin/icons/check.svg');
|
||||
background-size: cover;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,55 +2,62 @@
|
|||
* 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 React from "react";
|
||||
import React, { useEffect, useCallback, useRef } from "react";
|
||||
|
||||
export class ModalOverlayWrapper extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
function ModalOverlayWrapper({
|
||||
document = globalThis.document,
|
||||
unstyled,
|
||||
innerClassName,
|
||||
onClose,
|
||||
children,
|
||||
headerId,
|
||||
id,
|
||||
}) {
|
||||
const modalRef = useRef(null);
|
||||
|
||||
let className = unstyled ? "" : "modalOverlayInner active";
|
||||
if (innerClassName) {
|
||||
className += ` ${innerClassName}`;
|
||||
}
|
||||
|
||||
// The intended behaviour is to listen for an escape key
|
||||
// but not for a click; see Bug 1582242
|
||||
onKeyDown(event) {
|
||||
if (event.key === "Escape") {
|
||||
this.props.onClose(event);
|
||||
}
|
||||
}
|
||||
const onKeyDown = useCallback(
|
||||
event => {
|
||||
if (event.key === "Escape") {
|
||||
onClose(event);
|
||||
}
|
||||
},
|
||||
[onClose]
|
||||
);
|
||||
|
||||
componentWillMount() {
|
||||
this.props.document.addEventListener("keydown", this.onKeyDown);
|
||||
this.props.document.body.classList.add("modal-open");
|
||||
}
|
||||
useEffect(() => {
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
document.body.classList.add("modal-open");
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.document.removeEventListener("keydown", this.onKeyDown);
|
||||
this.props.document.body.classList.remove("modal-open");
|
||||
}
|
||||
return () => {
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
document.body.classList.remove("modal-open");
|
||||
};
|
||||
}, [document, onKeyDown]);
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
let className = props.unstyled ? "" : "modalOverlayInner active";
|
||||
if (props.innerClassName) {
|
||||
className += ` ${props.innerClassName}`;
|
||||
}
|
||||
return (
|
||||
return (
|
||||
<div
|
||||
className="modalOverlayOuter active"
|
||||
onKeyDown={onKeyDown}
|
||||
role="presentation"
|
||||
>
|
||||
<div
|
||||
className="modalOverlayOuter active"
|
||||
onKeyDown={this.onKeyDown}
|
||||
role="presentation"
|
||||
className={className}
|
||||
aria-labelledby={headerId}
|
||||
id={id}
|
||||
role="dialog"
|
||||
ref={modalRef}
|
||||
>
|
||||
<div
|
||||
className={className}
|
||||
aria-labelledby={props.headerId}
|
||||
id={props.id}
|
||||
role="dialog"
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ModalOverlayWrapper.defaultProps = { document: globalThis.document };
|
||||
export { ModalOverlayWrapper };
|
||||
|
|
|
@ -188,4 +188,5 @@ input {
|
|||
@import '../components/DiscoveryStreamComponents/FeatureHighlight/FeatureHighlight';
|
||||
@import '../components/DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight';
|
||||
@import '../components/DiscoveryStreamComponents/FeatureHighlight/WallpaperFeatureHighlight';
|
||||
@import '../components/DiscoveryStreamComponents/TopicSelection/TopicSelection';
|
||||
// stylelint-enable no-invalid-position-at-import-rule
|
||||
|
|
|
@ -2951,6 +2951,16 @@ main section {
|
|||
min-height: 19px;
|
||||
margin-bottom: 13px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
@media (max-width: 609px) {
|
||||
.collapsible-section .section-top-bar {
|
||||
flex-direction: column;
|
||||
gap: var(--space-small);
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
.collapsible-section.active {
|
||||
background: var(--newtab-element-hover-color);
|
||||
|
@ -5064,10 +5074,6 @@ main section {
|
|||
.thumbs-ui-compact .top-site-outer {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
.thumbs-ui-compact .top-site-outer .top-site-inner > a {
|
||||
padding-top: var(--space-xsmall);
|
||||
padding-bottom: var(--space-xsmall);
|
||||
}
|
||||
|
||||
.ds-signup {
|
||||
max-width: 300px;
|
||||
|
@ -5430,3 +5436,143 @@ main section {
|
|||
background-color: var(--button-background-color);
|
||||
margin-block-start: var(--space-small);
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.modalOverlayOuter.active:has(.topic-selection-container) {
|
||||
background-color: rgba(21, 20, 26, 0.5);
|
||||
}
|
||||
|
||||
.topic-selection-container {
|
||||
--transition: 0.6s opacity, 0.6s scale, 0.6s rotate, 0.6s translate;
|
||||
position: relative;
|
||||
border-radius: var(--space-small);
|
||||
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.2);
|
||||
padding: var(--size-item-large);
|
||||
max-width: 745px;
|
||||
height: auto;
|
||||
}
|
||||
.topic-selection-container .dismiss-button {
|
||||
position: absolute;
|
||||
appearance: none;
|
||||
border: none;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
inset-inline: auto 0;
|
||||
border-radius: var(--border-radius-small);
|
||||
padding: 0;
|
||||
margin: var(--space-small);
|
||||
display: block;
|
||||
float: inline-end;
|
||||
background: url("chrome://global/skin/icons/close.svg") no-repeat center/16px;
|
||||
height: var(--size-item-large);
|
||||
width: var(--size-item-large);
|
||||
align-self: end;
|
||||
min-height: var(--size-item-large);
|
||||
min-width: var(--size-item-large);
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
transition: var(--transition);
|
||||
}
|
||||
.topic-selection-container .dismiss-button:hover {
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
.topic-selection-container .dismiss-button:hover:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
.topic-selection-container .title {
|
||||
text-align: center;
|
||||
font-size: var(--font-size-xlarge);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-block-end: var(--space-small);
|
||||
}
|
||||
.topic-selection-container .subtitle {
|
||||
text-align: center;
|
||||
margin-block: 0 var(--space-xlarge);
|
||||
}
|
||||
.topic-selection-container .modal-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.topic-selection-container .modal-footer .button-group {
|
||||
gap: var(--space-medium);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.topic-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--size-item-small);
|
||||
margin: var(--size-item-large) auto;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
}
|
||||
.topic-list .topic-item {
|
||||
border-radius: 40px;
|
||||
padding-inline: 6px var(--size-item-small);
|
||||
padding-block: 6px;
|
||||
border: 1px solid var(--color-gray-60);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-self: center;
|
||||
max-width: fit-content;
|
||||
}
|
||||
.topic-list .topic-item:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
.topic-list .topic-item:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
.topic-list .topic-item:has(input:checked) {
|
||||
border-color: var(--color-accent-primary);
|
||||
}
|
||||
.topic-list .topic-item:focus-within {
|
||||
outline-offset: 2px;
|
||||
outline: 2px solid var(--color-accent-primary);
|
||||
}
|
||||
.topic-list .topic-item .topic-item-label {
|
||||
margin-inline-end: var(--space-small);
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 100%;
|
||||
background-color: var(--newtab-button-static-background);
|
||||
margin-inline-end: var(--space-large);
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox .topic-icon {
|
||||
font-size: 25px;
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox .topic-checked {
|
||||
display: none;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox] {
|
||||
opacity: 0;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: absolute;
|
||||
inset-inline-start: 0.5em;
|
||||
top: 0.4em;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox {
|
||||
background-color: var(--color-accent-primary);
|
||||
position: relative;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox .topic-icon {
|
||||
display: none;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox .topic-checked {
|
||||
color: var(--color-white);
|
||||
-moz-context-properties: fill;
|
||||
display: block;
|
||||
fill: currentColor;
|
||||
background: url("chrome://global/skin/icons/check.svg");
|
||||
background-size: cover;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
|
|
@ -2955,6 +2955,16 @@ main section {
|
|||
min-height: 19px;
|
||||
margin-bottom: 13px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
@media (max-width: 609px) {
|
||||
.collapsible-section .section-top-bar {
|
||||
flex-direction: column;
|
||||
gap: var(--space-small);
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
.collapsible-section.active {
|
||||
background: var(--newtab-element-hover-color);
|
||||
|
@ -5068,10 +5078,6 @@ main section {
|
|||
.thumbs-ui-compact .top-site-outer {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
.thumbs-ui-compact .top-site-outer .top-site-inner > a {
|
||||
padding-top: var(--space-xsmall);
|
||||
padding-bottom: var(--space-xsmall);
|
||||
}
|
||||
|
||||
.ds-signup {
|
||||
max-width: 300px;
|
||||
|
@ -5434,3 +5440,143 @@ main section {
|
|||
background-color: var(--button-background-color);
|
||||
margin-block-start: var(--space-small);
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.modalOverlayOuter.active:has(.topic-selection-container) {
|
||||
background-color: rgba(21, 20, 26, 0.5);
|
||||
}
|
||||
|
||||
.topic-selection-container {
|
||||
--transition: 0.6s opacity, 0.6s scale, 0.6s rotate, 0.6s translate;
|
||||
position: relative;
|
||||
border-radius: var(--space-small);
|
||||
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.2);
|
||||
padding: var(--size-item-large);
|
||||
max-width: 745px;
|
||||
height: auto;
|
||||
}
|
||||
.topic-selection-container .dismiss-button {
|
||||
position: absolute;
|
||||
appearance: none;
|
||||
border: none;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
inset-inline: auto 0;
|
||||
border-radius: var(--border-radius-small);
|
||||
padding: 0;
|
||||
margin: var(--space-small);
|
||||
display: block;
|
||||
float: inline-end;
|
||||
background: url("chrome://global/skin/icons/close.svg") no-repeat center/16px;
|
||||
height: var(--size-item-large);
|
||||
width: var(--size-item-large);
|
||||
align-self: end;
|
||||
min-height: var(--size-item-large);
|
||||
min-width: var(--size-item-large);
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
transition: var(--transition);
|
||||
}
|
||||
.topic-selection-container .dismiss-button:hover {
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
.topic-selection-container .dismiss-button:hover:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
.topic-selection-container .title {
|
||||
text-align: center;
|
||||
font-size: var(--font-size-xlarge);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-block-end: var(--space-small);
|
||||
}
|
||||
.topic-selection-container .subtitle {
|
||||
text-align: center;
|
||||
margin-block: 0 var(--space-xlarge);
|
||||
}
|
||||
.topic-selection-container .modal-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.topic-selection-container .modal-footer .button-group {
|
||||
gap: var(--space-medium);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.topic-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--size-item-small);
|
||||
margin: var(--size-item-large) auto;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
}
|
||||
.topic-list .topic-item {
|
||||
border-radius: 40px;
|
||||
padding-inline: 6px var(--size-item-small);
|
||||
padding-block: 6px;
|
||||
border: 1px solid var(--color-gray-60);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-self: center;
|
||||
max-width: fit-content;
|
||||
}
|
||||
.topic-list .topic-item:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
.topic-list .topic-item:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
.topic-list .topic-item:has(input:checked) {
|
||||
border-color: var(--color-accent-primary);
|
||||
}
|
||||
.topic-list .topic-item:focus-within {
|
||||
outline-offset: 2px;
|
||||
outline: 2px solid var(--color-accent-primary);
|
||||
}
|
||||
.topic-list .topic-item .topic-item-label {
|
||||
margin-inline-end: var(--space-small);
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 100%;
|
||||
background-color: var(--newtab-button-static-background);
|
||||
margin-inline-end: var(--space-large);
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox .topic-icon {
|
||||
font-size: 25px;
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox .topic-checked {
|
||||
display: none;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox] {
|
||||
opacity: 0;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: absolute;
|
||||
inset-inline-start: 0.5em;
|
||||
top: 0.4em;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox {
|
||||
background-color: var(--color-accent-primary);
|
||||
position: relative;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox .topic-icon {
|
||||
display: none;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox .topic-checked {
|
||||
color: var(--color-white);
|
||||
-moz-context-properties: fill;
|
||||
display: block;
|
||||
fill: currentColor;
|
||||
background: url("chrome://global/skin/icons/check.svg");
|
||||
background-size: cover;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
|
|
@ -2951,6 +2951,16 @@ main section {
|
|||
min-height: 19px;
|
||||
margin-bottom: 13px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
@media (max-width: 609px) {
|
||||
.collapsible-section .section-top-bar {
|
||||
flex-direction: column;
|
||||
gap: var(--space-small);
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
.collapsible-section.active {
|
||||
background: var(--newtab-element-hover-color);
|
||||
|
@ -5064,10 +5074,6 @@ main section {
|
|||
.thumbs-ui-compact .top-site-outer {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
.thumbs-ui-compact .top-site-outer .top-site-inner > a {
|
||||
padding-top: var(--space-xsmall);
|
||||
padding-bottom: var(--space-xsmall);
|
||||
}
|
||||
|
||||
.ds-signup {
|
||||
max-width: 300px;
|
||||
|
@ -5430,3 +5436,143 @@ main section {
|
|||
background-color: var(--button-background-color);
|
||||
margin-block-start: var(--space-small);
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.modalOverlayOuter.active:has(.topic-selection-container) {
|
||||
background-color: rgba(21, 20, 26, 0.5);
|
||||
}
|
||||
|
||||
.topic-selection-container {
|
||||
--transition: 0.6s opacity, 0.6s scale, 0.6s rotate, 0.6s translate;
|
||||
position: relative;
|
||||
border-radius: var(--space-small);
|
||||
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.2);
|
||||
padding: var(--size-item-large);
|
||||
max-width: 745px;
|
||||
height: auto;
|
||||
}
|
||||
.topic-selection-container .dismiss-button {
|
||||
position: absolute;
|
||||
appearance: none;
|
||||
border: none;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
inset-inline: auto 0;
|
||||
border-radius: var(--border-radius-small);
|
||||
padding: 0;
|
||||
margin: var(--space-small);
|
||||
display: block;
|
||||
float: inline-end;
|
||||
background: url("chrome://global/skin/icons/close.svg") no-repeat center/16px;
|
||||
height: var(--size-item-large);
|
||||
width: var(--size-item-large);
|
||||
align-self: end;
|
||||
min-height: var(--size-item-large);
|
||||
min-width: var(--size-item-large);
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
transition: var(--transition);
|
||||
}
|
||||
.topic-selection-container .dismiss-button:hover {
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
.topic-selection-container .dismiss-button:hover:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
.topic-selection-container .title {
|
||||
text-align: center;
|
||||
font-size: var(--font-size-xlarge);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-block-end: var(--space-small);
|
||||
}
|
||||
.topic-selection-container .subtitle {
|
||||
text-align: center;
|
||||
margin-block: 0 var(--space-xlarge);
|
||||
}
|
||||
.topic-selection-container .modal-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.topic-selection-container .modal-footer .button-group {
|
||||
gap: var(--space-medium);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.topic-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--size-item-small);
|
||||
margin: var(--size-item-large) auto;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
}
|
||||
.topic-list .topic-item {
|
||||
border-radius: 40px;
|
||||
padding-inline: 6px var(--size-item-small);
|
||||
padding-block: 6px;
|
||||
border: 1px solid var(--color-gray-60);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-self: center;
|
||||
max-width: fit-content;
|
||||
}
|
||||
.topic-list .topic-item:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
.topic-list .topic-item:active {
|
||||
background-color: var(--button-background-color-active);
|
||||
}
|
||||
.topic-list .topic-item:has(input:checked) {
|
||||
border-color: var(--color-accent-primary);
|
||||
}
|
||||
.topic-list .topic-item:focus-within {
|
||||
outline-offset: 2px;
|
||||
outline: 2px solid var(--color-accent-primary);
|
||||
}
|
||||
.topic-list .topic-item .topic-item-label {
|
||||
margin-inline-end: var(--space-small);
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 100%;
|
||||
background-color: var(--newtab-button-static-background);
|
||||
margin-inline-end: var(--space-large);
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox .topic-icon {
|
||||
font-size: 25px;
|
||||
}
|
||||
.topic-list .topic-item .topic-custom-checkbox .topic-checked {
|
||||
display: none;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox] {
|
||||
opacity: 0;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: absolute;
|
||||
inset-inline-start: 0.5em;
|
||||
top: 0.4em;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox {
|
||||
background-color: var(--color-accent-primary);
|
||||
position: relative;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox .topic-icon {
|
||||
display: none;
|
||||
}
|
||||
.topic-list .topic-item input[type=checkbox]:checked ~ .topic-custom-checkbox .topic-checked {
|
||||
color: var(--color-white);
|
||||
-moz-context-properties: fill;
|
||||
display: block;
|
||||
fill: currentColor;
|
||||
background: url("chrome://global/skin/icons/check.svg");
|
||||
background-size: cover;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
|
|
@ -216,6 +216,7 @@ for (const type of [
|
|||
"SYSTEM_TICK",
|
||||
"TELEMETRY_IMPRESSION_STATS",
|
||||
"TELEMETRY_USER_EVENT",
|
||||
"TOPIC_SELECTION_SPOTLIGHT_TOGGLE",
|
||||
"TOP_SITES_CANCEL_EDIT",
|
||||
"TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL",
|
||||
"TOP_SITES_EDIT",
|
||||
|
@ -4242,6 +4243,7 @@ ErrorBoundary.defaultProps = {
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A section that can collapse. As of bug 1710937, it can no longer collapse.
|
||||
* See bug 1727365 for follow-up work to simplify this component.
|
||||
|
@ -4253,11 +4255,12 @@ class _CollapsibleSection extends (external_React_default()).PureComponent {
|
|||
this.onMenuButtonMouseEnter = this.onMenuButtonMouseEnter.bind(this);
|
||||
this.onMenuButtonMouseLeave = this.onMenuButtonMouseLeave.bind(this);
|
||||
this.onMenuUpdate = this.onMenuUpdate.bind(this);
|
||||
this.setContextMenuButtonRef = this.setContextMenuButtonRef.bind(this);
|
||||
this.handleTopicSelectionButtonClick = this.handleTopicSelectionButtonClick.bind(this);
|
||||
this.state = {
|
||||
menuButtonHover: false,
|
||||
showContextMenu: false
|
||||
};
|
||||
this.setContextMenuButtonRef = this.setContextMenuButtonRef.bind(this);
|
||||
}
|
||||
setContextMenuButtonRef(element) {
|
||||
this.contextMenuButtonRef = element;
|
||||
|
@ -4280,6 +4283,11 @@ class _CollapsibleSection extends (external_React_default()).PureComponent {
|
|||
showContextMenu
|
||||
});
|
||||
}
|
||||
handleTopicSelectionButtonClick() {
|
||||
this.props.dispatch(actionCreators.AlsoToMain({
|
||||
type: actionTypes.TOPIC_SELECTION_SPOTLIGHT_TOGGLE
|
||||
}));
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
isAnimating,
|
||||
|
@ -4313,6 +4321,7 @@ class _CollapsibleSection extends (external_React_default()).PureComponent {
|
|||
};
|
||||
}
|
||||
const hasSubtitleClassName = subTitle ? `has-subtitle` : ``;
|
||||
const topicSelectionEnabled = this.props.Prefs.values["discoverystream.topicSelection.enabled"];
|
||||
return /*#__PURE__*/external_React_default().createElement("section", {
|
||||
className: `collapsible-section ${this.props.className}${active ? " active" : ""}`
|
||||
// Note: data-section-id is used for web extension api tests in mozilla central
|
||||
|
@ -4342,7 +4351,11 @@ class _CollapsibleSection extends (external_React_default()).PureComponent {
|
|||
})), mayHaveSponsoredStories && this.props.spocMessageVariant === "variant-a" && /*#__PURE__*/external_React_default().createElement(SponsoredContentHighlight, {
|
||||
position: "inset-block-start inset-inline-start",
|
||||
dispatch: this.props.dispatch
|
||||
}))), /*#__PURE__*/external_React_default().createElement(ErrorBoundary, {
|
||||
})), topicSelectionEnabled && /*#__PURE__*/external_React_default().createElement("moz-button", {
|
||||
label: "Personalize my feed",
|
||||
type: "primary",
|
||||
onClick: this.handleTopicSelectionButtonClick
|
||||
})), /*#__PURE__*/external_React_default().createElement(ErrorBoundary, {
|
||||
className: "section-body-fallback"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
ref: this.onBodyMount,
|
||||
|
@ -4397,50 +4410,49 @@ class DSMessage extends (external_React_default()).PureComponent {
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
class ModalOverlayWrapper extends (external_React_default()).PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
function ModalOverlayWrapper({
|
||||
document = globalThis.document,
|
||||
unstyled,
|
||||
innerClassName,
|
||||
onClose,
|
||||
children,
|
||||
headerId,
|
||||
id
|
||||
}) {
|
||||
const modalRef = (0,external_React_namespaceObject.useRef)(null);
|
||||
let className = unstyled ? "" : "modalOverlayInner active";
|
||||
if (innerClassName) {
|
||||
className += ` ${innerClassName}`;
|
||||
}
|
||||
|
||||
// The intended behaviour is to listen for an escape key
|
||||
// but not for a click; see Bug 1582242
|
||||
onKeyDown(event) {
|
||||
const onKeyDown = (0,external_React_namespaceObject.useCallback)(event => {
|
||||
if (event.key === "Escape") {
|
||||
this.props.onClose(event);
|
||||
onClose(event);
|
||||
}
|
||||
}
|
||||
componentWillMount() {
|
||||
this.props.document.addEventListener("keydown", this.onKeyDown);
|
||||
this.props.document.body.classList.add("modal-open");
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.props.document.removeEventListener("keydown", this.onKeyDown);
|
||||
this.props.document.body.classList.remove("modal-open");
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
props
|
||||
} = this;
|
||||
let className = props.unstyled ? "" : "modalOverlayInner active";
|
||||
if (props.innerClassName) {
|
||||
className += ` ${props.innerClassName}`;
|
||||
}
|
||||
return /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "modalOverlayOuter active",
|
||||
onKeyDown: this.onKeyDown,
|
||||
role: "presentation"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: className,
|
||||
"aria-labelledby": props.headerId,
|
||||
id: props.id,
|
||||
role: "dialog"
|
||||
}, props.children));
|
||||
}
|
||||
}, [onClose]);
|
||||
(0,external_React_namespaceObject.useEffect)(() => {
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
document.body.classList.add("modal-open");
|
||||
return () => {
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
document.body.classList.remove("modal-open");
|
||||
};
|
||||
}, [document, onKeyDown]);
|
||||
return /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "modalOverlayOuter active",
|
||||
onKeyDown: onKeyDown,
|
||||
role: "presentation"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: className,
|
||||
"aria-labelledby": headerId,
|
||||
id: id,
|
||||
role: "dialog",
|
||||
ref: modalRef
|
||||
}, children));
|
||||
}
|
||||
ModalOverlayWrapper.defaultProps = {
|
||||
document: globalThis.document
|
||||
};
|
||||
|
||||
;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx
|
||||
/* 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,
|
||||
|
@ -5808,6 +5820,7 @@ const INITIAL_STATE = {
|
|||
recentSavesData: [],
|
||||
isUserLoggedIn: false,
|
||||
recentSavesEnabled: false,
|
||||
showTopicSelection: false,
|
||||
},
|
||||
Notifications: {
|
||||
showNotifications: false,
|
||||
|
@ -6566,6 +6579,11 @@ function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
|
|||
};
|
||||
}
|
||||
return prevState;
|
||||
case actionTypes.TOPIC_SELECTION_SPOTLIGHT_TOGGLE:
|
||||
return {
|
||||
...prevState,
|
||||
showTopicSelection: !prevState.showTopicSelection,
|
||||
};
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
|
@ -10524,6 +10542,177 @@ function Notifications_Notifications({
|
|||
}, getToast()));
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/TopicSelection/TopicSelection.jsx
|
||||
/* 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/. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: move strings to newtab.ftl once strings have been approved
|
||||
const TOPIC_LABELS = {
|
||||
"newtab-topic-business": "Business",
|
||||
"newtab-topic-arts": "Entertainment",
|
||||
"newtab-topic-food": "Food",
|
||||
"newtab-topic-health": "Health",
|
||||
"newtab-topic-finance": "Money",
|
||||
"newtab-topic-government": "Politics",
|
||||
"newtab-topic-sports": "Sports",
|
||||
"newtab-topic-tech": "Tech",
|
||||
"newtab-topic-travel": "Travel",
|
||||
"newtab-topic-education": "Science",
|
||||
"newtab-topic-society": "Life Hacks"
|
||||
};
|
||||
const EMOJI_LABELS = {
|
||||
business: "💼",
|
||||
arts: "🎭",
|
||||
food: "🍕",
|
||||
health: "🩺",
|
||||
finance: "💰",
|
||||
government: "🏛️",
|
||||
sports: "⚽️",
|
||||
tech: "💻",
|
||||
travel: "✈️",
|
||||
education: "🧪",
|
||||
society: "💡"
|
||||
};
|
||||
function TopicSelection() {
|
||||
const dispatch = (0,external_ReactRedux_namespaceObject.useDispatch)();
|
||||
const inputRef = (0,external_React_namespaceObject.useRef)(null);
|
||||
const modalRef = (0,external_React_namespaceObject.useRef)(null);
|
||||
const checkboxWrapperRef = (0,external_React_namespaceObject.useRef)(null);
|
||||
const topics = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Prefs.values["discoverystream.topicSelection.topics"]).split(", ");
|
||||
const selectedTopics = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Prefs.values["discoverystream.topicSelection.selectedTopics"]);
|
||||
const suggestedTopics = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Prefs.values["discoverystream.topicSelection.suggestedTopics"]).split(", ");
|
||||
|
||||
// TODO: only show suggested topics during the first run
|
||||
// if selectedTopics is empty - default to using the suggestedTopics as a starting value
|
||||
const [topicsToSelect, setTopicsToSelect] = (0,external_React_namespaceObject.useState)(selectedTopics ? selectedTopics.split(", ") : suggestedTopics);
|
||||
function handleModalClose() {
|
||||
dispatch(actionCreators.AlsoToMain({
|
||||
type: actionTypes.TOPIC_SELECTION_SPOTLIGHT_TOGGLE
|
||||
}));
|
||||
}
|
||||
|
||||
// when component mounts, set focus to input
|
||||
(0,external_React_namespaceObject.useEffect)(() => {
|
||||
inputRef?.current?.focus();
|
||||
}, [inputRef]);
|
||||
const handleFocus = (0,external_React_namespaceObject.useCallback)(e => {
|
||||
// this list will have to be updated with other reusable components that get used inside of this modal
|
||||
const tabbableElements = modalRef.current.querySelectorAll('a[href], button, moz-button, input[tabindex="0"]');
|
||||
const [firstTabableEl] = tabbableElements;
|
||||
const lastTabbableEl = tabbableElements[tabbableElements.length - 1];
|
||||
let isTabPressed = e.key === "Tab" || e.keyCode === 9;
|
||||
let isArrowPressed = e.key === "ArrowUp" || e.key === "ArrowDown";
|
||||
if (isTabPressed) {
|
||||
if (e.shiftKey) {
|
||||
if (document.activeElement === firstTabableEl) {
|
||||
lastTabbableEl.focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (document.activeElement === lastTabbableEl) {
|
||||
firstTabableEl.focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (isArrowPressed && checkboxWrapperRef.current.contains(document.activeElement)) {
|
||||
const checkboxElements = checkboxWrapperRef.current.querySelectorAll("input");
|
||||
const [firstInput] = checkboxElements;
|
||||
const lastInput = checkboxElements[checkboxElements.length - 1];
|
||||
const inputArr = Array.from(checkboxElements);
|
||||
const currentIndex = inputArr.indexOf(document.activeElement);
|
||||
let nextEl;
|
||||
if (e.key === "ArrowUp") {
|
||||
nextEl = document.activeElement === firstInput ? lastInput : checkboxElements[currentIndex - 1];
|
||||
} else if (e.key === "ArrowDown") {
|
||||
nextEl = document.activeElement === lastInput ? firstInput : checkboxElements[currentIndex + 1];
|
||||
}
|
||||
nextEl.tabIndex = 0;
|
||||
document.activeElement.tabIndex = -1;
|
||||
nextEl.focus();
|
||||
}
|
||||
}, []);
|
||||
(0,external_React_namespaceObject.useEffect)(() => {
|
||||
const ref = modalRef.current;
|
||||
ref.addEventListener("keydown", handleFocus);
|
||||
inputRef.current.tabIndex = 0;
|
||||
return () => {
|
||||
ref.removeEventListener("keydown", handleFocus);
|
||||
};
|
||||
}, [handleFocus]);
|
||||
function handleChange(e) {
|
||||
const topic = e.target.name;
|
||||
const isChecked = e.target.checked;
|
||||
if (isChecked) {
|
||||
setTopicsToSelect([...topicsToSelect, topic]);
|
||||
} else {
|
||||
const updatedTopics = topicsToSelect.filter(t => t !== topic);
|
||||
setTopicsToSelect(updatedTopics);
|
||||
}
|
||||
}
|
||||
function handleSubmit() {
|
||||
dispatch(actionCreators.SetPref("discoverystream.topicSelection.selectedTopics", topicsToSelect.join(", ")));
|
||||
handleModalClose();
|
||||
}
|
||||
return /*#__PURE__*/external_React_default().createElement(ModalOverlayWrapper, {
|
||||
onClose: handleModalClose,
|
||||
innerClassName: "topic-selection-container"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "topic-selection-form",
|
||||
ref: modalRef
|
||||
}, /*#__PURE__*/external_React_default().createElement("button", {
|
||||
className: "dismiss-button",
|
||||
title: "dismiss",
|
||||
onClick: handleModalClose
|
||||
}), /*#__PURE__*/external_React_default().createElement("h1", {
|
||||
className: "title"
|
||||
}, "Select topics you care about"), /*#__PURE__*/external_React_default().createElement("p", {
|
||||
className: "subtitle"
|
||||
}, "Tell us what you are interested in and we\u2019ll recommend you great stories!"), /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "topic-list",
|
||||
ref: checkboxWrapperRef
|
||||
}, topics.map((topic, i) => {
|
||||
const checked = topicsToSelect.includes(topic);
|
||||
return /*#__PURE__*/external_React_default().createElement("label", {
|
||||
className: `topic-item`,
|
||||
key: topic
|
||||
}, /*#__PURE__*/external_React_default().createElement("input", {
|
||||
type: "checkbox",
|
||||
id: topic,
|
||||
name: topic,
|
||||
ref: i === 0 ? inputRef : null,
|
||||
onChange: handleChange,
|
||||
checked: checked,
|
||||
"aria-checked": checked,
|
||||
tabIndex: -1
|
||||
}), /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: `topic-custom-checkbox`
|
||||
}, /*#__PURE__*/external_React_default().createElement("span", {
|
||||
className: "topic-icon"
|
||||
}, EMOJI_LABELS[`${topic}`]), /*#__PURE__*/external_React_default().createElement("span", {
|
||||
className: "topic-checked"
|
||||
})), /*#__PURE__*/external_React_default().createElement("span", {
|
||||
className: "topic-item-label"
|
||||
}, TOPIC_LABELS[`newtab-topic-${topic}`]));
|
||||
})), /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "modal-footer"
|
||||
}, /*#__PURE__*/external_React_default().createElement("a", {
|
||||
href: "https://support.mozilla.org/en-US/kb/pocket-recommendations-firefox-new-tab"
|
||||
}, "How we protect your data and privacy"), /*#__PURE__*/external_React_default().createElement("moz-button-group", {
|
||||
className: "button-group"
|
||||
}, /*#__PURE__*/external_React_default().createElement("moz-button", {
|
||||
label: "Remove topics",
|
||||
onClick: handleModalClose
|
||||
}), /*#__PURE__*/external_React_default().createElement("moz-button", {
|
||||
label: "Save topics",
|
||||
type: "primary",
|
||||
onClick: handleSubmit
|
||||
})))));
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/FeatureHighlight/WallpaperFeatureHighlight.jsx
|
||||
/* 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,
|
||||
|
@ -10673,6 +10862,7 @@ function Base_extends() { Base_extends = Object.assign ? Object.assign.bind() :
|
|||
|
||||
|
||||
|
||||
|
||||
const Base_VISIBLE = "visible";
|
||||
const Base_VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
||||
const Base_WALLPAPER_HIGHLIGHT_DISMISSED_PREF = "newtabWallpapers.highlightDismissed";
|
||||
|
@ -10991,7 +11181,8 @@ class BaseContent extends (external_React_default()).PureComponent {
|
|||
props
|
||||
} = this;
|
||||
const {
|
||||
App
|
||||
App,
|
||||
DiscoveryStream
|
||||
} = props;
|
||||
const {
|
||||
initialized,
|
||||
|
@ -11002,6 +11193,10 @@ class BaseContent extends (external_React_default()).PureComponent {
|
|||
const wallpapersEnabled = prefs["newtabWallpapers.enabled"];
|
||||
const wallpapersV2Enabled = prefs["newtabWallpapers.v2.enabled"];
|
||||
const weatherEnabled = prefs.showWeather;
|
||||
const {
|
||||
showTopicSelection
|
||||
} = DiscoveryStream;
|
||||
const mayShowTopicSelection = showTopicSelection && prefs["discoverystream.topicSelection.enabled"];
|
||||
const {
|
||||
pocketConfig
|
||||
} = prefs;
|
||||
|
@ -11080,7 +11275,7 @@ class BaseContent extends (external_React_default()).PureComponent {
|
|||
firstVisibleTimestamp: this.state.firstVisibleTimestamp
|
||||
})) : /*#__PURE__*/external_React_default().createElement(Sections_Sections, null)), /*#__PURE__*/external_React_default().createElement(ConfirmDialog, null), wallpapersEnabled && this.renderWallpaperAttribution()), /*#__PURE__*/external_React_default().createElement("aside", null, this.props.Notifications?.showNotifications && /*#__PURE__*/external_React_default().createElement(ErrorBoundary, null, /*#__PURE__*/external_React_default().createElement(Notifications_Notifications, {
|
||||
dispatch: this.props.dispatch
|
||||
})))));
|
||||
}))), mayShowTopicSelection && /*#__PURE__*/external_React_default().createElement(TopicSelection, null)));
|
||||
}
|
||||
}
|
||||
BaseContent.defaultProps = {
|
||||
|
|
|
@ -180,6 +180,16 @@ module.exports = function (config) {
|
|||
functions: 0,
|
||||
branches: 0,
|
||||
},
|
||||
/**
|
||||
* TopicSelection.jsx is tested via an xpcshell test
|
||||
*/
|
||||
"content-src/components/DiscoveryStreamComponents/TopicSelection/*.jsx":
|
||||
{
|
||||
statements: 0,
|
||||
lines: 0,
|
||||
functions: 0,
|
||||
branches: 0,
|
||||
},
|
||||
"content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx":
|
||||
{
|
||||
statements: 98.25,
|
||||
|
|
|
@ -533,6 +533,28 @@ export const PREFS_CONFIG = new Map([
|
|||
value: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
"discoverystream.topicSelection.topics",
|
||||
{
|
||||
title: "Topics available",
|
||||
value:
|
||||
"business, arts, food, health, finance, government, sports, tech, travel, education, society",
|
||||
},
|
||||
],
|
||||
[
|
||||
"discoverystream.topicSelection.selectedTopics",
|
||||
{
|
||||
title: "Selected topics",
|
||||
value: "",
|
||||
},
|
||||
],
|
||||
[
|
||||
"discoverystream.topicSelection.suggestedTopics",
|
||||
{
|
||||
title: "Suggested topics to choose during onboarding for topic selection",
|
||||
value: "business, arts, government",
|
||||
},
|
||||
],
|
||||
[
|
||||
"showRecentSaves",
|
||||
{
|
||||
|
|
|
@ -51,5 +51,15 @@
|
|||
type="module"
|
||||
src="chrome://global/content/elements/moz-toggle.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button-group.mjs"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -40,5 +40,15 @@
|
|||
type="module"
|
||||
src="chrome://global/content/elements/moz-toggle.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button-group.mjs"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -51,5 +51,15 @@
|
|||
type="module"
|
||||
src="chrome://global/content/elements/moz-toggle.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button.mjs"
|
||||
></script>
|
||||
<script
|
||||
async
|
||||
type="module"
|
||||
src="chrome://global/content/elements/moz-button-group.mjs"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -74,10 +74,8 @@ class TestReopenFromLibrary(WindowManagerMixin, MarionetteTestCase):
|
|||
PlacesUtils.bookmarks.virtualToolbarGuid
|
||||
);
|
||||
|
||||
// Bookmarks may be imported and shift the expected one, so search
|
||||
// for it.
|
||||
let node;
|
||||
for (let i = 1; i < window.ContentTree.view.result.root.childCount; ++i) {
|
||||
for (let i = 0; i < window.ContentTree.view.result.root.childCount; ++i) {
|
||||
node = window.ContentTree.view.view.nodeForTreeIndex(i);
|
||||
if (node.uri.endsWith("empty.html")) {
|
||||
break;
|
||||
|
|
|
@ -31,8 +31,7 @@ updateAppInfo({
|
|||
platformVersion: "",
|
||||
});
|
||||
|
||||
// Default bookmarks constants.
|
||||
const DEFAULT_BOOKMARKS_ON_TOOLBAR = 1;
|
||||
// Default bookmarks constant.
|
||||
const DEFAULT_BOOKMARKS_ON_MENU = 1;
|
||||
|
||||
var createCorruptDB = async function () {
|
||||
|
|
|
@ -36,15 +36,14 @@ add_task(async function () {
|
|||
// The test will continue once import has finished.
|
||||
await promiseTopicObserved("places-browser-init-complete");
|
||||
|
||||
// Check that default bookmarks have been restored.
|
||||
// Check that default bookmarks folder has been restored.
|
||||
let bm = await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
index: 0,
|
||||
});
|
||||
|
||||
// Bug 1283076: Nightly bookmark points to Get Involved page, not Getting Started one
|
||||
let chanTitle = AppConstants.NIGHTLY_BUILD
|
||||
? "Get Involved"
|
||||
: "Getting Started";
|
||||
Assert.equal(bm.title, chanTitle);
|
||||
? "Firefox Nightly Resources"
|
||||
: "Mozilla Firefox";
|
||||
Assert.equal(bm.title, chanTitle, "Default bookmarks folder restored.");
|
||||
});
|
||||
|
|
|
@ -127,7 +127,7 @@ add_task(async function () {
|
|||
|
||||
toolbarItem = await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: 1 + DEFAULT_BOOKMARKS_ON_TOOLBAR,
|
||||
index: 1,
|
||||
});
|
||||
Assert.equal(toolbarItem.title, "Toolbar Folder After");
|
||||
Assert.ok(
|
||||
|
|
|
@ -113,13 +113,16 @@ add_task(async function test_restore() {
|
|||
|
||||
await simulatePlacesInit();
|
||||
|
||||
// Check bookmarks.html has been restored.
|
||||
Assert.ok(
|
||||
await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: 0,
|
||||
})
|
||||
);
|
||||
// Check default-bookmarks.html has been restored.
|
||||
let bm = await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
index: 0,
|
||||
});
|
||||
|
||||
let chanTitle = AppConstants.NIGHTLY_BUILD
|
||||
? "Firefox Nightly Resources"
|
||||
: "Mozilla Firefox";
|
||||
Assert.equal(bm.title, chanTitle, "Default bookmarks folder restored.");
|
||||
|
||||
// Check preferences have been reverted.
|
||||
Assert.ok(!Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
|
||||
|
@ -147,13 +150,16 @@ add_task(async function test_restore_import() {
|
|||
|
||||
await simulatePlacesInit();
|
||||
|
||||
// Check bookmarks.html has been restored.
|
||||
Assert.ok(
|
||||
await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: 0,
|
||||
})
|
||||
);
|
||||
// Check default-bookmarks.html has been restored.
|
||||
let bm = await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
index: 0,
|
||||
});
|
||||
|
||||
let chanTitle = AppConstants.NIGHTLY_BUILD
|
||||
? "Firefox Nightly Resources"
|
||||
: "Mozilla Firefox";
|
||||
Assert.equal(bm.title, chanTitle, "Default bookmarks folder restored.");
|
||||
|
||||
// Check preferences have been reverted.
|
||||
Assert.ok(!Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
|
||||
|
|
|
@ -1255,6 +1255,22 @@ var gPrivacyPane = {
|
|||
document.querySelector("menuitem[value='dontremember']").hidden = true;
|
||||
}
|
||||
|
||||
let privateBrowsingPref = Preferences.get(
|
||||
"browser.privatebrowsing.autostart"
|
||||
);
|
||||
|
||||
if (privateBrowsingPref.locked) {
|
||||
// If permanent private browsing mode is locked to off,
|
||||
// disable the "Never Remember History" option
|
||||
document.querySelector("menuitem[value='dontremember']").disabled =
|
||||
!privateBrowsingPref.value;
|
||||
|
||||
// If we're locked in permanent private browsing mode,
|
||||
// disable the dropdown menu completely
|
||||
document.getElementById("historyMode").disabled =
|
||||
privateBrowsingPref.value;
|
||||
}
|
||||
|
||||
/* init HTTPS-Only mode */
|
||||
this.initHttpsOnly();
|
||||
|
||||
|
|
|
@ -215,10 +215,6 @@ skip-if = ["true"]
|
|||
["browser_searchChangedEngine.js"]
|
||||
|
||||
["browser_searchDefaultEngine.js"]
|
||||
support-files = [
|
||||
"engine1/manifest.json",
|
||||
"engine2/manifest.json",
|
||||
]
|
||||
|
||||
["browser_searchFindMoreLink.js"]
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"name": "engine1",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "engine1@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"description": "A small test engine",
|
||||
"icons": {
|
||||
"16": "favicon.ico"
|
||||
},
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "engine1",
|
||||
"search_url": "https://1.example.com/search",
|
||||
"params": [
|
||||
{
|
||||
"name": "q",
|
||||
"value": "{searchTerms}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"name": "engine2",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "engine2@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"description": "A small test engine",
|
||||
"icons": {
|
||||
"16": "favicon.ico"
|
||||
},
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "engine2",
|
||||
"search_url": "https://2.example.com/search",
|
||||
"params": [
|
||||
{
|
||||
"name": "q",
|
||||
"value": "{searchTerms}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,10 +46,6 @@ support-files = [
|
|||
["browser_contextmenu_whereToOpenLink.js"]
|
||||
|
||||
["browser_defaultPrivate_nimbus.js"]
|
||||
support-files = [
|
||||
"search-engines/basic/manifest.json",
|
||||
"search-engines/private/manifest.json",
|
||||
]
|
||||
|
||||
["browser_google_behavior.js"]
|
||||
|
||||
|
|
|
@ -13,24 +13,6 @@ ChromeUtils.defineESModuleGetters(this, {
|
|||
SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs",
|
||||
});
|
||||
|
||||
const CONFIG_DEFAULT = [
|
||||
{
|
||||
webExtension: { id: "basic@search.mozilla.org" },
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
{
|
||||
webExtension: { id: "private@search.mozilla.org" },
|
||||
appliesTo: [
|
||||
{
|
||||
experiment: "testing",
|
||||
included: { everywhere: true },
|
||||
},
|
||||
],
|
||||
defaultPrivate: "yes",
|
||||
},
|
||||
];
|
||||
|
||||
const CONFIG_V2 = [
|
||||
{
|
||||
recordType: "engine",
|
||||
|
@ -75,11 +57,6 @@ const CONFIG_V2 = [
|
|||
SearchTestUtils.init(this);
|
||||
|
||||
add_setup(async () => {
|
||||
// Use engines in test directory
|
||||
let searchExtensions = getChromeDir(getResolvedURI(gTestPath));
|
||||
searchExtensions.append("search-engines");
|
||||
await SearchTestUtils.useMochitestEngines(searchExtensions);
|
||||
|
||||
// Current default values.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
|
@ -91,9 +68,7 @@ add_setup(async () => {
|
|||
});
|
||||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(
|
||||
SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
|
||||
);
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_V2);
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
let settingsWritten = SearchTestUtils.promiseSearchNotification(
|
||||
|
|
|
@ -2,21 +2,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/. */
|
||||
|
||||
const CONFIG_DEFAULT = [
|
||||
{
|
||||
webExtension: { id: "basic@search.mozilla.org" },
|
||||
urls: {
|
||||
trending: {
|
||||
fullPath:
|
||||
"https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs?richsuggestions=true",
|
||||
query: "",
|
||||
},
|
||||
},
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
];
|
||||
|
||||
const CONFIG_V2 = [
|
||||
{
|
||||
recordType: "engine",
|
||||
|
@ -72,11 +57,6 @@ const CONFIG_V2 = [
|
|||
SearchTestUtils.init(this);
|
||||
|
||||
add_setup(async () => {
|
||||
// Use engines in test directory
|
||||
let searchExtensions = getChromeDir(getResolvedURI(gTestPath));
|
||||
searchExtensions.append("search-engines");
|
||||
await SearchTestUtils.useMochitestEngines(searchExtensions);
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.urlbar.recentsearches.featureGate", false],
|
||||
|
@ -87,9 +67,7 @@ add_setup(async () => {
|
|||
});
|
||||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(
|
||||
SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
|
||||
);
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_V2);
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
let settingsWritten = SearchTestUtils.promiseSearchNotification(
|
||||
|
|
|
@ -22,26 +22,15 @@ const SEARCH_ENGINE_DETAILS = [
|
|||
},
|
||||
{
|
||||
alias: "b",
|
||||
baseURL: SearchUtils.newSearchConfigEnabled
|
||||
? `https://www.bing.com/search?pc=${
|
||||
SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "MOZR" : "MOZI"
|
||||
}&{code}q=foo`
|
||||
: `https://www.bing.com/search?{code}pc=${
|
||||
SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "MOZR" : "MOZI"
|
||||
}&q=foo`,
|
||||
codes: SearchUtils.newSearchConfigEnabled
|
||||
? {
|
||||
context: "form=MOZLBR&",
|
||||
keyword: "form=MOZLBR&",
|
||||
newTab: "form=MOZLBR&",
|
||||
submission: "form=MOZLBR&",
|
||||
}
|
||||
: {
|
||||
context: "form=MOZCON&",
|
||||
keyword: "form=MOZLBR&",
|
||||
newTab: "form=MOZTSB&",
|
||||
submission: "form=MOZSBR&",
|
||||
},
|
||||
baseURL: `https://www.bing.com/search?pc=${
|
||||
SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "MOZR" : "MOZI"
|
||||
}&{code}q=foo`,
|
||||
codes: {
|
||||
context: "form=MOZLBR&",
|
||||
keyword: "form=MOZLBR&",
|
||||
newTab: "form=MOZLBR&",
|
||||
submission: "form=MOZLBR&",
|
||||
},
|
||||
name: "Bing",
|
||||
},
|
||||
{
|
||||
|
|
|
@ -2,26 +2,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/. */
|
||||
|
||||
const CONFIG_DEFAULT = [
|
||||
{
|
||||
webExtension: { id: "basic@search.mozilla.org" },
|
||||
urls: {
|
||||
trending: {
|
||||
fullPath:
|
||||
"https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
query: "",
|
||||
},
|
||||
},
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
{
|
||||
webExtension: { id: "private@search.mozilla.org" },
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
];
|
||||
|
||||
const CONFIG_V2 = [
|
||||
{
|
||||
recordType: "engine",
|
||||
|
@ -84,11 +64,6 @@ const CONFIG_V2 = [
|
|||
SearchTestUtils.init(this);
|
||||
|
||||
add_setup(async () => {
|
||||
// Use engines in test directory
|
||||
let searchExtensions = getChromeDir(getResolvedURI(gTestPath));
|
||||
searchExtensions.append("search-engines");
|
||||
await SearchTestUtils.useMochitestEngines(searchExtensions);
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.urlbar.recentsearches.featureGate", false],
|
||||
|
@ -98,9 +73,7 @@ add_setup(async () => {
|
|||
});
|
||||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(
|
||||
SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
|
||||
);
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_V2);
|
||||
Services.telemetry.clearScalars();
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"name": "basic",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"description": "basic",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "basic@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "basic",
|
||||
"keyword": "@basic",
|
||||
"search_url": "https://mochi.test:8888/browser/browser/components/search/test/browser/?search={searchTerms}&foo=1",
|
||||
"suggest_url": "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs?richsuggestions=true&query={searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"name": "private",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"description": "A test private engine",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "private@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "private",
|
||||
"keyword": "@private",
|
||||
"search_url": "https://example.com",
|
||||
"suggest_url": "https://example.com?search={searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -247,6 +247,15 @@ var SidebarController = {
|
|||
this._switcherTarget = document.getElementById("sidebar-switcher-target");
|
||||
this._switcherArrow = document.getElementById("sidebar-switcher-arrow");
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"browser.tabs.allow_transparent_browser",
|
||||
false
|
||||
)
|
||||
) {
|
||||
this.browser.setAttribute("transparent", "true");
|
||||
}
|
||||
|
||||
const menubar = document.getElementById("viewSidebarMenu");
|
||||
for (const [commandID, sidebar] of this.sidebars.entries()) {
|
||||
if (
|
||||
|
|
|
@ -25,6 +25,17 @@ add_task(async function test() {
|
|||
ok(!tab5.multiselected, "Tab5 is not multiselected");
|
||||
is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs");
|
||||
|
||||
info("Adding a bookmark to the bookmarks toolbar.");
|
||||
let addedBookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Test",
|
||||
url: "https://example.com",
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.remove(addedBookmark);
|
||||
});
|
||||
|
||||
// Use getElementsByClassName so the list is live and will update as items change.
|
||||
let currentBookmarks =
|
||||
bookmarksToolbar.getElementsByClassName("bookmark-item");
|
||||
|
|
|
@ -26,6 +26,17 @@ async function expectHeightChanges(tab, expectedNewHeightChanges, msg) {
|
|||
}
|
||||
|
||||
async function expectBmToolbarVisibilityChange(triggerFn, visible, msg) {
|
||||
info("Adding a bookmark to the bookmarks toolbar.");
|
||||
let addedBookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Test",
|
||||
url: "https://example.com",
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.remove(addedBookmark);
|
||||
});
|
||||
|
||||
let collapsedState = BrowserTestUtils.waitForMutationCondition(
|
||||
BookmarkingUI.toolbar,
|
||||
{ attributes: true, attributeFilter: ["collapsed"] },
|
||||
|
|
|
@ -15,6 +15,8 @@ skip-if = ["os == 'linux'"]
|
|||
|
||||
["browser_browserGlue_upgradeDialog_trigger.js"]
|
||||
|
||||
["browser_browserGlue_userNamespacesNotification.js"]
|
||||
|
||||
["browser_bug538331.js"]
|
||||
skip-if = ["!updater"]
|
||||
reason = "test depends on update channel"
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const kCID = "@mozilla.org/browser/browserglue;1";
|
||||
const BrowserGlue = Cc[kCID].getService(Ci.nsISupports).wrappedJSObject;
|
||||
|
||||
const kNotificationSelector =
|
||||
'notification-message[message-bar-type="infobar"]' +
|
||||
'[value="sandbox-unprivileged-namespaces"]';
|
||||
|
||||
function closeExistingNotification() {
|
||||
const notification = document.querySelector(kNotificationSelector);
|
||||
if (notification) {
|
||||
notification.remove();
|
||||
}
|
||||
Assert.equal(
|
||||
null,
|
||||
document.querySelector(kNotificationSelector),
|
||||
"No more notification"
|
||||
);
|
||||
}
|
||||
|
||||
function setHasUsernamespaces(isPresent) {
|
||||
Services.sysinfo
|
||||
.QueryInterface(Ci.nsIWritablePropertyBag2)
|
||||
.setPropertyAsBool("hasUserNamespaces", isPresent);
|
||||
}
|
||||
|
||||
async function getNotification(shouldBeNull = false) {
|
||||
await TestUtils.waitForCondition(() => {
|
||||
if (shouldBeNull) {
|
||||
return document.querySelector(kNotificationSelector) === null;
|
||||
}
|
||||
return document.querySelector(kNotificationSelector) !== null;
|
||||
}, "Trying to get a notification");
|
||||
return document.querySelector(kNotificationSelector);
|
||||
}
|
||||
|
||||
if (AppConstants.platform === "linux" && AppConstants.MOZ_SANDBOX) {
|
||||
add_setup(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["security.sandbox.warn_unprivileged_namespaces", true]],
|
||||
});
|
||||
closeExistingNotification();
|
||||
const originalValue = Services.sysinfo.getProperty("hasUserNamespaces");
|
||||
registerCleanupFunction(() => {
|
||||
Services.sysinfo
|
||||
.QueryInterface(Ci.nsIWritablePropertyBag2)
|
||||
.setPropertyAsBool("hasUserNamespaces", originalValue);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function doNotShowNotificationCorrectly() {
|
||||
Assert.equal(
|
||||
null,
|
||||
document.querySelector(kNotificationSelector),
|
||||
"No existing notification"
|
||||
);
|
||||
setHasUsernamespaces(true);
|
||||
BrowserGlue._verifySandboxUserNamespaces(window);
|
||||
|
||||
const notification = await getNotification(/* shouldBeNull */ true);
|
||||
Assert.equal(
|
||||
null,
|
||||
notification,
|
||||
"Notification is not shown when the feature is supported"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function showNotificationCorrectly() {
|
||||
Assert.equal(
|
||||
null,
|
||||
document.querySelector(kNotificationSelector),
|
||||
"No existing notification"
|
||||
);
|
||||
setHasUsernamespaces(false);
|
||||
BrowserGlue._verifySandboxUserNamespaces(window);
|
||||
|
||||
const notification = await getNotification();
|
||||
Assert.notEqual(
|
||||
null,
|
||||
notification,
|
||||
"Notification is shown when the feature is not supported"
|
||||
);
|
||||
closeExistingNotification();
|
||||
});
|
||||
|
||||
add_task(async function prefDisablesNotification() {
|
||||
Assert.equal(
|
||||
null,
|
||||
document.querySelector(kNotificationSelector),
|
||||
"No existing notification"
|
||||
);
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["security.sandbox.warn_unprivileged_namespaces", false]],
|
||||
});
|
||||
setHasUsernamespaces(false);
|
||||
BrowserGlue._verifySandboxUserNamespaces(window);
|
||||
|
||||
const notification = await getNotification(/* shouldBeNull */ true);
|
||||
Assert.equal(
|
||||
null,
|
||||
notification,
|
||||
"Notification is not shown when the feature is unsupported but pref disabled"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function dontShowAgainTogglePref() {
|
||||
Assert.equal(
|
||||
null,
|
||||
document.querySelector(kNotificationSelector),
|
||||
"No existing notification"
|
||||
);
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["security.sandbox.warn_unprivileged_namespaces", true]],
|
||||
});
|
||||
|
||||
Assert.equal(
|
||||
Services.prefs.getBoolPref(
|
||||
"security.sandbox.warn_unprivileged_namespaces"
|
||||
),
|
||||
true,
|
||||
"Pref is enabled"
|
||||
);
|
||||
setHasUsernamespaces(false);
|
||||
BrowserGlue._verifySandboxUserNamespaces(window);
|
||||
|
||||
const notification = await getNotification();
|
||||
const dontShowAgain = notification.querySelector(".notification-button");
|
||||
Assert.notEqual(null, dontShowAgain, "Found dismiss for ever button");
|
||||
|
||||
dontShowAgain.click();
|
||||
Assert.equal(
|
||||
Services.prefs.getBoolPref(
|
||||
"security.sandbox.warn_unprivileged_namespaces"
|
||||
),
|
||||
false,
|
||||
"Pref is disabled"
|
||||
);
|
||||
});
|
||||
} else {
|
||||
add_task(async function doNotShowNotificationCorrectly() {
|
||||
Assert.equal(
|
||||
null,
|
||||
document.querySelector(kNotificationSelector),
|
||||
"No existing notification"
|
||||
);
|
||||
BrowserGlue._verifySandboxUserNamespaces(window);
|
||||
const notification = await getNotification(/* shouldBeNull */ true);
|
||||
Assert.equal(null, notification, "Notification is not shown on non linux");
|
||||
});
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import { BaseFeature } from "resource:///modules/urlbar/private/BaseFeature.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -240,6 +241,7 @@ export class SuggestBackendRust extends BaseFeature {
|
|||
|
||||
let builder = lazy.SuggestStoreBuilder.init()
|
||||
.dataPath(this.#storeDataPath)
|
||||
.loadExtension(AppConstants.SQLITE_LIBRARY_FILENAME, "sqlite3_fts5_init")
|
||||
.remoteSettingsServer(this.#remoteSettingsServer)
|
||||
.remoteSettingsBucketName(this.#remoteSettingsBucketName);
|
||||
try {
|
||||
|
|
|
@ -377,7 +377,6 @@ support-files = [
|
|||
["browser_raceWithTabs.js"]
|
||||
|
||||
["browser_recentsearches.js"]
|
||||
support-files = ["search-engines"]
|
||||
|
||||
["browser_redirect_error.js"]
|
||||
support-files = ["redirect_error.sjs"]
|
||||
|
@ -501,7 +500,7 @@ support-files = [
|
|||
["browser_search_bookmarks_from_bookmarks_menu.js"]
|
||||
|
||||
["browser_search_continuation.js"]
|
||||
support-files = ["search-engines", "../../../search/test/browser/trendingSuggestionEngine.sjs"]
|
||||
support-files = ["../../../search/test/browser/trendingSuggestionEngine.sjs"]
|
||||
|
||||
["browser_search_history_from_history_panel.js"]
|
||||
|
||||
|
|
|
@ -2,21 +2,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/. */
|
||||
|
||||
const CONFIG_DEFAULT = [
|
||||
{
|
||||
webExtension: { id: "basic@search.mozilla.org" },
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
urls: {
|
||||
trending: {
|
||||
fullPath:
|
||||
"https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
query: "",
|
||||
},
|
||||
},
|
||||
default: "yes",
|
||||
},
|
||||
];
|
||||
|
||||
const CONFIG_DEFAULT_V2 = [
|
||||
{
|
||||
recordType: "engine",
|
||||
|
@ -60,11 +45,6 @@ const TOP_SITES = [
|
|||
SearchTestUtils.init(this);
|
||||
|
||||
add_setup(async () => {
|
||||
// Use engines in test directory
|
||||
let searchExtensions = getChromeDir(getResolvedURI(gTestPath));
|
||||
searchExtensions.append("search-engines");
|
||||
await SearchTestUtils.useMochitestEngines(searchExtensions);
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.urlbar.suggest.searches", true],
|
||||
|
@ -80,9 +60,7 @@ add_setup(async () => {
|
|||
});
|
||||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(
|
||||
SearchUtils.newSearchConfigEnabled ? CONFIG_DEFAULT_V2 : CONFIG_DEFAULT
|
||||
);
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT_V2);
|
||||
Services.telemetry.clearScalars();
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
|
|
|
@ -6,21 +6,6 @@
|
|||
* Tests how trending and recent searches work together.
|
||||
*/
|
||||
|
||||
const CONFIG_DEFAULT = [
|
||||
{
|
||||
webExtension: { id: "basic@search.mozilla.org" },
|
||||
urls: {
|
||||
trending: {
|
||||
fullPath:
|
||||
"https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
query: "",
|
||||
},
|
||||
},
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
];
|
||||
|
||||
const CONFIG_V2 = [
|
||||
{
|
||||
recordType: "engine",
|
||||
|
@ -98,13 +83,16 @@ add_setup(async () => {
|
|||
});
|
||||
|
||||
await UrlbarTestUtils.formHistory.clear();
|
||||
await SearchTestUtils.setupTestEngines(
|
||||
"search-engines",
|
||||
SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
|
||||
);
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_V2);
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await UrlbarTestUtils.formHistory.clear();
|
||||
let settingsWritten = SearchTestUtils.promiseSearchNotification(
|
||||
"write-settings-to-disk-complete"
|
||||
);
|
||||
await SearchTestUtils.updateRemoteSettingsConfig();
|
||||
await settingsWritten;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"name": "basic",
|
||||
"manifest_version": 2,
|
||||
"version": "1.0",
|
||||
"description": "basic",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "basic@search.mozilla.org"
|
||||
}
|
||||
},
|
||||
"hidden": true,
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "basic",
|
||||
"keyword": "@basic",
|
||||
"search_url": "https://example.com/?search={searchTerms}&foo=1",
|
||||
"suggest_url": "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs?richsuggestions=true&query={searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -672,76 +672,47 @@ add_task(async function selected_result_trending() {
|
|||
});
|
||||
|
||||
let defaultEngine = await Services.search.getDefault();
|
||||
let extension;
|
||||
if (!SearchUtils.newSearchConfigEnabled) {
|
||||
extension = await SearchTestUtils.installSearchExtension(
|
||||
{
|
||||
name: "mozengine",
|
||||
search_url: "https://example.org/",
|
||||
},
|
||||
{ setAsDefault: true, skipUnload: true }
|
||||
);
|
||||
}
|
||||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(
|
||||
SearchUtils.newSearchConfigEnabled
|
||||
? [
|
||||
{
|
||||
recordType: "engine",
|
||||
identifier: "mozengine",
|
||||
base: {
|
||||
name: "mozengine",
|
||||
urls: {
|
||||
search: {
|
||||
base: "https://example.org/",
|
||||
searchTermParamName: "q",
|
||||
},
|
||||
trending: {
|
||||
base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
method: "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: [
|
||||
{
|
||||
environment: { allRegionsAndLocales: true },
|
||||
},
|
||||
],
|
||||
await SearchTestUtils.updateRemoteSettingsConfig([
|
||||
{
|
||||
recordType: "engine",
|
||||
identifier: "mozengine",
|
||||
base: {
|
||||
name: "mozengine",
|
||||
urls: {
|
||||
search: {
|
||||
base: "https://example.org/",
|
||||
searchTermParamName: "q",
|
||||
},
|
||||
{
|
||||
recordType: "defaultEngines",
|
||||
globalDefault: "mozengine",
|
||||
specificDefaults: [],
|
||||
trending: {
|
||||
base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
recordType: "engineOrders",
|
||||
orders: [],
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
webExtension: { id: "mozengine@tests.mozilla.org" },
|
||||
urls: {
|
||||
trending: {
|
||||
fullPath:
|
||||
"https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
query: "",
|
||||
},
|
||||
},
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
]
|
||||
);
|
||||
},
|
||||
},
|
||||
variants: [
|
||||
{
|
||||
environment: { allRegionsAndLocales: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
recordType: "defaultEngines",
|
||||
globalDefault: "mozengine",
|
||||
specificDefaults: [],
|
||||
},
|
||||
{
|
||||
recordType: "engineOrders",
|
||||
orders: [],
|
||||
},
|
||||
]);
|
||||
|
||||
if (SearchUtils.newSearchConfigEnabled) {
|
||||
let engine = Services.search.getEngineByName("mozengine");
|
||||
await Services.search.setDefault(
|
||||
engine,
|
||||
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
|
||||
);
|
||||
}
|
||||
let engine = Services.search.getEngineByName("mozengine");
|
||||
await Services.search.setDefault(
|
||||
engine,
|
||||
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
|
||||
);
|
||||
|
||||
await doTest(async () => {
|
||||
await openPopup("");
|
||||
|
@ -758,12 +729,7 @@ add_task(async function selected_result_trending() {
|
|||
]);
|
||||
});
|
||||
|
||||
if (SearchUtils.newSearchConfigEnabled) {
|
||||
let engine = Services.search.getEngineByName("mozengine");
|
||||
await Services.search.removeEngine(engine);
|
||||
} else {
|
||||
await extension.unload();
|
||||
}
|
||||
await Services.search.removeEngine(engine);
|
||||
|
||||
await Services.search.setDefault(
|
||||
defaultEngine,
|
||||
|
@ -791,82 +757,53 @@ add_task(async function selected_result_trending_rich() {
|
|||
});
|
||||
|
||||
let defaultEngine = await Services.search.getDefault();
|
||||
let extension;
|
||||
if (!SearchUtils.newSearchConfigEnabled) {
|
||||
extension = await SearchTestUtils.installSearchExtension(
|
||||
{
|
||||
name: "mozengine",
|
||||
search_url: "https://example.org/",
|
||||
},
|
||||
{ setAsDefault: true, skipUnload: true }
|
||||
);
|
||||
}
|
||||
|
||||
SearchTestUtils.useMockIdleService();
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(
|
||||
SearchUtils.newSearchConfigEnabled
|
||||
? [
|
||||
{
|
||||
recordType: "engine",
|
||||
identifier: "mozengine",
|
||||
base: {
|
||||
name: "mozengine",
|
||||
urls: {
|
||||
search: {
|
||||
base: "https://example.org/",
|
||||
searchTermParamName: "q",
|
||||
},
|
||||
trending: {
|
||||
base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
method: "GET",
|
||||
params: [
|
||||
{
|
||||
name: "richsuggestions",
|
||||
value: "true",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: [
|
||||
await SearchTestUtils.updateRemoteSettingsConfig([
|
||||
{
|
||||
recordType: "engine",
|
||||
identifier: "mozengine",
|
||||
base: {
|
||||
name: "mozengine",
|
||||
urls: {
|
||||
search: {
|
||||
base: "https://example.org/",
|
||||
searchTermParamName: "q",
|
||||
},
|
||||
trending: {
|
||||
base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
|
||||
method: "GET",
|
||||
params: [
|
||||
{
|
||||
environment: { allRegionsAndLocales: true },
|
||||
name: "richsuggestions",
|
||||
value: "true",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
recordType: "defaultEngines",
|
||||
globalDefault: "mozengine",
|
||||
specificDefaults: [],
|
||||
},
|
||||
{
|
||||
recordType: "engineOrders",
|
||||
orders: [],
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
webExtension: { id: "mozengine@tests.mozilla.org" },
|
||||
urls: {
|
||||
trending: {
|
||||
fullPath:
|
||||
"https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs?richsuggestions=true",
|
||||
query: "",
|
||||
},
|
||||
},
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
default: "yes",
|
||||
},
|
||||
]
|
||||
);
|
||||
},
|
||||
},
|
||||
variants: [
|
||||
{
|
||||
environment: { allRegionsAndLocales: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
recordType: "defaultEngines",
|
||||
globalDefault: "mozengine",
|
||||
specificDefaults: [],
|
||||
},
|
||||
{
|
||||
recordType: "engineOrders",
|
||||
orders: [],
|
||||
},
|
||||
]);
|
||||
|
||||
if (SearchUtils.newSearchConfigEnabled) {
|
||||
let engine = Services.search.getEngineByName("mozengine");
|
||||
await Services.search.setDefault(
|
||||
engine,
|
||||
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
|
||||
);
|
||||
}
|
||||
let engine = Services.search.getEngineByName("mozengine");
|
||||
await Services.search.setDefault(
|
||||
engine,
|
||||
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
|
||||
);
|
||||
|
||||
await doTest(async () => {
|
||||
await openPopup("");
|
||||
|
@ -883,12 +820,7 @@ add_task(async function selected_result_trending_rich() {
|
|||
]);
|
||||
});
|
||||
|
||||
if (SearchUtils.newSearchConfigEnabled) {
|
||||
let engine = Services.search.getEngineByName("mozengine");
|
||||
await Services.search.removeEngine(engine);
|
||||
} else {
|
||||
await extension.unload();
|
||||
}
|
||||
await Services.search.removeEngine(engine);
|
||||
|
||||
await Services.search.setDefault(
|
||||
defaultEngine,
|
||||
|
|
|
@ -110,6 +110,7 @@ restore-from-backup-password-description = This unlocks your encrypted backup.
|
|||
|
||||
restore-from-backup-cancel-button = Cancel
|
||||
restore-from-backup-confirm-button = Restore and restart
|
||||
restore-from-backup-restoring-button = Restoring…
|
||||
|
||||
## These strings are displayed in a modal when users want to enable encryption or change the password for an existing backup.
|
||||
|
||||
|
|
|
@ -205,6 +205,8 @@ policy-PopupBlocking = Allow certain websites to display popups by default.
|
|||
|
||||
policy-Preferences = Set and lock the value for a subset of preferences.
|
||||
|
||||
policy-PrivateBrowsingModeAvailability = Set availability of private browsing mode.
|
||||
|
||||
policy-PromptForDownloadLocation = Ask where to save files when downloading.
|
||||
|
||||
policy-Proxy = Configure proxy settings.
|
||||
|
|
|
@ -9,12 +9,6 @@
|
|||
default-bookmarks-title = Bookmarks
|
||||
default-bookmarks-heading = Bookmarks
|
||||
|
||||
default-bookmarks-toolbarfolder = Bookmarks Toolbar Folder
|
||||
default-bookmarks-toolbarfolder-description = Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar
|
||||
|
||||
# link title for https://www.mozilla.org/firefox/central/
|
||||
default-bookmarks-getting-started = Getting Started
|
||||
|
||||
# Firefox links folder name
|
||||
default-bookmarks-firefox-heading = Mozilla Firefox
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"af": {
|
||||
"pin": false,
|
||||
|
@ -35,7 +35,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"an": {
|
||||
"pin": false,
|
||||
|
@ -54,7 +54,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ar": {
|
||||
"pin": false,
|
||||
|
@ -73,7 +73,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ast": {
|
||||
"pin": false,
|
||||
|
@ -92,7 +92,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"az": {
|
||||
"pin": false,
|
||||
|
@ -111,7 +111,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"be": {
|
||||
"pin": false,
|
||||
|
@ -130,7 +130,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"bg": {
|
||||
"pin": false,
|
||||
|
@ -149,7 +149,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"bn": {
|
||||
"pin": false,
|
||||
|
@ -168,7 +168,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"bo": {
|
||||
"pin": false,
|
||||
|
@ -187,7 +187,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"br": {
|
||||
"pin": false,
|
||||
|
@ -206,7 +206,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"brx": {
|
||||
"pin": false,
|
||||
|
@ -225,7 +225,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"bs": {
|
||||
"pin": false,
|
||||
|
@ -244,7 +244,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ca": {
|
||||
"pin": false,
|
||||
|
@ -263,7 +263,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ca-valencia": {
|
||||
"pin": false,
|
||||
|
@ -282,7 +282,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"cak": {
|
||||
"pin": false,
|
||||
|
@ -301,7 +301,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ckb": {
|
||||
"pin": false,
|
||||
|
@ -320,7 +320,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"cs": {
|
||||
"pin": false,
|
||||
|
@ -339,7 +339,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"cy": {
|
||||
"pin": false,
|
||||
|
@ -358,7 +358,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"da": {
|
||||
"pin": false,
|
||||
|
@ -377,7 +377,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"de": {
|
||||
"pin": false,
|
||||
|
@ -396,7 +396,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"dsb": {
|
||||
"pin": false,
|
||||
|
@ -415,7 +415,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"el": {
|
||||
"pin": false,
|
||||
|
@ -434,7 +434,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"en-CA": {
|
||||
"pin": false,
|
||||
|
@ -453,7 +453,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"en-GB": {
|
||||
"pin": false,
|
||||
|
@ -472,7 +472,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"eo": {
|
||||
"pin": false,
|
||||
|
@ -491,7 +491,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"es-AR": {
|
||||
"pin": false,
|
||||
|
@ -510,7 +510,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"es-CL": {
|
||||
"pin": false,
|
||||
|
@ -529,7 +529,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"es-ES": {
|
||||
"pin": false,
|
||||
|
@ -548,7 +548,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"es-MX": {
|
||||
"pin": false,
|
||||
|
@ -567,7 +567,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"et": {
|
||||
"pin": false,
|
||||
|
@ -586,7 +586,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"eu": {
|
||||
"pin": false,
|
||||
|
@ -605,7 +605,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"fa": {
|
||||
"pin": false,
|
||||
|
@ -624,7 +624,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ff": {
|
||||
"pin": false,
|
||||
|
@ -643,7 +643,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"fi": {
|
||||
"pin": false,
|
||||
|
@ -662,7 +662,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"fr": {
|
||||
"pin": false,
|
||||
|
@ -681,7 +681,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"fur": {
|
||||
"pin": false,
|
||||
|
@ -700,7 +700,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"fy-NL": {
|
||||
"pin": false,
|
||||
|
@ -719,7 +719,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ga-IE": {
|
||||
"pin": false,
|
||||
|
@ -738,7 +738,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"gd": {
|
||||
"pin": false,
|
||||
|
@ -757,7 +757,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"gl": {
|
||||
"pin": false,
|
||||
|
@ -776,7 +776,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"gn": {
|
||||
"pin": false,
|
||||
|
@ -795,7 +795,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"gu-IN": {
|
||||
"pin": false,
|
||||
|
@ -814,7 +814,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"he": {
|
||||
"pin": false,
|
||||
|
@ -833,7 +833,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"hi-IN": {
|
||||
"pin": false,
|
||||
|
@ -852,7 +852,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"hr": {
|
||||
"pin": false,
|
||||
|
@ -871,7 +871,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"hsb": {
|
||||
"pin": false,
|
||||
|
@ -890,7 +890,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"hu": {
|
||||
"pin": false,
|
||||
|
@ -909,7 +909,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"hy-AM": {
|
||||
"pin": false,
|
||||
|
@ -928,7 +928,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"hye": {
|
||||
"pin": false,
|
||||
|
@ -947,7 +947,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ia": {
|
||||
"pin": false,
|
||||
|
@ -966,7 +966,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"id": {
|
||||
"pin": false,
|
||||
|
@ -985,7 +985,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"is": {
|
||||
"pin": false,
|
||||
|
@ -1004,7 +1004,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"it": {
|
||||
"pin": false,
|
||||
|
@ -1023,7 +1023,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ja": {
|
||||
"pin": false,
|
||||
|
@ -1040,7 +1040,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ja-JP-mac": {
|
||||
"pin": false,
|
||||
|
@ -1048,7 +1048,7 @@
|
|||
"macosx64",
|
||||
"macosx64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ka": {
|
||||
"pin": false,
|
||||
|
@ -1067,7 +1067,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"kab": {
|
||||
"pin": false,
|
||||
|
@ -1086,7 +1086,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"kk": {
|
||||
"pin": false,
|
||||
|
@ -1105,7 +1105,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"km": {
|
||||
"pin": false,
|
||||
|
@ -1124,7 +1124,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"kn": {
|
||||
"pin": false,
|
||||
|
@ -1143,7 +1143,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ko": {
|
||||
"pin": false,
|
||||
|
@ -1162,7 +1162,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"lij": {
|
||||
"pin": false,
|
||||
|
@ -1181,7 +1181,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"lo": {
|
||||
"pin": false,
|
||||
|
@ -1200,7 +1200,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"lt": {
|
||||
"pin": false,
|
||||
|
@ -1219,7 +1219,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ltg": {
|
||||
"pin": false,
|
||||
|
@ -1238,7 +1238,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"lv": {
|
||||
"pin": false,
|
||||
|
@ -1257,7 +1257,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"meh": {
|
||||
"pin": false,
|
||||
|
@ -1276,7 +1276,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"mk": {
|
||||
"pin": false,
|
||||
|
@ -1295,7 +1295,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"mr": {
|
||||
"pin": false,
|
||||
|
@ -1314,7 +1314,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ms": {
|
||||
"pin": false,
|
||||
|
@ -1333,7 +1333,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"my": {
|
||||
"pin": false,
|
||||
|
@ -1352,7 +1352,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"nb-NO": {
|
||||
"pin": false,
|
||||
|
@ -1371,7 +1371,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ne-NP": {
|
||||
"pin": false,
|
||||
|
@ -1390,7 +1390,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"nl": {
|
||||
"pin": false,
|
||||
|
@ -1409,7 +1409,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"nn-NO": {
|
||||
"pin": false,
|
||||
|
@ -1428,7 +1428,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"oc": {
|
||||
"pin": false,
|
||||
|
@ -1447,7 +1447,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"pa-IN": {
|
||||
"pin": false,
|
||||
|
@ -1466,7 +1466,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"pl": {
|
||||
"pin": false,
|
||||
|
@ -1485,7 +1485,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"pt-BR": {
|
||||
"pin": false,
|
||||
|
@ -1504,7 +1504,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"pt-PT": {
|
||||
"pin": false,
|
||||
|
@ -1523,7 +1523,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"rm": {
|
||||
"pin": false,
|
||||
|
@ -1542,7 +1542,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ro": {
|
||||
"pin": false,
|
||||
|
@ -1561,7 +1561,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ru": {
|
||||
"pin": false,
|
||||
|
@ -1580,7 +1580,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sat": {
|
||||
"pin": false,
|
||||
|
@ -1599,7 +1599,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sc": {
|
||||
"pin": false,
|
||||
|
@ -1618,7 +1618,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"scn": {
|
||||
"pin": false,
|
||||
|
@ -1637,7 +1637,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sco": {
|
||||
"pin": false,
|
||||
|
@ -1656,7 +1656,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"si": {
|
||||
"pin": false,
|
||||
|
@ -1675,7 +1675,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sk": {
|
||||
"pin": false,
|
||||
|
@ -1694,7 +1694,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"skr": {
|
||||
"pin": false,
|
||||
|
@ -1713,7 +1713,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sl": {
|
||||
"pin": false,
|
||||
|
@ -1732,7 +1732,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"son": {
|
||||
"pin": false,
|
||||
|
@ -1751,7 +1751,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sq": {
|
||||
"pin": false,
|
||||
|
@ -1770,7 +1770,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sr": {
|
||||
"pin": false,
|
||||
|
@ -1789,7 +1789,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"sv-SE": {
|
||||
"pin": false,
|
||||
|
@ -1808,7 +1808,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"szl": {
|
||||
"pin": false,
|
||||
|
@ -1827,7 +1827,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ta": {
|
||||
"pin": false,
|
||||
|
@ -1846,7 +1846,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"te": {
|
||||
"pin": false,
|
||||
|
@ -1865,7 +1865,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"tg": {
|
||||
"pin": false,
|
||||
|
@ -1884,7 +1884,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"th": {
|
||||
"pin": false,
|
||||
|
@ -1903,7 +1903,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"tl": {
|
||||
"pin": false,
|
||||
|
@ -1922,7 +1922,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"tr": {
|
||||
"pin": false,
|
||||
|
@ -1941,7 +1941,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"trs": {
|
||||
"pin": false,
|
||||
|
@ -1960,7 +1960,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"uk": {
|
||||
"pin": false,
|
||||
|
@ -1979,7 +1979,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"ur": {
|
||||
"pin": false,
|
||||
|
@ -1998,7 +1998,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"uz": {
|
||||
"pin": false,
|
||||
|
@ -2017,7 +2017,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"vi": {
|
||||
"pin": false,
|
||||
|
@ -2036,7 +2036,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"wo": {
|
||||
"pin": false,
|
||||
|
@ -2055,7 +2055,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"xh": {
|
||||
"pin": false,
|
||||
|
@ -2074,7 +2074,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"zh-CN": {
|
||||
"pin": false,
|
||||
|
@ -2093,7 +2093,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
},
|
||||
"zh-TW": {
|
||||
"pin": false,
|
||||
|
@ -2112,6 +2112,6 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "130d8357414d533291c3c2880748ad8cec92cde8"
|
||||
"revision": "84033faef5b836dbc50cf65dab575e5e0fc1f7ac"
|
||||
}
|
||||
}
|
|
@ -73,6 +73,17 @@ const click = el => {
|
|||
};
|
||||
|
||||
add_task(async function toolbarButtons() {
|
||||
info("Adding a bookmark to the bookmarks toolbar.");
|
||||
let addedBookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Test",
|
||||
url: "https://example.com",
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.remove(addedBookmark);
|
||||
});
|
||||
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async () => {
|
||||
let customButton = await new Promise(resolve => {
|
||||
CustomizableUI.createWidget({
|
||||
|
|
|
@ -520,14 +520,16 @@
|
|||
* width of the close button. We don't do this in forced-colors mode since
|
||||
* the button has a visible outline shown. */
|
||||
@media not (forced-colors) {
|
||||
.tabbrowser-tab:not([labelendaligned], :hover) > .tab-stack > .tab-content > .tab-close-button {
|
||||
padding-inline-start: 0;
|
||||
width: 18px;
|
||||
}
|
||||
#tabbrowser-tabs:not([orient="vertical"]) {
|
||||
.tabbrowser-tab:not([labelendaligned], :hover) > .tab-stack > .tab-content > .tab-close-button {
|
||||
padding-inline-start: 0;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[visuallyselected]:not([labelendaligned]):hover,
|
||||
#tabbrowser-tabs:not([closebuttons=activetab]) > #tabbrowser-arrowscrollbox > .tabbrowser-tab:not([visuallyselected], [labelendaligned]):hover {
|
||||
--tab-label-mask-size: 2em;
|
||||
.tabbrowser-tab[visuallyselected]:not([labelendaligned]):hover,
|
||||
&:not([closebuttons=activetab]) > #tabbrowser-arrowscrollbox > .tabbrowser-tab:not([visuallyselected], [labelendaligned]):hover {
|
||||
--tab-label-mask-size: 2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -741,14 +743,22 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
&::part(scrollbox-clip) {
|
||||
min-height: inherit;
|
||||
&::part(scrollbox) {
|
||||
scrollbar-width: thin;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&[overflowing="true"]:not([scrolledtoend="true"]) {
|
||||
mask-image: linear-gradient(to bottom, black 98%, transparent 100%);
|
||||
}
|
||||
}
|
||||
|
||||
#tabbrowser-tabs[orient="vertical"]:has(> #tabbrowser-arrowscrollbox[overflowing="true"]) {
|
||||
border-bottom: 1px solid color-mix(in srgb, currentColor 25%, transparent);
|
||||
}
|
||||
|
||||
#vertical-tabs {
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: thin;
|
||||
display: none;
|
||||
|
||||
&[activated] {
|
||||
|
|
14
config/external/gkcodecs/gkcodecs.symbols
vendored
14
config/external/gkcodecs/gkcodecs.symbols
vendored
|
@ -100,20 +100,6 @@ opus_packet_parse
|
|||
opus_strerror
|
||||
opus_multistream_encode_float
|
||||
opus_multistream_surround_encoder_create
|
||||
# libtheora symbols
|
||||
th_comment_clear
|
||||
th_comment_init
|
||||
th_decode_alloc
|
||||
th_decode_free
|
||||
th_decode_headerin
|
||||
th_decode_packetin
|
||||
th_decode_ycbcr_out
|
||||
th_granule_frame
|
||||
th_info_clear
|
||||
th_info_init
|
||||
th_packet_isheader
|
||||
th_packet_iskeyframe
|
||||
th_setup_free
|
||||
vorbis_block_clear
|
||||
vorbis_block_init
|
||||
vorbis_comment_clear
|
||||
|
|
1
config/external/moz.build
vendored
1
config/external/moz.build
vendored
|
@ -60,7 +60,6 @@ external_dirs += [
|
|||
"media/libnestegg",
|
||||
"media/libogg",
|
||||
"media/libopus",
|
||||
"media/libtheora",
|
||||
"media/libspeex_resampler",
|
||||
"media/libsoundtouch",
|
||||
"media/mp4parse-rust",
|
||||
|
|
|
@ -1016,7 +1016,6 @@ system_headers = [
|
|||
"opus/opus.h",
|
||||
"opus/opus_multistream.h",
|
||||
"ogg/ogg.h",
|
||||
"theora/theoradec.h",
|
||||
"vpx/svc_context.h",
|
||||
"vpx/vp8.h",
|
||||
"vpx/vp8cx.h",
|
||||
|
|
|
@ -116,6 +116,9 @@ export class ConditionalPanel extends PureComponent {
|
|||
|
||||
showConditionalPanel(prevProps) {
|
||||
const { location, editor, breakpoint, selectedSource } = this.props;
|
||||
if (!selectedSource || !location) {
|
||||
return;
|
||||
}
|
||||
// When breakpoint is removed
|
||||
if (prevProps?.breakpoint && !breakpoint) {
|
||||
editor.removeLineContentMarker(markerTypes.CONDITIONAL_BP_MARKER);
|
||||
|
@ -182,6 +185,9 @@ export class ConditionalPanel extends PureComponent {
|
|||
this.clearConditionalPanel();
|
||||
}
|
||||
const { location, editor } = props;
|
||||
if (!location) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editorLine = toEditorLine(location.source.id, location.line || 0);
|
||||
this.cbPanel = editor.codeMirror.addLineWidget(
|
||||
|
@ -309,7 +315,7 @@ const mapStateToProps = state => {
|
|||
const location = getConditionalPanelLocation(state);
|
||||
|
||||
if (!location) {
|
||||
throw new Error("Conditional panel location needed.");
|
||||
return {};
|
||||
}
|
||||
|
||||
const breakpoint = getClosestBreakpoint(state, location);
|
||||
|
|
|
@ -41,6 +41,9 @@ class EmptyLines extends Component {
|
|||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const { breakableLines, selectedSource } = this.props;
|
||||
if (!selectedSource) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
// Breakable lines are something that evolves over time,
|
||||
// but we either have them loaded or not. So only compare the size
|
||||
|
@ -52,6 +55,9 @@ class EmptyLines extends Component {
|
|||
|
||||
disableEmptyLines() {
|
||||
const { breakableLines, selectedSource, editor } = this.props;
|
||||
if (!selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { codeMirror } = editor;
|
||||
const isSourceWasm = isWasm(selectedSource.id);
|
||||
|
@ -78,7 +84,7 @@ class EmptyLines extends Component {
|
|||
const mapStateToProps = state => {
|
||||
const selectedSource = getSelectedSource(state);
|
||||
if (!selectedSource) {
|
||||
throw new Error("no selectedSource");
|
||||
return {};
|
||||
}
|
||||
const breakableLines = getSelectedBreakableLines(state);
|
||||
|
||||
|
|
|
@ -195,9 +195,8 @@ export class HighlightLine extends Component {
|
|||
|
||||
export default connect(state => {
|
||||
const selectedLocation = getSelectedLocation(state);
|
||||
|
||||
if (!selectedLocation) {
|
||||
throw new Error("must have selected location");
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
pauseCommand: getPauseCommand(state, getCurrentThread(state)),
|
||||
|
|
|
@ -92,34 +92,12 @@ class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
|
|||
return this._form.selectorsSpecificity;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a rule is nested in another non-at-rule (aka CSS Nesting), this will return
|
||||
* the "full" selectors, which includes ancestor rules selectors.
|
||||
* To compute it, the parent selector (&) is recursively replaced by the parent
|
||||
* rule selector wrapped in `:is()`.
|
||||
* For example, with the following nested rule: `body { & > main {} }`,
|
||||
* the desugared selectors will be [`:is(body) > main`],
|
||||
* while the "regular" selectors will only be [`main`].
|
||||
*
|
||||
* See https://www.w3.org/TR/css-nesting-1/#nest-selector for more information.
|
||||
*
|
||||
* @returns {Array<String>} An array of the desugared selectors for this rule.
|
||||
* This falls back to the regular list of selectors
|
||||
* when desugared selectors are not sent by the server.
|
||||
*/
|
||||
get desugaredSelectors() {
|
||||
// @backward-compat { version 128 } This whole function can be removed once 128 hits release
|
||||
// We don't send the desugaredSelectors for top-level selectors, so fall back to
|
||||
// the regular selectors in that case.
|
||||
return this._form.desugaredSelectors || this._form.selectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a concatenation of the rule's selector and all its ancestor "selectors".
|
||||
* This is different than desugaredSelector as what's returned is not an actual
|
||||
* selector, but some kind of key that represent the rule selectors. This is used
|
||||
* for the selector highlighter, where we need to know what's being highlighted (we shouldn't
|
||||
* use desugaredSelector as it can be very expensive).
|
||||
* This is different from a "desugared" selector as what's returned is not an
|
||||
* actual selector, but some kind of key that represent the rule selectors.
|
||||
* This is used for the selector highlighter, where we need to know what's
|
||||
* being highlighted.
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
|
@ -177,11 +155,6 @@ class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
|
|||
return this._form.traits && this._form.traits.canSetRuleText;
|
||||
}
|
||||
|
||||
// @backward-compat { version 128 } Can be removed when 128 hits release
|
||||
get hasMatchedSelectorIndexesTrait() {
|
||||
return this._form.traits?.hasMatchedSelectorIndexes;
|
||||
}
|
||||
|
||||
get location() {
|
||||
return {
|
||||
source: this.parentStyleSheet,
|
||||
|
|
|
@ -571,12 +571,7 @@ class ElementStyle {
|
|||
// longer matches the node. This strict check avoids accidentally causing
|
||||
// declarations to be overridden in the remaining matching rules.
|
||||
const isStyleRule =
|
||||
rule.pseudoElement === "" &&
|
||||
// @backward-compat { version 128 } When 128 hits release, we can remove the
|
||||
// ternary and only check rule.matchedSelectorIndexes.length.
|
||||
(rule.domRule.hasMatchedSelectorIndexesTrait
|
||||
? !!rule.matchedSelectorIndexes.length
|
||||
: !!rule.matchedDesugaredSelectors.length);
|
||||
rule.pseudoElement === "" && rule.matchedSelectorIndexes.length;
|
||||
|
||||
// Style rules for pseudo-elements must always be considered, regardless if their
|
||||
// selector matches the node. As a convenience, declarations in rules for
|
||||
|
|
|
@ -52,14 +52,7 @@ class Rule {
|
|||
this.domRule = options.rule;
|
||||
this.compatibilityIssues = null;
|
||||
|
||||
if (this.domRule.hasMatchedSelectorIndexesTrait) {
|
||||
this.matchedSelectorIndexes = options.matchedSelectorIndexes || [];
|
||||
} else {
|
||||
// @backward-compat { version 128 } this.matchedDesugaredSelectors can be removed
|
||||
// once 128 hits release
|
||||
this.matchedDesugaredSelectors = options.matchedDesugaredSelectors || [];
|
||||
}
|
||||
|
||||
this.matchedSelectorIndexes = options.matchedSelectorIndexes || [];
|
||||
this.pseudoElement = options.pseudoElement || "";
|
||||
this.isSystem = options.isSystem;
|
||||
this.isUnmatched = options.isUnmatched || false;
|
||||
|
@ -108,23 +101,14 @@ class Rule {
|
|||
}
|
||||
|
||||
get selector() {
|
||||
const data = {
|
||||
return {
|
||||
getUniqueSelector: this.getUniqueSelector,
|
||||
matchedSelectorIndexes: this.matchedSelectorIndexes,
|
||||
selectors: this.domRule.selectors,
|
||||
selectorsSpecificity: this.domRule.selectorsSpecificity,
|
||||
selectorWarnings: this.domRule.selectors,
|
||||
selectorText: this.keyframes ? this.domRule.keyText : this.selectorText,
|
||||
};
|
||||
|
||||
if (this.domRule.hasMatchedSelectorIndexesTrait) {
|
||||
data.matchedSelectorIndexes = this.matchedSelectorIndexes;
|
||||
} else {
|
||||
// @backward-compat { version 128 } matchedDesugaredSelectors can be removed
|
||||
// once 128 hits release
|
||||
data.matchedDesugaredSelectors = this.matchedDesugaredSelectors;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
get sourceMapURLService() {
|
||||
|
@ -652,13 +636,8 @@ class Rule {
|
|||
* properties as needed.
|
||||
*/
|
||||
refresh(options) {
|
||||
if (this.domRule.hasMatchedSelectorIndexesTrait) {
|
||||
this.matchedSelectorIndexes = options.matchedSelectorIndexes || [];
|
||||
} else {
|
||||
// @backward-compat { version 128 } this.matchedDesugaredSelectors can be removed
|
||||
// once 128 hits release
|
||||
this.matchedDesugaredSelectors = options.matchedDesugaredSelectors || [];
|
||||
}
|
||||
this.matchedSelectorIndexes = options.matchedSelectorIndexes || [];
|
||||
|
||||
const newTextProps = this._getTextProperties();
|
||||
|
||||
// The element style rule behaves differently on refresh. We basically need to update
|
||||
|
|
|
@ -114,10 +114,6 @@ exports.pseudoClasses = {
|
|||
const selector = (exports.selector = {
|
||||
// Function that returns a Promise containing an unique CSS selector.
|
||||
getUniqueSelector: PropTypes.func,
|
||||
// Array of the selectors that match the selected element.
|
||||
// @backward-compat { version 128 } matchedDesugaredSelectors shouldn't be used anymore
|
||||
// when 128 hits release.
|
||||
matchedDesugaredSelectors: PropTypes.arrayOf(PropTypes.string),
|
||||
// Array of the indexes in `selectors` that match the selected element.
|
||||
matchedSelectorIndexes: PropTypes.arrayOf(PropTypes.number),
|
||||
// The CSS rule's selector text content.
|
||||
|
|
|
@ -356,13 +356,7 @@ RuleEditor.prototype = {
|
|||
// This is a "normal" rule with a selector.
|
||||
let computedSelector = "";
|
||||
if (this.rule.domRule.selectors) {
|
||||
if (this.rule.domRule.hasMatchedSelectorIndexesTrait) {
|
||||
computedSelector = this.rule.domRule.computedSelector;
|
||||
} else {
|
||||
// @backward-compat { version 128 } This else block can be removed once 128 hits
|
||||
// release.
|
||||
computedSelector = this.rule.domRule.desugaredSelectors?.join(", ");
|
||||
}
|
||||
computedSelector = this.rule.domRule.computedSelector;
|
||||
// Otherwise, the rule is either inherited or inline, and selectors will
|
||||
// be computed on demand when the highlighter is requested.
|
||||
}
|
||||
|
@ -641,9 +635,8 @@ RuleEditor.prototype = {
|
|||
} else if (this.rule.domRule.type === CSSRule.KEYFRAME_RULE) {
|
||||
this.selectorText.textContent = this.rule.domRule.keyText;
|
||||
} else {
|
||||
const desugaredSelectors = this.rule.domRule.desugaredSelectors;
|
||||
this.rule.domRule.selectors.forEach((selector, i) => {
|
||||
this._populateSelector(selector, i, desugaredSelectors);
|
||||
this._populateSelector(selector, i);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -689,11 +682,8 @@ RuleEditor.prototype = {
|
|||
*
|
||||
* @param {String} selector: The selector text to display
|
||||
* @param {Number} selectorIndex: Its index in the rule
|
||||
* @param {Array<String>} desugaredSelectors: The array of desugared selectors for the
|
||||
* rule. This is only for backward compatibility and can be removed when 128
|
||||
* hits release.
|
||||
*/
|
||||
_populateSelector(selector, selectorIndex, desugaredSelectors) {
|
||||
_populateSelector(selector, selectorIndex) {
|
||||
if (selectorIndex !== 0) {
|
||||
createChild(this.selectorText, "span", {
|
||||
class: "ruleview-selector-separator",
|
||||
|
@ -706,21 +696,10 @@ RuleEditor.prototype = {
|
|||
// Only add matched/unmatched class when the rule does have some matched
|
||||
// selectors. We don't always have some (e.g. rules for pseudo elements)
|
||||
|
||||
if (this.rule.domRule.hasMatchedSelectorIndexesTrait) {
|
||||
if (this.rule.matchedSelectorIndexes.length) {
|
||||
containerClass += this.rule.matchedSelectorIndexes.includes(
|
||||
selectorIndex
|
||||
)
|
||||
? "matched"
|
||||
: "unmatched";
|
||||
}
|
||||
} else if (this.rule.matchedDesugaredSelectors.length) {
|
||||
// @backward-compat { version 128 } This whole elseif block can be removed once 128
|
||||
// hits release, as matchedDesugaredSelectors shouldn't be used then.
|
||||
const desugaredSelector = desugaredSelectors[selectorIndex];
|
||||
const matchedSelector =
|
||||
this.rule.matchedDesugaredSelectors.includes(desugaredSelector);
|
||||
containerClass += matchedSelector ? "matched" : "unmatched";
|
||||
if (this.rule.matchedSelectorIndexes.length) {
|
||||
containerClass += this.rule.matchedSelectorIndexes.includes(selectorIndex)
|
||||
? "matched"
|
||||
: "unmatched";
|
||||
}
|
||||
|
||||
let selectorContainerTitle;
|
||||
|
@ -996,11 +975,7 @@ RuleEditor.prototype = {
|
|||
this.isEditing = true;
|
||||
|
||||
// Remove highlighter for the previous selector.
|
||||
const computedSelector = this.rule.domRule.hasMatchedSelectorIndexesTrait
|
||||
? this.rule.domRule.computedSelector
|
||||
: // @backward-compat { version 128 } We can remove the ternary and directly use
|
||||
// this.rule.domRule.computedSelector once 128 hits release
|
||||
this.rule.domRule.desugaredSelectors?.join(", ");
|
||||
const computedSelector = this.rule.domRule.computedSelector;
|
||||
if (this.ruleView.isSelectorHighlighted(computedSelector)) {
|
||||
await this.ruleView.toggleSelectorHighlighter(
|
||||
this.rule,
|
||||
|
|
|
@ -148,3 +148,49 @@ add_task(async function testInvalidSameSiteMessage() {
|
|||
});
|
||||
|
||||
add_task(cleanUp);
|
||||
|
||||
add_task(async function testInvalidMaxAgeMessage() {
|
||||
const message1 =
|
||||
"Invalid “max-age“ value for cookie “a”. The attribute is ignored.";
|
||||
const message2 =
|
||||
"Invalid “max-age“ value for cookie “b”. The attribute is ignored.";
|
||||
|
||||
const { hud, tab, win } = await openNewWindowAndConsole(
|
||||
"http://example.org/" + TEST_FILE
|
||||
);
|
||||
|
||||
info("Test cookie messages");
|
||||
|
||||
SpecialPowers.spawn(tab.linkedBrowser, [], () => {
|
||||
content.wrappedJSObject.createCookie("a=1; max-age=abc; samesite=lax");
|
||||
content.wrappedJSObject.createCookie("b=1; max-age=1,2; samesite=lax");
|
||||
});
|
||||
|
||||
const { node } = await waitForMessageByType(hud, COOKIE_GROUP, ".warn");
|
||||
is(
|
||||
node.querySelector(".warning-group-badge").textContent,
|
||||
"2",
|
||||
"The badge has the expected text"
|
||||
);
|
||||
|
||||
await checkConsoleOutputForWarningGroup(hud, [`▶︎⚠ ${COOKIE_GROUP} 2`]);
|
||||
|
||||
info("Open the group");
|
||||
node.querySelector(".arrow").click();
|
||||
await waitFor(() => findWarningMessage(hud, "Cookie"));
|
||||
|
||||
await checkConsoleOutputForWarningGroup(hud, [
|
||||
`▼︎⚠ ${COOKIE_GROUP} 2`,
|
||||
`| ${message1}`,
|
||||
`| ${message2}`,
|
||||
]);
|
||||
|
||||
// Source map are being resolved in background and we might have
|
||||
// pending request related to this service if we close the window
|
||||
// immeditely. So just wait for these request to finish before proceeding.
|
||||
await hud.toolbox.sourceMapURLService.waitForSourcesLoading();
|
||||
|
||||
await win.close();
|
||||
});
|
||||
|
||||
add_task(cleanUp);
|
||||
|
|
|
@ -1025,9 +1025,12 @@ function isTrackingProtectionMessage(message) {
|
|||
*/
|
||||
function isCookieMessage(message) {
|
||||
const { category } = message;
|
||||
return ["cookiesCHIPS", "cookiesOversize", "cookieSameSite"].includes(
|
||||
category
|
||||
);
|
||||
return [
|
||||
"cookiesCHIPS",
|
||||
"cookiesOversize",
|
||||
"cookieSameSite",
|
||||
"cookieInvalidAttribute",
|
||||
].includes(category);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -144,7 +144,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
|||
"pointer-events",
|
||||
"position",
|
||||
"position-anchor",
|
||||
"position-try-options",
|
||||
"position-try-fallbacks",
|
||||
"position-try-order",
|
||||
"position-visibility",
|
||||
"print-color-adjust",
|
||||
|
|
|
@ -293,8 +293,6 @@ class StyleRuleActor extends Actor {
|
|||
// Indicates whether StyleRuleActor implements and can use the setRuleText method.
|
||||
// It cannot use it if the stylesheet was programmatically mutated via the CSSOM.
|
||||
canSetRuleText: this.canSetRuleText,
|
||||
// @backward-compat { version 128 } Can be removed when 128 hits release.
|
||||
hasMatchedSelectorIndexes: true,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
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