Files
tubestation/browser/components/privatebrowsing/ResetPBMPanel.sys.mjs
Sandor Molnar b59809ee6a Backed out 8 changesets (bug 1917532, bug 1575506, bug 1917530) for causing node newtab failures CLOSED TREE
Backed out changeset 8d6f7bc74d08 (bug 1917532)
Backed out changeset 7c963e72cf06 (bug 1575506)
Backed out changeset d5e110187781 (bug 1917530)
Backed out changeset 1d2325ffded6 (bug 1917530)
Backed out changeset 8a361e37e32c (bug 1917530)
Backed out changeset c4011d92c7f7 (bug 1917530)
Backed out changeset 1a45047dfb3c (bug 1917530)
Backed out changeset ed6b35444c45 (bug 1917530)
2024-09-12 20:45:28 +03:00

272 lines
8.5 KiB
JavaScript

/* -*- 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",
SessionStore: "resource:///modules/sessionstore/SessionStore.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);
},
onViewHiding(aEvent) {
ResetPBMPanel.onViewHiding(aEvent);
},
hideInNonPrivateBrowsing: true,
};
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 panelview = event.target;
let triggeringWindow = panelview.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(panelview);
// Trigger the restart action.
await this._restartPBM(triggeringWindow);
Glean.privateBrowsingResetPbm.resetAction.record({ did_confirm: false });
return;
}
panelview.addEventListener("command", this);
// Before the panel is shown, update checkbox state based on pref.
this._rememberCheck(triggeringWindow).checked = this._shouldConfirmClear;
Glean.privateBrowsingResetPbm.confirmPanel.record({
action: "show",
reason: "toolbar-btn",
});
},
onViewHiding(event) {
let panelview = event.target;
panelview.removeEventListener("command", this);
},
handleEvent(event) {
let button = event.target;
switch (button.id) {
case "reset-pbm-panel-cancel-button":
this.onCancel(button);
break;
case "reset-pbm-panel-confirm-button":
this.onConfirm(button);
break;
}
},
/**
* 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);
Glean.privateBrowsingResetPbm.confirmPanel.record({
action: "hide",
reason: "cancel-btn",
});
},
/**
* 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);
Glean.privateBrowsingResetPbm.confirmPanel.record({
action: "hide",
reason: "confirm-btn",
});
// Clear the private browsing session.
await this._restartPBM(triggeringWindow);
Glean.privateBrowsingResetPbm.resetAction.record({ did_confirm: true });
},
/**
* 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,
// Instruct the SessionStore to not save closed tab data for these tabs.
// We don't want to leak them into the next private browsing session.
skipSessionStore: true,
animate: false,
skipWarnAboutClosingTabs: true,
skipPinnedOrSelectedTabs: false,
});
// In the remaining PBM window: If the sidebar is open close it.
triggeringWindow.SidebarController?.hide();
// Clear session store data for the remaining PBM window.
lazy.SessionStore.purgeDataForPrivateWindow(triggeringWindow);
// 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
);