зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1583398 - Newly added logins should show breach notifications if they apply. r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D47527 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
f51a51c27d
Коммит
c03d373e19
|
@ -166,6 +166,7 @@ let LEGACY_ACTORS = {
|
|||
"AboutLogins:LoginRemoved",
|
||||
"AboutLogins:MasterPasswordResponse",
|
||||
"AboutLogins:SendFavicons",
|
||||
"AboutLogins:SetBreaches",
|
||||
"AboutLogins:Setup",
|
||||
"AboutLogins:ShowLoginItemError",
|
||||
"AboutLogins:SyncState",
|
||||
|
|
|
@ -219,6 +219,9 @@ class AboutLoginsChild extends ActorChild {
|
|||
case "AboutLogins:SendFavicons":
|
||||
this.sendToContent("SendFavicons", message.data);
|
||||
break;
|
||||
case "AboutLogins:SetBreaches":
|
||||
this.sendToContent("SetBreaches", message.data);
|
||||
break;
|
||||
case "AboutLogins:Setup":
|
||||
this.sendToContent("Setup", message.data);
|
||||
Cu.waiveXrays(this.content).AboutLoginsUtils.masterPasswordEnabled =
|
||||
|
|
|
@ -242,7 +242,7 @@ var AboutLoginsParent = {
|
|||
);
|
||||
const messageManager = message.target.messageManager;
|
||||
messageManager.sendAsyncMessage(
|
||||
"AboutLogins:UpdateBreaches",
|
||||
"AboutLogins:SetBreaches",
|
||||
breachesByLoginGUID
|
||||
);
|
||||
break;
|
||||
|
@ -513,6 +513,13 @@ var AboutLoginsParent = {
|
|||
return;
|
||||
}
|
||||
this.messageSubscribers("AboutLogins:LoginAdded", login);
|
||||
|
||||
if (BREACH_ALERTS_ENABLED) {
|
||||
this.messageSubscribers(
|
||||
"AboutLogins:UpdateBreaches",
|
||||
await LoginBreaches.getPotentialBreachesByLoginGUID([login])
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "modifyLogin": {
|
||||
|
@ -725,7 +732,7 @@ var AboutLoginsParent = {
|
|||
};
|
||||
if (BREACH_ALERTS_ENABLED) {
|
||||
sendMessageFn(
|
||||
"AboutLogins:UpdateBreaches",
|
||||
"AboutLogins:SetBreaches",
|
||||
await LoginBreaches.getPotentialBreachesByLoginGUID(logins)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,11 @@ window.addEventListener("AboutLoginsChromeToContent", event => {
|
|||
gElements.loginList.addFavicons(event.detail.value);
|
||||
break;
|
||||
}
|
||||
case "SetBreaches": {
|
||||
gElements.loginList.setBreaches(event.detail.value);
|
||||
gElements.loginItem.setBreaches(event.detail.value);
|
||||
break;
|
||||
}
|
||||
case "Setup": {
|
||||
handleAllLogins(event.detail.value.logins);
|
||||
gElements.loginFooter.showStoreIconsForLocales(
|
||||
|
|
|
@ -176,11 +176,21 @@ export default class LoginItem extends HTMLElement {
|
|||
this._updatePasswordRevealState();
|
||||
}
|
||||
|
||||
updateBreaches(breachesByLoginGUID) {
|
||||
setBreaches(breachesByLoginGUID) {
|
||||
this._breachesMap = breachesByLoginGUID;
|
||||
this.render();
|
||||
}
|
||||
|
||||
updateBreaches(breachesByLoginGUID) {
|
||||
if (!this._breachesMap) {
|
||||
this._breachesMap = new Map();
|
||||
}
|
||||
for (const [guid, breach] of [...breachesByLoginGUID]) {
|
||||
this._breachesMap.set(guid, breach);
|
||||
}
|
||||
this.setBreaches(this._breachesMap);
|
||||
}
|
||||
|
||||
dismissBreachAlert() {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("AboutLoginsDismissBreachAlert", {
|
||||
|
|
|
@ -327,7 +327,7 @@ export default class LoginList extends HTMLElement {
|
|||
* @param {Map} breachesByLoginGUID A Map of breaches by login GUIDs used
|
||||
* for displaying breached login indicators.
|
||||
*/
|
||||
updateBreaches(breachesByLoginGUID) {
|
||||
setBreaches(breachesByLoginGUID) {
|
||||
this._breachesByLoginGUID = breachesByLoginGUID;
|
||||
if (this._breachesByLoginGUID.size === 0) {
|
||||
this.render();
|
||||
|
@ -343,6 +343,21 @@ export default class LoginList extends HTMLElement {
|
|||
this.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Map} breachesByLoginGUID A Map of breaches by login GUIDs that
|
||||
* should be added to the local cache of
|
||||
* breaches.
|
||||
*/
|
||||
updateBreaches(breachesByLoginGUID) {
|
||||
if (!this._breachesByLoginGUID) {
|
||||
this._breachesByLoginGUID = new Map();
|
||||
}
|
||||
for (const [guid, breach] of [...breachesByLoginGUID]) {
|
||||
this._breachesByLoginGUID.set(guid, breach);
|
||||
}
|
||||
this.setBreaches(this._breachesByLoginGUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {login} login A login that was added to storage.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@ support-files =
|
|||
skip-if = asan || debug
|
||||
[browser_breachAlertDismissals.js]
|
||||
skip-if = asan || debug || verify # bug 1574023
|
||||
[browser_breachAlertShowingForAddedLogin.js]
|
||||
[browser_confirmDeleteDialog.js]
|
||||
[browser_contextmenuFillLogins.js]
|
||||
[browser_copyToClipboardButton.js]
|
||||
|
|
|
@ -9,7 +9,7 @@ const TEST_BREACHES = [
|
|||
{
|
||||
AddedDate: "2019-12-20T23:56:26Z",
|
||||
BreachDate: "2018-12-16",
|
||||
Domain: "breached.com",
|
||||
Domain: "breached.example.com",
|
||||
Name: "Breached",
|
||||
PwnCount: 1643100,
|
||||
DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
|
||||
|
@ -40,10 +40,10 @@ add_task(async function test_show_login() {
|
|||
TEST_BREACHES
|
||||
);
|
||||
browser.messageManager.sendAsyncMessage(
|
||||
"AboutLogins:UpdateBreaches",
|
||||
"AboutLogins:SetBreaches",
|
||||
testBreaches
|
||||
);
|
||||
await ContentTask.spawn(browser, TEST_LOGIN3, async () => {
|
||||
await ContentTask.spawn(browser, null, async () => {
|
||||
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
|
||||
let breachAlert = loginItem.shadowRoot.querySelector(".breach-alert");
|
||||
let breachAlertVisible = await ContentTaskUtils.waitForCondition(() => {
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let { LoginBreaches } = ChromeUtils.import(
|
||||
"resource:///modules/LoginBreaches.jsm"
|
||||
);
|
||||
|
||||
const TEST_BREACHES = [
|
||||
{
|
||||
AddedDate: "2019-12-20T23:56:26Z",
|
||||
BreachDate: "2018-12-16",
|
||||
Domain: "breached.example.com",
|
||||
Name: "Breached",
|
||||
PwnCount: 1643100,
|
||||
DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
|
||||
_status: "synced",
|
||||
id: "047940fe-d2fd-4314-b636-b4a952ee0043",
|
||||
last_modified: "1541615610052",
|
||||
schema: "1541615609018",
|
||||
},
|
||||
];
|
||||
|
||||
add_task(async function setup() {
|
||||
let oldGetPotentialBreachesByLoginGUID =
|
||||
LoginBreaches.getPotentialBreachesByLoginGUID;
|
||||
LoginBreaches.getPotentialBreachesByLoginGUID = logins => {
|
||||
if (!logins.length) {
|
||||
return new Map();
|
||||
}
|
||||
let breaches = new Map();
|
||||
breaches.set(logins[0].guid, TEST_BREACHES[0]);
|
||||
return breaches;
|
||||
};
|
||||
await BrowserTestUtils.openNewForegroundTab({
|
||||
gBrowser,
|
||||
url: "about:logins",
|
||||
});
|
||||
registerCleanupFunction(() => {
|
||||
LoginBreaches.getPotentialBreachesByLoginGUID = oldGetPotentialBreachesByLoginGUID;
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
Services.logins.removeAllLogins();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_added_login_shows_breach_warning() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
await ContentTask.spawn(browser, null, async () => {
|
||||
let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
|
||||
is(
|
||||
loginList._loginGuidsSortedOrder.length,
|
||||
0,
|
||||
"the login list should be empty"
|
||||
);
|
||||
});
|
||||
|
||||
TEST_LOGIN3 = await addLogin(TEST_LOGIN3);
|
||||
await ContentTask.spawn(browser, TEST_LOGIN3.guid, async aTestLogin3Guid => {
|
||||
let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
|
||||
is(
|
||||
loginList._loginGuidsSortedOrder.length,
|
||||
1,
|
||||
"one login should be in the list"
|
||||
);
|
||||
let breachedLoginListItems;
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
breachedLoginListItems = loginList._list.querySelectorAll(
|
||||
".login-list-item[data-guid].breached"
|
||||
);
|
||||
return breachedLoginListItems.length == 1;
|
||||
}, "waiting for the login to get marked as breached");
|
||||
is(
|
||||
breachedLoginListItems[0].dataset.guid,
|
||||
aTestLogin3Guid,
|
||||
"the breached login should be login3"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -27,8 +27,8 @@ let TEST_LOGIN2 = new nsLoginInfo(
|
|||
);
|
||||
|
||||
let TEST_LOGIN3 = new nsLoginInfo(
|
||||
"https://breached.com",
|
||||
"https://breached.com",
|
||||
"https://breached.example.com",
|
||||
"https://breached.example.com",
|
||||
null,
|
||||
"breachedLogin1",
|
||||
"pass3",
|
||||
|
|
|
@ -139,7 +139,7 @@ add_task(async function test_set_login() {
|
|||
|
||||
add_task(async function test_update_breaches() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
gLoginItem.updateBreaches(TEST_BREACHES_MAP);
|
||||
gLoginItem.setBreaches(TEST_BREACHES_MAP);
|
||||
await asyncElementRendered();
|
||||
|
||||
let correspondingBreach = TEST_BREACHES_MAP.get(gLoginItem._login.guid);
|
||||
|
@ -150,7 +150,7 @@ add_task(async function test_update_breaches() {
|
|||
|
||||
add_task(async function test_breach_alert_is_correctly_hidden() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_2);
|
||||
gLoginItem.updateBreaches(TEST_BREACHES_MAP);
|
||||
gLoginItem.setBreaches(TEST_BREACHES_MAP);
|
||||
await asyncElementRendered();
|
||||
|
||||
let breachAlert = gLoginItem.shadowRoot.querySelector(".breach-alert");
|
||||
|
|
|
@ -242,7 +242,7 @@ add_task(async function test_populated_list() {
|
|||
});
|
||||
|
||||
add_task(async function test_breach_indicator() {
|
||||
gLoginList.updateBreaches(TEST_BREACHES_MAP);
|
||||
gLoginList.setBreaches(TEST_BREACHES_MAP);
|
||||
let loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item:not(#new-login-list-item):not([hidden])");
|
||||
let warningIcon = loginListItems[0].querySelector(".list-item-warning-icon");
|
||||
let hiddenWarningIcon = loginListItems[1].querySelector(".list-item-warning-icon");
|
||||
|
@ -459,7 +459,7 @@ add_task(async function test_sorted_list() {
|
|||
is(pwChanged2 > pwChanged3, true, "Logins sorted by timePasswordChanged. Second: " + pwChanged2 + "; Third: " + pwChanged3);
|
||||
|
||||
// sort by breached when there are breached logins
|
||||
gLoginList.updateBreaches(TEST_BREACHES_MAP);
|
||||
gLoginList.setBreaches(TEST_BREACHES_MAP);
|
||||
loginSort.selectedIndex = 3;
|
||||
dispatchChangeEvent(loginSort);
|
||||
loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item:not(#new-login-list-item):not([hidden])");
|
||||
|
@ -467,7 +467,7 @@ add_task(async function test_sorted_list() {
|
|||
is(!loginListItems[1].classList.contains("breached"), true, "Non-breached login should be displayed below breached");
|
||||
|
||||
// sort by name when there are no breached logins
|
||||
gLoginList.updateBreaches(new Map());
|
||||
gLoginList.setBreaches(new Map());
|
||||
loginSort.selectedIndex = 3;
|
||||
dispatchChangeEvent(loginSort);
|
||||
loginListItems = gLoginList.shadowRoot.querySelectorAll(".login-list-item:not(#new-login-list-item):not([hidden])");
|
||||
|
|
|
@ -240,7 +240,7 @@ add_task(async function test_ExceptionsThrownByNonStandardURIsAreCaught() {
|
|||
);
|
||||
});
|
||||
|
||||
add_task(async function test_updateBreachesFromRemoteSettingsSync() {
|
||||
add_task(async function test_setBreachesFromRemoteSettingsSync() {
|
||||
const login = NOT_BREACHED_SUBDOMAIN_LOGIN;
|
||||
const nowExampleIsInBreachedRecords = [
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче