commit f52055643f402a739ac3649b90949aaf288711d9 parent 369d1019f57689030bb0702f10e0137972e9612f Author: Benjamin VanderSloot <bvandersloot@mozilla.com> Date: Mon, 22 Dec 2025 20:46:58 +0000 Bug 2001196 - Implement "History" card - r=emz,fluent-reviewers,akulyk,bolsson Using temporary strings. Differential Revision: https://phabricator.services.mozilla.com/D276291 Diffstat:
16 files changed, 626 insertions(+), 133 deletions(-)
diff --git a/browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js b/browser/base/content/test/sanitize/browser_sanitizeDialog_v2.js @@ -301,26 +301,30 @@ add_task(async function test_pref_remembering() { dh.open(); await dh.promiseClosed; - // test rememebering prefs from the clear history context - // since clear history and clear site data have seperate remembering - // of prefs - dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); - dh.onload = function () { - this.checkPrefCheckbox("cookiesAndStorage", true); - this.checkPrefCheckbox("siteSettings", false); - this.checkPrefCheckbox("cache", false); - - this.acceptDialog(); - }; - dh.open(); - await dh.promiseClosed; + if (!settingsRedesignHistoryEnabled()) { + // test rememebering prefs from the clear history context + // since clear history and clear site data have seperate remembering + // of prefs + dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); + dh.onload = function () { + this.checkPrefCheckbox("cookiesAndStorage", true); + this.checkPrefCheckbox("siteSettings", false); + this.checkPrefCheckbox("cache", false); + + this.acceptDialog(); + }; + dh.open(); + await dh.promiseClosed; + } // validate if prefs are remembered across both clear history and browser dh = new ClearHistoryDialogHelper({ mode: "browser" }); dh.onload = function () { this.validateCheckbox("cookiesAndStorage", true); this.validateCheckbox("siteSettings", false); - this.validateCheckbox("cache", false); + if (!settingsRedesignHistoryEnabled()) { + this.validateCheckbox("cache", false); + } this.cancelDialog(); }; @@ -767,111 +771,113 @@ add_task(async function test_clear_on_shutdown() { await SiteDataTestUtils.clear(); }); -add_task(async function testClearHistoryCheckboxStatesAfterMigration() { - await SpecialPowers.pushPrefEnv({ - set: [ - ["privacy.cpd.history", false], - ["privacy.cpd.formdata", true], - ["privacy.cpd.cookies", true], - ["privacy.cpd.offlineApps", false], - ["privacy.cpd.sessions", false], - ["privacy.cpd.siteSettings", false], - ["privacy.cpd.cache", true], - // Set cookiesAndStorage to verify that the pref is flipped in the test - ["privacy.clearHistory.cookiesAndStorage", false], - // We set the old migrate pref to false to simulate a user who has not migrated to the new dialog. - // we should follow the user's old prefs with "cpd." prefix in this case. - ["privacy.sanitize.cpd.hasMigratedToNewPrefs2", false], - ["privacy.sanitize.cpd.hasMigratedToNewPrefs3", false], - ], - }); - - let dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); - dh.onload = function () { - this.validateCheckbox("cookiesAndStorage", true); - this.validateCheckbox("browsingHistoryAndDownloads", false); - this.validateCheckbox("formdata", true); - this.validateCheckbox("cache", true); - this.validateCheckbox("siteSettings", false); +if (!settingsRedesignHistoryEnabled()) { + add_task(async function testClearHistoryCheckboxStatesAfterMigration() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.cpd.history", false], + ["privacy.cpd.formdata", true], + ["privacy.cpd.cookies", true], + ["privacy.cpd.offlineApps", false], + ["privacy.cpd.sessions", false], + ["privacy.cpd.siteSettings", false], + ["privacy.cpd.cache", true], + // Set cookiesAndStorage to verify that the pref is flipped in the test + ["privacy.clearHistory.cookiesAndStorage", false], + // We set the old migrate pref to false to simulate a user who has not migrated to the new dialog. + // we should follow the user's old prefs with "cpd." prefix in this case. + ["privacy.sanitize.cpd.hasMigratedToNewPrefs2", false], + ["privacy.sanitize.cpd.hasMigratedToNewPrefs3", false], + ], + }); + + let dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); + dh.onload = function () { + this.validateCheckbox("cookiesAndStorage", true); + this.validateCheckbox("browsingHistoryAndDownloads", false); + this.validateCheckbox("formdata", true); + this.validateCheckbox("cache", true); + this.validateCheckbox("siteSettings", false); + + this.checkPrefCheckbox("siteSettings", true); + this.checkPrefCheckbox("cookiesAndStorage", false); + this.acceptDialog(); + }; + dh.open(); + await dh.promiseClosed; - this.checkPrefCheckbox("siteSettings", true); - this.checkPrefCheckbox("cookiesAndStorage", false); - this.acceptDialog(); - }; - dh.open(); - await dh.promiseClosed; - - is( - Services.prefs.getBoolPref("privacy.sanitize.cpd.hasMigratedToNewPrefs3"), - true, - "Migration is complete for cpd branch" - ); - - // make sure the migration doesn't run again - dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); - dh.onload = function () { - this.validateCheckbox("siteSettings", true); - this.validateCheckbox("cookiesAndStorage", false); - this.cancelDialog(); - }; - dh.open(); - await dh.promiseClosed; -}); + is( + Services.prefs.getBoolPref("privacy.sanitize.cpd.hasMigratedToNewPrefs3"), + true, + "Migration is complete for cpd branch" + ); -add_task(async function testClearHistoryCheckboxStatesAfterMigration3() { - await SpecialPowers.pushPrefEnv({ - set: [ - ["privacy.cpd.history", false], - ["privacy.cpd.formdata", true], - ["privacy.cpd.cookies", true], - ["privacy.cpd.offlineApps", false], - ["privacy.cpd.sessions", false], - ["privacy.cpd.siteSettings", true], - ["privacy.cpd.cache", true], - // Verify that prefs not in not touched in migration from v2 - ["privacy.clearHistory.cookiesAndStorage", false], - ["privacy.clearHistory.siteSettings", false], - ["privacy.clearHistory.cache", false], - // Verify that formData and browsingHistoryAndDownloads inherit this value - ["privacy.clearHistory.historyFormDataAndDownloads", true], - // migrate from v2 to v3, dont redo the v1 to v2 migration - ["privacy.sanitize.cpd.hasMigratedToNewPrefs2", true], - ["privacy.sanitize.cpd.hasMigratedToNewPrefs3", false], - ], + // make sure the migration doesn't run again + dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); + dh.onload = function () { + this.validateCheckbox("siteSettings", true); + this.validateCheckbox("cookiesAndStorage", false); + this.cancelDialog(); + }; + dh.open(); + await dh.promiseClosed; }); - let dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); - dh.onload = function () { - // migration to v3 shouldn't modify these values - this.validateCheckbox("cookiesAndStorage", false); - this.validateCheckbox("siteSettings", false); - this.validateCheckbox("cache", false); - - // migration to v3 should set them initially to true from historyFormDataAndDownloads pref - this.validateCheckbox("browsingHistoryAndDownloads", true); - this.validateCheckbox("formdata", true); + add_task(async function testClearHistoryCheckboxStatesAfterMigration3() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.cpd.history", false], + ["privacy.cpd.formdata", true], + ["privacy.cpd.cookies", true], + ["privacy.cpd.offlineApps", false], + ["privacy.cpd.sessions", false], + ["privacy.cpd.siteSettings", true], + ["privacy.cpd.cache", true], + // Verify that prefs not in not touched in migration from v2 + ["privacy.clearHistory.cookiesAndStorage", false], + ["privacy.clearHistory.siteSettings", false], + ["privacy.clearHistory.cache", false], + // Verify that formData and browsingHistoryAndDownloads inherit this value + ["privacy.clearHistory.historyFormDataAndDownloads", true], + // migrate from v2 to v3, dont redo the v1 to v2 migration + ["privacy.sanitize.cpd.hasMigratedToNewPrefs2", true], + ["privacy.sanitize.cpd.hasMigratedToNewPrefs3", false], + ], + }); + + let dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); + dh.onload = function () { + // migration to v3 shouldn't modify these values + this.validateCheckbox("cookiesAndStorage", false); + this.validateCheckbox("siteSettings", false); + this.validateCheckbox("cache", false); + + // migration to v3 should set them initially to true from historyFormDataAndDownloads pref + this.validateCheckbox("browsingHistoryAndDownloads", true); + this.validateCheckbox("formdata", true); + + // flip two prefs to open to verify migration doesn't happen again and checkboxes retain their value + this.checkPrefCheckbox("siteSettings", true); + this.checkPrefCheckbox("browsingHistoryAndDownloads", false); + this.acceptDialog(); + }; + dh.open(); + await dh.promiseClosed; - // flip two prefs to open to verify migration doesn't happen again and checkboxes retain their value - this.checkPrefCheckbox("siteSettings", true); - this.checkPrefCheckbox("browsingHistoryAndDownloads", false); - this.acceptDialog(); - }; - dh.open(); - await dh.promiseClosed; - - is( - Services.prefs.getBoolPref("privacy.sanitize.cpd.hasMigratedToNewPrefs3"), - true, - "Migration is complete for cpd branch" - ); + is( + Services.prefs.getBoolPref("privacy.sanitize.cpd.hasMigratedToNewPrefs3"), + true, + "Migration is complete for cpd branch" + ); - // make sure the migration doesn't run again - dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); - dh.onload = function () { - this.validateCheckbox("siteSettings", true); - this.validateCheckbox("browsingHistoryAndDownloads", false); - this.cancelDialog(); - }; - dh.open(); - await dh.promiseClosed; -}); + // make sure the migration doesn't run again + dh = new ClearHistoryDialogHelper({ mode: "clearHistory" }); + dh.onload = function () { + this.validateCheckbox("siteSettings", true); + this.validateCheckbox("browsingHistoryAndDownloads", false); + this.cancelDialog(); + }; + dh.open(); + await dh.promiseClosed; + }); +} diff --git a/browser/base/content/test/sanitize/head.js b/browser/base/content/test/sanitize/head.js @@ -499,6 +499,15 @@ function promiseSanitizationComplete() { return TestUtils.topicObserved("sanitizer-sanitization-complete"); } +function settingsRedesignHistoryEnabled() { + return ( + Services.prefs.getBoolPref( + "browser.settings-redesign.history2.enabled", + false + ) || Services.prefs.getBoolPref("browser.settings-redesign.enabled", false) + ); +} + /** * This wraps the dialog and provides some convenience methods for interacting * with it. @@ -651,9 +660,15 @@ ClearHistoryDialogHelper.prototype = { // We want to simulate opening the dialog inside preferences for clear history // and clear site data if (this._mode != "browser") { - await openPreferencesViaOpenPreferencesAPI("privacy", { - leaveOpen: true, - }); + if (this._mode == "clearOnShutdown" && settingsRedesignHistoryEnabled()) { + await openPreferencesViaOpenPreferencesAPI("history", { + leaveOpen: true, + }); + } else { + await openPreferencesViaOpenPreferencesAPI("privacy", { + leaveOpen: true, + }); + } let tabWindow = gBrowser.selectedBrowser.contentWindow; let clearDialogOpenButtonId = this._mode + "Button"; // the id for clear on shutdown is of a different format diff --git a/browser/components/enterprisepolicies/tests/browser/browser.toml b/browser/components/enterprisepolicies/tests/browser/browser.toml @@ -115,6 +115,9 @@ https_first_disabled = true ["browser_policy_privatebrowsingmodeavailability.js"] +["browser_policy_privatebrowsingmodeavailability_srd.js"] +prefs = ["browser.settings-redesign.history2.enabled=true"] + ["browser_policy_search_engine.js"] skip-if = [ "os == 'win' && os_version == '11.26100' && arch == 'x86_64' && opt && verify-standalone", diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_privatebrowsingmodeavailability_srd.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_privatebrowsingmodeavailability_srd.js @@ -0,0 +1,61 @@ +/* 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 + .getElementById("historyMode") + .querySelector("moz-option[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 selector should be disabled" + ); + } + ); + await BrowserTestUtils.closeWindow(newWin); +}); diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -3180,6 +3180,93 @@ SettingGroupManager.registerGroups({ }, ], }, + history2: { + inProgress: true, + l10nId: "history-section-header", + items: [ + { + id: "deleteOnCloseInfo", + l10nId: "sitedata-delete-on-close-private-browsing3", + control: "moz-message-bar", + }, + { + id: "historyMode", + control: "moz-radio-group", + options: [ + { + value: "remember", + l10nId: "history-remember-option-all", + }, + { value: "dontremember", l10nId: "history-remember-option-never" }, + { + value: "custom", + l10nId: "history-remember-option-custom", + items: [ + { + id: "customHistoryButton", + control: "moz-box-button", + l10nId: "history-custom-button", + }, + ], + }, + ], + controlAttrs: { + "search-l10n-ids": ` + history-remember-description3, + history-dontremember-description3, + history-private-browsing-permanent.label, + history-remember-browser-option.label, + history-remember-search-option.label, + history-clear-on-close-option.label, + history-clear-on-close-settings.label + `, + }, + }, + ], + }, + historyAdvanced: { + l10nId: "history-custom-section-header", + headingLevel: 2, + items: [ + { + id: "privateBrowsingAutoStart", + l10nId: "history-private-browsing-permanent", + }, + { + id: "rememberHistory", + l10nId: "history-remember-browser-option", + }, + { + id: "rememberForms", + l10nId: "history-remember-search-option", + }, + { + id: "alwaysClear", + l10nId: "history-clear-on-close-option", + items: [ + { + id: "clearDataSettings", + l10nId: "history-clear-on-close-settings", + control: "moz-box-button", + controlAttrs: { + "search-l10n-ids": ` + clear-data-settings-label, + history-section-label, + item-history-and-downloads.label, + item-cookies.label, + item-active-logins.label, + item-cache.label, + item-form-search-history.label, + data-section-label, + item-site-settings.label, + item-offline-apps.label + `, + }, + }, + ], + }, + ], + }, permissions: { id: "permissions", l10nId: "permissions-header2", diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js @@ -287,6 +287,11 @@ const CONFIG_PANES = Object.freeze({ module: "chrome://browser/content/preferences/config/aiFeatures.mjs", visible: () => srdSectionEnabled("aiFeatures"), }, + history: { + parent: "privacy", + l10nId: "history-header2", + groupIds: ["historyAdvanced"], + }, }); var gLastCategory = { category: undefined, subcategory: undefined }; diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml @@ -575,10 +575,11 @@ </groupbox> <!-- History --> -<groupbox id="historyGroup" data-category="panePrivacy" hidden="true" aria-describedby="totalSiteDataSize"> +<groupbox id="historyGroup" data-category="panePrivacy" hidden="true" aria-describedby="totalSiteDataSize" data-srd-groupid="history2"> <label><html:h2 data-l10n-id="history-header"/></label> <html:setting-group groupid="history"/> </groupbox> +<html:setting-group groupid="history2" data-category="panePrivacy" hidden="true"/> <hbox id="permissionsCategory" class="subcategory" diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js @@ -2172,13 +2172,15 @@ Preferences.addSetting({ return privateBrowsingAutoStart.locked && privateBrowsingAutoStart.value; }, getControlConfig(config, { privateBrowsingAutoStart }, setting) { - let l10nId = null; - if (setting.value == "remember") { - l10nId = "history-remember-description3"; - } else if (setting.value == "dontremember") { - l10nId = "history-dontremember-description3"; - } else if (setting.value == "custom") { - l10nId = "history-custom-description3"; + let l10nId = undefined; + if (!srdSectionEnabled("history2")) { + if (setting.value == "remember") { + l10nId = "history-remember-description3"; + } else if (setting.value == "dontremember") { + l10nId = "history-dontremember-description3"; + } else if (setting.value == "custom") { + l10nId = "history-custom-description3"; + } } let dontRememberOption = config.options.find( @@ -2201,6 +2203,14 @@ Preferences.addSetting({ }); Preferences.addSetting({ + id: "customHistoryButton", + onUserClick(e) { + e.preventDefault(); + gotoPref("paneHistory"); + }, +}); + +Preferences.addSetting({ id: "privateBrowsingAutoStart", pref: "browser.privatebrowsing.autostart", deps: ["historyMode"], @@ -3778,6 +3788,7 @@ var gPrivacyPane = { initSettingGroup("certificates"); initSettingGroup("ipprotection"); initSettingGroup("history"); + initSettingGroup("history2"); initSettingGroup("permissions"); initSettingGroup("dnsOverHttps"); initSettingGroup("dnsOverHttpsAdvanced"); diff --git a/browser/components/preferences/tests/browser.toml b/browser/components/preferences/tests/browser.toml @@ -254,11 +254,21 @@ skip-if = [ "os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11' && a11y_checks && opt", ] +["browser_privacypane_2_srd.js"] +skip-if = [ + "os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11' && a11y_checks && opt", +] + ["browser_privacypane_3.js"] skip-if = [ "os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11' && a11y_checks && opt", ] +["browser_privacypane_3_srd.js"] +skip-if = [ + "os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11' && a11y_checks && opt", +] + ["browser_proxy_backup.js"] ["browser_sanitizeOnShutdown_prefLocked.js"] @@ -371,6 +381,8 @@ support-files = [ ["browser_warning_permanent_private_browsing.js"] +["browser_warning_permanent_private_browsing_srd.js"] + ["browser_windows_launch_on_login.js"] run-if = [ "os == 'win' && !msix", diff --git a/browser/components/preferences/tests/browser_privacypane_2_srd.js b/browser/components/preferences/tests/browser_privacypane_2_srd.js @@ -0,0 +1,19 @@ +let rootDir = getRootDirectory(gTestPath); +let jar = getJar(rootDir); +if (jar) { + let tmpdir = extractJarToTmp(jar); + rootDir = "file://" + tmpdir.path + "/"; +} +/* import-globals-from privacypane_tests_perwindow.js */ +Services.scriptloader.loadSubScript( + rootDir + "privacypane_tests_perwindow.js", + this +); + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["browser.settings-redesign.history2.enabled", "true"]], + }); +}); + +run_test_subset([test_dependent_elements_redesigned]); diff --git a/browser/components/preferences/tests/browser_privacypane_3_srd.js b/browser/components/preferences/tests/browser_privacypane_3_srd.js @@ -0,0 +1,27 @@ +let rootDir = getRootDirectory(gTestPath); +let jar = getJar(rootDir); +if (jar) { + let tmpdir = extractJarToTmp(jar); + rootDir = "file://" + tmpdir.path + "/"; +} +/* import-globals-from privacypane_tests_perwindow.js */ +Services.scriptloader.loadSubScript( + rootDir + "privacypane_tests_perwindow.js", + this +); + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["browser.settings-redesign.history2.enabled", "true"]], + }); +}); + +run_test_subset([ + test_custom_retention_redesign("rememberHistory", "remember"), + test_custom_retention_redesign("rememberHistory", "custom"), + test_custom_retention_redesign("rememberForms", "custom"), + test_custom_retention_redesign("rememberForms", "custom"), + test_historymode_retention_redesign("remember", "custom"), + test_custom_retention_redesign("alwaysClear", "remember"), + test_custom_retention_redesign("alwaysClear", "custom"), +]); diff --git a/browser/components/preferences/tests/browser_warning_permanent_private_browsing.js b/browser/components/preferences/tests/browser_warning_permanent_private_browsing.js @@ -29,11 +29,31 @@ function checkForPrompt(prefVal) { promptFired = true; return doc.defaultView.CONFIRM_RESTART_PROMPT_RESTART_NOW; }; + // Tick the checkbox and pretend the user did it: - await updateCheckBox( - gBrowser.contentWindow, - "privateBrowsingAutoStart", - prefVal + let checkbox = gBrowser.contentWindow.document.querySelector( + "setting-group[groupid='history'] #privateBrowsingAutoStart" + ); + + ok(checkbox, "the privateBrowsingAutoStart checkbox should exist"); + is_element_visible( + checkbox, + "the privateBrowsingAutoStart checkbox should be visible" + ); + + // No need to click if we're already in the desired state. + if (checkbox.checked === prefVal) { + return; + } + + // Scroll into view for click to succeed. + checkbox.scrollIntoView(); + + // Toggle the state. + await EventUtils.synthesizeMouseAtCenter( + checkbox, + {}, + checkbox.ownerGlobal ); // Now the prompt should have shown. diff --git a/browser/components/preferences/tests/browser_warning_permanent_private_browsing_srd.js b/browser/components/preferences/tests/browser_warning_permanent_private_browsing_srd.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +function checkForPrompt(prefVal) { + return async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.history.custom", true], + ["browser.privatebrowsing.autostart", !prefVal], + ["browser.settings-redesign.history2.enabled", true], + ], + }); + + await openPreferencesViaOpenPreferencesAPI("paneHistory", { + leaveOpen: true, + }); + let doc = gBrowser.contentDocument; + + // Stub out the prompt method as an easy way to check it was shown. We throw away + // the tab straight after so don't need to bother restoring it. + let promptFired = false; + doc.defaultView.confirmRestartPrompt = () => { + promptFired = true; + return doc.defaultView.CONFIRM_RESTART_PROMPT_RESTART_NOW; + }; + // Tick the checkbox and pretend the user did it: + let checkbox = gBrowser.contentWindow.document.querySelector( + "setting-group[groupid='historyAdvanced'] #privateBrowsingAutoStart" + ); + + ok(checkbox, "the privateBrowsingAutoStart checkbox should exist"); + is_element_visible( + checkbox, + "the privateBrowsingAutoStart checkbox should be visible" + ); + + // No need to click if we're already in the desired state. + if (checkbox.checked === prefVal) { + return; + } + + // Scroll into view for click to succeed. + checkbox.scrollIntoView(); + + // Toggle the state. + await EventUtils.synthesizeMouseAtCenter( + checkbox, + {}, + checkbox.ownerGlobal + ); + + // Now the prompt should have shown. + ok( + promptFired, + `Expect a prompt when turning permanent private browsing ${ + prefVal ? "on" : "off" + }!` + ); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); + }; +} + +/** + * Check we show the prompt if the permanent private browsing pref is false + * and we flip the checkbox to true. + */ +add_task(checkForPrompt(true)); + +/** + * Check it works in the other direction: + */ +add_task(checkForPrompt(false)); diff --git a/browser/components/preferences/tests/head.js b/browser/components/preferences/tests/head.js @@ -690,6 +690,54 @@ async function selectHistoryMode(win, value) { await popupHiddenPromise; } +/** + * Select the given history mode in the redesigned privacy pane. + * + * @param {Window} win - The preferences window which contains the + * dropdown. + * @param {string} value - The history mode to select. + */ +async function selectRedesignedHistoryMode(win, value) { + let historyMode = win.document.querySelector( + "setting-group[groupid='history2'] #historyMode" + ); + let updated = waitForSettingControlChange(historyMode); + + let optionItems = Array.from(historyMode.children); + let targetItem = optionItems.find(option => option.value == value); + if (!targetItem) { + throw new Error( + "Could not find history mode popup item for value: " + value + ); + } + + if (historyMode.value == value) { + return; + } + + targetItem.click(); + await updated; +} + +async function updateCheckBoxElement(checkbox, value) { + ok(checkbox, "the " + checkbox.id + " checkbox should exist"); + is_element_visible( + checkbox, + "the " + checkbox.id + " checkbox should be visible" + ); + + // No need to click if we're already in the desired state. + if (checkbox.checked === value) { + return; + } + + // Scroll into view for click to succeed. + checkbox.scrollIntoView(); + + // Toggle the state. + await EventUtils.synthesizeMouseAtCenter(checkbox, {}, checkbox.ownerGlobal); +} + async function updateCheckBox(win, id, value) { let checkbox = win.document.getElementById(id); ok(checkbox, "the " + id + " checkbox should exist"); diff --git a/browser/components/preferences/tests/privacypane_tests_perwindow.js b/browser/components/preferences/tests/privacypane_tests_perwindow.js @@ -38,7 +38,9 @@ async function test_pane_visibility(win) { await selectHistoryMode(win, "custom"); for (let id of customElementIds) { - let element = win.document.getElementById(id); + let element = win.document.querySelector( + `setting-group[groupid='history'] #${id}` + ); ok(element, `the ${id} element should exist`); is_element_visible( element, @@ -49,7 +51,9 @@ async function test_pane_visibility(win) { await selectHistoryMode(win, "remember"); for (let id of customElementIds) { - let element = win.document.getElementById(id); + let element = win.document.querySelector( + `setting-group[groupid='history'] #${id}` + ); ok(element, `the ${id} element should exist`); is_element_hidden( element, @@ -152,6 +156,24 @@ async function test_dependent_elements(win) { await selectHistoryMode(win, "remember"); } +async function test_dependent_elements_redesigned(win) { + let historymode = win.document.getElementById("historyMode"); + ok(historymode, "history mode options should exist"); + + let customButton = win.document.getElementById("customHistoryButton"); + ok(customButton, "advanced settings button should exist"); + + // button should only change in custom mode + ok(customButton.parentDisabled, "button is disabled in remember mode"); + + // setting the mode to custom shouldn't change anything + await selectRedesignedHistoryMode(win, "custom"); + ok(!customButton.parentDisabled, "button is enabled in custom mode"); + + await selectRedesignedHistoryMode(win, "remember"); + ok(customButton.parentDisabled, "button is disabled in remember mode"); +} + async function test_dependent_cookie_elements(win) { let deleteOnCloseCheckbox = win.document.getElementById("deleteOnClose"); let deleteOnCloseNote = win.document.getElementById("deleteOnCloseInfo"); @@ -336,6 +358,31 @@ function test_historymode_retention(mode, expect) { }; } +function test_historymode_retention_redesign(mode, expect) { + return async function test_historymode_retention_fn(win) { + let historymode = win.document.getElementById("historyMode"); + ok(historymode, "history mode menulist should exist"); + + if ( + (historymode.value == "remember" && mode == "dontremember") || + (historymode.value == "dontremember" && mode == "remember") || + (historymode.value == "custom" && mode == "dontremember") + ) { + return; + } + + if (expect !== undefined) { + is( + historymode.value, + expect, + "history mode is expected to remain " + expect + ); + } + + await selectRedesignedHistoryMode(win, mode); + }; +} + function test_custom_retention(controlToChange, expect, valueIncrement) { return async function test_custom_retention_fn(win) { let historymode = win.document.getElementById("historyMode"); @@ -364,6 +411,46 @@ function test_custom_retention(controlToChange, expect, valueIncrement) { }; } +function test_custom_retention_redesign( + controlToChange, + expect, + valueIncrement +) { + return async function test_custom_retention_fn(win) { + let historymode = win.document.getElementById("historyMode"); + ok(historymode, "history mode options should exist"); + + if (expect !== undefined) { + is( + historymode.value, + expect, + "history mode is expected to remain " + expect + ); + } + + await selectRedesignedHistoryMode(win, "custom"); + + // Navigate to the custom subpane + let paneChange = waitForPaneChange("history"); + let customButton = win.document.getElementById("customHistoryButton"); + customButton.click(); + await paneChange; + + controlToChange = win.document.querySelector( + `setting-group[groupid='historyAdvanced'] #${controlToChange}` + ); + ok(controlToChange, "the control to change should exist"); + switch (controlToChange.localName) { + case "moz-checkbox": + await updateCheckBoxElement(controlToChange, !controlToChange.checked); + break; + case "menulist": + await selectRedesignedHistoryMode(win, valueIncrement); + break; + } + }; +} + const gPrefCache = new Map(); function cache_preferences(win) { diff --git a/browser/locales-preview/privacyPreferences.ftl b/browser/locales-preview/privacyPreferences.ftl @@ -338,3 +338,19 @@ sitedata-cookies-exceptions3 = .label = Manage exceptions .accesskey = x .description = Choose how specific sites handle cookies and site data. + +## History + +history-header2 = + .heading = History + +history-section-header = + .label = History + .description = Choose what you want { -brand-short-name } to remember when you close the browser. + +history-custom-section-header = + .label = Advanced settings + .description = Customize what you want { -brand-short-name } to remember when you close the browser. + +history-custom-button = + .label = Choose what you want { -brand-short-name } to remember