Bug 1332613 - Add support for removeAllLogins to take an optional parameter 'since'; r?bsilverberg draft
authorThomas Wisniewski <wisniewskit@gmail.com>
Sun, 09 Apr 2017 00:10:56 -0400
changeset 559171 2100a3e04f34aeb4584d438877d72436b3379df0
parent 559154 2a3ecdb7d1ea814708021fee6735b3aedcf03e48
child 559172 56131c3fba3d6889aaaae60002d948e7115a9876
push id53010
push userwisniewskit@gmail.com
push dateSun, 09 Apr 2017 04:14:03 +0000
reviewersbsilverberg
bugs1332613
milestone55.0a1
Bug 1332613 - Add support for removeAllLogins to take an optional parameter 'since'; r?bsilverberg MozReview-Commit-ID: 7ONnH6CJ1At
toolkit/components/passwordmgr/nsILoginManager.idl
toolkit/components/passwordmgr/nsILoginManagerStorage.idl
toolkit/components/passwordmgr/nsLoginManager.js
toolkit/components/passwordmgr/storage-json.js
toolkit/components/passwordmgr/storage-mozStorage.js
toolkit/components/passwordmgr/test/unit/test_notifications.js
--- a/toolkit/components/passwordmgr/nsILoginManager.idl
+++ b/toolkit/components/passwordmgr/nsILoginManager.idl
@@ -70,24 +70,25 @@ interface nsILoginManager : nsISupports 
    *
    * If the propertybag contains an item named "timesUsedIncrement", the
    * login's timesUsed property will be incremented by the item's value.
    */
   void modifyLogin(in nsILoginInfo oldLogin, in nsISupports newLoginData);
 
 
   /**
-   * Remove all logins known to login manager.
+   * Remove all logins known to login manager (optionally since a given time).
    *
    * The browser sanitization feature allows the user to clear any stored
    * passwords. This interface allows that to be done without getting each
    * login first (which might require knowing the master password).
    *
+   * @param since   earliest timestamp to clear from (inclusive).
    */
-  void removeAllLogins();
+  void removeAllLogins([optional] in int64_t since);
 
 
   /**
    * Fetch all logins in the login manager. An array is always returned;
    * if there are no logins the array is empty.
    *
    * @param count
    *        The number of elements in the array. JS callers can simply use
--- a/toolkit/components/passwordmgr/nsILoginManagerStorage.idl
+++ b/toolkit/components/passwordmgr/nsILoginManagerStorage.idl
@@ -89,24 +89,25 @@ interface nsILoginManagerStorage : nsISu
    *
    * If the propertybag contains an item named "timesUsedIncrement", the
    * login's timesUsed property will be incremented by the item's value.
    */
   void modifyLogin(in nsILoginInfo oldLogin, in nsISupports newLoginData);
 
 
   /**
-   * Remove all stored logins.
+   * Remove all stored logins (optionally since a given time).
    *
    * The browser sanitization feature allows the user to clear any stored
    * passwords. This interface allows that to be done without getting each
    * login first (which might require knowing the master password).
    *
+   * @param since   earliest timestamp to clear from (inclusive).
    */
-  void removeAllLogins();
+  void removeAllLogins([optional] in int64_t since);
 
 
   /**
    * Fetch all logins in the login manager. An array is always returned;
    * if there are no logins the array is empty.
    *
    * @param count
    *        The number of elements in the array. JS callers can simply use
--- a/toolkit/components/passwordmgr/nsLoginManager.js
+++ b/toolkit/components/passwordmgr/nsLoginManager.js
@@ -338,21 +338,21 @@ LoginManager.prototype = {
    */
   getAllLogins(count) {
     log.debug("Getting a list of all logins");
     return this._storage.getAllLogins(count);
   },
 
 
   /**
-   * Remove all stored logins.
+   * Remove all stored logins (optionally since a given time).
    */
