Bug 1595656 - Only clear user-facing passwords with the browsingData API. r=rpl
☠☠ backed out by 141a109d768e ☠ ☠
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Wed, 20 Nov 2019 15:07:32 +0000
changeset 503123 061c92c4b95c161ed9baedbb84aa27e2b0a99028
parent 503122 ef8d5090979a392b69500f0a43402d42a2fea529
child 503124 ab47a4eac76c3f7166c9a4d6ae84da926c92e166
push id101129
push usermozilla@noorenberghe.ca
push dateWed, 20 Nov 2019 23:11:27 +0000
treeherderautoland@061c92c4b95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrpl
bugs1595656
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1595656 - Only clear user-facing passwords with the browsingData API. r=rpl FxA/Sync stores a credential in login storage but this is no longer user-facing so users shouldn't expect it to be cleared. Users can still diconnect Sync properly from about:preferences. Differential Revision: https://phabricator.services.mozilla.com/D53834
browser/components/extensions/parent/ext-browsingData.js
browser/components/extensions/test/xpcshell/test_ext_browsingData_passwords.js
--- a/browser/components/extensions/parent/ext-browsingData.js
+++ b/browser/components/extensions/parent/ext-browsingData.js
@@ -1,45 +1,29 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et 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/. */
 
 "use strict";
 
-var { PlacesUtils } = ChromeUtils.import(
-  "resource://gre/modules/PlacesUtils.jsm"
+var { XPCOMUtils } = ChromeUtils.import(
+  "resource://gre/modules/XPCOMUtils.jsm"
 );
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "Preferences",
-  "resource://gre/modules/Preferences.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "Sanitizer",
-  "resource:///modules/Sanitizer.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "Services",
-  "resource://gre/modules/Services.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "setTimeout",
-  "resource://gre/modules/Timer.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
-  "ServiceWorkerCleanUp",
-  "resource://gre/modules/ServiceWorkerCleanUp.jsm"
-);
+XPCOMUtils.defineLazyModuleGetters(this, {
+  LoginHelper: "resource://gre/modules/LoginHelper.jsm",
+  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
+  Preferences: "resource://gre/modules/Preferences.jsm",
+  Sanitizer: "resource:///modules/Sanitizer.jsm",
+  Services: "resource://gre/modules/Services.jsm",
+  setTimeout: "resource://gre/modules/Timer.jsm",
+  ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
+});
 
 XPCOMUtils.defineLazyServiceGetter(
   this,
   "quotaManagerService",
   "@mozilla.org/dom/quota-manager-service;1",
   "nsIQuotaManagerService"
 );
 
@@ -226,34 +210,27 @@ const clearLocalStorage = async function
       });
     });
 
     return Promise.all(promises);
   }
 };
 
 const clearPasswords = async function(options) {
-  let loginManager = Services.logins;
   let yieldCounter = 0;
 
-  if (options.since) {
-    // Iterate through the logins and delete any updated after our cutoff.
-    let logins = loginManager.getAllLogins();
-    for (let login of logins) {
-      login.QueryInterface(Ci.nsILoginMetaInfo);
-      if (login.timePasswordChanged >= options.since) {
-        loginManager.removeLogin(login);
-        if (++yieldCounter % YIELD_PERIOD == 0) {
-          await new Promise(resolve => setTimeout(resolve, 0)); // Don't block the main thread too long.
-        }
+  // Iterate through the logins and delete any updated after our cutoff.
+  for (let login of await LoginHelper.getAllUserFacingLogins()) {
+    login.QueryInterface(Ci.nsILoginMetaInfo);
+    if (!options.since || login.timePasswordChanged >= options.since) {
+      Services.logins.removeLogin(login);
+      if (++yieldCounter % YIELD_PERIOD == 0) {
+        await new Promise(resolve => setTimeout(resolve, 0)); // Don't block the main thread too long.
       }
     }
-  } else {
-    // Remove everything.
-    loginManager.removeAllLogins();
   }
 };
 
 const clearPluginData = options => {
   return Sanitizer.items.pluginData.clear(makeRange(options));
 };
 
 const doRemoval = (options, dataToRemove, extension) => {
--- a/browser/components/extensions/test/xpcshell/test_ext_browsingData_passwords.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_browsingData_passwords.js
@@ -7,52 +7,44 @@ XPCOMUtils.defineLazyServiceGetter(
   "loginManager",
   "@mozilla.org/login-manager;1",
   "nsILoginManager"
 );
 
 const REFERENCE_DATE = Date.now();
 const LOGIN_USERNAME = "username";
 const LOGIN_PASSWORD = "password";
-const LOGIN_USERNAME_FIELD = "username_field";
-const LOGIN_PASSWORD_FIELD = "password_field";
 const OLD_HOST = "http://mozilla.org";
 const NEW_HOST = "http://mozilla.com";
+const FXA_HOST = "chrome://FirefoxAccounts";
 
 function checkLoginExists(host, shouldExist) {
   let logins = loginManager.findLogins(host, "", null);
   equal(
     logins.length,
     shouldExist ? 1 : 0,
     `Login was ${shouldExist ? "" : "not "} found.`
   );
 }
 
 function addLogin(host, timestamp) {
   checkLoginExists(host, false);
   let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
     Ci.nsILoginInfo
   );
-  login.init(
-    host,
-    "",
-    null,
-    LOGIN_USERNAME,
-    LOGIN_PASSWORD,
-    LOGIN_USERNAME_FIELD,
-    LOGIN_PASSWORD_FIELD
-  );
+  login.init(host, "", null, LOGIN_USERNAME, LOGIN_PASSWORD);
   login.QueryInterface(Ci.nsILoginMetaInfo);
   login.timePasswordChanged = timestamp;
   loginManager.addLogin(login);
   checkLoginExists(host, true);
 }
 
 async function setupPasswords() {
   loginManager.removeAllLogins();
+  addLogin(FXA_HOST, REFERENCE_DATE);
   addLogin(NEW_HOST, REFERENCE_DATE);
   addLogin(OLD_HOST, REFERENCE_DATE - 10000);
 }
 
 add_task(async function testPasswords() {
   function background() {
     browser.test.onMessage.addListener(async (msg, options) => {
       if (msg == "removeHistory") {
@@ -74,32 +66,35 @@ add_task(async function testPasswords() 
   async function testRemovalMethod(method) {
     // Clear passwords with no since value.
     await setupPasswords();
     extension.sendMessage(method, {});
     await extension.awaitMessage("passwordsRemoved");
 
     checkLoginExists(OLD_HOST, false);
     checkLoginExists(NEW_HOST, false);
+    checkLoginExists(FXA_HOST, true);
 
     // Clear passwords with recent since value.
     await setupPasswords();
     extension.sendMessage(method, { since: REFERENCE_DATE - 1000 });
     await extension.awaitMessage("passwordsRemoved");
 
     checkLoginExists(OLD_HOST, true);
     checkLoginExists(NEW_HOST, false);
+    checkLoginExists(FXA_HOST, true);
 
     // Clear passwords with old since value.
     await setupPasswords();
     extension.sendMessage(method, { since: REFERENCE_DATE - 20000 });
     await extension.awaitMessage("passwordsRemoved");
 
     checkLoginExists(OLD_HOST, false);
     checkLoginExists(NEW_HOST, false);
+    checkLoginExists(FXA_HOST, true);
   }
 
   await extension.startup();
 
   await testRemovalMethod("removePasswords");
   await testRemovalMethod("remove");
 
   await extension.unload();