From 518585cfb58a44241af24fb243e3b548632ac673 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 29 Aug 2017 12:52:11 -0400 Subject: [PATCH] track last used autofill for priority filling --- src/background.js | 2 +- src/models/domainModels.js | 6 +- src/services/autofillService.js | 12 ++-- src/services/loginService.js | 102 +++++++++++++++++++++++++++----- 4 files changed, 99 insertions(+), 23 deletions(-) diff --git a/src/background.js b/src/background.js index ae68600f08..0a0533fcf0 100644 --- a/src/background.js +++ b/src/background.js @@ -83,7 +83,7 @@ chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { messageTab(msg.tab.id, 'pageDetails', { details: msg.details, forms: forms }); } else if (msg.sender === 'autofiller') { - bg_autofillService.doAutoFillForFirstLogin([{ + bg_autofillService.doAutoFillForLastUsedLogin([{ frameId: sender.frameId, tab: msg.tab, details: msg.details }]); } diff --git a/src/models/domainModels.js b/src/models/domainModels.js index cd1479b0a1..10b1815ece 100644 --- a/src/models/domainModels.js +++ b/src/models/domainModels.js @@ -88,13 +88,14 @@ var CipherString = function () { } }; -var Login = function (obj, alreadyEncrypted) { +var Login = function (obj, alreadyEncrypted, localData) { this.id = obj.id ? obj.id : null; this.organizationId = obj.organizationId ? obj.organizationId : null; this.folderId = obj.folderId ? obj.folderId : null; this.favorite = obj.favorite ? true : false; this.organizationUseTotp = obj.organizationUseTotp ? true : false; this.edit = obj.edit ? true : false; + this.localData = localData; if (alreadyEncrypted === true) { this.name = obj.name ? obj.name : null; @@ -176,7 +177,8 @@ var Folder = function (obj, alreadyEncrypted) { id: self.id, organizationId: self.organizationId, folderId: self.folderId, - favorite: self.favorite + favorite: self.favorite, + localData: self.localData }; var attachments = []; diff --git a/src/services/autofillService.js b/src/services/autofillService.js index b7f231a43a..b6c1ed39dd 100644 --- a/src/services/autofillService.js +++ b/src/services/autofillService.js @@ -135,7 +135,7 @@ function initAutofill() { return formData; }; - AutofillService.prototype.doAutoFill = function (login, pageDetails, fromBackground, skipTotp) { + AutofillService.prototype.doAutoFill = function (login, pageDetails, fromBackground, skipTotp, skipLastUsed) { var deferred = Q.defer(); var self = this; @@ -168,6 +168,9 @@ function initAutofill() { } didAutofill = true; + if (!skipLastUsed) { + self.loginService.updateLastUsedDate(login.id, function () { }); + } chrome.tabs.sendMessage(tab.id, { command: 'fillForm', @@ -207,7 +210,7 @@ function initAutofill() { return deferred.promise; }; - AutofillService.prototype.doAutoFillForFirstLogin = function (pageDetails) { + AutofillService.prototype.doAutoFillForLastUsedLogin = function (pageDetails) { var self = this; chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { @@ -230,10 +233,11 @@ function initAutofill() { return; } - self.doAutoFill(logins[0], pageDetails, true, true); + var sortedLogins = logins.sort(self.loginService.sortLoginsByLastUsed); + self.doAutoFill(sortedLogins[0], pageDetails, true, true, true); }); }); - } + }; function loadPasswordFields(pageDetails, canBeHidden) { var arr = []; diff --git a/src/services/loginService.js b/src/services/loginService.js index 04bf852b3c..050c1dcd1d 100644 --- a/src/services/loginService.js +++ b/src/services/loginService.js @@ -55,15 +55,23 @@ function initLoginService() { this.userService.getUserId(function (userId) { var loginsKey = 'sites_' + userId; + var localDataKey = 'sitesLocalData'; - chrome.storage.local.get(loginsKey, function (obj) { - var logins = obj[loginsKey]; - if (logins && id in logins) { - callback(new Login(logins[id])); - return; + chrome.storage.local.get(localDataKey, function (localDataObj) { + var localData = localDataObj[localDataKey]; + if (!localData) { + localData = {}; } - callback(null); + chrome.storage.local.get(loginsKey, function (obj) { + var logins = obj[loginsKey]; + if (logins && id in logins) { + callback(new Login(logins[id], false, localData[id])); + return; + } + + callback(null); + }); }); }); }; @@ -75,19 +83,27 @@ function initLoginService() { this.userService.getUserId(function (userId) { var loginsKey = 'sites_' + userId; + var localDataKey = 'sitesLocalData'; - chrome.storage.local.get(loginsKey, function (obj) { - var logins = obj[loginsKey]; - var response = []; - for (var id in logins) { - if (!id) { - continue; - } - - response.push(new Login(logins[id])); + chrome.storage.local.get(localDataKey, function (localDataObj) { + var localData = localDataObj[localDataKey]; + if (!localData) { + localData = {}; } - callback(response); + chrome.storage.local.get(loginsKey, function (obj) { + var logins = obj[loginsKey]; + var response = []; + for (var id in logins) { + if (!id) { + continue; + } + + response.push(new Login(logins[id], false, localData[id])); + } + + callback(response); + }); }); }); }; @@ -242,6 +258,46 @@ function initLoginService() { }); }; + LoginService.prototype.updateLastUsedDate = function (id, callback) { + if (!callback || typeof callback !== 'function') { + throw 'callback function required'; + } + + var self = this; + var localDataKey = 'sitesLocalData'; + + chrome.storage.local.get(localDataKey, function (obj) { + var loginsLocalData = obj[localDataKey]; + if (!loginsLocalData) { + loginsLocalData = {}; + } + + if (loginsLocalData[id]) { + loginsLocalData[id].lastUsedDate = new Date().getTime(); + } + else { + loginsLocalData[id] = { + lastUsedDate: new Date().getTime() + }; + } + + obj[localDataKey] = loginsLocalData; + + chrome.storage.local.set(obj, function () { + if (self.decryptedLoginCache) { + for (var i = 0; i < self.decryptedLoginCache.length; i++) { + if (self.decryptedLoginCache[i].id === id) { + self.decryptedLoginCache[i].localData = loginsLocalData[id]; + break; + } + } + } + + callback(); + }); + }); + }; + LoginService.prototype.replace = function (logins, callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; @@ -441,6 +497,20 @@ function initLoginService() { return deferred.promise; }; + LoginService.prototype.sortLoginsByLastUsed = function (a, b) { + var aLastUsed = a.localData && a.localData.lastUsedDate ? a.localData.lastUsedDate : null; + var bLastUsed = b.localData && b.localData.lastUsedDate ? b.localData.lastUsedDate : null; + + if (aLastUsed && (!bLastUsed || aLastUsed < bLastUsed)) { + return 1; + } + if (bLastUsed && (!aLastUsed || aLastUsed > bLastUsed)) { + return -1; + } + + return 0; + }; + function handleError(error, deferred) { deferred.reject(error); }