Bug 1953900 - Update "Forget Site Data" prompt to new dialog r=sidebar-reviewers,fluent-reviewers,places-reviewers,bolsson,kcochrane,mak

Depends on D241874

Differential Revision: https://phabricator.services.mozilla.com/D245463
This commit is contained in:
Nikki Sharpley
2025-04-18 16:23:02 +00:00
parent e09635079a
commit 9dc7dba546
10 changed files with 182 additions and 100 deletions

View File

@@ -0,0 +1,9 @@
/* 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/. */
#clearDataForSiteDialog::part(dialog-button) {
min-height: 24px;
align-items: center;
justify-content: center;
}

View File

@@ -0,0 +1,35 @@
/* 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";
let lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
ForgetAboutSite: "resource://gre/modules/ForgetAboutSite.sys.mjs",
});
window.addEventListener("load", () => {
let retVals = window.arguments[0];
document.addEventListener("dialogaccept", e => {
e.preventDefault();
lazy.ForgetAboutSite.removeDataFromBaseDomain(retVals.host).catch(
console.error
);
window.close();
});
document.addEventListener("dialogcancel", e => {
e.preventDefault();
window.close();
});
document.l10n.setAttributes(
document.getElementById("clear-data-for-site-list"),
"clear-data-for-site-list",
{
site: retVals.hostOrBaseDomain,
}
);
});

View File

@@ -0,0 +1,56 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?csp default-src chrome: ?>
<window
id="clearDataForSiteDialogWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
aria-describedby="infoTitle"
>
<dialog
id="clearDataForSiteDialog"
buttons="accept,cancel"
defaultButton="accept"
buttonidaccept="clear-data-for-site-dialog-accept-button"
buttonidcancel="clear-data-for-site-dialog-cancel-button"
>
<linkset>
<html:link rel="stylesheet" href="chrome://global/skin/global.css" />
<html:link
rel="stylesheet"
href="chrome://global/skin/commonDialog.css"
/>
<html:link
rel="stylesheet"
href="chrome://browser/content/places/clearDataForSite.css"
/>
<html:link rel="localization" href="browser/clearDataForSite.ftl" />
</linkset>
<div xmlns="http://www.w3.org/1999/xhtml" id="dialogGrid">
<h4 data-l10n-id="clear-data-for-site-title" id="infoTitle"></h4>
<!-- Use placeholder l10n arg "this site" so dialog height is calculated correctly
at dialog opening before l10n args are updated with actual site name in clearDataForSite.js -->
<p
data-l10n-id="clear-data-for-site-list"
data-l10n-args='{"site": "URL"}'
id="clear-data-for-site-list"
></p>
<ul>
<li data-l10n-id="clear-data-for-site-browsing-history"></li>
<li data-l10n-id="clear-data-for-site-cookies"></li>
<li data-l10n-id="clear-data-for-site-cache"></li>
<li data-l10n-id="cclear-data-for-site-permissions"></li>
</ul>
<p data-l10n-id="clear-data-for-site-exceptions"></p>
</div>
<script src="chrome://browser/content/places/clearDataForSite.js" />
</dialog>
</window>

View File

@@ -1408,37 +1408,20 @@ PlacesController.prototype = {
} catch (e) {
// If there is no baseDomain we fall back to host
}
const [title, body, forget] = await document.l10n.formatValues([
{ id: "places-forget-about-this-site-confirmation-title" },
{
id: "places-forget-about-this-site-confirmation-msg",
args: { hostOrBaseDomain: baseDomain ?? host },
},
{ id: "places-forget-about-this-site-forget" },
]);
const flags =
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
Services.prompt.BUTTON_POS_1_DEFAULT;
let bag = await Services.prompt.asyncConfirmEx(
window.browsingContext,
Services.prompt.MODAL_TYPE_INTERNAL_WINDOW,
title,
body,
flags,
forget,
null,
null,
null,
false
);
if (bag.getProperty("buttonNumClicked") !== 0) {
return;
let params = { host, hostOrBaseDomain: baseDomain ?? host };
if (window.gDialogBox) {
await window.gDialogBox.open(
"chrome://browser/content/places/clearDataForSite.xhtml",
params
);
} else {
await window.openDialog(
"chrome://browser/content/places/clearDataForSite.xhtml",
null,
"modal,centerscreen",
params
);
}
await this.ForgetAboutSite.removeDataFromBaseDomain(host);
},
showInFolder(aBookmarkGuid) {

View File

@@ -20,6 +20,9 @@ browser.jar:
content/browser/places/historySidebar.js (content/historySidebar.js)
* content/browser/places/bookmarksSidebar.xhtml (content/bookmarksSidebar.xhtml)
content/browser/places/bookmarksSidebar.js (content/bookmarksSidebar.js)
content/browser/places/clearDataForSite.xhtml (content/clearDataForSite.xhtml)
content/browser/places/clearDataForSite.js (content/clearDataForSite.js)
content/browser/places/clearDataForSite.css (content/clearDataForSite.css)
content/browser/places/editBookmark.js (content/editBookmark.js)
content/browser/places/placesContextMenu.js (content/placesContextMenu.js)
content/browser/places/interactionsViewer.css (metadataViewer/interactionsViewer.css)

View File

@@ -115,35 +115,28 @@ async function testForgetAboutThisSite(
return;
}
// Resolves once the confirmation prompt has been closed.
let promptPromise;
// Resolves once the confirmation dialog has been closed.
let dialogPromise;
// Cancel prompt via esc key. We have to get the prompt closed promise
// Cancel dialog via esc key. We have to get the dialog closed promise
// ourselves.
if (cancelConfirmWithEsc) {
promptPromise = PromptTestUtils.waitForPrompt(organizer, {
modalType: Services.prompt.MODAL_TYPE_WINDOW,
promptType: "confirmEx",
}).then(dialog => {
let dialogWindow = dialog.ui.prompt;
let dialogClosedPromise = BrowserTestUtils.waitForEvent(
dialogWindow.opener,
"DOMModalDialogClosed"
);
EventUtils.synthesizeKey("KEY_Escape", undefined, dialogWindow);
dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
null,
"chrome://browser/content/places/clearDataForSite.xhtml"
).then(dialog => {
let dialogClosedPromise = BrowserTestUtils.waitForEvent(dialog, "unload");
EventUtils.synthesizeKey("KEY_Escape", undefined, dialog);
return dialogClosedPromise;
});
} else {
// Close prompt via buttons. PromptTestUtils supplies the closed promise.
promptPromise = PromptTestUtils.handleNextPrompt(
organizer,
{ modalType: Services.prompt.MODAL_TYPE_WINDOW, promptType: "confirmEx" },
{ buttonNumClick: shouldForget ? 0 : 1 }
dialogPromise = BrowserTestUtils.promiseAlertDialog(
shouldForget ? "accept" : "cancel",
"chrome://browser/content/places/clearDataForSite.xhtml"
);
}
// If we cancel the prompt, create stubs to check that none of the clear
// If we cancel the dialog, create stubs to check that none of the clear
// methods are called.
if (!shouldForget) {
sinon.stub(ForgetAboutSite, "removeDataFromBaseDomain").resolves();
@@ -158,8 +151,8 @@ async function testForgetAboutThisSite(
// Execute the delete command.
contextmenu.activateItem(forgetThisSite);
// Wait for prompt to be handled.
await promptPromise;
// Wait for dialog to be handled.
await dialogPromise;
// If we expect to remove items, wait the page-removed event to fire. If we
// don't wait, we may test the list before any items have been removed.

View File

@@ -16,7 +16,6 @@ const { LightweightThemeConsumer } = ChromeUtils.importESModule(
);
ChromeUtils.defineESModuleGetters(lazy, {
BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
ForgetAboutSite: "resource://gre/modules/ForgetAboutSite.sys.mjs",
PlacesUIUtils: "resource:///modules/PlacesUIUtils.sys.mjs",
});
@@ -173,7 +172,6 @@ export class SidebarPage extends MozLitElement {
}
}
// TO DO: find a central place for this to live that's not PlacesController or here Bug 1954843
async forgetAboutThisSite() {
let host;
if (PlacesUtils.nodeIsHost(this.triggerNode)) {
@@ -187,37 +185,10 @@ export class SidebarPage extends MozLitElement {
} catch (e) {
// If there is no baseDomain we fall back to host
}
const [title, body, forget] = await document.l10n.formatValues([
{ id: "places-forget-about-this-site-confirmation-title" },
{
id: "places-forget-about-this-site-confirmation-msg",
args: { hostOrBaseDomain: baseDomain ?? host },
},
{ id: "places-forget-about-this-site-forget" },
]);
const flags =
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
Services.prompt.BUTTON_POS_1_DEFAULT;
let bag = await Services.prompt.asyncConfirmEx(
window.browsingContext,
Services.prompt.MODAL_TYPE_INTERNAL_WINDOW,
title,
body,
flags,
forget,
null,
null,
null,
false
await this.topWindow.gDialogBox.open(
"chrome://browser/content/places/clearDataForSite.xhtml",
{ host, hostOrBaseDomain: baseDomain ?? host }
);
if (bag.getProperty("buttonNumClicked") !== 0) {
return;
}
await lazy.ForgetAboutSite.removeDataFromBaseDomain(host);
}
/**

View File

@@ -585,18 +585,45 @@ add_task(async function test_history_context_menu() {
is(window.gBrowser.currentURI.spec, rows[0].mainEl.href, "New tab opened");
info("Clear all data from website");
const promptPromise = PromptTestUtils.handleNextPrompt(
window.SidebarController.browser,
{ modalType: Services.prompt.MODAL_TYPE_WINDOW, promptType: "confirmEx" },
{ buttonNumClick: 0 }
let dialogOpened = BrowserTestUtils.promiseAlertDialogOpen(
null,
"chrome://browser/content/places/clearDataForSite.xhtml",
{ isSubDialog: true }
);
site = rows[0].mainEl.href;
const promiseForgotten = PlacesTestUtils.waitForNotification("page-removed");
await openAndWaitForContextMenu(contextMenu, rows[0].mainEl, () =>
contextMenu.activateItem(getItem("forget-site"))
);
await promptPromise;
await promiseForgotten;
let dialog = await dialogOpened;
let forgetSiteText = dialog.document.getElementById(
"clear-data-for-site-list"
);
let siteToForget = rows[0].mainEl.href.substring(
rows[0].mainEl.href.includes("https") ? 8 : 7,
rows[0].mainEl.href.length - 1
);
let siteForgottenIsCorrect;
await BrowserTestUtils.waitForMutationCondition(
forgetSiteText,
{ attributes: true, attributeFilter: ["data-l10n-args"] },
() => {
let text = JSON.parse(forgetSiteText.getAttribute("data-l10n-args")).site;
siteForgottenIsCorrect =
text.includes(siteToForget) || siteToForget.includes(text);
return siteForgottenIsCorrect;
}
);
ok(
siteForgottenIsCorrect,
"The text for forgetting a specific site should be set"
);
let dialogClosed = BrowserTestUtils.waitForEvent(dialog, "unload");
let removeButton = dialog.document
.querySelector("dialog")
.getButton("accept");
removeButton.click();
await Promise.all([dialogClosed, promiseForgotten]);
await TestUtils.waitForCondition(
() => rows[0].mainEl.href !== site,
"The forgotten entry should no longer be visible."

View File

@@ -0,0 +1,15 @@
# 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/.
clear-data-for-site-title = Clear all data for this website?
# Variables:
# $site (string) - Website name
clear-data-for-site-list = This will clear all data for { $site } including:
clear-data-for-site-browsing-history = Browsing and download history
clear-data-for-site-cookies = Cookies and site data, which may sign you out of the site
clear-data-for-site-cache = Cached files and pages
cclear-data-for-site-permissions = Permissions and preferences
clear-data-for-site-exceptions = Bookmarks and saved passwords wont be deleted
clear-data-for-site-dialog-accept-button = Clear data
clear-data-for-site-dialog-cancel-button = Cancel

View File

@@ -144,16 +144,6 @@ places-manage-bookmarks =
.label = Manage Bookmarks
.accesskey = M
places-forget-about-this-site-confirmation-title =
Forgetting about this site
# Variables:
# $hostOrBaseDomain (string) - The base domain (or host in case there is no base domain) for which data is being removed
places-forget-about-this-site-confirmation-msg =
This action will remove data related to { $hostOrBaseDomain } including history, cookies, cache and content preferences. Related bookmarks and passwords will not be removed. Are you sure you want to proceed?
places-forget-about-this-site-forget = Forget
places-library3 =
.title = Library