Bug 1846498 - Add a restart PBM session button and panel for private windows. r=desktop-theme-reviewers,mconley,dao

Differential Revision: https://phabricator.services.mozilla.com/D187223
This commit is contained in:
Paul Zuehlcke 2023-09-27 15:14:36 +00:00
Родитель b7fd479f26
Коммит 4c51feffea
13 изменённых файлов: 341 добавлений и 3 удалений

Просмотреть файл

@ -2879,3 +2879,9 @@ pref("cookiebanners.ui.desktop.cfrVariant", 0);
#ifdef NIGHTLY_BUILD
pref("dom.security.credentialmanagement.identity.enabled", true);
#endif
// Reset Private Browsing Session feature
pref("browser.privatebrowsing.resetPBM.enabled", false);
// Whether the reset private browsing panel should ask for confirmation before
// performing the clear action.
pref("browser.privatebrowsing.resetPBM.showConfirmationDialog", true);

Просмотреть файл

@ -687,4 +687,27 @@
onclick="ToolbarPanelHub.toggleWhatsNewPref(event)"
data-l10n-id="whatsnew-panel-footer-checkbox"/>
</panelview>
<panelview id="reset-pbm-panel" class="PanelUI-subView">
<hbox id="reset-pbm-panel-container">
<hbox id="reset-pbm-panel-header">
<description data-l10n-id="reset-pbm-panel-heading"/>
</hbox>
<description id="reset-pbm-panel-description" data-l10n-id="reset-pbm-panel-description"/>
<checkbox id="reset-pbm-panel-checkbox" data-l10n-id="reset-pbm-panel-always-ask-checkbox"/>
<html:moz-button-group id="reset-pbm-panel-footer" class="panel-footer">
<button id="reset-pbm-panel-cancel-button"
class="panel-footer-button"
data-l10n-id="reset-pbm-panel-cancel-button"
oncommand="ResetPBMPanel.onCancel(this)"></button>
<button slot="primary"
id="reset-pbm-panel-confirm-button"
class="panel-footer-button"
data-l10n-id="reset-pbm-panel-confirm-button"
oncommand="ResetPBMPanel.onConfirm(this)"></button>
</html:moz-button-group>
</hbox>
</panelview>
</html:template>

Просмотреть файл

