Pier Angelo Vendrame pushed to branch mullvad-browser-153.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser Commits: 59bcec0c by june wilde at 2026-08-10T10:28:18-07:00 MB 446: Selective Saving Mode Backend - - - - - 11 changed files: - browser/app/profile/000-mullvad-browser.js - toolkit/components/moz.build - + toolkit/components/selectivesavingmode/SelectiveSavingMode.manifest - + toolkit/components/selectivesavingmode/SelectiveSavingMode.sys.mjs - + toolkit/components/selectivesavingmode/components.conf - + toolkit/components/selectivesavingmode/content/broom-clean.svg - + toolkit/components/selectivesavingmode/content/broom-saved.svg - + toolkit/components/selectivesavingmode/jar.mn - + toolkit/components/selectivesavingmode/moz.build - + toolkit/components/selectivesavingmode/tests/xpcshell/test_selective_saving_mode.js - + toolkit/components/selectivesavingmode/tests/xpcshell/xpcshell.toml Changes: ===================================== browser/app/profile/000-mullvad-browser.js ===================================== @@ -39,3 +39,20 @@ pref("app.update.url.details", "https://mullvad.net/download/browser"); pref("app.update.badgeWaitTime", 0); // point to our feedback url rather than Mozilla's pref("app.feedback.baseURL", "https://mullvad.net/help/tag/browser/"); + +// mullvad-browser#446: Default to unconfigured for selective saving mode for alpha +// Controls what selective saving mode the browser operates in. +// On initial startup the selective saving toolkit component sets this mode pref +// when the user hasn't modified any of the prefs this pref controls. Otherwise, +// the mode is set to selective saving +// +// 0 = mode has yet to be configured +// 1 = always on private browsing mode (old default) +// 2 = selective saving mode (new default) +// 3 = normal browsing mode +pref("browser.selectiveSavingMode", 0); +#if MOZ_UPDATE_CHANNEL == release +pref("browser.selectiveSavingMode.enabled", false); +#else +pref("browser.selectiveSavingMode.enabled", true); +#endif ===================================== toolkit/components/moz.build ===================================== @@ -78,6 +78,7 @@ DIRS += [ "resistfingerprinting", "search", "securitylevel", + "selectivesavingmode", "sessionstore", "shell", "startup", ===================================== toolkit/components/selectivesavingmode/SelectiveSavingMode.manifest ===================================== @@ -0,0 +1 @@ +category profile-after-change SelectiveSavingMode @torproject.org/selective-saving-mode;1 ===================================== toolkit/components/selectivesavingmode/SelectiveSavingMode.sys.mjs ===================================== @@ -0,0 +1,229 @@ +/* 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/. */ + +// Pref to select browsing mode via this component +export const kSelectiveSavingModePref = "browser.selectiveSavingMode"; + +// Selective Saving Mode underlaying functionality prefs +// Sanitize site data upon shutdown +const kSanitizeOnShutdown = "privacy.sanitize.sanitizeOnShutdown"; +// Start browser in private window +const kPrivateBrowsingAutostart = "browser.privatebrowsing.autostart"; +// Keep site permissions stored in memory rather than on disk +const kKeepPermissionInMemory = "permissions.memory_only"; + +// Valid options for the browsing mode pref to be set to +export const SelectiveSavingModes = Object.freeze({ + unconfigured: 0, + total_clearing: 1, + selective_saving: 2, + normal_browsing: 3, + custom: 4, +}); + +// A table of all prefs used to move between default browsing modes. +const kSelectiveSavingModeSettings = { + total_clearing: { + [kSanitizeOnShutdown]: true, + [kPrivateBrowsingAutostart]: true, + [kKeepPermissionInMemory]: true, + }, + selective_saving: { + [kSanitizeOnShutdown]: true, + [kPrivateBrowsingAutostart]: false, + [kKeepPermissionInMemory]: false, + }, + normal_browsing: { + [kSanitizeOnShutdown]: false, + [kPrivateBrowsingAutostart]: false, + [kKeepPermissionInMemory]: false, + }, +}; + +/** + * Selective Saving Mode Pref Controller + * + * Listens for and handles changes in prefs relevant to Selective Saving Mode in + * order to keep the browsing mode pref and the corresponding functionality + * prefs in sync with each other each time any of the aforementioned prefs are + * changed + */ +export class SelectiveSavingPrefController { + QueryInterface = ChromeUtils.generateQI(["nsIObserver"]); + + /** + * Initialize pref controller + */ + init() { + if (!Services.prefs.getBoolPref("browser.selectiveSavingMode.enabled")) { + return; + } + + if ( + Services.prefs.getIntPref(kSelectiveSavingModePref) === + SelectiveSavingModes.unconfigured + ) { + this.#setBrowsingModeFromPrefs(); + } else { + this.#setPrefsFromBrowsingMode(); + } + + this.#createPreferenceObservers(); + } + + /** + * Shutdown pref controller + */ + shutdown() { + this.#removePreferenceObservers(); + } + + /** + * Component hook for observing relevant event messages + * + * @param {string} aSubject + * @param {string} aTopic + */ + observe(aSubject, aTopic) { + if (aTopic === "profile-after-change") { + this.init(); + } + } + + /** + * Sets current Selective Saving browsing mode to closely match how + * functionality prefs are configured in kSelectiveSavingModeSettings + */ + #setBrowsingModeFromPrefs() { + const currentSanitizePref = Services.prefs.getBoolPref(kSanitizeOnShutdown); + const currentAutostartPref = Services.prefs.getBoolPref( + kPrivateBrowsingAutostart + ); + const currentPermissionPref = Services.prefs.getBoolPref( + kKeepPermissionInMemory + ); + + for (let [mode, settings] of Object.entries(kSelectiveSavingModeSettings)) { + if ( + currentSanitizePref === settings[kSanitizeOnShutdown] && + currentAutostartPref === settings[kPrivateBrowsingAutostart] && + currentPermissionPref === settings[kKeepPermissionInMemory] + ) { + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes[mode] + ); + return; + } + } + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.custom + ); + } + + /** + * A wrapper for setBrowsingModeFromPrefs to reset pref observers + */ + #setModeAndResetObservers = () => { + this.#removePreferenceObservers(); + this.#setBrowsingModeFromPrefs(); + this.#createPreferenceObservers(); + }; + + /** + * Sets current Selective Saving functionality prefs to closely match the + * currently assigned browsing mode. Corrects for anomalous settings if present + * as well + */ + #setPrefsFromBrowsingMode() { + let currentBrowsingMode = Services.prefs.getIntPref( + kSelectiveSavingModePref + ); + + const mode = Object.entries(SelectiveSavingModes).find( + ([, value]) => value === currentBrowsingMode + )?.[0]; + + if ( + mode === undefined || + currentBrowsingMode === SelectiveSavingModes.unconfigured + ) { + this.#setBrowsingModeFromPrefs(); + return; + } + + if (kSelectiveSavingModeSettings[mode]) { + Services.prefs.setBoolPref( + kSanitizeOnShutdown, + kSelectiveSavingModeSettings[mode][kSanitizeOnShutdown] + ); + Services.prefs.setBoolPref( + kPrivateBrowsingAutostart, + kSelectiveSavingModeSettings[mode][kPrivateBrowsingAutostart] + ); + Services.prefs.setBoolPref( + kKeepPermissionInMemory, + kSelectiveSavingModeSettings[mode][kKeepPermissionInMemory] + ); + } + } + + /** + * A wrapper for setPrefsFromBrowsingMode to reset pref observers + */ + #setPrefsAndResetObservers = () => { + this.#removePreferenceObservers(); + this.#setPrefsFromBrowsingMode(); + this.#createPreferenceObservers(); + }; + + /** + * A helper function for standing up pref observers with the correct callback + */ + #createPreferenceObservers() { + Services.prefs.addObserver( + kSelectiveSavingModePref, + this.#setPrefsAndResetObservers + ); + + Services.prefs.addObserver( + kSanitizeOnShutdown, + this.#setModeAndResetObservers + ); + Services.prefs.addObserver( + kPrivateBrowsingAutostart, + this.#setModeAndResetObservers + ); + Services.prefs.addObserver( + kKeepPermissionInMemory, + this.#setModeAndResetObservers + ); + } + + /** + * A helper function for disabling pref observers keyed to their respective + * callbacks + */ + #removePreferenceObservers() { + Services.prefs.removeObserver( + kSelectiveSavingModePref, + this.#setPrefsAndResetObservers + ); + + Services.prefs.removeObserver( + kSanitizeOnShutdown, + this.#setModeAndResetObservers + ); + Services.prefs.removeObserver( + kPrivateBrowsingAutostart, + this.#setModeAndResetObservers + ); + Services.prefs.removeObserver( + kKeepPermissionInMemory, + this.#setModeAndResetObservers + ); + } +} /* Selective Saving Mode Pref Controller */ ===================================== toolkit/components/selectivesavingmode/components.conf ===================================== @@ -0,0 +1,14 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +Classes = [ + { + "cid": "{b4a1073c-9e3c-4ce7-b13b-c100f5c64ccb}", + "contract_ids": [ + "@torproject.org/selective-saving-mode;1", + ], + "esModule": "moz-src:///toolkit/components/selectivesavingmode/SelectiveSavingMode.sys.mjs", + "constructor": "SelectiveSavingPrefController", + } +] ===================================== toolkit/components/selectivesavingmode/content/broom-clean.svg ===================================== @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g fill="context-fill" fill-opacity="context-fill-opacity"> + <path d="m13.5383 14.5627c-.1712-.0053-.3194-.1334-.3505-.3028-.0419-.294-.1441-.5789-.3001-.8369-.2583-.1558-.5436-.2579-.838-.2998-.1694-.0313-.2974-.1793-.3026-.3501-.0053-.1708.1136-.3146.2813-.3402.2944-.0329.5762-.1254.8284-.272.1426-.2476.2313-.5243.2608-.8129.0237-.1679.1662-.2884.3372-.2851.1699.0042.3181.1295.3517.2973.0471.2931.1533.5763.312.8323.2565.1573.5396.263.8326.3109.1682.0345.2929.1836.2958.3536.0028.17-.1171.3116-.2843.3357-.2894.0285-.5669.1172-.8147.2604-.1462.2521-.2386.5335-.2717.8274-.025.167-.1675.2861-.3379.2822z"/> + <path d="m6.49858 2.99992c-.14675-.00459-.27377-.11436-.3004-.25961-.03593-.25196-.12354-.49621-.25729-.71731-.22137-.13358-.46594-.22109-.71822-.25699-.14526-.02682-.25492-.15363-.25945-.30004-.00454-.14641.09737-.26967.24112-.29164.25236-.02817.49393-.10747.71013-.233093.12217-.2123.19825-.449454.22353-.696834.0203-.143878.14242-.24714456.28897-.24434753.14565.00358504.27273.11100153.30149.25484453.0404.251183.13139.493923.2674.713349.21988.134841.46256.225461.71364.266481.14417.02957.25114.15744.25358.30313.00244.1457-.10035.26707-.24368.28774-.2481.02441-.48592.10041-.69835.22319-.1253.2161-.20449.45729-.23284.7092-.0214.14312-.14361.24521-.28963.24193z"/> + <path d="m1.82093 5.3609c-.15279-.00473-.28512-.11875-.31315-.26981-.02739-.18014-.08781-.35525-.1782-.51643-.16152-.09021-.336989-.15052-.517512-.17788-.151437-.02794-.265749-.16003-.270474-.31254-.004724-.15251.101518-.2809.251381-.30378.181146-.02145.355265-.07593.513815-.16075.08209-.15545.13363-.32622.15197-.50355.02095-.15059.14903-.25861.3025-.25512.15164.00368.28404.11525.31428.26484.03021.18029.09338.35503.18632.51538.16048.09192.33508.15452.51517.18469.1503.0308.26181.164.26435.31577.00254.15176-.10462.27819-.25404.29971-.17764.01914-.34855.07141-.50396.15412-.08502.1582-.13963.33194-.16114.5127-.022.14911-.14912.25571-.30131.25265z"/> + <path clip-rule="evenodd" d="m15.3213 1.06694c.2441-.244076.2441-.639804 0-.883882-.2441-.2440775-.6398-.2440774-.8839 0l-5.96506 5.965062h-.50519c-1.996-1.09517-4.49023.42233-6.49079 1.63948-.41545.25277-.80961.49258-1.173597.69335-.16756.10002-.289261.26641-.30145394.48048-.01219156.21407.06079654.41038.21802994.56743l1.243691 1.24224 2.37084-1.02603c.15392-.06661.30331.14022.18601.25753l-1.66213 1.6621 1.46329 1.4616 1.66126-1.6613c.1173-.1173.32413.0321.25752.186l-1.02482 2.3682 1.25462 1.2531c.15724.157.35379.23.56815.2178.19095-.0561.35851-.1561.45869-.3234.20012-.3592.43577-.7455.68321-1.1511 1.22241-2.0039 2.73233-4.47901 1.66484-6.47533v-.49654zm-7.46715 6.55077c1.12692 1.12692.64113 2.69369-.05278 3.70149h-.50137l-3.13-3.1492v-.5c1.00858-.68566 2.56556-1.17088 3.68415-.05229z" fill-rule="evenodd"/> + </g> +</svg> ===================================== toolkit/components/selectivesavingmode/content/broom-saved.svg ===================================== @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g fill="context-fill" fill-opacity="context-fill-opacity"> + <path d="M1.31604 2.56132C1.07376 2.31905 0.680954 2.31905 0.438678 2.56132C0.196403 2.8036 0.196403 3.1964 0.438678 3.43868L12.3649 15.3649C12.6072 15.6072 13 15.6072 13.2423 15.3649C13.4845 15.1226 13.4845 14.7298 13.2423 14.4875L1.31604 2.56132Z" /> + <path d="M5.75301 6.99811C5.17481 7.10048 4.6182 7.36528 4.17 7.66998V8.16998L7.29989 11.3194H7.80184C8.11144 10.8697 8.37762 10.3082 8.47957 9.72467L9.40926 10.6544C9.01989 11.8129 8.31279 12.978 7.67977 14.0157C7.43234 14.4213 7.19629 14.8079 6.99617 15.1671C6.89602 15.3341 6.72885 15.4342 6.53817 15.4903C6.32389 15.5024 6.12701 15.4295 5.96981 15.2725L4.71492 14.0196L5.74031 11.6514C5.8069 11.4976 5.59983 11.3479 5.4825 11.4649L3.82137 13.126L2.3575 11.6651L4.01961 10.003C4.13689 9.88571 3.98795 9.67869 3.83406 9.74518L1.46297 10.7715L0.219804 9.52936C0.0625708 9.37231 -0.0111371 9.17507 0.00105446 8.961C0.0133896 8.74714 0.135367 8.58049 0.302812 8.48053C0.666747 8.27978 1.06126 8.03989 1.47664 7.78717C2.50628 7.16073 3.6674 6.45677 4.82332 6.06842L5.75301 6.99811ZM14.4375 0.182679C14.6816 -0.0610732 15.0773 -0.0611198 15.3213 0.182679C15.5654 0.426757 15.5654 0.823367 15.3213 1.06744L9.34481 7.04401V7.5401C9.6249 8.06391 9.72625 8.62084 9.70321 9.19342L6.28426 5.77545C6.86809 5.75137 7.43503 5.85671 7.96688 6.1485H8.47274L14.4375 0.182679Z" /> + </g> +</svg> ===================================== toolkit/components/selectivesavingmode/jar.mn ===================================== @@ -0,0 +1,7 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +toolkit.jar: + content/global/selectivesaving/broom-clean.svg (content/broom-clean.svg) + content/global/selectivesaving/broom-saved.svg (content/broom-saved.svg) ===================================== toolkit/components/selectivesavingmode/moz.build ===================================== @@ -0,0 +1,23 @@ +# 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/. + +XPCSHELL_TESTS_MANIFESTS += [ + "tests/xpcshell/xpcshell.toml", +] + +MOZ_SRC_FILES += [ + "SelectiveSavingMode.sys.mjs", +] + +XPCOM_MANIFESTS += [ + "components.conf", +] + +EXTRA_COMPONENTS += [ + "SelectiveSavingMode.manifest", +] + +JAR_MANIFESTS += [ + "jar.mn", +] ===================================== toolkit/components/selectivesavingmode/tests/xpcshell/test_selective_saving_mode.js ===================================== @@ -0,0 +1,755 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + SelectiveSavingPrefController, + SelectiveSavingModes, + kSelectiveSavingModePref, +} = ChromeUtils.importESModule( + "moz-src:///toolkit/components/selectivesavingmode/SelectiveSavingMode.sys.mjs" +); + +// secondary prefs +const kSanitizeOnShutdown = "privacy.sanitize.sanitizeOnShutdown"; +const kPrivateBrowsingAutostart = "browser.privatebrowsing.autostart"; +const kKeepPermissionInMemory = "permissions.memory_only"; + +const controller = new SelectiveSavingPrefController(); + +function resetToTotalSavingPrefs() { + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); +} + +registerCleanupFunction(async () => { + controller.shutdown(); +}); + +add_task(async function test_init_from_secondary_prefs() { + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.unconfigured + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "After pref controller init from unconfigured state, primary pref should be set to total clearing due to the way secondary prefs were set earlier" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.unconfigured + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "After pref controller init from unconfigured state, primary pref should be set to selective saving due to the way secondary prefs were set earlier" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.unconfigured + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "After pref controller init from unconfigured state, primary pref should be set to normal browsing due to the way secondary prefs were set earlier" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.unconfigured + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "After pref controller init from unconfigured state, primary pref should be set to custom browsing due to the way secondary prefs were set earlier" + ); + + controller.shutdown(); +}); + +add_task(async function test_init_from_secondary_prefs() { + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.total_clearing + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "After pref controller init from total clearing mode configured state (primary and secondary), primary pref shouldn't be changed from total clearing" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "After pref controller init from total clearing mode configured state (primary and secondary), secondary pref for sanitize on shutdown should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "After pref controller init from total clearing mode configured state (primary and secondary), secondary pref for pbm autostart should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + true, + "After pref controller init from total clearing mode configured state (primary and secondary), secondary pref for memory only permissions should be set to true" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.selective_saving + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "After pref controller init from selective saving configured state (primary and secondary), primary pref shouldn't be changed from selective saving" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "After pref controller init from selective saving mode configured state (primary and secondary), secondary pref for sanitize on shutdown should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "After pref controller init from selective saving mode configured state (primary and secondary), secondary pref for pbm autostart should be set to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "After pref controller init from selective saving mode configured state (primary and secondary), secondary pref for memory only permissions should be set to false" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.normal_browsing + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "After pref controller init from normal browsing mode configured state (primary and secondary), primary pref shouldn't be changed from normal browsing" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + false, + "After pref controller init from normal browsing mode configured state (primary and secondary), secondary pref for sanitize on shutdown should be set to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "After pref controller init from normal browsing mode configured state (primary and secondary), secondary pref for pbm autostart should be set to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "After pref controller init from normal browsing mode configured state (primary and secondary), secondary pref for memory only permissions should be set to false" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.custom + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "After pref controller init from custom mode configured state (primary and secondary), primary pref shouldn't be changed from custom" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "After pref contoller init from total clearing mode configured state (primary and secondary), secondary pref for sanitize on shutdown should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "After pref contoller init from total clearing mode configured state (primary and secondary), secondary pref for pbm autostart should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "After pref contoller init from total clearing mode configured state (primary and secondary), secondary pref for memory only permissions should be set to false" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.total_clearing + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "After pref controller init from configured state, primary pref shouldn't be changed from total clearing" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "After pref contoller init from total clearing mode configured state, secondary pref for sanitize on shutdown should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "After pref contoller init from total clearing mode configured state, secondary pref for pbm autostart should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + true, + "After pref contoller init from total clearing mode configured state, secondary pref for memory only permissions should be set to true" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.selective_saving + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "After pref controller init from configured state, primary pref shouldn't be changed from normal browsing" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "After pref contoller init from selective saving mode configured state, secondary pref for sanitize on shutdown should be set to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "After pref contoller init from selective saving mode configured state, secondary pref for pbm autostart should be set to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "After pref contoller init from selective saving mode configured state, secondary pref for memory only permissions should be set to false" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.normal_browsing + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "After pref controller init from configured state, primary pref shouldn't be changed from normal browsing" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + false, + "After pref contoller init from normal browsing mode configured state, secondary pref for sanitize on shutdown should be set to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "After pref contoller init from normal browsing mode configured state, secondary pref for pbm autostart should be set to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "After pref contoller init from normal browsing mode configured state, secondary pref for memory only permissions should be set to false" + ); + + controller.shutdown(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.custom + ); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + controller.init(); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "After pref controller init from configured state, primary pref shouldn't be changed from custom" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + false, + "After pref contoller init from custom mode configured state, secondary pref for sanitize on shutdown should remain unchanged" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "After pref contoller init from custom mode configured state, secondary pref for pbm autostart should remain unchanged" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "After pref contoller init from custom mode configured state, secondary pref for memory only permissions should remain unchanged" + ); +}); + +add_task(async function test_secondary_prefs_update_mode() { + controller.init(); + + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "After pref update mode should be set to total clearing" + ); + + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "After pref update mode should be set to selective saving" + ); + + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "After pref update mode should be set to normal browsing" + ); + + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "Duplicate for idempotency. after pref update mode should be set to normal browsing" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + false, + "Duplicate for idempotency. Changing browsing mode to normal browsing should set sanitize on shutdown to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "Duplicate for idempotency. Changing browsing mode to normal browsing should set pbm autostart to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "Duplicate for idempotency. Changing browsing mode to normal browsing should set memory only permissions to false" + ); + + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "After pref update mode should be set to custom" + ); + + resetToTotalSavingPrefs(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.custom + ); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "Manually changing to custom browsing via primary pref then changing secondary prefs to match another browsing mode should leave custom browsing" + ); + + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "Secondary Prefs set to (true, true, false) should result in Custom Browsing Mode" + ); + + Services.prefs.setBoolPref(kSanitizeOnShutdown, true); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "Secondary Prefs set to (true, false, true) should result in Custom Browsing Mode" + ); + + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "Secondary Prefs set to (false, false, true) should result in Custom Browsing Mode" + ); + + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "Secondary Prefs set to (false, true, false) should result in Custom Browsing Mode" + ); + + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, true); + Services.prefs.setBoolPref(kKeepPermissionInMemory, true); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "Secondary Prefs set to (false, true, true) should result in Custom Browsing Mode" + ); +}); + +add_task(async function test_mode_updates_from_secondary_prefs() { + controller.init(); + + Services.prefs.setBoolPref(kKeepPermissionInMemory, false); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, false); + Services.prefs.setBoolPref(kSanitizeOnShutdown, false); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.total_clearing + ); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "Changing browsing mode to total clearing should set browsing mode to match" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "Changing browsing mode to total clearing should set sanitize on shutdown to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "Changing browsing mode to total clearing should set pbm autostart to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + true, + "Changing browsing mode to total clearing should set memory only permissions to true" + ); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.total_clearing + ); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "Duplicate for idempotency. Changing browsing mode to total clearing should set browsing mode to match" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "Duplicate for idempotency. Changing browsing mode to total clearing should set sanitize on shutdown to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "Duplicate for idempotency. Changing browsing mode to total clearing should set pbm autostart to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + true, + "Duplicate for idempotency. Changing browsing mode to total clearing should set memory only permissions to true" + ); + + resetToTotalSavingPrefs(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.selective_saving + ); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "Changing browsing mode to selective saving should set browsing mode to match" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "Changing browsing mode to selective saving should set sanitize on shutdown to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "Changing browsing mode to selective saving should set pbm autostart to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "Changing browsing mode to selective saving should set memory only permissions to false" + ); + + resetToTotalSavingPrefs(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.normal_browsing + ); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "Changing browsing mode to normal browsing should set browsing mode to match" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + false, + "Changing browsing mode to normal browsing should set sanitize on shutdown to true" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + false, + "Changing browsing mode to normal browsing should set pbm autostart to false" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + false, + "Changing browsing mode to normal browsing should set memory only permissions to false" + ); + + resetToTotalSavingPrefs(); + + for (const sanitize of [false, true]) { + for (const pbmAutostart of [false, true]) { + for (const permissions of [false, true]) { + Services.prefs.setBoolPref(kSanitizeOnShutdown, sanitize); + Services.prefs.setBoolPref(kPrivateBrowsingAutostart, pbmAutostart); + Services.prefs.setBoolPref(kKeepPermissionInMemory, permissions); + + if (sanitize && pbmAutostart && permissions) { + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.total_clearing, + "pref settings for true true true should result in total clearing" + ); + } else if (sanitize && !pbmAutostart && !permissions) { + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.selective_saving, + "pref settings for true false false should result in selective saving" + ); + } else if (!sanitize && !pbmAutostart && !permissions) { + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.normal_browsing, + "pref settings for false false false should result in normal browsing" + ); + } else { + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + `pref settings of ${sanitize} ${pbmAutostart} ${permissions} should result in custom browsing` + ); + } + } + } + } + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.custom + ); + + Assert.equal( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.custom, + "Manually changing to custom browsing via primary pref should happen regardless of secondary prefs" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "Changing browsing mode to custom should leave sanitize on shutdown as previously set" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "Changing browsing mode to custom should leave pbm autostart as previously set" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + true, + "Changing browsing mode to custom should leave memory only permissions as previously set" + ); + + resetToTotalSavingPrefs(); + + Services.prefs.setIntPref( + kSelectiveSavingModePref, + SelectiveSavingModes.unconfigured + ); + + Assert.notEqual( + Services.prefs.getIntPref(kSelectiveSavingModePref), + SelectiveSavingModes.unconfigured, + "Manually changing to unconfigured mode via primary pref should set primary pref based on secondary prefs" + ); + + Assert.equal( + Services.prefs.getBoolPref(kSanitizeOnShutdown), + true, + "Changing browsing mode to unconfigured should leave sanitize on shutdown as previously set" + ); + + Assert.equal( + Services.prefs.getBoolPref(kPrivateBrowsingAutostart), + true, + "Changing browsing mode to unconfigured should leave pbm autostart to true as previously set" + ); + + Assert.equal( + Services.prefs.getBoolPref(kKeepPermissionInMemory), + true, + "Changing browsing mode to unconfigured should leave memory only permissions to true as previously set" + ); +}); ===================================== toolkit/components/selectivesavingmode/tests/xpcshell/xpcshell.toml ===================================== @@ -0,0 +1,7 @@ +[DEFAULT] +tags = "mullvad" +prefs = [ + "browser.selectiveSavingMode.enabled=true" +] + +["test_selective_saving_mode.js"] View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/59bc... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/59bc... You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help