Bug 1595656 - Only clear user-facing passwords with the browsingData API. r=rpl
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 21 Nov 2019 14:42:57 +0000
changeset 503245 942c83d4c62d147d6de02004cc312fc2540c029d
parent 503244 bb120dcc1726ee5590bbba188203379c4be4e261
child 503246 f1ab1efbf08780e8401bd233f98fd39f29de3ea3
push id101213
push usermozilla@noorenberghe.ca
push dateFri, 22 Nov 2019 00:26:38 +0000
treeherderautoland@942c83d4c62d [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-bookmarks.js
browser/components/extensions/parent/ext-browsingData.js
browser/components/extensions/parent/ext-history.js
browser/components/extensions/test/xpcshell/test_ext_browsingData_passwords.js
--- a/browser/components/extensions/parent/ext-bookmarks.js
+++ b/browser/components/extensions/parent/ext-bookmarks.js
@@ -1,20 +1,24 @@
 /* -*- 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"
 );
 
+XPCOMUtils.defineLazyModuleGetters(this, {
+  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
+});
+
 var { ExtensionError } = ExtensionUtils;
 
 const { TYPE_BOOKMARK, TYPE_FOLDER, TYPE_SEPARATOR } = PlacesUtils.bookmarks;
 
 const BOOKMARKS_TYPES_TO_API_TYPES_MAP = new Map([
   [TYPE_BOOKMARK, "bookmark"],
   [TYPE_FOLDER, "folder"],
   [TYPE_SEPARATOR, "separator"],
--- 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/parent/ext-history.js
+++ b/browser/components/extensions/parent/ext-history.js
@@ -1,25 +1,24 @@
 /* -*- 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,
-  "Services",
-  "resource://gre/modules/Services.jsm"
-);
+XPCOMUtils.defineLazyModuleGetters(this, {
+  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
+  Services: "resource://gre/modules/Services.jsm",
+});
 
 var { normalizeTime } = ExtensionCommon;
 
 let nsINavHistoryService = Ci.nsINavHistoryService;
 const TRANSITION_TO_TRANSITION_TYPES_MAP = new Map([
   ["link", nsINavHistoryService.TRANSITION_LINK],
   ["typed", nsINavHistoryService.TRANSITION_TYPED],
   ["auto_bookmark", nsINavHistoryService.TRANSITION_BOOKMARK],
--- 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();