@ -63,6 +63,7 @@ ChromeUtils.defineESModuleGetters(this, {
PromiseUtils: "resource://gre/modules/PromiseUtils.sys.mjs",
PromptUtils: "resource://gre/modules/PromptUtils.sys.mjs",
ReaderMode: "resource://gre/modules/ReaderMode.sys.mjs",
ResetPBMPanel: "resource:///modules/ResetPBMPanel.sys.mjs",
SafeBrowsing: "resource://gre/modules/SafeBrowsing.sys.mjs",
Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
SaveToPocket: "chrome://pocket/content/SaveToPocket.sys.mjs",
@ -9739,6 +9740,7 @@ var ConfirmationHint = {
* An object with the following optional properties:
* - event (DOM event): The event that triggered the feedback
* - descriptionId (string): message ID of the description text
* - position (string): position of the panel relative to the anchor.
*
*/
show(anchor, messageId, options = {}) {
@ -9784,7 +9786,7 @@ var ConfirmationHint = {
);
this._panel.openPopup(anchor, {
position: "bottomcenter topleft",
position: options.position ?? "bottomcenter topleft",
triggerEvent: options.event,
});
},

Просмотреть файл

@ -69,6 +69,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
RemoteSecuritySettings:
"resource://gre/modules/psm/RemoteSecuritySettings.sys.mjs",
RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
ResetPBMPanel: "resource:///modules/ResetPBMPanel.sys.mjs",
SafeBrowsing: "resource://gre/modules/SafeBrowsing.sys.mjs",
Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
SaveToPocket: "chrome://pocket/content/SaveToPocket.sys.mjs",
@ -1394,6 +1395,8 @@ BrowserGlue.prototype = {
lazy.SaveToPocket.init();
lazy.ResetPBMPanel.init();
AboutHomeStartupCache.init();
Services.obs.notifyObservers(null, "browser-ui-startup-complete");

Просмотреть файл

@ -57,7 +57,7 @@ const kSubviewEvents = ["ViewShowing", "ViewHiding"];
* The current version. We can use this to auto-add new default widgets as necessary.
* (would be const but isn't because of testing purposes)
*/
var kVersion = 19;
var kVersion = 20;
/**
* Buttons removed from built-ins by version they were removed. kVersion must be
@ -185,6 +185,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
}
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"resetPBMToolbarButtonEnabled",
"browser.privatebrowsing.resetPBM.enabled",
false
);
ChromeUtils.defineLazyGetter(lazy, "log", () => {
let { ConsoleAPI } = ChromeUtils.importESModule(
"resource://gre/modules/Console.sys.mjs"
@ -249,6 +256,7 @@ var CustomizableUIInternal = {
"downloads-button",
AppConstants.MOZ_DEV_EDITION ? "developer-button" : null,
"fxa-toolbar-menu-button",
lazy.resetPBMToolbarButtonEnabled ? "reset-pbm-toolbar-button" : null,
].filter(name => name);
this.registerArea(
@ -658,6 +666,18 @@ var CustomizableUIInternal = {
...addonsPlacements,
];
}
// Add the PBM reset button as the right most button item
if (currentVersion < 20) {
let navbarPlacements = gSavedState.placements[CustomizableUI.AREA_NAVBAR];
// Place the button as the first item to the left of the hamburger menu
if (
navbarPlacements &&
!navbarPlacements.includes("reset-pbm-toolbar-button")
) {
navbarPlacements.push("reset-pbm-toolbar-button");
}
}
},
_updateForNewProtonVersion() {

Просмотреть файл

@ -0,0 +1,216 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
/* eslint-env mozilla/browser-window */
/**
* ResetPBMPanel contains the logic for the restart private browsing action.
* The feature is exposed via a toolbar button in private browsing windows. It
* allows users to restart their private browsing session, clearing all site
* data and closing all PBM tabs / windows.
* The toolbar button for triggering the panel is only shown in private browsing
* windows or if permanent private browsing mode is enabled.
*/
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const ENABLED_PREF = "browser.privatebrowsing.resetPBM.enabled";
const SHOW_CONFIRM_DIALOG_PREF =
"browser.privatebrowsing.resetPBM.showConfirmationDialog";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
CustomizableUI: "resource:///modules/CustomizableUI.sys.mjs",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
});
export const ResetPBMPanel = {
// Button and view config for CustomizableUI.
_widgetConfig: null,
/**
* Initialize the widget code depending on pref state.
*/
init() {
// Populate _widgetConfig during init to defer (lazy) CustomizableUI import.
this._widgetConfig ??= {
id: "reset-pbm-toolbar-button",
l10nId: "reset-pbm-toolbar-button",
type: "view",
viewId: "reset-pbm-panel",
defaultArea: lazy.CustomizableUI.AREA_NAVBAR,
onViewShowing(aEvent) {
ResetPBMPanel.onViewShowing(aEvent);
},
};
if (this._enabled) {
lazy.CustomizableUI.createWidget(this._widgetConfig);
} else {
lazy.CustomizableUI.destroyWidget(this._widgetConfig.id);
}
},
/**
* Called when the reset pbm panelview is showing as the result of clicking
* the toolbar button.
*/
async onViewShowing(event) {
let triggeringWindow = event.target.ownerGlobal;
// We may skip the confirmation panel if disabled via pref.
if (!this._shouldConfirmClear) {
// Prevent the panel from showing up.
event.preventDefault();
// If the action is triggered from the overflow menu make sure that the
// panel gets hidden.
lazy.CustomizableUI.hidePanelForNode(event.target);
// Trigger the restart action.
await this._restartPBM(triggeringWindow);
return;
}
// Before the panel is shown, update checkbox state based on pref.
this._rememberCheck(triggeringWindow).checked = this._shouldConfirmClear;
},
/**
* Handles the confirmation panel cancel button.
* @param {MozButton} button - Cancel button that triggered the action.
*/
onCancel(button) {
if (!this._enabled) {
throw new Error("Not initialized.");
}
lazy.CustomizableUI.hidePanelForNode(button);
},
/**
* Handles the confirmation panel confirm button which triggers the clear
* action.
* @param {MozButton} button - Confirm button that triggered the action.
*/
async onConfirm(button) {
if (!this._enabled) {
throw new Error("Not initialized.");
}
let triggeringWindow = button.ownerGlobal;
// Write the checkbox state to pref. Only do this when the user
// confirms.
// Setting this pref to true means there is no way to see the panel
// again other than flipping the pref back via about:config or resetting
// the profile. This is by design.
Services.prefs.setBoolPref(
SHOW_CONFIRM_DIALOG_PREF,
this._rememberCheck(triggeringWindow).checked
);
lazy.CustomizableUI.hidePanelForNode(button);
// Clear the private browsing session.
await this._restartPBM(triggeringWindow);
},
/**
* Restart the private browsing session. This is achieved by closing all other
* PBM windows, closing all tabs in the current window but
* about:privatebrowsing and triggering PBM data clearing.
*
* @param {ChromeWindow} triggeringWindow - The (private browsing) chrome window which
* triggered the restart action.
*/
async _restartPBM(triggeringWindow) {
if (
!triggeringWindow ||
!lazy.PrivateBrowsingUtils.isWindowPrivate(triggeringWindow)
) {
throw new Error("Invalid triggering window.");
}
// 1. Close all PBM windows but the current one.
for (let w of Services.ww.getWindowEnumerator()) {
if (
w != triggeringWindow &&
lazy.PrivateBrowsingUtils.isWindowPrivate(w)
) {
// This suppresses confirmation dialogs like the beforeunload
// handler and the tab close warning.
// Skip over windows that don't have the closeWindow method.
w.closeWindow?.(true, null, "restart-pbm");
}
}
// 2. For the current PBM window create a new tab which will be used for
// the initial newtab page.
let newTab = triggeringWindow.gBrowser.addTab(
triggeringWindow.BROWSER_NEW_TAB_URL,
{
triggeringPrincipal:
Services.scriptSecurityManager.getSystemPrincipal(),
}
);
if (!newTab) {
throw new Error("Could not open new tab.");
}
// 3. Close all other tabs.
triggeringWindow.gBrowser.removeAllTabsBut(newTab, {
skipPermitUnload: true,
animate: false,
});
// 4. Clear private browsing data.
// TODO: this doesn't wait for data to be cleared. This is probably
// fine since PBM data is stored in memory and can be cleared quick
// enough. The mechanism is brittle though, some callers still
// perform clearing async. Bug 1846494 will address this.
Services.obs.notifyObservers(null, "last-pb-context-exited");
// Once clearing is complete show a toast message.
let toolbarButton = this._toolbarButton(triggeringWindow);
// Find the anchor used for the confirmation hint panel. If the toolbar
// button is in the overflow menu we can't use it as an anchor. Instead we
// anchor off the overflow button as indicated by cui-anchorid.
let anchor;
let anchorID = toolbarButton.getAttribute("cui-anchorid");
if (anchorID) {
anchor = triggeringWindow.document.getElementById(anchorID);
}
triggeringWindow.ConfirmationHint.show(
anchor ?? toolbarButton,
"reset-pbm-panel-complete",
{ position: "bottomright topright" }
);
},
_toolbarButton(win) {
return lazy.CustomizableUI.getWidget(this._widgetConfig.id).forWindow(win)
.node;
},
_rememberCheck(win) {
return win.document.getElementById("reset-pbm-panel-checkbox");
},
};
XPCOMUtils.defineLazyPreferenceGetter(
ResetPBMPanel,
"_enabled",
ENABLED_PREF,
false,
// On pref change update the init state.
ResetPBMPanel.init.bind(ResetPBMPanel)
);
XPCOMUtils.defineLazyPreferenceGetter(
ResetPBMPanel,
"_shouldConfirmClear",
SHOW_CONFIRM_DIALOG_PREF,
true
);

Просмотреть файл

@ -4,6 +4,6 @@
browser.jar:
content/browser/aboutPrivateBrowsing.css (content/aboutPrivateBrowsing.css)
content/browser/aboutPrivateBrowsing.html (content/aboutPrivateBrowsing.html)
content/browser/aboutPrivateBrowsing.html (content/aboutPrivateBrowsing.html)
content/browser/aboutPrivateBrowsing.js (content/aboutPrivateBrowsing.js)
content/browser/assets/ (content/assets/*)

Просмотреть файл

@ -10,5 +10,9 @@ BROWSER_CHROME_MANIFESTS += [
JAR_MANIFESTS += ["jar.mn"]
EXTRA_JS_MODULES += [
"ResetPBMPanel.sys.mjs",
]
with Files("**"):
BUG_COMPONENT = ("Firefox", "Private Browsing")

Просмотреть файл

@ -974,6 +974,24 @@ unified-extensions-button-quarantined =
Extensions
Some extensions are not allowed
## Private browsing reset button
reset-pbm-toolbar-button =
.label = End Private Session
.tooltiptext = End Private Session
reset-pbm-panel-heading = End your private session?
reset-pbm-panel-description = Close all private tabs and delete history, cookies, and all other site data.
reset-pbm-panel-always-ask-checkbox =
.label = Always ask me
.accesskey = A
reset-pbm-panel-cancel-button =
.label = Cancel
.accesskey = C
reset-pbm-panel-confirm-button =
.label = Delete session data
.accesskey = D
reset-pbm-panel-complete = Private session data deleted
## Autorefresh blocker
refresh-blocked-refresh-label = { -brand-short-name } prevented this page from automatically reloading.

Просмотреть файл

@ -1972,3 +1972,34 @@ panelview:not([mainview]) #PanelUI-whatsNew-title {
.webextension-popup-stack {
position: relative;
}
/* Reset/Restart Private Browsing Panel */
#reset-pbm-panel {
max-width: var(--menu-panel-width-wide);
}
#reset-pbm-panel-container {
padding: 16px 16px 0;
display: flex;
flex-direction: column;
gap: 8px;
}
#reset-pbm-panel-header > description {
margin-bottom: 0;
}
#reset-pbm-panel-header > description,
#reset-pbm-panel-description,
#reset-pbm-panel-footer {
margin-inline: 0;
}
#reset-pbm-panel-header > description {
font-weight: var(--font-weight-bold);
}
#reset-pbm-panel-checkbox {
margin-inline: 0 8px;
}