-  removeAllLogins() {
-    log.debug("Removing all logins");
-    this._storage.removeAllLogins();
+  removeAllLogins(since) {
+    log.debug("Removing all logins" + (since ? "since " + since : ""));
+    this._storage.removeAllLogins(since);
   },
 
   /**
    * Get a list of all origins for which logins are disabled.
    *
    * @param {Number} count - only needed for XPCOM.
    *
    * @return {String[]} of disabled origins. If there are no disabled origins,
--- a/toolkit/components/passwordmgr/storage-json.js
+++ b/toolkit/components/passwordmgr/storage-json.js
@@ -358,23 +358,29 @@ this.LoginManagerStorage_json.prototype 
     }
 
     this.log("_searchLogins: returning", foundLogins.length, "logins for", matchData,
              "with options", aOptions);
     return [foundLogins, foundIds];
   },
 
   /**
-   * Removes all logins from storage.
+   * Removes all logins from storage (optionally since a given time).
    */
-  removeAllLogins() {
+  removeAllLogins(since) {
     this._store.ensureDataReady();
 
-    this.log("Removing all logins");
-    this._store.data.logins = [];
+    this.log("Removing all logins" + (since ? "since " + since : ""));
+    if (since) {
+      this._store.data.logins = this._store.data.logins.filter(item => {
+        return item.timePasswordChanged < since;
+      });
+    } else {
+      this._store.data.logins = [];
+    }
     this._store.saveSoon();
 
     LoginHelper.notifyStorageChanged("removeAllLogins", null);
   },
 
   findLogins(count, hostname, formSubmitURL, httpRealm) {
     let loginData = {
       hostname,
--- a/toolkit/components/passwordmgr/storage-mozStorage.js
+++ b/toolkit/components/passwordmgr/storage-mozStorage.js
@@ -565,30 +565,32 @@ LoginManagerStorage_mozStorage.prototype
     } finally {
       if (stmt)
         stmt.reset();
     }
   },
 
 
   /**
-   * Removes all logins from storage.
+   * Removes all logins from storage (optionally since a given time).
    */
-  removeAllLogins() {
-    this.log("Removing all logins");
+  removeAllLogins(aSince) {
+    this.log("Removing all logins" + (aSince ? "since " + aSince : ""));
     let query;
     let stmt;
     let transaction = new Transaction(this._dbConnection);
 
     // Disabled hosts kept, as one presumably doesn't want to erase those.
     // TODO: Add these items to the deleted items table once we've sorted
     //       out the issues from bug 756701
     query = "DELETE FROM moz_logins";
+    if (aSince) query += " WHERE timePasswordChanged >= :since";
     try {
-      stmt = this._dbCreateStatement(query);
+      let params = {since: aSince};
+      stmt = this._dbCreateStatement(query, params);
       stmt.execute();
       transaction.commit();
     } catch (e) {
       this.log("_removeAllLogins failed: " + e.name + " : " + e.message);
       transaction.rollback();
       throw new Error("Couldn't write to database");
     } finally {
       if (stmt) {
--- a/toolkit/components/passwordmgr/test/unit/test_notifications.js
+++ b/toolkit/components/passwordmgr/test/unit/test_notifications.js
@@ -116,47 +116,67 @@ testdesc = "removeAllLogins (again)";
 expectedNotification = "removeAllLogins";
 expectedData = null;
 Services.logins.removeAllLogins();
 do_check_eq(expectedNotification, null);
 LoginTestUtils.checkLogins([]);
 
 /* ========== 7 ========== */
 testnum++;
+testdesc = "removeAllLogins since";
+
+expectedNotification = "removeAllLogins";
+expectedData = null;
+Services.logins.removeAllLogins(123);
+do_check_eq(expectedNotification, null);
+LoginTestUtils.checkLogins([]);
+
+/* ========== 8 ========== */
+testnum++;
+testdesc = "removeAllLogins since (again)";
+
+expectedNotification = "removeAllLogins";
+expectedData = null;
+Services.logins.removeAllLogins(123);
+do_check_eq(expectedNotification, null);
+LoginTestUtils.checkLogins([]);
+
+/* ========== 9 ========== */
+testnum++;
 testdesc = "setLoginSavingEnabled / false";
 
 expectedNotification = "hostSavingDisabled";
 expectedData = "http://site.com";
 Services.logins.setLoginSavingEnabled("http://site.com", false);
 do_check_eq(expectedNotification, null);
 LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(),
                                         ["http://site.com"]);
 
-/* ========== 8 ========== */
+/* ========== 10 ========== */
 testnum++;
 testdesc = "setLoginSavingEnabled / false (again)";
 
 expectedNotification = "hostSavingDisabled";
 expectedData = "http://site.com";
 Services.logins.setLoginSavingEnabled("http://site.com", false);
 do_check_eq(expectedNotification, null);
 LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(),
                                         ["http://site.com"]);
 
-/* ========== 9 ========== */
+/* ========== 11 ========== */
 testnum++;
 testdesc = "setLoginSavingEnabled / true";
 
 expectedNotification = "hostSavingEnabled";
 expectedData = "http://site.com";
 Services.logins.setLoginSavingEnabled("http://site.com", true);
 do_check_eq(expectedNotification, null);
 LoginTestUtils.checkLogins([]);
 
-/* ========== 10 ========== */
+/* ========== 12 ========== */
 testnum++;
 testdesc = "setLoginSavingEnabled / true (again)";
 
 expectedNotification = "hostSavingEnabled";
 expectedData = "http://site.com";
 Services.logins.setLoginSavingEnabled("http://site.com", true);
 do_check_eq(expectedNotification, null);
 LoginTestUtils.checkLogins([]);