/* 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/. */ Components.utils.import("resource://gre/modules/AppConstants.jsm"); Components.utils.import("resource://gre/modules/PluralForm.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm"); var gPrivacyPane = { /** * Whether the use has selected the auto-start private browsing mode in the UI. */ _autoStartPrivateBrowsing: false, /** * Whether the prompt to restart Firefox should appear when changing the autostart pref. */ _shouldPromptForRestart: true, #ifdef MOZ_SAFE_BROWSING /** * Show the Tracking Protection UI depending on the * privacy.trackingprotection.ui.enabled pref, and linkify its Learn More link */ _initTrackingProtection: function () { if (!Services.prefs.getBoolPref("privacy.trackingprotection.ui.enabled")) { return; } let link = document.getElementById("trackingProtectionLearnMore"); let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection"; link.setAttribute("href", url); this.trackingProtectionReadPrefs(); document.getElementById("trackingprotectionbox").hidden = false; document.getElementById("trackingprotectionpbmbox").hidden = true; }, /** * Linkify the Learn More link of the Private Browsing Mode Tracking * Protection UI. */ _initTrackingProtectionPBM: function () { let link = document.getElementById("trackingProtectionPBMLearnMore"); let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection-pbm"; link.setAttribute("href", url); }, #endif /** * Initialize autocomplete to ensure prefs are in sync. */ _initAutocomplete: function () { Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] .getService(Components.interfaces.mozIPlacesAutoComplete); }, /** * Sets up the UI for the number of days of history to keep, and updates the * label of the "Clear Now..." button. */ init: function () { function setEventListener(aId, aEventType, aCallback) { document.getElementById(aId) .addEventListener(aEventType, aCallback.bind(gPrivacyPane)); } this._updateSanitizeSettingsButton(); this.initializeHistoryMode(); this.updateHistoryModePane(); this.updatePrivacyMicroControls(); this.initAutoStartPrivateBrowsingReverter(); #ifdef MOZ_SAFE_BROWSING this._initTrackingProtection(); this._initTrackingProtectionPBM(); #endif this._initAutocomplete(); setEventListener("privacy.sanitize.sanitizeOnShutdown", "change", gPrivacyPane._updateSanitizeSettingsButton); setEventListener("browser.privatebrowsing.autostart", "change", gPrivacyPane.updatePrivacyMicroControls); setEventListener("historyMode", "command", function () { gPrivacyPane.updateHistoryModePane(); gPrivacyPane.updateHistoryModePrefs(); gPrivacyPane.updatePrivacyMicroControls(); gPrivacyPane.updateAutostart(); }); setEventListener("historyRememberClear", "click", function () { gPrivacyPane.clearPrivateDataNow(false); return false; }); setEventListener("historyRememberCookies", "click", function () { gPrivacyPane.showCookies(); return false; }); setEventListener("historyDontRememberClear", "click", function () { gPrivacyPane.clearPrivateDataNow(true); return false; }); #ifdef MOZ_SAFE_BROWSING setEventListener("doNotTrackSettings", "click", function () { gPrivacyPane.showDoNotTrackSettings(); return false; }); #endif setEventListener("privateBrowsingAutoStart", "command", gPrivacyPane.updateAutostart); setEventListener("cookieExceptions", "command", gPrivacyPane.showCookieExceptions); setEventListener("showCookiesButton", "command", gPrivacyPane.showCookies); setEventListener("clearDataSettings", "command", gPrivacyPane.showClearPrivateDataSettings); #ifdef MOZ_SAFE_BROWSING setEventListener("trackingProtectionRadioGroup", "command", gPrivacyPane.trackingProtectionWritePrefs); setEventListener("trackingProtectionExceptions", "command", gPrivacyPane.showTrackingProtectionExceptions); setEventListener("changeBlockList", "command", gPrivacyPane.showBlockLists); setEventListener("changeBlockListPBM", "command", gPrivacyPane.showBlockLists); #endif }, #ifdef MOZ_SAFE_BROWSING // TRACKING PROTECTION MODE /** * Selects the right item of the Tracking Protection radiogroup. */ trackingProtectionReadPrefs() { let enabledPref = document.getElementById("privacy.trackingprotection.enabled"); let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled"); let radiogroup = document.getElementById("trackingProtectionRadioGroup"); // Global enable takes precedence over enabled in Private Browsing. if (enabledPref.value) { radiogroup.value = "always"; } else if (pbmPref.value) { radiogroup.value = "private"; } else { radiogroup.value = "never"; } }, /** * Sets the pref values based on the selected item of the radiogroup. */ trackingProtectionWritePrefs() { let enabledPref = document.getElementById("privacy.trackingprotection.enabled"); let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled"); let radiogroup = document.getElementById("trackingProtectionRadioGroup"); switch (radiogroup.value) { case "always": enabledPref.value = true; pbmPref.value = true; break; case "private": enabledPref.value = false; pbmPref.value = true; break; case "never": enabledPref.value = false; pbmPref.value = false; break; } }, #endif // HISTORY MODE /** * The list of preferences which affect the initial history mode settings. * If the auto start private browsing mode pref is active, the initial * history mode would be set to "Don't remember anything". * If ALL of these preferences are set to the values that correspond * to keeping some part of history, and the auto-start * private browsing mode is not active, the initial history mode would be * set to "Remember everything". * Otherwise, the initial history mode would be set to "Custom". * * Extensions adding their own preferences can set values here if needed. */ prefsForKeepingHistory: { "places.history.enabled": true, // History is enabled "browser.formfill.enable": true, // Form information is saved "network.cookie.cookieBehavior": 0, // All cookies are enabled "network.cookie.lifetimePolicy": 0, // Cookies use supplied lifetime "privacy.sanitize.sanitizeOnShutdown": false, // Private date is NOT cleared on shutdown }, /** * The list of control IDs which are dependent on the auto-start private * browsing setting, such that in "Custom" mode they would be disabled if * the auto-start private browsing checkbox is checked, and enabled otherwise. * * Extensions adding their own controls can append their IDs to this array if needed. */ dependentControls: [ "rememberHistory", "rememberForms", "keepUntil", "keepCookiesUntil", "alwaysClear", "clearDataSettings" ], /** * Check whether preferences values are set to keep history * * @param aPrefs an array of pref names to check for * @returns boolean true if all of the prefs are set to keep history, * false otherwise */ _checkHistoryValues: function(aPrefs) { for (let pref of Object.keys(aPrefs)) { if (document.getElementById(pref).value != aPrefs[pref]) return false; } return true; }, /** * Initialize the history mode menulist based on the privacy preferences */ initializeHistoryMode: function PPP_initializeHistoryMode() { let mode; let getVal = aPref => document.getElementById(aPref).value; if (this._checkHistoryValues(this.prefsForKeepingHistory)) { if (getVal("browser.privatebrowsing.autostart")) mode = "dontremember"; else mode = "remember"; } else mode = "custom"; document.getElementById("historyMode").value = mode; }, /** * Update the selected pane based on the history mode menulist */ updateHistoryModePane: function PPP_updateHistoryModePane() { let selectedIndex = -1; switch (document.getElementById("historyMode").value) { case "remember": selectedIndex = 0; break; case "dontremember": selectedIndex = 1; break; case "custom": selectedIndex = 2; break; } document.getElementById("historyPane").selectedIndex = selectedIndex; }, /** * Update the private browsing auto-start pref and the history mode * micro-management prefs based on the history mode menulist */ updateHistoryModePrefs: function PPP_updateHistoryModePrefs() { let pref = document.getElementById("browser.privatebrowsing.autostart"); switch (document.getElementById("historyMode").value) { case "remember": if (pref.value) pref.value = false; // select the remember history option if needed let rememberHistoryCheckbox = document.getElementById("rememberHistory"); if (!rememberHistoryCheckbox.checked) rememberHistoryCheckbox.checked = true; // select the remember forms history option document.getElementById("browser.formfill.enable").value = true; // select the allow cookies option document.getElementById("network.cookie.cookieBehavior").value = 0; // select the cookie lifetime policy option document.getElementById("network.cookie.lifetimePolicy").value = 0; // select the clear on close option document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false; break; case "dontremember": if (!pref.value) pref.value = true; break; } }, /** * Update the privacy micro-management controls based on the * value of the private browsing auto-start checkbox. */ updatePrivacyMicroControls: function PPP_updatePrivacyMicroControls() { if (document.getElementById("historyMode").value == "custom") { let disabled = this._autoStartPrivateBrowsing = document.getElementById("privateBrowsingAutoStart").checked; this.dependentControls.forEach(function (aElement) { let control = document.getElementById(aElement); let preferenceId = control.getAttribute("preference"); if (!preferenceId) { let dependentControlId = control.getAttribute("control"); if (dependentControlId) { let dependentControl = document.getElementById(dependentControlId); preferenceId = dependentControl.getAttribute("preference"); } } let preference = preferenceId ? document.getElementById(preferenceId) : {}; control.disabled = disabled || preference.locked; }); // adjust the cookie controls status this.readAcceptCookies(); let lifetimePolicy = document.getElementById("network.cookie.lifetimePolicy").value; if (lifetimePolicy != Ci.nsICookieService.ACCEPT_NORMALLY && lifetimePolicy != Ci.nsICookieService.ACCEPT_SESSION && lifetimePolicy != Ci.nsICookieService.ACCEPT_FOR_N_DAYS) { lifetimePolicy = Ci.nsICookieService.ACCEPT_NORMALLY; } document.getElementById("keepCookiesUntil").value = disabled ? 2 : lifetimePolicy; // adjust the checked state of the sanitizeOnShutdown checkbox document.getElementById("alwaysClear").checked = disabled ? false : document.getElementById("privacy.sanitize.sanitizeOnShutdown").value; // adjust the checked state of the remember history checkboxes document.getElementById("rememberHistory").checked = disabled ? false : document.getElementById("places.history.enabled").value; document.getElementById("rememberForms").checked = disabled ? false : document.getElementById("browser.formfill.enable").value; if (!disabled) { // adjust the Settings button for sanitizeOnShutdown this._updateSanitizeSettingsButton(); } } }, // PRIVATE BROWSING /** * Initialize the starting state for the auto-start private browsing mode pref reverter. */ initAutoStartPrivateBrowsingReverter: function PPP_initAutoStartPrivateBrowsingReverter() { let mode = document.getElementById("historyMode"); let autoStart = document.getElementById("privateBrowsingAutoStart"); this._lastMode = mode.selectedIndex; this._lastCheckState = autoStart.hasAttribute('checked'); }, _lastMode: null, _lastCheckState: null, updateAutostart: function PPP_updateAutostart() { let mode = document.getElementById("historyMode"); let autoStart = document.getElementById("privateBrowsingAutoStart"); let pref = document.getElementById("browser.privatebrowsing.autostart"); if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) || (mode.value == "remember" && !this._lastCheckState) || (mode.value == "dontremember" && this._lastCheckState)) { // These are all no-op changes, so we don't need to prompt. this._lastMode = mode.selectedIndex; this._lastCheckState = autoStart.hasAttribute('checked'); return; } if (!this._shouldPromptForRestart) { // We're performing a revert. Just let it happen. return; } let buttonIndex = confirmRestartPrompt(autoStart.checked, 1, true, false); if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { pref.value = autoStart.hasAttribute('checked'); let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"] .getService(Ci.nsIAppStartup); appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); return; } this._shouldPromptForRestart = false; if (this._lastCheckState) { autoStart.checked = "checked"; } else { autoStart.removeAttribute('checked'); } pref.value = autoStart.hasAttribute('checked'); mode.selectedIndex = this._lastMode; mode.doCommand(); this._shouldPromptForRestart = true; }, #ifdef MOZ_SAFE_BROWSING /** * Displays fine-grained, per-site preferences for tracking protection. */ showTrackingProtectionExceptions() { let bundlePreferences = document.getElementById("bundlePreferences"); let params = { permissionType: "trackingprotection", hideStatusColumn: true, windowTitle: bundlePreferences.getString("trackingprotectionpermissionstitle"), introText: bundlePreferences.getString("trackingprotectionpermissionstext"), }; gSubDialog.open("chrome://browser/content/preferences/permissions.xul", null, params); }, #endif #ifdef MOZ_SAFE_BROWSING /** * Displays the available block lists for tracking protection. */ showBlockLists: function () { var bundlePreferences = document.getElementById("bundlePreferences"); let brandName = document.getElementById("bundleBrand") .getString("brandShortName"); var params = { brandShortName: brandName, windowTitle: bundlePreferences.getString("blockliststitle"), introText: bundlePreferences.getString("blockliststext") }; gSubDialog.open("chrome://browser/content/preferences/blocklists.xul", null, params); }, /** * Displays the Do Not Track settings dialog. */ showDoNotTrackSettings() { gSubDialog.open("chrome://browser/content/preferences/donottrack.xul", "resizable=no"); }, #endif // HISTORY /* * Preferences: * * places.history.enabled * - whether history is enabled or not * browser.formfill.enable * - true if entries in forms and the search bar should be saved, false * otherwise */ // COOKIES /* * Preferences: * * network.cookie.cookieBehavior * - determines how the browser should handle cookies: * 0 means enable all cookies * 1 means reject all third party cookies * 2 means disable all cookies * 3 means reject third party cookies unless at least one is already set for the eTLD * see netwerk/cookie/src/nsCookieService.cpp for details * network.cookie.lifetimePolicy * - determines how long cookies are stored: * 0 means keep cookies until they expire * 2 means keep cookies until the browser is closed */ /** * Reads the network.cookie.cookieBehavior preference value and * enables/disables the rest of the cookie UI accordingly, returning true * if cookies are enabled. */ readAcceptCookies: function () { var pref = document.getElementById("network.cookie.cookieBehavior"); var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel"); var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu"); var keepUntil = document.getElementById("keepUntil"); var menu = document.getElementById("keepCookiesUntil"); // enable the rest of the UI for anything other than "disable all cookies" var acceptCookies = (pref.value != 2); acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies; keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies; return acceptCookies; }, /** * Enables/disables the "keep until" label and menulist in response to the * "accept cookies" checkbox being checked or unchecked. */ writeAcceptCookies: function () { var accept = document.getElementById("acceptCookies"); var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu"); // if we're enabling cookies, automatically select 'accept third party always' if (accept.checked) acceptThirdPartyMenu.selectedIndex = 0; return accept.checked ? 0 : 2; }, /** * Converts between network.cookie.cookieBehavior and the third-party cookie UI */ readAcceptThirdPartyCookies: function () { var pref = document.getElementById("network.cookie.cookieBehavior"); switch (pref.value) { case 0: return "always"; case 1: return "never"; case 2: return "never"; case 3: return "visited"; default: return undefined; } }, writeAcceptThirdPartyCookies: function () { var accept = document.getElementById("acceptThirdPartyMenu").selectedItem; switch (accept.value) { case "always": return 0; case "visited": return 3; case "never": return 1; default: return undefined; } }, /** * Displays fine-grained, per-site preferences for cookies. */ showCookieExceptions: function () { var bundlePreferences = document.getElementById("bundlePreferences"); var params = { blockVisible : true, sessionVisible : true, allowVisible : true, prefilledHost : "", permissionType : "cookie", windowTitle : bundlePreferences.getString("cookiepermissionstitle"), introText : bundlePreferences.getString("cookiepermissionstext") }; gSubDialog.open("chrome://browser/content/preferences/permissions.xul", null, params); }, /** * Displays all the user's cookies in a dialog. */ showCookies: function (aCategory) { gSubDialog.open("chrome://browser/content/preferences/cookies.xul"); }, // CLEAR PRIVATE DATA /* * Preferences: * * privacy.sanitize.sanitizeOnShutdown * - true if the user's private data is cleared on startup according to the * Clear Private Data settings, false otherwise */ /** * Displays the Clear Private Data settings dialog. */ showClearPrivateDataSettings: function () { gSubDialog.open("chrome://browser/content/preferences/sanitize.xul", "resizable=no"); }, /** * Displays a dialog from which individual parts of private data may be * cleared. */ clearPrivateDataNow: function (aClearEverything) { var ts = document.getElementById("privacy.sanitize.timeSpan"); var timeSpanOrig = ts.value; if (aClearEverything) { ts.value = 0; } gSubDialog.open("chrome://browser/content/sanitize.xul", "resizable=no", null, () => { // reset the timeSpan pref if (aClearEverything) { ts.value = timeSpanOrig; } Services.obs.notifyObservers(null, "clear-private-data", null); }); }, /** * Enables or disables the "Settings..." button depending * on the privacy.sanitize.sanitizeOnShutdown preference value */ _updateSanitizeSettingsButton: function () { var settingsButton = document.getElementById("clearDataSettings"); var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown"); settingsButton.disabled = !sanitizeOnShutdownPref.value; }, };