--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1365,16 +1365,23 @@ var gBrowserInit = {
Cu.reportError(e);
}
}
// Wait until chrome is painted before executing code not critical to making the window visible
this._boundDelayedStartup = this._delayedStartup.bind(this);
window.addEventListener("MozAfterPaint", this._boundDelayedStartup);
+ if (!PrivateBrowsingUtils.enabled) {
+ document.getElementById("Tools:PrivateBrowsing").hidden = true;
+ // Setting disabled doesn't disable the shortcut, so we just remove
+ // the keybinding.
+ document.getElementById("key_privatebrowsing").remove();
+ }
+
this._loadHandled = true;
},
_cancelDelayedStartup() {
window.removeEventListener("MozAfterPaint", this._boundDelayedStartup);
this._boundDelayedStartup = null;
},
@@ -1966,16 +1973,19 @@ if (AppConstants.platform == "macosx") {
} catch (e) {
}
}
}
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
document.getElementById("macDockMenuNewWindow").hidden = true;
}
+ if (!PrivateBrowsingUtils.enabled) {
+ document.getElementById("macDockMenuNewPrivateWindow").hidden = true;
+ }
this._delayedStartupTimeoutId = setTimeout(this.nonBrowserWindowDelayedStartup.bind(this), 0);
};
gBrowserInit.nonBrowserWindowDelayedStartup = function() {
this._delayedStartupTimeoutId = null;
// initialise the offline listener
@@ -4134,17 +4144,17 @@ function OpenBrowserWindow(options) {
TelemetryStopwatch.start("FX_NEW_WINDOW_MS", telemetryObj);
var handler = Cc["@mozilla.org/browser/clh;1"]
.getService(Ci.nsIBrowserHandler);
var defaultArgs = handler.defaultArgs;
var wintype = document.documentElement.getAttribute("windowtype");
var extraFeatures = "";
- if (options && options.private) {
+ if (options && options.private && PrivateBrowsingUtils.enabled) {
extraFeatures = ",private";
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
// Force the new window to load about:privatebrowsing instead of the default home page
defaultArgs = "about:privatebrowsing";
}
} else {
extraFeatures = ",non-private";
}
--- a/browser/base/content/macBrowserOverlay.xul
+++ b/browser/base/content/macBrowserOverlay.xul
@@ -53,13 +53,14 @@
<!-- Dock menu -->
<popupset>
<menupopup id="menu_mac_dockmenu">
<!-- The command cannot be cmd_newNavigator because we need to activate
the application. -->
<menuitem label="&newNavigatorCmd.label;" oncommand="OpenBrowserWindowFromDockMenu();"
id="macDockMenuNewWindow" />
- <menuitem label="&newPrivateWindow.label;" oncommand="OpenBrowserWindowFromDockMenu({private: true});" />
+ <menuitem label="&newPrivateWindow.label;" oncommand="OpenBrowserWindowFromDockMenu({private: true});"
+ id="macDockMenuNewPrivateWindow" />
</menupopup>
</popupset>
</overlay>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -353,17 +353,17 @@ nsContextMenu.prototype = {
gBrowserBundle.formatStringFromName("userContextOpenLink.label",
[label], 1));
}
var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
var showContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
this.showItem("context-openlink", shouldShow && !isWindowPrivate);
- this.showItem("context-openlinkprivate", shouldShow);
+ this.showItem("context-openlinkprivate", shouldShow && PrivateBrowsingUtils.enabled);
this.showItem("context-openlinkintab", shouldShow && !inContainer);
this.showItem("context-openlinkincontainertab", shouldShow && inContainer);
this.showItem("context-openlinkinusercontext-menu", shouldShow && !isWindowPrivate && showContainers);
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
this.showItem("context-sep-open", shouldShow);
},
initNavigationItems: function CM_initNavigationItems() {
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -234,23 +234,16 @@ const CustomizableWidgets = [
} else {
element.classList.add("subviewbutton-iconic", "bookmark-item");
}
}
panelview.appendChild(body);
panelview.appendChild(footer);
}
}, {
- id: "privatebrowsing-button",
- shortcutId: "key_privatebrowsing",
- onCommand(e) {
- let win = e.target.ownerGlobal;
- win.OpenBrowserWindow({private: true});
- }
- }, {
id: "save-page-button",
shortcutId: "key_savePage",
tooltiptext: "save-page-button.tooltiptext3",
onCommand(aEvent) {
let win = aEvent.target.ownerGlobal;
win.saveBrowser(win.gBrowser.selectedBrowser);
}
}, {
@@ -943,8 +936,19 @@ if (Services.prefs.getBoolPref("privacy.
forgetButton.addEventListener("command", this);
},
onViewHiding(aEvent) {
let forgetButton = aEvent.target.querySelector("#PanelUI-panic-view-button");
forgetButton.removeEventListener("command", this);
},
});
}
+
+if (PrivateBrowsingUtils.enabled) {
+ CustomizableWidgets.push({
+ id: "privatebrowsing-button",
+ shortcutId: "key_privatebrowsing",
+ onCommand(e) {
+ let win = e.target.ownerGlobal;
+ win.OpenBrowserWindow({private: true});
+ }
+ });
+}
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -167,16 +167,27 @@ var Policies = {
"DisablePocket": {
onBeforeAddons(manager, param) {
if (param) {
setAndLockPref("extensions.pocket.enabled", false);
}
}
},
+ "DisablePrivateBrowsing": {
+ onBeforeAddons(manager, param) {
+ if (param) {
+ manager.disallowFeature("privatebrowsing");
+ manager.disallowFeature("about:privatebrowsing", true);
+ setAndLockPref("browser.privatebrowsing.autostart", false);
+ }
+ }
+ },
+
+
"DisplayBookmarksToolbar": {
onBeforeUIStartup(manager, param) {
if (param) {
// This policy is meant to change the default behavior, not to force it.
// If this policy was alreay applied and the user chose to re-hide the
// bookmarks toolbar, do not show it again.
runOnce("displayBookmarksToolbar", () => {
gXulStore.setValue(BROWSER_DOCUMENT_URL, "PersonalToolbar", "collapsed", "false");
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -148,16 +148,24 @@
"DisablePocket": {
"description": "Prevents ability to save webpages to Pocket.",
"first_available": "60.0",
"type": "boolean",
"enum": [true]
},
+ "DisablePrivateBrowsing": {
+ "description": "Disables private browsing.",
+ "first_available": "60.0",
+
+ "type": "boolean",
+ "enum": [true]
+ },
+
"DisplayBookmarksToolbar": {
"description": "Causes the bookmarks toolbar to be displayed by default.",
"first_available": "60.0",
"type": "boolean",
"enum": [true]
},
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini
+++ b/browser/components/enterprisepolicies/tests/browser/browser.ini
@@ -20,12 +20,13 @@ support-files =
[browser_policy_block_about_support.js]
[browser_policy_block_set_desktop_background.js]
[browser_policy_bookmarks.js]
[browser_policy_default_browser_check.js]
[browser_policy_disable_formhistory.js]
[browser_policy_disable_fxscreenshots.js]
[browser_policy_disable_masterpassword.js]
[browser_policy_disable_pocket.js]
+[browser_policy_disable_privatebrowsing.js]
[browser_policy_disable_shield.js]
[browser_policy_display_bookmarks.js]
[browser_policy_display_menu.js]
[browser_policy_remember_passwords.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_privatebrowsing.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
+
+add_task(async function setup() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "DisablePrivateBrowsing": true
+ }
+ });
+});
+
+add_task(async function test_menu_shown() {
+ 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.closeWindow(newWin);
+});
--- a/browser/components/extensions/ext-windows.js
+++ b/browser/components/extensions/ext-windows.js
@@ -123,16 +123,19 @@ this.windows = class extends ExtensionAP
let tab = tabTracker.getTab(createData.tabId);
// Private browsing tabs can only be moved to private browsing
// windows.
let incognito = PrivateBrowsingUtils.isBrowserPrivate(tab.linkedBrowser);
if (createData.incognito !== null && createData.incognito != incognito) {
return Promise.reject({message: "`incognito` property must match the incognito state of tab"});
}
+ if (createData.incognito && !PrivateBrowsingUtils.enabled) {
+ return Promise.reject({message: "`incognito` cannot be used if incognito mode is disabled"});
+ }
createData.incognito = incognito;
args.appendElement(tab);
} else if (createData.url !== null) {
if (Array.isArray(createData.url)) {
let array = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
for (let url of createData.url) {
array.appendElement(mkstr(url));
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -376,17 +376,17 @@ nsBrowserContentHandler.prototype = {
let localSchemes = new Set(["chrome", "file", "resource"]);
if (uri instanceof Ci.nsINestedURI) {
uri = uri.QueryInterface(Ci.nsINestedURI).innerMostURI;
}
return localSchemes.has(uri.scheme);
};
if (isLocal(resolvedURI)) {
// If the URI is local, we are sure it won't wrongly inherit chrome privs
- var features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
+ let features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
openWindow(null, resolvedURI.spec, "_blank", features);
cmdLine.preventDefault = true;
} else {
dump("*** Preventing load of web URI as chrome\n");
dump(" If you're trying to load a webpage, do not pass --chrome.\n");
}
} catch (e) {
Cu.reportError(e);
@@ -397,43 +397,55 @@ nsBrowserContentHandler.prototype = {
cmdLine.preventDefault = true;
}
if (cmdLine.handleFlag("silent", false))
cmdLine.preventDefault = true;
try {
var privateWindowParam = cmdLine.handleFlagWithParam("private-window", false);
if (privateWindowParam) {
- let resolvedURI = resolveURIInternal(cmdLine, privateWindowParam);
- handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true,
+ let forcePrivate = true;
+ let resolvedURI;
+ if (!PrivateBrowsingUtils.enabled) {
+ // Load about:privatebrowsing in a normal tab, which will display an error indicating
+ // access to private browsing has been disabled.
+ forcePrivate = false;
+ resolvedURI = Services.io.newURI("about:privatebrowsing");
+ } else {
+ resolvedURI = resolveURIInternal(cmdLine, privateWindowParam);
+ }
+ handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, forcePrivate,
Services.scriptSecurityManager.getSystemPrincipal());
- cmdLine.preventDefault = true;
}
} catch (e) {
if (e.result != Cr.NS_ERROR_INVALID_ARG) {
throw e;
}
// NS_ERROR_INVALID_ARG is thrown when flag exists, but has no param.
if (cmdLine.handleFlag("private-window", false)) {
+ let features = "chrome,dialog=no,all";
+ if (PrivateBrowsingUtils.enabled) {
+ features += ",private";
+ }
openWindow(null, this.chromeURL, "_blank",
- "chrome,dialog=no,private,all" + this.getFeatures(cmdLine),
+ features + this.getFeatures(cmdLine),
"about:privatebrowsing");
cmdLine.preventDefault = true;
}
}
var searchParam = cmdLine.handleFlagWithParam("search", false);
if (searchParam) {
doSearch(searchParam, cmdLine);
cmdLine.preventDefault = true;
}
// The global PB Service consumes this flag, so only eat it in per-window
// PB builds.
- if (cmdLine.handleFlag("private", false)) {
+ if (cmdLine.handleFlag("private", false) && PrivateBrowsingUtils.enabled) {
PrivateBrowsingUtils.enterTemporaryAutoStartMode();
}
var fileParam = cmdLine.handleFlagWithParam("file", false);
if (fileParam) {
var file = cmdLine.resolveFile(fileParam);
var fileURI = Services.io.newFileURI(file);
openWindow(null, this.chromeURL, "_blank",
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -467,16 +467,20 @@ PlacesController.prototype = {
* @param aMenuItem
* the context menu item
* @param aMetaData
* meta data about the selection
* @return true if the conditions (see buildContextMenu) are satisfied
* and the item can be displayed, false otherwise.
*/
_shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) {
+ if (aMenuItem.hasAttribute("hideifprivatebrowsing") && !PrivateBrowsingUtils.enabled) {
+ return false;
+ }
+
var selectiontype = aMenuItem.getAttribute("selectiontype");
if (!selectiontype) {
selectiontype = "single|multiple";
}
var selectionTypes = selectiontype.split("|");
if (selectionTypes.includes("any")) {
return true;
}
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -454,16 +454,21 @@ var gPrivacyPane = {
pkiBundle.getString("enable_fips"),
]);
appendSearchKeywords("siteDataSettings", [
bundlePrefs.getString("siteDataSettings2.description"),
bundlePrefs.getString("removeAllCookies.label"),
bundlePrefs.getString("removeSelectedCookies.label"),
]);
+ if (!PrivateBrowsingUtils.enabled) {
+ document.getElementById("privateBrowsingAutoStart").hidden = true;
+ document.querySelector("menuitem[value='dontremember']").hidden = true;
+ }
+
// Notify observers that the UI is now ready
Services.obs.notifyObservers(window, "privacy-pane-loaded");
},
// TRACKING PROTECTION MODE
/**
* Selects the right item of the Tracking Protection radiogroup.
--- a/browser/components/syncedtabs/TabListView.js
+++ b/browser/components/syncedtabs/TabListView.js
@@ -1,16 +1,19 @@
/* 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";
ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
+ "resource://gre/modules/PrivateBrowsingUtils.jsm");
+
let { getChromeWindow } = ChromeUtils.import("resource:///modules/syncedtabs/util.js", {});
let log = ChromeUtils.import("resource://gre/modules/Log.jsm", {})
.Log.repository.getLogger("Sync.RemoteTabs");
var EXPORTED_SYMBOLS = [
"TabListView"
];
@@ -515,18 +518,20 @@ TabListView.prototype = {
let item = this.container.querySelector(".item.selected");
let showTabOptions = this._isTab(item);
let el = menu.firstChild;
while (el) {
let show = false;
if (showTabOptions) {
- if (el.getAttribute("id") != "syncedTabsOpenAllInTabs" &&
- el.getAttribute("id") != "syncedTabsManageDevices") {
+ if (el.getAttribute("id") == "syncedTabsOpenSelectedInPrivateWindow") {
+ show = PrivateBrowsingUtils.enabled;
+ } else if (el.getAttribute("id") != "syncedTabsOpenAllInTabs" &&
+ el.getAttribute("id") != "syncedTabsManageDevices") {
show = true;
}
} else if (el.getAttribute("id") == "syncedTabsOpenAllInTabs") {
const tabs = item.querySelectorAll(".item-tabs-list > .item.tab");
show = tabs.length > 0;
} else if (el.getAttribute("id") == "syncedTabsRefresh") {
show = true;
} else if (el.getAttribute("id") == "syncedTabsManageDevices") {
--- a/browser/modules/WindowsJumpLists.jsm
+++ b/browser/modules/WindowsJumpLists.jsm
@@ -96,28 +96,28 @@ var tasksCfg = [
get title() { return _getString("taskbar.tasks.newWindow.label"); },
get description() { return _getString("taskbar.tasks.newWindow.description"); },
args: "-browser",
iconIndex: 2, // New tab icon
open: true,
close: true, // No point, but we don't always update the list on
// shutdown. Thus true for consistency.
},
+];
- // Open new private window
- {
- get title() { return _getString("taskbar.tasks.newPrivateWindow.label"); },
- get description() { return _getString("taskbar.tasks.newPrivateWindow.description"); },
- args: "-private-window",
- iconIndex: 4, // Private browsing mode icon
- open: true,
- close: true, // No point, but we don't always update the list on
- // shutdown. Thus true for consistency.
- },
-];
+// Open new private window
+let privateWindowTask = {
+ get title() { return _getString("taskbar.tasks.newPrivateWindow.label"); },
+ get description() { return _getString("taskbar.tasks.newPrivateWindow.description"); },
+ args: "-private-window",
+ iconIndex: 4, // Private browsing mode icon
+ open: true,
+ close: true, // No point, but we don't always update the list on
+ // shutdown. Thus true for consistency.
+};
// Implementation
var WinTaskbarJumpList =
{
_builder: null,
_tasks: null,
_shuttingDown: false,
@@ -129,16 +129,20 @@ var WinTaskbarJumpList =
startup: function WTBJL_startup() {
// exit if this isn't win7 or higher.
if (!this._initTaskbar())
return;
// Store our task list config data
this._tasks = tasksCfg;
+ if (PrivateBrowsingUtils.enabled) {
+ tasksCfg.push(privateWindowTask);
+ }
+
// retrieve taskbar related prefs.
this._refreshPrefs();
// observer for private browsing and our prefs branch
this._initObs();
// jump list refresh timer
this._updateTimer();
--- a/toolkit/modules/PrivateBrowsingUtils.jsm
+++ b/toolkit/modules/PrivateBrowsingUtils.jsm
@@ -8,16 +8,20 @@ ChromeUtils.import("resource://gre/modul
const kAutoStartPref = "browser.privatebrowsing.autostart";
// This will be set to true when the PB mode is autostarted from the command
// line for the current session.
var gTemporaryAutoStartMode = false;
var PrivateBrowsingUtils = {
+ get enabled() {
+ return Services.policies.isAllowed("privatebrowsing");
+ },
+
// Rather than passing content windows to this function, please use
// isBrowserPrivate since it works with e10s.
isWindowPrivate: function pbu_isWindowPrivate(aWindow) {
if (!aWindow.isChromeWindow) {
dump("WARNING: content window passed to PrivateBrowsingUtils.isWindowPrivate. " +
"Use isContentWindowPrivate instead (but only for frame scripts).\n"
+ new Error().stack);
}