Просмотреть файл

@ -0,0 +1,6 @@
<!-- 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/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity">
<path d="M12.88 5.07999C12.61 4.63999 11.88 4.63999 11.6 5.07999C11.35 5.48999 11.04 5.86999 10.7 6.20999C10.33 3.39999 8.35 0.989993 5.55 0.0399925C5.28 -0.0500075 4.99 0.0199925 4.79 0.209993C4.59 0.409993 4.51 0.699993 4.6 0.969993C5.21 2.92999 4.76 5.08999 3.42 6.65999C3.4 6.67999 3.37 6.70999 3.35 6.72999C3.33 6.74999 3.31 6.77999 3.29 6.79999L3.24 6.85999C3.24 6.85999 3.21 6.89999 3.2 6.91999C1.46 9.13999 1.66 12.35 3.7 14.35C4.82 15.44 6.29 15.99 7.76 15.99C9.23 15.99 10.71 15.44 11.83 14.34C13.23 12.93 14 11.04 14 8.99999C14 7.60999 13.61 6.24999 12.88 5.06999V5.07999ZM10.77 13.28C10.52 13.53 10.23 13.72 9.94 13.9C9.98 13.69 10 13.48 10 13.26C10 11.84 9.3 10.56 8.21 10.05C8.08 9.98999 7.92 9.98999 7.79 10.05C6.7 10.56 6 11.84 6 13.26C6 13.58 6.04 13.88 6.11 14.18C5.61 13.98 5.15 13.68 4.75 13.29C3.22 11.8 3.08 9.47999 4.4 7.83999C5.85 6.25999 6.54 4.14999 6.35 2.05999C8.15 3.15999 9.29 5.09999 9.29 7.22999C9.29 7.37999 9.29 7.52999 9.27 7.66999C9.25 7.94999 9.39 8.21999 9.63 8.36999C9.87 8.51999 10.17 8.50999 10.42 8.36999C11.06 7.96999 11.64 7.47999 12.13 6.91999C12.38 7.58999 12.51 8.29999 12.51 9.01999C12.51 10.66 11.89 12.18 10.78 13.29L10.77 13.28Z"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Просмотреть файл

@ -165,6 +165,7 @@
skin/classic/browser/edit-paste.svg (../shared/icons/edit-paste.svg)
skin/classic/browser/fingerprint.svg (../shared/icons/fingerprint.svg)
skin/classic/browser/firefox-view.svg (../shared/icons/firefox-view.svg)
skin/classic/browser/flame.svg (../shared/icons/flame.svg)
skin/classic/browser/forget.svg (../shared/icons/forget.svg)
skin/classic/browser/forward.svg (../shared/icons/forward.svg)
skin/classic/browser/fullscreen.svg (../shared/icons/fullscreen.svg)

Просмотреть файл

@ -368,6 +368,14 @@
list-style-image: url("chrome://mozapps/skin/extensions/extension.svg");
}
#reset-pbm-toolbar-button {
list-style-image: url("chrome://browser/skin/flame.svg");
:root:not([privatebrowsingmode]) & {
display: none;
}
}
#email-link-button {
list-style-image: url("chrome://browser/skin/mail.svg");
}