diff options
Diffstat (limited to 'browser/components/preferences/in-content/privacy.js')
-rw-r--r-- | browser/components/preferences/in-content/privacy.js | 712 |
1 files changed, 712 insertions, 0 deletions
diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js new file mode 100644 index 000000000..7dfc7de5a --- /dev/null +++ b/browser/components/preferences/in-content/privacy.js @@ -0,0 +1,712 @@ +/* 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, "ContextualIdentityService", + "resource://gre/modules/ContextualIdentityService.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, + + /** + * 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); + }, + + /** + * Initialize autocomplete to ensure prefs are in sync. + */ + _initAutocomplete: function () { + Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] + .getService(Components.interfaces.mozIPlacesAutoComplete); + }, + + /** + * Show the Containers UI depending on the privacy.userContext.ui.enabled pref. + */ + _initBrowserContainers: function () { + if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) { + return; + } + + let link = document.getElementById("browserContainersLearnMore"); + link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers"; + + document.getElementById("browserContainersbox").hidden = false; + + document.getElementById("browserContainersCheckbox").checked = + Services.prefs.getBoolPref("privacy.userContext.enabled"); + }, + + _checkBrowserContainers: function(event) { + let checkbox = document.getElementById("browserContainersCheckbox"); + if (checkbox.checked) { + Services.prefs.setBoolPref("privacy.userContext.enabled", true); + return; + } + + let count = ContextualIdentityService.countContainerTabs(); + if (count == 0) { + Services.prefs.setBoolPref("privacy.userContext.enabled", false); + return; + } + + let bundlePreferences = document.getElementById("bundlePreferences"); + + let title = bundlePreferences.getString("disableContainersAlertTitle"); + let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg")) + .replace("#S", count) + let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton")) + .replace("#S", count) + let cancelButton = bundlePreferences.getString("disableContainersButton2"); + + let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) + + (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1); + + let rv = Services.prompt.confirmEx(window, title, message, buttonFlags, + okButton, cancelButton, null, null, {}); + if (rv == 0) { + ContextualIdentityService.closeAllContainerTabs(); + Services.prefs.setBoolPref("privacy.userContext.enabled", false); + return; + } + + checkbox.checked = true; + }, + + /** + * 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(); + this._initTrackingProtection(); + this._initTrackingProtectionPBM(); + this._initAutocomplete(); + this._initBrowserContainers(); + + 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; + }); + setEventListener("doNotTrackSettings", "click", function () { + gPrivacyPane.showDoNotTrackSettings(); + return false; + }); + setEventListener("privateBrowsingAutoStart", "command", + gPrivacyPane.updateAutostart); + setEventListener("cookieExceptions", "command", + gPrivacyPane.showCookieExceptions); + setEventListener("showCookiesButton", "command", + gPrivacyPane.showCookies); + setEventListener("clearDataSettings", "command", + gPrivacyPane.showClearPrivateDataSettings); + setEventListener("trackingProtectionRadioGroup", "command", + gPrivacyPane.trackingProtectionWritePrefs); + setEventListener("trackingProtectionExceptions", "command", + gPrivacyPane.showTrackingProtectionExceptions); + setEventListener("changeBlockList", "command", + gPrivacyPane.showBlockLists); + setEventListener("changeBlockListPBM", "command", + gPrivacyPane.showBlockLists); + setEventListener("browserContainersCheckbox", "command", + gPrivacyPane._checkBrowserContainers); + setEventListener("browserContainersSettings", "command", + gPrivacyPane.showContainerSettings); + }, + + // 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; + } + }, + + // 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; + }, + + /** + * 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); + }, + + /** + * Displays container panel for customising and adding containers. + */ + showContainerSettings() { + gotoPref("containers"); + }, + + /** + * 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"); + }, + + // 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; + }, + + // CONTAINERS + + /* + * preferences: + * + * privacy.userContext.enabled + * - true if containers is enabled + */ + + /** + * Enables/disables the Settings button used to configure containers + */ + readBrowserContainersCheckbox: function () + { + var pref = document.getElementById("privacy.userContext.enabled"); + var settings = document.getElementById("browserContainersSettings"); + + settings.disabled = !pref.value; + } + +}; |