Bug 1332613 - Add support for removeAllLogins to take an optional parameter 'since'; r?bsilverberg
MozReview-Commit-ID: 7ONnH6CJ1At
--- 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([]);