From b1135c232d41cd260d4ddeb1732db11129a40134 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sat, 2 Sep 2017 13:12:36 +0300 Subject: [PATCH 01/12] Added browser-polyfill, merged changes from latest passifox, fixed HTTP auth --- CHANGELOG | 7 ++ README.md | 39 +--------- keepassxc-browser/background/browserAction.js | 64 ++++++++-------- keepassxc-browser/background/event.js | 38 +++++----- keepassxc-browser/background/httpauth.js | 51 +++++++++---- keepassxc-browser/background/init.js | 47 +++++++++--- keepassxc-browser/background/keepass.js | 48 +++++++----- keepassxc-browser/background/page.js | 74 ++++++++++++------- keepassxc-browser/browser-polyfill.min.js | 9 +++ keepassxc-browser/global.js | 6 +- keepassxc-browser/keepassxc-browser.js | 26 +++---- keepassxc-browser/manifest.json | 9 ++- keepassxc-browser/options/options.html | 3 +- keepassxc-browser/options/options.js | 72 +++++++++--------- keepassxc-browser/popups/popup.html | 1 + keepassxc-browser/popups/popup.js | 9 +-- keepassxc-browser/popups/popup_functions.js | 9 +-- keepassxc-browser/popups/popup_httpauth.html | 5 +- keepassxc-browser/popups/popup_httpauth.js | 4 +- keepassxc-browser/popups/popup_login.html | 5 +- keepassxc-browser/popups/popup_login.js | 6 +- .../popups/popup_multiple-fields.html | 1 + keepassxc-browser/popups/popup_remember.html | 1 + keepassxc-browser/popups/popup_remember.js | 10 +-- 24 files changed, 311 insertions(+), 233 deletions(-) create mode 100644 keepassxc-browser/browser-polyfill.min.js diff --git a/CHANGELOG b/CHANGELOG index adf145c..31eaa61 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +0.3.0 (2017-??-??) +========================= +- Added Mozilla's browser-polyfill +- Merged changes from the latest passifox (credits to smorks): +- HTTP auth works with all browsers +- TODO: Automatic detectal of div's with forms that are non-hidden by user interaction + 0.2.9 (2017-08-27) ========================= - Code cleaning, global functions moved to global.js diff --git a/README.md b/README.md index b65cfd0..be48651 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Chrome extension for [KeePassXC](https://keepassxc.org/) with Native Messaging. This is a heavily forked version of [pfn](https://github.com/pfn)'s [chromeIPass](https://github.com/pfn/passifox). -Some changes merged also from [projectgus'](https://github.com/projectgus/passifox) fork. +Some changes merged also from [projectgus'](https://github.com/projectgus/passifox) and [smorks'](https://github.com/smorks/passifox) fork. For testing purposes, please use following unofficial KeePassXC [release's](https://github.com/varjolintu/keepassxc/releases). Get the extension for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome/Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf). @@ -269,41 +269,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ``` -The following quick method to determine which browser is used with API calls by [David Rousset](https://github.com/davrous): -```javascript -window.browser = (function () { - return window.msBrowser || - window.browser || - window.chrome; -})(); -``` - -``` -MIT License - -Copyright (c) 2016 David Rousset - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -``` - ## Donations Feel free to support this project: - Donate via [PayPal](https://paypal.me/varjolintu) -- Donate via Bitcoin: 1LHbD69CcmpLW5hjUXs2MGJhw3GxwqLdw3 \ No newline at end of file +- Donate via Bitcoin: 1LHbD69CcmpLW5hjUXs2MGJhw3GxwqLdw3 + +Also consider donating to [KeePassXC](https://flattr.com/submit/auto?fid=x7yqz0&url=https%3A%2F%2Fkeepassxc.org) and passifox teams [(1)](https://github.com/smorks/passifox),[(2)](https://github.com/projectgus/passifox),[(3)](https://github.com/pfn/passifox). They are doing great job. \ No newline at end of file diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index 39fa94c..7c0dbfd 100644 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -218,43 +218,45 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { }; browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) { - const settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings); - const id = tabId || page.currentTabId; - let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)); + browser.storage.local.get({'settings': {}}).then((item) => { + const settings = item.settings; + const id = tabId || page.currentTabId; + let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)); - if (timeoutMinMillis > 0) { - timeoutMinMillis += Date.now(); - } + if (timeoutMinMillis > 0) { + timeoutMinMillis += Date.now(); + } - const blinkTimeout = getValueOrDefault(settings, 'blinkTimeout', BLINK_TIMEOUT_DEFAULT, 0); - const pageUpdateAllowance = getValueOrDefault(settings, 'allowedRedirect', BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); + const blinkTimeout = getValueOrDefault(settings, 'blinkTimeout', BLINK_TIMEOUT_DEFAULT, 0); + const pageUpdateAllowance = getValueOrDefault(settings, 'allowedRedirect', BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); - const stackData = { - visibleForMilliSeconds: blinkTimeout, - visibleForPageUpdates: pageUpdateAllowance, - redirectOffset: timeoutMinMillis, - level: 10, - intervalIcon: { - index: 0, - counter: 0, - max: 2, - icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png'] - }, - icon: 'icon_remember_red_background_19x19.png', - popup: 'popup_remember.html' - } + const stackData = { + visibleForMilliSeconds: blinkTimeout, + visibleForPageUpdates: pageUpdateAllowance, + redirectOffset: timeoutMinMillis, + level: 10, + intervalIcon: { + index: 0, + counter: 0, + max: 2, + icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png'] + }, + icon: 'icon_remember_red_background_19x19.png', + popup: 'popup_remember.html' + } - browserAction.stackPush(stackData, id); + browserAction.stackPush(stackData, id); - page.tabs[id].credentials = { - username: username, - password: password, - url: url, - usernameExists: usernameExists, - list: credentialsList - }; + page.tabs[id].credentials = { + username: username, + password: password, + url: url, + usernameExists: usernameExists, + list: credentialsList + }; - browserAction.show(null, {'id': id}); + browserAction.show(null, {'id': id}); + }); } function getValueOrDefault(settings, key, defaultVal, min) { diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 0a09842..eb3b40b 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -41,7 +41,7 @@ event.invoke = function(handler, callback, senderTabId, args, secondTime) { // remove information from no longer existing tabs page.removePageInformationFromNotExistingTabs(); - browser.tabs.get(senderTabId, (tab) => { + browser.tabs.get(senderTabId).then((tab) => { if (!tab) { return; } @@ -101,27 +101,32 @@ event.showStatus = function(configured, tab, callback) { } event.onLoadSettings = function(callback, tab) { - page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); + browser.storage.local.get({'settings': {}}).then((item) => { + callback(item.settings); + }, (err) => { + console.log('error loading settings: ' + err); + }); } event.onLoadKeyRing = function(callback, tab) { - keepass.keyRing = (typeof(localStorage.keyRing) === 'undefined') ? {} : JSON.parse(localStorage.keyRing); - if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { - keepass.associated = { - value: false, - hash: null - }; - } -} - -event.onGetSettings = function(callback, tab) { - event.onLoadSettings(); - callback({ data: page.settings }); + browser.storage.local.get({'keyRing': {}}).then(function(item) { + keepass.keyRing = item.keyRing; + if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { + keepass.associated = { + "value": false, + "hash": null + }; + } + callback(item.keyRing); + }, (err) => { + console.log('error loading keyRing: ' + err); + }); } event.onSaveSettings = function(callback, tab, settings) { - localStorage.settings = JSON.stringify(settings); - event.onLoadSettings(); + browser.storage.local.set({'settings': settings}).then(function() { + event.onLoadSettings(); + }); } event.onGetStatus = function(callback, tab) { @@ -237,7 +242,6 @@ event.messageHandlers = { 'check_update_keepassxc': event.onCheckUpdateKeePassXC, 'get_connected_database': event.onGetConnectedDatabase, 'get_keepassxc_versions': event.onGetKeePassXCVersions, - 'get_settings': event.onGetSettings, 'get_status': event.onGetStatus, 'get_tab_information': event.onGetTabInformation, 'load_keyring': event.onLoadKeyRing, diff --git a/keepassxc-browser/background/httpauth.js b/keepassxc-browser/background/httpauth.js index 5c91eca..04f64e9 100644 --- a/keepassxc-browser/background/httpauth.js +++ b/keepassxc-browser/background/httpauth.js @@ -9,7 +9,21 @@ httpAuth.proxyUrl = null; httpAuth.resolve = null; httpAuth.reject = null; -httpAuth.handleRequest = function (details, callback) { +httpAuth.handleRequest = function(details) { + return new Promise((resolve, reject) => { + if (httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { + reject({}); + } + else { + httpAuth.requestId = details.requestId; + httpAuth.resolve = resolve; + httpAuth.reject = reject; + httpAuth.processPendingCallbacks(details); + } + }); +} + +httpAuth.handleRequestChrome = function(details, callback) { if (httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { callback({}); } @@ -21,12 +35,14 @@ httpAuth.handleRequest = function (details, callback) { } httpAuth.processPendingCallbacks = function(details) { - httpAuth.callback = httpAuth.pendingCallbacks.pop(); + if (!isFirefox) { + httpAuth.callback = httpAuth.pendingCallbacks.pop(); + } httpAuth.tabId = details.tabId; httpAuth.url = details.url; httpAuth.isProxy = details.isProxy; - if (details.challenger){ + if (details.challenger) { httpAuth.proxyUrl = details.challenger.host; } @@ -35,8 +51,7 @@ httpAuth.processPendingCallbacks = function(details) { // chrome.tabs.get(tabId, callback) <-- but what should callback be? const url = (httpAuth.isProxy && httpAuth.proxyUrl) ? httpAuth.proxyUrl : httpAuth.url; - - keepass.retrieveCredentials(httpAuth.loginOrShowCredentials, { 'id' : details.tabId }, url, url, true); + keepass.retrieveCredentials(httpAuth.loginOrShowCredentials, { "id" : details.tabId }, url, url, true); } httpAuth.loginOrShowCredentials = function(logins) { @@ -47,19 +62,29 @@ httpAuth.loginOrShowCredentials = function(logins) { //generate popup-list for HTTP Auth usernames + descriptions if (page.settings.autoFillAndSend) { - httpAuth.callback({ - authCredentials: { - username: logins[0].login, - password: logins[0].password - } - }); + if (isFirefox) { + httpAuth.resolve({ + authCredentials: { + username: logins[0].login, + password: logins[0].password + } + }); + } + else { + httpAuth.callback({ + authCredentials: { + username: logins[0].login, + password: logins[0].password + } + }); + } } else { - httpAuth.callback({}); + isFirefox ? httpAuth.reject({}) : httpAuth.callback({}); } } // no logins found else { - httpAuth.callback({}); + isFirefox ? httpAuth.reject({}) : httpAuth.callback({}); } } \ No newline at end of file diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 3f94f04..e9ee7e4 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -1,3 +1,4 @@ +/* keepass.convertKeyToKeyRing(); page.initSettings(); page.initOpenedTabs(); @@ -6,12 +7,30 @@ keepass.generateNewKeyPair(); keepass.changePublicKeys(null, (pkRes) => { keepass.getDatabaseHash((gdRes) => {}, null); }); +*/ -// Set initial tab-ID -browser.tabs.query({"active": true, "currentWindow": true}, (tabs) => { - if (tabs.length === 0) - return; // For example: only the background devtools or a popup are opened - page.currentTabId = tabs[0].id; +// since version 2.0 the extension is using a keyRing instead of a single key-name-pair +keepass.migrateKeyRing().then(() => { + // load settings + page.initSettings().then(() => { + // initial connection with KeePassHttp + keepass.connectToNative(); + keepass.generateNewKeyPair(); + keepass.changePublicKeys(null, (pkRes) => { + keepass.getDatabaseHash((gdRes) => { + // create tab information structure for every opened tab + page.initOpenedTabs(); + + // set initial tab-ID + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { + if (tabs.length === 0) + return; // For example: only the background devtools or a popup are opened + page.currentTabId = tabs[0].id; + browserAction.show(null, tabs[0]); + }); + }, null); + }); + }); }); // Milliseconds for intervall (e.g. to update browserAction) @@ -55,8 +74,7 @@ browser.tabs.onActivated.addListener((activeInfo) => { page.clearCredentials(page.currentTabId, true); browserAction.removeRememberPopup(null, {'id': page.currentTabId}, true); - browser.tabs.get(activeInfo.tabId, (info) => { - //console.log(info.id + ': ' + info.url); + browser.tabs.get(activeInfo.tabId).then((info) => { if (info && info.id) { page.currentTabId = info.id; if (info.status === 'complete') { @@ -79,9 +97,16 @@ browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { }); // Retrieve Credentials and try auto-login for HTTPAuth requests -browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, - { urls: [''] }, ['asyncBlocking'] -); +if (browser.webRequest.onAuthRequired) { + if (isFirefox) { + browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, + { urls: [""] }, ["blocking"]); + } + else { + browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequestChrome, + { urls: [""] }, ["asyncBlocking"]); + } +} browser.runtime.onMessage.addListener(event.onMessage); @@ -100,7 +125,7 @@ for (const item of contextMenuItems) { onclick: (info, tab) => { browser.tabs.sendMessage(tab.id, { action: item.action - }); + }).catch((e) => {console.log(e);}); } }); } diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 8b0a662..506f15b 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -64,6 +64,14 @@ const kpErrors = { } }; +browser.storage.local.get({ + 'latestKeePassXC': {'version': 0, 'versionParsed': 0, 'lastChecked': null}, + 'keyRing': {}}) + .then((item) => { + keepass.latestKeePassHttp = item.latestKeePassHttp; + keepass.keyRing = item.keyRing; +}); + keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials(callback, tab, null, username, password, url); } @@ -551,23 +559,29 @@ keepass.isAssociated = function() { return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash === keepass.databaseHash); } -keepass.convertKeyToKeyRing = function() { - if (keepass.keyId in localStorage && keepass.keyBody in localStorage && !('keyRing' in localStorage)) { - keepass.getDatabaseHash((hash) => { - keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); - +keepass.migrateKeyRing = () => { + return new Promise((resolve, reject) => { + browser.storage.local.get('keyRing').then((item) => { + var keyring = item.keyRing; if ('keyRing' in localStorage) { + if (!keyring) { + keyring = JSON.parse(localStorage['keyRing']); + browser.storage.local.set({'keyRing': keyring}); + } + delete localStorage['keyRing']; + } + if (keepass.keyId in localStorage && keepass.keyBody in localStorage) { + if (!keyring) { + var hash = keepass.getDatabaseHash(null); + keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); + } delete localStorage[keepass.keyId]; delete localStorage[keepass.keyBody]; } - }, null); - } - - if ('keyRing' in localStorage) { - delete localStorage[keepass.keyId]; - delete localStorage[keepass.keyBody]; - } -} + resolve(); + }); + }); +}; keepass.saveKey = function(hash, id, key) { if (!(hash in keepass.keyRing)) { @@ -584,19 +598,19 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].key = key; keepass.keyRing[hash].hash = hash; } - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); } keepass.updateLastUsed = function(hash) { if ((hash in keepass.keyRing)) { keepass.keyRing[hash].lastUsed = new Date(); - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); } } keepass.deleteKey = function(hash) { delete keepass.keyRing[hash]; - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); } keepass.setcurrentKeePassXCVersion = function(version) { @@ -635,7 +649,7 @@ keepass.checkForNewKeePassXCVersion = function() { } if (version !== -1) { - localStorage.latestKeePassXC = JSON.stringify(keepass.latestKeePassXC); + browser.storage.local.set({'latestKeePassXC': keepass.latestKeePassXC}); } }; diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 0063dc0..1500c81 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -15,34 +15,56 @@ page.currentTabId = -1; page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); page.blockedTabs = {}; +page.migrateSettings = () => { + return new Promise((resolve, reject) => { + const old = localStorage.getItem('settings'); + if (old) { + const settings = JSON.parse(old); + browser.storage.local.set({'settings': settings}).then(() => { + localStorage.removeItem('settings'); + resolve(obj); + }); + } else { + event.onLoadSettings((settings) => { + resolve(settings); + }); + } + }); +}; + page.initSettings = function() { - event.onLoadSettings(); - if (!('checkUpdateKeePassXC' in page.settings)) { - page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; - } - if (!('autoCompleteUsernames' in page.settings)) { - page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; - } - if (!('autoFillAndSend' in page.settings)) { - page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; - } - if (!('usePasswordGenerator' in page.settings)) { - page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; - } - if (!('autoFillSingleEntry' in page.settings)) { - page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; - } - if (!('autoRetrieveCredentials' in page.settings)) { - page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; - } - if (!('port' in page.settings)) { - page.settings.port = defaultSettings.proxyPort; - } - localStorage.settings = JSON.stringify(page.settings); + return new Promise((resolve, reject) => { + page.migrateSettings().then((settings) => { + page.settings = settings; + if (!('checkUpdateKeePassXC' in page.settings)) { + page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; + } + if (!('autoCompleteUsernames' in page.settings)) { + page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; + } + if (!('autoFillAndSend' in page.settings)) { + page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; + } + if (!('usePasswordGenerator' in page.settings)) { + page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; + } + if (!('autoFillSingleEntry' in page.settings)) { + page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; + } + if (!('autoRetrieveCredentials' in page.settings)) { + page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; + } + if (!('port' in page.settings)) { + page.settings.port = defaultSettings.proxyPort; + } + browser.storage.local.set({'settings': page.settings}); + resolve(); + }); + }); } page.initOpenedTabs = function() { - browser.tabs.query({}, (tabs) => { + browser.tabs.query({}).then((tabs) => { for (const i of tabs) { page.createTabEntry(i.id); } @@ -57,7 +79,7 @@ page.isValidProtocol = function(url) { page.switchTab = function(callback, tab) { browserAction.showDefault(null, tab); - browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}); + browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {console.log(e);}); } page.clearCredentials = function(tabId, complete) { @@ -73,7 +95,7 @@ page.clearCredentials = function(tabId, complete) { browser.tabs.sendMessage(tabId, { action: 'clear_credentials' - }); + }).catch((e) => {console.log(e);}); } } diff --git a/keepassxc-browser/browser-polyfill.min.js b/keepassxc-browser/browser-polyfill.min.js new file mode 100644 index 0000000..47125a6 --- /dev/null +++ b/keepassxc-browser/browser-polyfill.min.js @@ -0,0 +1,9 @@ +"use strict";if("undefined"==typeof browser){this.browser=(()=>{class c extends WeakMap{constructor(m,n=void 0){super(n),this.createItem=m}get(m){return this.has(m)||this.set(m,this.createItem(m)),super.get(m)}}const d=m=>{return m&&"object"==typeof m&&"function"==typeof m.then},e=m=>{return(...n)=>{chrome.runtime.lastError?m.reject(chrome.runtime.lastError):1===n.length?m.resolve(n[0]):m.resolve(n)}},f=(m,n)=>{const o=p=>1==p?"argument":"arguments";return function(q,...r){if(r.lengthn.maxArgs)throw new Error(`Expected at most ${n.maxArgs} ${o(n.maxArgs)} for ${m}(), got ${r.length}`);return new Promise((s,t)=>{q[m](...r,e({resolve:s,reject:t}))})}},g=(m,n,o)=>{return new Proxy(n,{apply(p,q,r){return o.call(q,m,...r)}})};let h=Function.call.bind(Object.prototype.hasOwnProperty);const i=(m,n={},o={})=>{let p=Object.create(null),q={has(r,s){return s in r||s in p},get(r,s){if(s in p)return p[s];if(s in r){let u=r[s];if("function"==typeof u){if("function"==typeof n[s])u=g(r,r[s],n[s]);else if(h(o,s)){let v=f(s,o[s]);u=g(r,r[s],v)}else u=u.bind(r);}else if("object"==typeof u&&null!==u&&(h(n,s)||h(o,s)))u=i(u,n[s],o[s]);else return Object.defineProperty(p,s,{configurable:!0,enumerable:!0,get(){return r[s]},set(v){r[s]=v}}),u;return p[s]=u,u}},set(r,s,t){return s in p?p[s]=t:r[s]=t,!0},defineProperty(r,s,t){return Reflect.defineProperty(p,s,t)},deleteProperty(r,s){return Reflect.deleteProperty(p,s)}};return new Proxy(m,q)},k=new c(m=>{return"function"==typeof m?function(o,p,q){let r=!1,s=m(o,p,function(t){r=!0,q(t)});return r||!0===s?s:d(s)?(s.then(q,t=>{console.error(t),q(t)}),!0):void(void 0!==s&&q(s))}:m}),l={runtime:{onMessage:(m=>({addListener(n,o,...p){n.addListener(m.get(o),...p)},hasListener(n,o){return n.hasListener(m.get(o))},removeListener(n,o){n.removeListener(m.get(o))}}))(k)}};return i(chrome,l,{alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},"export":{minArgs:0,maxArgs:0},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},getSubTree:{minArgs:1,maxArgs:1},"import":{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},setIcon:{minArgs:1,maxArgs:1}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{update:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},downloads:{download:{minArgs:1,maxArgs:1},cancel:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:0,maxArgs:0},setIcon:{minArgs:1,maxArgs:1},show:{minArgs:0,maxArgs:0}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getBrowserInfo:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{create:{minArgs:1,maxArgs:1},captureVisibleTab:{minArgs:0,maxArgs:2},detectLanguage:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},query:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}})})()} +//# sourceMappingURL=browser-polyfill.min.js.map + + +// webextension-polyfill v.0.1.0 (https://github.com/mozilla/webextension-polyfill) + +/* 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/. */ \ No newline at end of file diff --git a/keepassxc-browser/global.js b/keepassxc-browser/global.js index 245478b..c6b5df2 100644 --- a/keepassxc-browser/global.js +++ b/keepassxc-browser/global.js @@ -1,6 +1,4 @@ var isFirefox = false; -if (typeof browser !== 'undefined') { +if (!(/Chrome/.test(navigator.userAgent) && /Google/.test(navigator.vendor))) { isFirefox = true; -} - -window.browser = (function () { return window.msBrowser || window.browser || window.chrome; })(); \ No newline at end of file +} \ No newline at end of file diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index a1927d4..77d387a 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -52,9 +52,9 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { } else if (req.action === 'redetect_fields') { browser.runtime.sendMessage({ - action: 'get_settings', - }, (response) => { - cip.settings = response.data; + action: 'load_settings', + }).then((settings) => { + cip.settings = settings; cip.initCredentialFields(true); }); } @@ -254,7 +254,7 @@ cipPassword.createDialog = function() { e.preventDefault(); browser.runtime.sendMessage({ action: 'generate_password' - }, cipPassword.callbackGeneratedPassword); + }).then(cipPassword.callbackGeneratedPassword); } }, 'Copy': @@ -419,7 +419,7 @@ cipPassword.callbackGeneratedPassword = function(entries) { cipPassword.onRequestPassword = function() { browser.runtime.sendMessage({ action: 'generate_password' - }, cipPassword.callbackGeneratedPassword); + }).then(cipPassword.callbackGeneratedPassword); } cipPassword.checkObservedElements = function() { @@ -1102,9 +1102,9 @@ jQuery(function() { cip.init = function() { browser.runtime.sendMessage({ - action: 'get_settings', - }, (response) => { - cip.settings = response.data; + action: 'load_settings', + }).then((settings) => { + cip.settings = settings; cip.initCredentialFields(); }); } @@ -1139,7 +1139,7 @@ cip.initCredentialFields = function(forceCall) { browser.runtime.sendMessage({ action: 'retrieve_credentials', args: [ cip.url, cip.submitUrl ] - }, cip.retrieveCredentialsCallback); + }).then(cip.retrieveCredentialsCallback); } } // end function init @@ -1160,11 +1160,11 @@ cip.receiveCredentialsIfNecessary = function () { browser.runtime.sendMessage({ action: 'retrieve_credentials', args: [ cip.url, cip.submitUrl ] - }, cip.retrieveCredentialsCallback); + }).then(cip.retrieveCredentialsCallback); } } -cip.retrieveCredentialsCallback = function (credentials, dontAutoFillIn) { +cip.retrieveCredentialsCallback = function(credentials, dontAutoFillIn) { if (cipFields.combinations.length > 0) { cip.u = _f(cipFields.combinations[0].username); cip.p = _f(cipFields.combinations[0].password); @@ -1301,7 +1301,7 @@ cip.fillInCredentials = function(combination, onlyPassword, suppressWarnings) { browser.runtime.sendMessage({ action: 'retrieve_credentials', args: [ cip.url, cip.submitUrl, false, true ] - }, (credentials) => { + }).then((credentials) => { cip.retrieveCredentialsCallback(credentials, true); cip.fillIn(combination, onlyPassword, suppressWarnings); }); @@ -1692,6 +1692,6 @@ cipEvents.triggerActivatedTab = function() { browser.runtime.sendMessage({ action: 'retrieve_credentials', args: [ cip.url, cip.submitUrl ] - }, cip.retrieveCredentialsCallback); + }).then(cip.retrieveCredentialsCallback); } } diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index 3dddae5..12882b8 100644 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "keepassxc-browser", - "version": "0.2.9", + "version": "0.3.0", "description": "KeePassXC integration for modern web browsers", "author": "Sami Vänttinen", "icons": { @@ -24,6 +24,7 @@ }, "background": { "scripts": [ + "browser-polyfill.min.js", "global.js", "background/nacl.min.js", "background/nacl-util.min.js", @@ -38,10 +39,10 @@ "content_scripts": [ { "matches": [ - "http://*/*", - "https://*/*" + "" ], "js": [ + "browser-polyfill.min.js", "global.js", "jquery-3.2.1.min.js", "jquery-ui.min.js", @@ -75,9 +76,11 @@ "icons/key.png" ], "permissions": [ + "activeTab", "contextMenus", "clipboardWrite", "nativeMessaging", + "storage", "tabs", "webRequest", "webRequestBlocking", diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html index ad791ae..15b6ad9 100644 --- a/keepassxc-browser/options/options.html +++ b/keepassxc-browser/options/options.html @@ -5,6 +5,7 @@ + @@ -307,7 +308,7 @@
diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 6730b62..1414ff7 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -3,17 +3,34 @@ if (jQuery) { } $(function() { - options.initMenu(); - options.initGeneralSettings(); - options.initConnectedDatabases(); - options.initSpecifiedCredentialFields(); - options.initAbout(); + browser.runtime.sendMessage({ action: 'load_settings' }).then((settings) => { + options.settings = settings; + browser.runtime.sendMessage({ action: 'load_keyring' }).then((keyRing) => { + options.keyRing = keyRing; + options.initMenu(); + options.initGeneralSettings(); + options.initConnectedDatabases(); + options.initSpecifiedCredentialFields(); + options.initAbout(); + }); + }); }); var options = options || {}; -options.settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings); -options.keyRing = typeof(localStorage.keyRing) === 'undefined' ? {} : JSON.parse(localStorage.keyRing); +options.saveSettings = function() { + browser.storage.local.set({'settings': options.settings}); + browser.runtime.sendMessage({ + action: 'load_settings' + }); +}; + +options.saveKeyRing = function() { + browser.storage.local.set({'keyRing': options.keyRing}); + browser.runtime.sendMessage({ + action: 'load_keyring' + }); +}; options.initMenu = function() { $('.navbar:first ul.nav:first li a').click(function(e) { @@ -31,12 +48,7 @@ options.saveSetting = function(name) { const $id = '#' + name; $($id).closest('.control-group').removeClass('error').addClass('success'); setTimeout(() => { $($id).closest('.control-group').removeClass('success') }, 2500); - - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); } options.initGeneralSettings = function() { @@ -46,38 +58,30 @@ options.initGeneralSettings = function() { $('#tab-general-settings input[type=checkbox]').change(function() { options.settings[$(this).attr('name')] = $(this).is(':checked'); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); $('#tab-general-settings input[type=radio]').each(function() { - if($(this).val() === options.settings[$(this).attr('name')]) { + if ($(this).val() === options.settings[$(this).attr('name')]) { $(this).attr('checked', options.settings[$(this).attr('name')]); } }); $('#tab-general-settings input[type=radio]').change(function() { options.settings[$(this).attr('name')] = $(this).val(); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); browser.runtime.sendMessage({ action: 'get_keepassxc_versions' - }, options.showKeePassXCVersions); + }).then(options.showKeePassXCVersions); $('#tab-general-settings button.checkUpdateKeePassXC:first').click(function(e) { e.preventDefault(); $(this).attr('disabled', true); browser.runtime.sendMessage({ action: 'check_update_keepassxc' - }, options.showKeePassXCVersions); + }).then(options.showKeePassXCVersions); }); $('#port').val(options.settings['port']); @@ -152,11 +156,7 @@ options.initConnectedDatabases = function() { $('#tab-connected-databases #tr-cd-' + $hash).remove(); delete options.keyRing[$hash]; - localStorage.keyRing = JSON.stringify(options.keyRing); - - browser.runtime.sendMessage({ - action: 'load_keyring' - }); + options.saveKeyRing(); if ($('#tab-connected-databases table tbody:first tr').length > 2) { $('#tab-connected-databases table tbody:first tr.empty:first').hide(); @@ -218,11 +218,7 @@ options.initSpecifiedCredentialFields = function() { $('#tab-specified-fields #' + $trId).remove(); delete options.settings['defined-credential-fields'][$url]; - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); if($('#tab-specified-fields table tbody:first tr').length > 2) { $('#tab-specified-fields table tbody:first tr.empty:first').hide(); @@ -235,7 +231,7 @@ options.initSpecifiedCredentialFields = function() { const $trClone = $('#tab-specified-fields table tr.clone:first').clone(true); $trClone.removeClass('clone'); let counter = 1; - for(let url in options.settings['defined-credential-fields']) { + for (let url in options.settings['defined-credential-fields']) { const $tr = $trClone.clone(true); $tr.data('url', url); $tr.attr('id', 'tr-scf' + counter); @@ -245,7 +241,7 @@ options.initSpecifiedCredentialFields = function() { $('#tab-specified-fields table tbody:first').append($tr); } - if($('#tab-specified-fields table tbody:first tr').length > 2) { + if ($('#tab-specified-fields table tbody:first tr').length > 2) { $('#tab-specified-fields table tbody:first tr.empty:first').hide(); } else { diff --git a/keepassxc-browser/popups/popup.html b/keepassxc-browser/popups/popup.html index f02373d..1fef03b 100644 --- a/keepassxc-browser/popups/popup.html +++ b/keepassxc-browser/popups/popup.html @@ -4,6 +4,7 @@ + diff --git a/keepassxc-browser/popups/popup.js b/keepassxc-browser/popups/popup.js index a289c4e..f902671 100644 --- a/keepassxc-browser/popups/popup.js +++ b/keepassxc-browser/popups/popup.js @@ -53,18 +53,17 @@ $(function() { $('#reload-status-button').click(function() { browser.runtime.sendMessage({ action: 'reconnect' - }, status_response); + }).then(status_response); }); $('#reopen-database-button').click(function() { browser.runtime.sendMessage({ action: 'get_status' - }, status_response); - close(); + }).then(status_response); }); $('#redetect-fields-button').click(function() { - browser.tabs.query({"active": true, "currentWindow": true}, (tabs) => { + browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened let tab = tabs[0]; @@ -77,5 +76,5 @@ $(function() { browser.runtime.sendMessage({ action: 'get_status' - }, status_response); + }).then(status_response); }); \ No newline at end of file diff --git a/keepassxc-browser/popups/popup_functions.js b/keepassxc-browser/popups/popup_functions.js index 0fc5d1c..39fc703 100644 --- a/keepassxc-browser/popups/popup_functions.js +++ b/keepassxc-browser/popups/popup_functions.js @@ -1,5 +1,5 @@ var $ = jQuery.noConflict(true); -var _settings = typeof(localStorage.settings) ==='undefined' ? {} : JSON.parse(localStorage.settings); +//var _settings = typeof(localStorage.settings) ==='undefined' ? {} : JSON.parse(localStorage.settings); function updateAvailableResponse(available) { if (available) { @@ -12,12 +12,11 @@ function updateAvailableResponse(available) { function initSettings() { $ ('#settings #btn-options').click(function() { - browser.runtime.openOptionsPage(); - close(); + browser.runtime.openOptionsPage().then(close()); }); $ ('#settings #btn-choose-credential-fields').click(function() { - browser.runtime.getBackgroundPage((global) => { + browser.runtime.getBackgroundPage().then((global) => { browser.tabs.sendMessage(global.page.currentTabId, { action: 'choose_credential_fields' }); @@ -32,5 +31,5 @@ $(function() { browser.runtime.sendMessage({ action: 'update_available_keepassxc' - }, updateAvailableResponse); + }).then(updateAvailableResponse); }); diff --git a/keepassxc-browser/popups/popup_httpauth.html b/keepassxc-browser/popups/popup_httpauth.html index 2c48ab6..a6b67c2 100644 --- a/keepassxc-browser/popups/popup_httpauth.html +++ b/keepassxc-browser/popups/popup_httpauth.html @@ -4,6 +4,7 @@ + @@ -12,8 +13,8 @@
- - + +
You use an old version of KeePassXC. diff --git a/keepassxc-browser/popups/popup_httpauth.js b/keepassxc-browser/popups/popup_httpauth.js index 9425fef..b5f15ff 100644 --- a/keepassxc-browser/popups/popup_httpauth.js +++ b/keepassxc-browser/popups/popup_httpauth.js @@ -1,6 +1,6 @@ $(function() { - browser.runtime.getBackgroundPage(function(global) { - browser.tabs.query({"active": true, "currentWindow": true}, (tab) => { + browser.runtime.getBackgroundPage().then((global) => { + browser.tabs.query({"active": true, "currentWindow": true}.then((tab) => { const data = global.page.tabs[tab.id].loginList; let ul = document.getElementById('login-list'); for (let i = 0; i < data.logins.length; i++) { diff --git a/keepassxc-browser/popups/popup_login.html b/keepassxc-browser/popups/popup_login.html index d2e8af8..655104f 100644 --- a/keepassxc-browser/popups/popup_login.html +++ b/keepassxc-browser/popups/popup_login.html @@ -4,6 +4,7 @@ + @@ -12,8 +13,8 @@
- - + +
You use an old version of KeePassXC. diff --git a/keepassxc-browser/popups/popup_login.js b/keepassxc-browser/popups/popup_login.js index 389e982..23a6e1e 100644 --- a/keepassxc-browser/popups/popup_login.js +++ b/keepassxc-browser/popups/popup_login.js @@ -1,6 +1,6 @@ $(function() { - browser.runtime.getBackgroundPage(function(global) { - browser.tabs.query({"active": true, "currentWindow": true}, (tabs) => { + browser.runtime.getBackgroundPage().then((global) => { + browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened const tab = tabs[0]; @@ -14,7 +14,7 @@ $(function() { li.appendChild(a); a.setAttribute('id', '' + i); a.addEventListener('click', (e) => { - var id = e.target.id; + const id = e.target.id; browser.tabs.sendMessage(tab.id, { action: 'fill_user_pass_with_specific_login', id: id diff --git a/keepassxc-browser/popups/popup_multiple-fields.html b/keepassxc-browser/popups/popup_multiple-fields.html index 656c45b..663a7e6 100644 --- a/keepassxc-browser/popups/popup_multiple-fields.html +++ b/keepassxc-browser/popups/popup_multiple-fields.html @@ -4,6 +4,7 @@ + diff --git a/keepassxc-browser/popups/popup_remember.html b/keepassxc-browser/popups/popup_remember.html index 643a513..ec91f69 100644 --- a/keepassxc-browser/popups/popup_remember.html +++ b/keepassxc-browser/popups/popup_remember.html @@ -4,6 +4,7 @@ + diff --git a/keepassxc-browser/popups/popup_remember.js b/keepassxc-browser/popups/popup_remember.js index aac9fcb..1396ad8 100644 --- a/keepassxc-browser/popups/popup_remember.js +++ b/keepassxc-browser/popups/popup_remember.js @@ -23,7 +23,7 @@ function _initialize(tab) { browser.runtime.sendMessage({ action: 'add_credentials', args: [_tab.credentials.username, _tab.credentials.password, _tab.credentials.url] - }, _verifyResult); + }).then(_verifyResult); }); $('#btn-update').click(function(e) { @@ -34,7 +34,7 @@ function _initialize(tab) { browser.runtime.sendMessage({ action: 'update_credentials', args: [_tab.credentials.list[0].uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url] - }, _verifyResult); + }).then(_verifyResult); } else { $('.credentials:first .username-new:first strong:first').text(_tab.credentials.username); @@ -59,7 +59,7 @@ function _initialize(tab) { browser.runtime.sendMessage({ action: 'update_credentials', args: [_tab.credentials.list[$(this).data('entryId')].uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url] - }, _verifyResult); + }).then(_verifyResult); }); if (_tab.credentials.usernameExists && _tab.credentials.username === _tab.credentials.list[i].login) { @@ -116,9 +116,9 @@ $(function() { browser.runtime.sendMessage({ action: 'get_tab_information' - }, _initialize); + }).then(_initialize); browser.runtime.sendMessage({ action: 'get_connected_database' - }, _connected_database); + }).then(_connected_database); }); \ No newline at end of file From 481cc286ff3fc8f15f4130a923ffa5f269e59206 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Fri, 8 Sep 2017 08:30:20 +0300 Subject: [PATCH 02/12] "Fixed showing credentials from previous logins in the popup (credits to smorks) --- CHANGELOG | 3 +- keepassxc-browser/background/event.js | 5 +++ keepassxc-browser/background/page.js | 6 +++- keepassxc-browser/keepassxc-browser.js | 48 ++++++++++++++------------ 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 31eaa61..869d9ad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,9 @@ 0.3.0 (2017-??-??) ========================= - Added Mozilla's browser-polyfill -- Merged changes from the latest passifox (credits to smorks): +- Merged changes from the latest passifox (credits to smorks) - HTTP auth works with all browsers +- Fixed showing credentials from previous login in popup (credits to smorks) - TODO: Automatic detectal of div's with forms that are non-hidden by user interaction 0.2.9 (2017-08-27) diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index eb3b40b..e053d30 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -233,6 +233,10 @@ event.onMultipleFieldsPopup = function(callback, tab) { browserAction.show(null, tab); } +event.onPageClearLogins = function(callback, tab) { + page.clearLogins(tab.id); + callback(); +} // all methods named in this object have to be declared BEFORE this! event.messageHandlers = { @@ -246,6 +250,7 @@ event.messageHandlers = { 'get_tab_information': event.onGetTabInformation, 'load_keyring': event.onLoadKeyRing, 'load_settings': event.onLoadSettings, + 'page_clear_logins': event.onPageClearLogins, 'pop_stack': event.onPopStack, 'popup_login': event.onLoginPopup, 'popup_multiple-fields': event.onMultipleFieldsPopup, diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 1500c81..09a17a6 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -91,7 +91,7 @@ page.clearCredentials = function(tabId, complete) { delete page.tabs[tabId].credentials; if (complete) { - page.tabs[tabId].loginList = []; + page.clearLogins(tabId); browser.tabs.sendMessage(tabId, { action: 'clear_credentials' @@ -99,6 +99,10 @@ page.clearCredentials = function(tabId, complete) { } } +page.clearLogins = function(tabId) { + page.tabs[tabId].loginList = []; +} + page.createTabEntry = function(tabId) { //console.log('page.createTabEntry('+tabId+')'); page.tabs[tabId] = { diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index 77d387a..3123813 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -1115,32 +1115,34 @@ cip.initCredentialFields = function(forceCall) { } _called.initCredentialFields = true; - const inputs = cipFields.getAllFields(); - cipFields.prepareVisibleFieldsWithID('select'); - cip.initPasswordGenerator(inputs); + browser.runtime.sendMessage({ 'action': 'page_clear_logins' }).then(() => { + const inputs = cipFields.getAllFields(); + cipFields.prepareVisibleFieldsWithID('select'); + cip.initPasswordGenerator(inputs); - if (!cipFields.useDefinedCredentialFields()) { - // get all combinations of username + password fields - cipFields.combinations = cipFields.getAllCombinations(inputs); - } - cipFields.prepareCombinations(cipFields.combinations); + if (!cipFields.useDefinedCredentialFields()) { + // get all combinations of username + password fields + cipFields.combinations = cipFields.getAllCombinations(inputs); + } + cipFields.prepareCombinations(cipFields.combinations); - if (cipFields.combinations.length === 0) { - browser.runtime.sendMessage({ - action: 'show_default_browseraction' - }); - return; - } + if (cipFields.combinations.length === 0) { + browser.runtime.sendMessage({ + action: 'show_default_browseraction' + }); + return; + } - cip.url = document.location.origin; - cip.submitUrl = cip.getFormActionUrl(cipFields.combinations[0]); + cip.url = document.location.origin; + cip.submitUrl = cip.getFormActionUrl(cipFields.combinations[0]); - if (cip.settings.autoRetrieveCredentials) { - browser.runtime.sendMessage({ - action: 'retrieve_credentials', - args: [ cip.url, cip.submitUrl ] - }).then(cip.retrieveCredentialsCallback); - } + if (cip.settings.autoRetrieveCredentials) { + browser.runtime.sendMessage({ + action: 'retrieve_credentials', + args: [ cip.url, cip.submitUrl ] + }).then(cip.retrieveCredentialsCallback); + } + }); } // end function init cip.initPasswordGenerator = function(inputs) { @@ -1694,4 +1696,4 @@ cipEvents.triggerActivatedTab = function() { args: [ cip.url, cip.submitUrl ] }).then(cip.retrieveCredentialsCallback); } -} +} \ No newline at end of file From ca6883cb08888f03895a4d62fbbf1e623d8468d9 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Fri, 8 Sep 2017 08:30:35 +0300 Subject: [PATCH 03/12] "Fixed showing credentials from previous logins in the popup (credits to smorks) --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 869d9ad..009001f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ - Added Mozilla's browser-polyfill - Merged changes from the latest passifox (credits to smorks) - HTTP auth works with all browsers -- Fixed showing credentials from previous login in popup (credits to smorks) +- Fixed showing credentials from previous logins in the popup (credits to smorks) - TODO: Automatic detectal of div's with forms that are non-hidden by user interaction 0.2.9 (2017-08-27) From 4d11ce7b5fa0228dec661199a493030b1af533a5 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Fri, 8 Sep 2017 09:04:27 +0300 Subject: [PATCH 04/12] Automatic detection of divs with forms that are non-hidden by user interaction --- CHANGELOG | 2 +- keepassxc-browser/keepassxc-browser.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 009001f..95cde52 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,7 @@ - Merged changes from the latest passifox (credits to smorks) - HTTP auth works with all browsers - Fixed showing credentials from previous logins in the popup (credits to smorks) -- TODO: Automatic detectal of div's with forms that are non-hidden by user interaction +- Automatic detection of div's with forms that are non-hidden by user interaction 0.2.9 (2017-08-27) ========================= diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index 3123813..807f07e 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -1696,4 +1696,15 @@ cipEvents.triggerActivatedTab = function() { args: [ cip.url, cip.submitUrl ] }).then(cip.retrieveCredentialsCallback); } -} \ No newline at end of file +} + +// Detect div's that include forms and are visible +$(function() { + const divDetect = setInterval(function() { + const fields = cipFields.getAllFields(); + if (fields.length > 0) { + cip.initCredentialFields(true); + clearInterval(divDetect); + } + }, 1000); +}); \ No newline at end of file From b78ee812e60d5bbdc3ab2845856338f4b0c744e5 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Mon, 11 Sep 2017 09:18:21 +0300 Subject: [PATCH 05/12] HTTP auth fixes --- CHANGELOG | 4 +- keepassxc-browser/background/httpauth.js | 96 +++++++++--------------- keepassxc-browser/background/init.js | 29 +++---- keepassxc-browser/background/page.js | 1 - keepassxc-browser/keepassxc-browser.js | 2 +- 5 files changed, 48 insertions(+), 84 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 95cde52..6049e28 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,9 @@ 0.3.0 (2017-??-??) ========================= - Added Mozilla's browser-polyfill -- Merged changes from the latest passifox (credits to smorks) +- Merged changes from the latest passifox (credits to smorks/passifox) - HTTP auth works with all browsers -- Fixed showing credentials from previous logins in the popup (credits to smorks) +- Fixed showing credentials from previous logins in the popup (credits to smorks/passifox) - Automatic detection of div's with forms that are non-hidden by user interaction 0.2.9 (2017-08-27) diff --git a/keepassxc-browser/background/httpauth.js b/keepassxc-browser/background/httpauth.js index 04f64e9..efb3892 100644 --- a/keepassxc-browser/background/httpauth.js +++ b/keepassxc-browser/background/httpauth.js @@ -1,90 +1,62 @@ var httpAuth = httpAuth || {}; +httpAuth.requests = []; httpAuth.pendingCallbacks = []; -httpAuth.requestId = ''; -httpAuth.tabId = 0; -httpAuth.url = null; -httpAuth.isProxy = false; -httpAuth.proxyUrl = null; -httpAuth.resolve = null; -httpAuth.reject = null; -httpAuth.handleRequest = function(details) { +httpAuth.requestCompleted = function(details) { + let index = httpAuth.requests.indexOf(details.requestId); + if (index > -1) { + httpAuth.requests.splice(index, 1); + } +} + +httpAuth.handleRequestPromise = function(details) { return new Promise((resolve, reject) => { - if (httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { - reject({}); - } - else { - httpAuth.requestId = details.requestId; - httpAuth.resolve = resolve; - httpAuth.reject = reject; - httpAuth.processPendingCallbacks(details); - } + httpAuth.processPendingCallbacks(details, resolve, reject); }); } -httpAuth.handleRequestChrome = function(details, callback) { - if (httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { - callback({}); - } - else { - httpAuth.requestId = details.requestId; - httpAuth.pendingCallbacks.push(callback); - httpAuth.processPendingCallbacks(details); - } +httpAuth.handleRequestCallback = function(details, callback) { + httpAuth.processPendingCallbacks(details, callback, callback); } -httpAuth.processPendingCallbacks = function(details) { - if (!isFirefox) { - httpAuth.callback = httpAuth.pendingCallbacks.pop(); +httpAuth.processPendingCallbacks = function(details, resolve, reject) { + if (httpAuth.requests.indexOf(details.requestId) >= 0 || !page.tabs[details.tabId]) { + reject({}); } - httpAuth.tabId = details.tabId; - httpAuth.url = details.url; - httpAuth.isProxy = details.isProxy; + + httpAuth.requests.push(details.requestId); if (details.challenger) { - httpAuth.proxyUrl = details.challenger.host; + details.proxyUrl = details.challenger.host; } - // WORKAROUND: second parameter should be tab, but is an own object with tab-id - // but in background.js only tab.id is used. To get tabs we could use - // chrome.tabs.get(tabId, callback) <-- but what should callback be? + details.searchUrl = (details.isProxy && details.proxyUrl) ? details.proxyUrl : details.url; - const url = (httpAuth.isProxy && httpAuth.proxyUrl) ? httpAuth.proxyUrl : httpAuth.url; - keepass.retrieveCredentials(httpAuth.loginOrShowCredentials, { "id" : details.tabId }, url, url, true); + keepass.retrieveCredentials((logins) => { + httpAuth.loginOrShowCredentials(logins, details, resolve, reject); + }, { "id": details.tabId }, details.searchUrl, details.searchUrl, true); } -httpAuth.loginOrShowCredentials = function(logins) { +httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) { // at least one login found --> use first to login if (logins.length > 0) { - const url = (httpAuth.isProxy && httpAuth.proxyUrl) ? httpAuth.proxyUrl : httpAuth.url; - event.onHTTPAuthPopup(null, {'id': httpAuth.tabId}, {'logins': logins, 'url': url}); + event.onHTTPAuthPopup(null, { "id": details.tabId }, { "logins": logins, "url": details.searchUrl }); //generate popup-list for HTTP Auth usernames + descriptions if (page.settings.autoFillAndSend) { - if (isFirefox) { - httpAuth.resolve({ - authCredentials: { - username: logins[0].login, - password: logins[0].password - } - }); - } - else { - httpAuth.callback({ - authCredentials: { - username: logins[0].login, - password: logins[0].password - } - }); - } - } - else { - isFirefox ? httpAuth.reject({}) : httpAuth.callback({}); + resolve({ + authCredentials: { + username: logins[0].login, + password: logins[0].password + } + }); + } else { + reject({}); } } // no logins found else { - isFirefox ? httpAuth.reject({}) : httpAuth.callback({}); + reject({}); } -} \ No newline at end of file +} diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index e9ee7e4..f9754ef 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -1,14 +1,3 @@ -/* -keepass.convertKeyToKeyRing(); -page.initSettings(); -page.initOpenedTabs(); -keepass.connectToNative(); -keepass.generateNewKeyPair(); -keepass.changePublicKeys(null, (pkRes) => { - keepass.getDatabaseHash((gdRes) => {}, null); -}); -*/ - // since version 2.0 the extension is using a keyRing instead of a single key-name-pair keepass.migrateKeyRing().then(() => { // load settings @@ -98,14 +87,18 @@ browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { // Retrieve Credentials and try auto-login for HTTPAuth requests if (browser.webRequest.onAuthRequired) { - if (isFirefox) { - browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, - { urls: [""] }, ["blocking"]); - } - else { - browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequestChrome, - { urls: [""] }, ["asyncBlocking"]); + let handleReq = httpAuth.handleRequestPromise; + let reqType = 'blocking'; + let opts = { urls: [''] }; + + if (!isFirefox) { + handleReq = httpAuth.handleRequestCallback; + reqType = 'asyncBlocking'; } + + browser.webRequest.onAuthRequired.addListener(handleReq, opts, [reqType]); + browser.webRequest.onCompleted.addListener(httpAuth.requestCompleted, opts); + browser.webRequest.onErrorOccurred.addListener(httpAuth.requestCompleted, opts); } browser.runtime.onMessage.addListener(event.onMessage); diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 09a17a6..abdf32e 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -104,7 +104,6 @@ page.clearLogins = function(tabId) { } page.createTabEntry = function(tabId) { - //console.log('page.createTabEntry('+tabId+')'); page.tabs[tabId] = { 'stack': [], 'errorMessage': null, diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index 807f07e..ccd1107 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -1707,4 +1707,4 @@ $(function() { clearInterval(divDetect); } }, 1000); -}); \ No newline at end of file +}); From b1b5e3642e186b5547a6c8304a5c3a021c40f417 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Mon, 11 Sep 2017 11:33:45 +0300 Subject: [PATCH 06/12] Fixed saving Dates with local storage and Chrome/Chromium --- keepassxc-browser/background/event.js | 4 ++-- keepassxc-browser/background/init.js | 6 +++--- keepassxc-browser/background/keepass.js | 16 ++++++++-------- keepassxc-browser/background/page.js | 2 +- keepassxc-browser/keepassxc-browser.js | 8 ++++++++ keepassxc-browser/options/options.js | 2 +- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index e053d30..5342edc 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -110,14 +110,14 @@ event.onLoadSettings = function(callback, tab) { event.onLoadKeyRing = function(callback, tab) { browser.storage.local.get({'keyRing': {}}).then(function(item) { - keepass.keyRing = item.keyRing; + keepass.keyRing = JSON.parse(item.keyRing); if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { keepass.associated = { "value": false, "hash": null }; } - callback(item.keyRing); + callback(JSON.parse(item.keyRing)); }, (err) => { console.log('error loading keyRing: ' + err); }); diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index f9754ef..204dbfd 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -11,7 +11,7 @@ keepass.migrateKeyRing().then(() => { page.initOpenedTabs(); // set initial tab-ID - browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { + browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened page.currentTabId = tabs[0].id; @@ -126,7 +126,7 @@ for (const item of contextMenuItems) { // Listen for keyboard shortcuts specified by user browser.commands.onCommand.addListener((command) => { if (command === 'fill-username-password') { - browser.tabs.query({ active: true, currentWindow: true }, (tabs) => { + browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { if (tabs.length) { browser.tabs.sendMessage(tabs[0].id, { action: 'fill_user_pass' }); } @@ -134,7 +134,7 @@ browser.commands.onCommand.addListener((command) => { } if (command === 'fill-password') { - browser.tabs.query({ active: true, currentWindow: true }, (tabs) => { + browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { if (tabs.length) { browser.tabs.sendMessage(tabs[0].id, { action: 'fill_pass_only' }); } diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 506f15b..ebb6e39 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -68,8 +68,8 @@ browser.storage.local.get({ 'latestKeePassXC': {'version': 0, 'versionParsed': 0, 'lastChecked': null}, 'keyRing': {}}) .then((item) => { - keepass.latestKeePassHttp = item.latestKeePassHttp; - keepass.keyRing = item.keyRing; + keepass.latestKeePassXC = item.latestKeePassXC; + keepass.keyRing = JSON.parse(item.keyRing); }); keepass.addCredentials = function(callback, tab, username, password, url) { @@ -562,17 +562,17 @@ keepass.isAssociated = function() { keepass.migrateKeyRing = () => { return new Promise((resolve, reject) => { browser.storage.local.get('keyRing').then((item) => { - var keyring = item.keyRing; + let keyring = item.keyRing; if ('keyRing' in localStorage) { if (!keyring) { keyring = JSON.parse(localStorage['keyRing']); - browser.storage.local.set({'keyRing': keyring}); + browser.storage.local.set({'keyRing': JSON.stringify(keyring)}); } delete localStorage['keyRing']; } if (keepass.keyId in localStorage && keepass.keyBody in localStorage) { if (!keyring) { - var hash = keepass.getDatabaseHash(null); + const hash = keepass.getDatabaseHash(null); keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); } delete localStorage[keepass.keyId]; @@ -598,19 +598,19 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].key = key; keepass.keyRing[hash].hash = hash; } - browser.storage.local.set({'keyRing': keepass.keyRing}); + browser.storage.local.set({'keyRing': JSON.stringify(keepass.keyRing)}); } keepass.updateLastUsed = function(hash) { if ((hash in keepass.keyRing)) { keepass.keyRing[hash].lastUsed = new Date(); - browser.storage.local.set({'keyRing': keepass.keyRing}); + browser.storage.local.set({'keyRing': JSON.stringify(keepass.keyRing)}); } } keepass.deleteKey = function(hash) { delete keepass.keyRing[hash]; - browser.storage.local.set({'keyRing': keepass.keyRing}); + browser.storage.local.set({'keyRing': JSON.stringify(keepass.keyRing)}); } keepass.setcurrentKeePassXCVersion = function(version) { diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index abdf32e..ee3a201 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -114,7 +114,7 @@ page.createTabEntry = function(tabId) { page.removePageInformationFromNotExistingTabs = function() { let rand = Math.floor(Math.random()*1001); if (rand === 28) { - browser.tabs.query({}, (tabs) => { + browser.tabs.query({}).then(function(tabs) { let $tabIds = {}; const $infoIds = Object.keys(page.tabs); diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index ccd1107..e00ca3e 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -1701,10 +1701,18 @@ cipEvents.triggerActivatedTab = function() { // Detect div's that include forms and are visible $(function() { const divDetect = setInterval(function() { + /*browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { + const fields = cipFields.getAllFields(); + if (fields.length > 0) { + cip.initCredentialFields(true); + clearInterval(divDetect); + } + });*/ const fields = cipFields.getAllFields(); if (fields.length > 0) { cip.initCredentialFields(true); clearInterval(divDetect); } + console.log("Check.."); }, 1000); }); diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 1414ff7..b5c678a 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -26,7 +26,7 @@ options.saveSettings = function() { }; options.saveKeyRing = function() { - browser.storage.local.set({'keyRing': options.keyRing}); + browser.storage.local.set({'keyRing': JSON.stringify(options.keyRing)}); browser.runtime.sendMessage({ action: 'load_keyring' }); From 971d5e5e428c2897be219743faa4507d092fe471 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Mon, 11 Sep 2017 18:04:39 +0300 Subject: [PATCH 07/12] More various fixes --- keepassxc-browser/background/init.js | 18 ++++++----------- keepassxc-browser/background/page.js | 22 +++++++++++++++----- keepassxc-browser/keepassxc-browser.js | 28 +++++++++----------------- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 204dbfd..5b1ca27 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -6,18 +6,12 @@ keepass.migrateKeyRing().then(() => { keepass.connectToNative(); keepass.generateNewKeyPair(); keepass.changePublicKeys(null, (pkRes) => { - keepass.getDatabaseHash((gdRes) => { - // create tab information structure for every opened tab - page.initOpenedTabs(); - - // set initial tab-ID - browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { - if (tabs.length === 0) - return; // For example: only the background devtools or a popup are opened - page.currentTabId = tabs[0].id; - browserAction.show(null, tabs[0]); - }); - }, null); + // create tab information structure for every opened tab + page.initOpenedTabs().then(() => { + keepass.getDatabaseHash((gdRes) => { + + }, null); + }); }); }); }); diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index ee3a201..7044c6a 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -12,7 +12,6 @@ var page = {}; page.tabs = {}; page.currentTabId = -1; -page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); page.blockedTabs = {}; page.migrateSettings = () => { @@ -64,10 +63,23 @@ page.initSettings = function() { } page.initOpenedTabs = function() { - browser.tabs.query({}).then((tabs) => { - for (const i of tabs) { - page.createTabEntry(i.id); - } + return new Promise((resolve, reject) => { + browser.tabs.query({}).then(function (tabs) { + for (var i = 0; i < tabs.length; i++) { + page.createTabEntry(tabs[i].id); + } + + // set initial tab-ID + browser.tabs.query({ "active": true, "currentWindow": true }).then(function (tabs) { + if (tabs.length === 0) { + resolve(); + return; // For example: only the background devtools or a popup are opened + } + page.currentTabId = tabs[0].id; + browserAction.show(null, tabs[0]); + resolve(); + }); + }); }); } diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index e00ca3e..b117598 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -1098,6 +1098,15 @@ cip.credentials = []; jQuery(function() { cip.init(); + + // Detect div's that include forms and are visible + const divDetect = setInterval(function() { + const fields = cipFields.getAllFields(); + if (fields.length > 0) { + cip.initCredentialFields(true); + clearInterval(divDetect); + } + }, 1000); }); cip.init = function() { @@ -1697,22 +1706,3 @@ cipEvents.triggerActivatedTab = function() { }).then(cip.retrieveCredentialsCallback); } } - -// Detect div's that include forms and are visible -$(function() { - const divDetect = setInterval(function() { - /*browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { - const fields = cipFields.getAllFields(); - if (fields.length > 0) { - cip.initCredentialFields(true); - clearInterval(divDetect); - } - });*/ - const fields = cipFields.getAllFields(); - if (fields.length > 0) { - cip.initCredentialFields(true); - clearInterval(divDetect); - } - console.log("Check.."); - }, 1000); -}); From 68e41d65c6abea7611f4d8c6d21e59afb9e96a6e Mon Sep 17 00:00:00 2001 From: varjolintu Date: Tue, 12 Sep 2017 14:18:47 +0300 Subject: [PATCH 08/12] Reverted back to old database system --- keepassxc-browser/background/browserAction.js | 64 +++++++------ keepassxc-browser/background/event.js | 41 ++++----- keepassxc-browser/background/init.js | 24 ++--- keepassxc-browser/background/keepass.js | 50 ++++------ keepassxc-browser/background/page.js | 92 ++++++------------- keepassxc-browser/keepassxc-browser.js | 14 +-- keepassxc-browser/options/options.js | 54 +++++------ keepassxc-browser/popups/popup.js | 6 +- keepassxc-browser/popups/popup_functions.js | 1 - 9 files changed, 143 insertions(+), 203 deletions(-) diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index 7c0dbfd..39fa94c 100644 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -218,45 +218,43 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { }; browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) { - browser.storage.local.get({'settings': {}}).then((item) => { - const settings = item.settings; - const id = tabId || page.currentTabId; - let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)); + const settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings); + const id = tabId || page.currentTabId; + let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)); - if (timeoutMinMillis > 0) { - timeoutMinMillis += Date.now(); - } + if (timeoutMinMillis > 0) { + timeoutMinMillis += Date.now(); + } - const blinkTimeout = getValueOrDefault(settings, 'blinkTimeout', BLINK_TIMEOUT_DEFAULT, 0); - const pageUpdateAllowance = getValueOrDefault(settings, 'allowedRedirect', BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); + const blinkTimeout = getValueOrDefault(settings, 'blinkTimeout', BLINK_TIMEOUT_DEFAULT, 0); + const pageUpdateAllowance = getValueOrDefault(settings, 'allowedRedirect', BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); - const stackData = { - visibleForMilliSeconds: blinkTimeout, - visibleForPageUpdates: pageUpdateAllowance, - redirectOffset: timeoutMinMillis, - level: 10, - intervalIcon: { - index: 0, - counter: 0, - max: 2, - icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png'] - }, - icon: 'icon_remember_red_background_19x19.png', - popup: 'popup_remember.html' - } + const stackData = { + visibleForMilliSeconds: blinkTimeout, + visibleForPageUpdates: pageUpdateAllowance, + redirectOffset: timeoutMinMillis, + level: 10, + intervalIcon: { + index: 0, + counter: 0, + max: 2, + icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png'] + }, + icon: 'icon_remember_red_background_19x19.png', + popup: 'popup_remember.html' + } - browserAction.stackPush(stackData, id); + browserAction.stackPush(stackData, id); - page.tabs[id].credentials = { - username: username, - password: password, - url: url, - usernameExists: usernameExists, - list: credentialsList - }; + page.tabs[id].credentials = { + username: username, + password: password, + url: url, + usernameExists: usernameExists, + list: credentialsList + }; - browserAction.show(null, {'id': id}); - }); + browserAction.show(null, {'id': id}); } function getValueOrDefault(settings, key, defaultVal, min) { diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 5342edc..5070f69 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -101,32 +101,27 @@ event.showStatus = function(configured, tab, callback) { } event.onLoadSettings = function(callback, tab) { - browser.storage.local.get({'settings': {}}).then((item) => { - callback(item.settings); - }, (err) => { - console.log('error loading settings: ' + err); - }); + page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); } event.onLoadKeyRing = function(callback, tab) { - browser.storage.local.get({'keyRing': {}}).then(function(item) { - keepass.keyRing = JSON.parse(item.keyRing); - if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { - keepass.associated = { - "value": false, - "hash": null - }; - } - callback(JSON.parse(item.keyRing)); - }, (err) => { - console.log('error loading keyRing: ' + err); - }); + keepass.keyRing = (typeof(localStorage.keyRing) === 'undefined') ? {} : JSON.parse(localStorage.keyRing); + if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { + keepass.associated = { + value: false, + hash: null + }; + } +} + +event.onGetSettings = function(callback, tab) { + event.onLoadSettings(); + callback({ data: page.settings }); } event.onSaveSettings = function(callback, tab, settings) { - browser.storage.local.set({'settings': settings}).then(function() { - event.onLoadSettings(); - }); + localStorage.settings = JSON.stringify(settings); + event.onLoadSettings(); } event.onGetStatus = function(callback, tab) { @@ -233,11 +228,12 @@ event.onMultipleFieldsPopup = function(callback, tab) { browserAction.show(null, tab); } -event.onPageClearLogins = function(callback, tab) { +event.pageClearLogins = function(callback, tab) { page.clearLogins(tab.id); callback(); } + // all methods named in this object have to be declared BEFORE this! event.messageHandlers = { 'add_credentials': keepass.addCredentials, @@ -246,11 +242,12 @@ event.messageHandlers = { 'check_update_keepassxc': event.onCheckUpdateKeePassXC, 'get_connected_database': event.onGetConnectedDatabase, 'get_keepassxc_versions': event.onGetKeePassXCVersions, + 'get_settings': event.onGetSettings, 'get_status': event.onGetStatus, 'get_tab_information': event.onGetTabInformation, 'load_keyring': event.onLoadKeyRing, 'load_settings': event.onLoadSettings, - 'page_clear_logins': event.onPageClearLogins, + 'page_clear_logins': event.pageClearLogins, 'pop_stack': event.onPopStack, 'popup_login': event.onLoginPopup, 'popup_multiple-fields': event.onMultipleFieldsPopup, diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 5b1ca27..f231fea 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -1,21 +1,13 @@ -// since version 2.0 the extension is using a keyRing instead of a single key-name-pair -keepass.migrateKeyRing().then(() => { - // load settings - page.initSettings().then(() => { - // initial connection with KeePassHttp - keepass.connectToNative(); - keepass.generateNewKeyPair(); - keepass.changePublicKeys(null, (pkRes) => { - // create tab information structure for every opened tab - page.initOpenedTabs().then(() => { - keepass.getDatabaseHash((gdRes) => { - - }, null); - }); - }); - }); +keepass.convertKeyToKeyRing(); +page.initSettings(); +page.initOpenedTabs(); +keepass.connectToNative(); +keepass.generateNewKeyPair(); +keepass.changePublicKeys(null, (pkRes) => { + keepass.getDatabaseHash((gdRes) => {}, null); }); + // Milliseconds for intervall (e.g. to update browserAction) let _interval = 250; diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index ebb6e39..70051cf 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -64,14 +64,6 @@ const kpErrors = { } }; -browser.storage.local.get({ - 'latestKeePassXC': {'version': 0, 'versionParsed': 0, 'lastChecked': null}, - 'keyRing': {}}) - .then((item) => { - keepass.latestKeePassXC = item.latestKeePassXC; - keepass.keyRing = JSON.parse(item.keyRing); -}); - keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials(callback, tab, null, username, password, url); } @@ -376,7 +368,7 @@ keepass.testAssociation = function (callback, tab, triggerUnlock) { const nonce = nacl.randomBytes(keepass.keySize); const {dbid, dbkey} = keepass.getCryptoKey(); - if (dbkey === null || dbid === null) { + if (dbkey === null || dbid === null) { if (tab && page.tabs[tab.id]) { keepass.handleError(tab, kpErrors.NO_SAVED_DATABASES_FOUND); } @@ -559,29 +551,23 @@ keepass.isAssociated = function() { return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash === keepass.databaseHash); } -keepass.migrateKeyRing = () => { - return new Promise((resolve, reject) => { - browser.storage.local.get('keyRing').then((item) => { - let keyring = item.keyRing; +keepass.convertKeyToKeyRing = function() { + if (keepass.keyId in localStorage && keepass.keyBody in localStorage && !('keyRing' in localStorage)) { + keepass.getDatabaseHash((hash) => { + keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); + if ('keyRing' in localStorage) { - if (!keyring) { - keyring = JSON.parse(localStorage['keyRing']); - browser.storage.local.set({'keyRing': JSON.stringify(keyring)}); - } - delete localStorage['keyRing']; - } - if (keepass.keyId in localStorage && keepass.keyBody in localStorage) { - if (!keyring) { - const hash = keepass.getDatabaseHash(null); - keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); - } delete localStorage[keepass.keyId]; delete localStorage[keepass.keyBody]; } - resolve(); - }); - }); -}; + }, null); + } + + if ('keyRing' in localStorage) { + delete localStorage[keepass.keyId]; + delete localStorage[keepass.keyBody]; + } +} keepass.saveKey = function(hash, id, key) { if (!(hash in keepass.keyRing)) { @@ -598,19 +584,19 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].key = key; keepass.keyRing[hash].hash = hash; } - browser.storage.local.set({'keyRing': JSON.stringify(keepass.keyRing)}); + localStorage.keyRing = JSON.stringify(keepass.keyRing); } keepass.updateLastUsed = function(hash) { if ((hash in keepass.keyRing)) { keepass.keyRing[hash].lastUsed = new Date(); - browser.storage.local.set({'keyRing': JSON.stringify(keepass.keyRing)}); + localStorage.keyRing = JSON.stringify(keepass.keyRing); } } keepass.deleteKey = function(hash) { delete keepass.keyRing[hash]; - browser.storage.local.set({'keyRing': JSON.stringify(keepass.keyRing)}); + localStorage.keyRing = JSON.stringify(keepass.keyRing); } keepass.setcurrentKeePassXCVersion = function(version) { @@ -649,7 +635,7 @@ keepass.checkForNewKeePassXCVersion = function() { } if (version !== -1) { - browser.storage.local.set({'latestKeePassXC': keepass.latestKeePassXC}); + localStorage.latestKeePassXC = JSON.stringify(keepass.latestKeePassXC); } }; diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 7044c6a..c825f59 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -12,74 +12,40 @@ var page = {}; page.tabs = {}; page.currentTabId = -1; +page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); page.blockedTabs = {}; -page.migrateSettings = () => { - return new Promise((resolve, reject) => { - const old = localStorage.getItem('settings'); - if (old) { - const settings = JSON.parse(old); - browser.storage.local.set({'settings': settings}).then(() => { - localStorage.removeItem('settings'); - resolve(obj); - }); - } else { - event.onLoadSettings((settings) => { - resolve(settings); - }); - } - }); -}; - page.initSettings = function() { - return new Promise((resolve, reject) => { - page.migrateSettings().then((settings) => { - page.settings = settings; - if (!('checkUpdateKeePassXC' in page.settings)) { - page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; - } - if (!('autoCompleteUsernames' in page.settings)) { - page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; - } - if (!('autoFillAndSend' in page.settings)) { - page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; - } - if (!('usePasswordGenerator' in page.settings)) { - page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; - } - if (!('autoFillSingleEntry' in page.settings)) { - page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; - } - if (!('autoRetrieveCredentials' in page.settings)) { - page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; - } - if (!('port' in page.settings)) { - page.settings.port = defaultSettings.proxyPort; - } - browser.storage.local.set({'settings': page.settings}); - resolve(); - }); - }); + event.onLoadSettings(); + if (!('checkUpdateKeePassXC' in page.settings)) { + page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; + } + if (!('autoCompleteUsernames' in page.settings)) { + page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; + } + if (!('autoFillAndSend' in page.settings)) { + page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; + } + if (!('usePasswordGenerator' in page.settings)) { + page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; + } + if (!('autoFillSingleEntry' in page.settings)) { + page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; + } + if (!('autoRetrieveCredentials' in page.settings)) { + page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; + } + if (!('port' in page.settings)) { + page.settings.port = defaultSettings.proxyPort; + } + localStorage.settings = JSON.stringify(page.settings); } page.initOpenedTabs = function() { - return new Promise((resolve, reject) => { - browser.tabs.query({}).then(function (tabs) { - for (var i = 0; i < tabs.length; i++) { - page.createTabEntry(tabs[i].id); - } - - // set initial tab-ID - browser.tabs.query({ "active": true, "currentWindow": true }).then(function (tabs) { - if (tabs.length === 0) { - resolve(); - return; // For example: only the background devtools or a popup are opened - } - page.currentTabId = tabs[0].id; - browserAction.show(null, tabs[0]); - resolve(); - }); - }); + browser.tabs.query({}).then((tabs) => { + for (const i of tabs) { + page.createTabEntry(i.id); + } }); } @@ -126,7 +92,7 @@ page.createTabEntry = function(tabId) { page.removePageInformationFromNotExistingTabs = function() { let rand = Math.floor(Math.random()*1001); if (rand === 28) { - browser.tabs.query({}).then(function(tabs) { + browser.tabs.query({}, (tabs) => { let $tabIds = {}; const $infoIds = Object.keys(page.tabs); diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index b117598..7975192 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -52,9 +52,9 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { } else if (req.action === 'redetect_fields') { browser.runtime.sendMessage({ - action: 'load_settings', - }).then((settings) => { - cip.settings = settings; + action: 'get_settings', + }).then((response) => { + cip.settings = response.data; cip.initCredentialFields(true); }); } @@ -1111,9 +1111,9 @@ jQuery(function() { cip.init = function() { browser.runtime.sendMessage({ - action: 'load_settings', - }).then((settings) => { - cip.settings = settings; + action: 'get_settings', + }).then((response) => { + cip.settings = response.data; cip.initCredentialFields(); }); } @@ -1175,7 +1175,7 @@ cip.receiveCredentialsIfNecessary = function () { } } -cip.retrieveCredentialsCallback = function(credentials, dontAutoFillIn) { +cip.retrieveCredentialsCallback = function (credentials, dontAutoFillIn) { if (cipFields.combinations.length > 0) { cip.u = _f(cipFields.combinations[0].username); cip.p = _f(cipFields.combinations[0].password); diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index b5c678a..2b94fd6 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -3,34 +3,17 @@ if (jQuery) { } $(function() { - browser.runtime.sendMessage({ action: 'load_settings' }).then((settings) => { - options.settings = settings; - browser.runtime.sendMessage({ action: 'load_keyring' }).then((keyRing) => { - options.keyRing = keyRing; - options.initMenu(); - options.initGeneralSettings(); - options.initConnectedDatabases(); - options.initSpecifiedCredentialFields(); - options.initAbout(); - }); - }); + options.initMenu(); + options.initGeneralSettings(); + options.initConnectedDatabases(); + options.initSpecifiedCredentialFields(); + options.initAbout(); }); var options = options || {}; -options.saveSettings = function() { - browser.storage.local.set({'settings': options.settings}); - browser.runtime.sendMessage({ - action: 'load_settings' - }); -}; - -options.saveKeyRing = function() { - browser.storage.local.set({'keyRing': JSON.stringify(options.keyRing)}); - browser.runtime.sendMessage({ - action: 'load_keyring' - }); -}; +options.settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings); +options.keyRing = typeof(localStorage.keyRing) === 'undefined' ? {} : JSON.parse(localStorage.keyRing); options.initMenu = function() { $('.navbar:first ul.nav:first li a').click(function(e) { @@ -48,7 +31,26 @@ options.saveSetting = function(name) { const $id = '#' + name; $($id).closest('.control-group').removeClass('error').addClass('success'); setTimeout(() => { $($id).closest('.control-group').removeClass('success') }, 2500); - options.saveSettings(); + + localStorage.settings = JSON.stringify(options.settings); + + browser.runtime.sendMessage({ + action: 'load_settings' + }); +} + +options.saveSettings = function() { + localStorage.settings = JSON.stringify(options.settings); + browser.runtime.sendMessage({ + action: 'load_settings' + }); +} + +options.saveKeyRing = function() { + localStorage.keyRing = JSON.stringify(options.keyRing); + browser.runtime.sendMessage({ + action: 'load_keyring' + }); } options.initGeneralSettings = function() { @@ -220,7 +222,7 @@ options.initSpecifiedCredentialFields = function() { delete options.settings['defined-credential-fields'][$url]; options.saveSettings(); - if($('#tab-specified-fields table tbody:first tr').length > 2) { + if ($('#tab-specified-fields table tbody:first tr').length > 2) { $('#tab-specified-fields table tbody:first tr.empty:first').hide(); } else { diff --git a/keepassxc-browser/popups/popup.js b/keepassxc-browser/popups/popup.js index f902671..7d12e60 100644 --- a/keepassxc-browser/popups/popup.js +++ b/keepassxc-browser/popups/popup.js @@ -63,7 +63,7 @@ $(function() { }); $('#redetect-fields-button').click(function() { - browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened let tab = tabs[0]; @@ -75,6 +75,6 @@ $(function() { }); browser.runtime.sendMessage({ - action: 'get_status' + action: "get_status" }).then(status_response); -}); \ No newline at end of file +}); diff --git a/keepassxc-browser/popups/popup_functions.js b/keepassxc-browser/popups/popup_functions.js index 39fc703..3417757 100644 --- a/keepassxc-browser/popups/popup_functions.js +++ b/keepassxc-browser/popups/popup_functions.js @@ -1,5 +1,4 @@ var $ = jQuery.noConflict(true); -//var _settings = typeof(localStorage.settings) ==='undefined' ? {} : JSON.parse(localStorage.settings); function updateAvailableResponse(available) { if (available) { From db603a4c663f621d187df4497e71a01f6fecd39b Mon Sep 17 00:00:00 2001 From: varjolintu Date: Tue, 12 Sep 2017 15:27:18 +0300 Subject: [PATCH 09/12] Fix for popup with polyfill --- keepassxc-browser/background/page.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index c825f59..4f82bc1 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -46,6 +46,15 @@ page.initOpenedTabs = function() { for (const i of tabs) { page.createTabEntry(i.id); } + + // set initial tab-ID + browser.tabs.query({ "active": true, "currentWindow": true }).then((tabs) => { + if (tabs.length === 0) { + return; // For example: only the background devtools or a popup are opened + } + page.currentTabId = tabs[0].id; + browserAction.show(null, tabs[0]); + }); }); } From 61d2090496141eefb2fcf4339c6ddc11c22bdbf7 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sun, 17 Sep 2017 10:03:57 +0300 Subject: [PATCH 10/12] Better implementation of non-hidden forms detection. Code verified via JSHint. --- CHANGELOG | 1 + README.md | 2 +- keepassxc-browser/background/browserAction.js | 21 ++- keepassxc-browser/background/event.js | 51 +++--- keepassxc-browser/background/httpauth.js | 10 +- keepassxc-browser/background/init.js | 2 +- keepassxc-browser/background/keepass.js | 107 ++++++------ keepassxc-browser/background/page.js | 23 ++- keepassxc-browser/keepassxc-browser.js | 163 ++++++++++-------- keepassxc-browser/options/options.js | 18 +- keepassxc-browser/popups/popup_httpauth.js | 2 +- keepassxc-browser/popups/popup_login.js | 3 +- 12 files changed, 210 insertions(+), 193 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6049e28..2ee000a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ - HTTP auth works with all browsers - Fixed showing credentials from previous logins in the popup (credits to smorks/passifox) - Automatic detection of div's with forms that are non-hidden by user interaction +- Verified the source code via JSHint 0.2.9 (2017-08-27) ========================= diff --git a/README.md b/README.md index be48651..3972f10 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Chrome extension for [KeePassXC](https://keepassxc.org/) with Native Messaging. This is a heavily forked version of [pfn](https://github.com/pfn)'s [chromeIPass](https://github.com/pfn/passifox). -Some changes merged also from [projectgus'](https://github.com/projectgus/passifox) and [smorks'](https://github.com/smorks/passifox) fork. +Some changes merged also from [smorks'](https://github.com/smorks/keepasshttp-connector) KeePassHttp-Connector fork. For testing purposes, please use following unofficial KeePassXC [release's](https://github.com/varjolintu/keepassxc/releases). Get the extension for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome/Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf). diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index 39fa94c..12dd782 100644 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -27,7 +27,7 @@ browserAction.show = function(callback, tab) { popup: 'popups/' + data.popup }); } -} +}; browserAction.update = function(interval) { if (!page.tabs[page.currentTabId] || page.tabs[page.currentTabId].stack.length === 0) { @@ -79,14 +79,14 @@ browserAction.update = function(interval) { path: '/icons/19x19/' + browserAction.generateIconName(null, data.intervalIcon.icons[data.intervalIcon.index]) }); } -} +}; browserAction.showDefault = function(callback, tab) { let stackData = { level: 1, iconType: 'normal', popup: 'popup.html' - } + }; keepass.isConfigured((response) => { if (!response || keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable || page.tabs[tab.id].errorMessage) { stackData.iconType = 'cross'; @@ -100,7 +100,7 @@ browserAction.showDefault = function(callback, tab) { browserAction.stackUnshift(stackData, tab.id); browserAction.show(null, tab); }); -} +}; browserAction.stackAdd = function(callback, tab, icon, popup, level, push, visibleForMilliSeconds, visibleForPageUpdates, redirectOffset, dontShow) { const id = tab.id || page.currentTabId; @@ -112,7 +112,7 @@ browserAction.stackAdd = function(callback, tab, icon, popup, level, push, visib let stackData = { level: level, icon: icon - } + }; if (popup) { stackData.popup = popup; @@ -140,8 +140,7 @@ browserAction.stackAdd = function(callback, tab, icon, popup, level, push, visib if (!dontShow) { browserAction.show(null, {'id': id}); } -} - +}; browserAction.removeLevelFromStack = function(callback, tab, level, type, dontShow) { if (!page.tabs[tab.id]) { @@ -172,7 +171,7 @@ browserAction.removeLevelFromStack = function(callback, tab, level, type, dontSh if (!dontShow) { browserAction.show(callback, tab); } -} +}; browserAction.stackPop = function(tabId) { const id = tabId || page.currentTabId; @@ -242,7 +241,7 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna }, icon: 'icon_remember_red_background_19x19.png', popup: 'popup_remember.html' - } + }; browserAction.stackPush(stackData, id); @@ -255,7 +254,7 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna }; browserAction.show(null, {'id': id}); -} +}; function getValueOrDefault(settings, key, defaultVal, min) { try { @@ -280,4 +279,4 @@ browserAction.generateIconName = function(iconType, icon) { name += '_19x19.png'; return name; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 5070f69..0052b20 100644 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -16,7 +16,7 @@ event.onMessage = function(request, sender, callback) { return true; } } -} +}; /** * Get interesting information about the given tab. @@ -73,13 +73,12 @@ event.invoke = function(handler, callback, senderTabId, args, secondTime) { console.log('undefined handler for tab ' + tab.id); } }); -} - +}; event.onShowAlert = function(callback, tab, message) { if (page.settings.supressAlerts) { console.log(message); } else { alert(message); } -} +}; event.showStatus = function(configured, tab, callback) { let keyId = null; @@ -98,11 +97,11 @@ event.showStatus = function(configured, tab, callback) { associated: keepass.isAssociated(), error: errorMessage ? errorMessage : null }); -} +}; event.onLoadSettings = function(callback, tab) { page.settings = (typeof(localStorage.settings) === 'undefined') ? {} : JSON.parse(localStorage.settings); -} +}; event.onLoadKeyRing = function(callback, tab) { keepass.keyRing = (typeof(localStorage.keyRing) === 'undefined') ? {} : JSON.parse(localStorage.keyRing); @@ -112,17 +111,17 @@ event.onLoadKeyRing = function(callback, tab) { hash: null }; } -} +}; event.onGetSettings = function(callback, tab) { event.onLoadSettings(); callback({ data: page.settings }); -} +}; event.onSaveSettings = function(callback, tab, settings) { localStorage.settings = JSON.stringify(settings); event.onLoadSettings(); -} +}; event.onGetStatus = function(callback, tab) { keepass.testAssociation((response) => { @@ -130,7 +129,7 @@ event.onGetStatus = function(callback, tab) { event.showStatus(configured, tab, callback); }); }, tab); -} +}; event.onReconnect = function(callback, tab) { keepass.connectToNative(); @@ -150,24 +149,24 @@ event.onReconnect = function(callback, tab) { }, null); }); }, 2000); -} +}; event.onPopStack = function(callback, tab) { browserAction.stackPop(tab.id); browserAction.show(null, tab); -} +}; event.onGetTabInformation = function(callback, tab) { const id = tab.id || page.currentTabId; callback(page.tabs[id]); -} +}; event.onGetConnectedDatabase = function(callback, tab) { callback({ count: Object.keys(keepass.keyRing).length, identifier: (keepass.keyRing[keepass.associated.hash]) ? keepass.keyRing[keepass.associated.hash].id : null }); -} +}; event.onGetKeePassXCVersions = function(callback, tab) { if (keepass.currentKeePassXC.version === 0) { @@ -176,62 +175,62 @@ event.onGetKeePassXCVersions = function(callback, tab) { }, tab); } callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version}); -} +}; event.onCheckUpdateKeePassXC = function(callback, tab) { keepass.checkForNewKeePassXCVersion(); callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version}); -} +}; event.onUpdateAvailableKeePassXC = function(callback, tab) { callback(keepass.keePassXCUpdateAvailable()); -} +}; event.onRemoveCredentialsFromTabInformation = function(callback, tab) { const id = tab.id || page.currentTabId; page.clearCredentials(id); -} +}; event.onSetRememberPopup = function(callback, tab, username, password, url, usernameExists, credentialsList) { browserAction.setRememberPopup(tab.id, username, password, url, usernameExists, credentialsList); -} +}; event.onLoginPopup = function(callback, tab, logins) { let stackData = { level: 1, iconType: 'questionmark', popup: 'popup_login.html' - } + }; browserAction.stackUnshift(stackData, tab.id); page.tabs[tab.id].loginList = logins; browserAction.show(null, tab); -} +}; event.onHTTPAuthPopup = function(callback, tab, data) { let stackData = { level: 1, iconType: 'questionmark', popup: 'popup_httpauth.html' - } + }; browserAction.stackUnshift(stackData, tab.id); page.tabs[tab.id].loginList = data; browserAction.show(null, tab); -} +}; event.onMultipleFieldsPopup = function(callback, tab) { let stackData = { level: 1, iconType: 'normal', popup: 'popup_multiple-fields.html' - } + }; browserAction.stackUnshift(stackData, tab.id); browserAction.show(null, tab); -} +}; event.pageClearLogins = function(callback, tab) { page.clearLogins(tab.id); callback(); -} +}; // all methods named in this object have to be declared BEFORE this! diff --git a/keepassxc-browser/background/httpauth.js b/keepassxc-browser/background/httpauth.js index efb3892..06936d6 100644 --- a/keepassxc-browser/background/httpauth.js +++ b/keepassxc-browser/background/httpauth.js @@ -8,17 +8,17 @@ httpAuth.requestCompleted = function(details) { if (index > -1) { httpAuth.requests.splice(index, 1); } -} +}; httpAuth.handleRequestPromise = function(details) { return new Promise((resolve, reject) => { httpAuth.processPendingCallbacks(details, resolve, reject); }); -} +}; httpAuth.handleRequestCallback = function(details, callback) { httpAuth.processPendingCallbacks(details, callback, callback); -} +}; httpAuth.processPendingCallbacks = function(details, resolve, reject) { if (httpAuth.requests.indexOf(details.requestId) >= 0 || !page.tabs[details.tabId]) { @@ -36,7 +36,7 @@ httpAuth.processPendingCallbacks = function(details, resolve, reject) { keepass.retrieveCredentials((logins) => { httpAuth.loginOrShowCredentials(logins, details, resolve, reject); }, { "id": details.tabId }, details.searchUrl, details.searchUrl, true); -} +}; httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) { // at least one login found --> use first to login @@ -59,4 +59,4 @@ httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) { else { reject({}); } -} +}; diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index f231fea..a4b1a4e 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -94,7 +94,7 @@ const contextMenuItems = [ {title: 'Fill &Pass Only', action: 'fill_pass_only'}, {title: 'Show Password &Generator Icons', action: 'activate_password_generator'}, {title: '&Save credentials', action: 'remember_credentials'} -] +]; // Create context menu items for (const item of contextMenuItems) { diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 70051cf..8ee12ed 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -3,6 +3,7 @@ var keepass = {}; keepass.associated = {'value': false, 'hash': null}; keepass.keyPair = {publicKey: null, secretKey: null}; keepass.serverPublicKey = ''; +keepass.clientID = ''; keepass.isConnected = false; keepass.isDatabaseClosed = false; keepass.isKeePassXCAvailable = false; @@ -66,7 +67,7 @@ const kpErrors = { keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials(callback, tab, null, username, password, url); -} +}; keepass.updateCredentials = function(callback, tab, entryId, username, password, url) { page.debug('keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})', tab.id, entryId, username, url); @@ -76,9 +77,7 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, if (!response) { browserAction.showDefault(null, tab); - if (forceCallback) { - callback([]); - } + callback([]); return; } @@ -102,7 +101,8 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce) + nonce: keepass.b64e(nonce), + clientID: keepass.clientID }; console.log(request); @@ -124,7 +124,7 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, }); keepass.nativePort.postMessage(request); }); -} +}; keepass.retrieveCredentials = function (callback, tab, url, submiturl, forceCallback, triggerUnlock) { page.debug('keepass.retrieveCredentials(callback, {1}, {2}, {3}, {4})', tab.id, url, submiturl, forceCallback); @@ -164,7 +164,8 @@ keepass.retrieveCredentials = function (callback, tab, url, submiturl, forceCall const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce) + nonce: keepass.b64e(nonce), + clientID: keepass.clientID }; keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, (response) => { @@ -199,7 +200,7 @@ keepass.retrieveCredentials = function (callback, tab, url, submiturl, forceCall }); keepass.nativePort.postMessage(request); }, tab); -} +}; // Redirects the callback to a listener (handleReply()) keepass.callbackOnId = function (ev, id, callback) { @@ -209,11 +210,11 @@ keepass.callbackOnId = function (ev, id, callback) { ev.removeListener(handler); callback(msg); } - } + }; return handler; })(ev, id, callback); ev.addListener(listener); -} +}; keepass.generatePassword = function (callback, tab, forceCallback) { if (!keepass.isConnected) { @@ -242,7 +243,8 @@ keepass.generatePassword = function (callback, tab, forceCallback) { const request = { action: kpAction, - nonce: keepass.b64e(nonce) + nonce: keepass.b64e(nonce), + clientID: keepass.clientID }; keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, (response) => { @@ -254,7 +256,6 @@ keepass.generatePassword = function (callback, tab, forceCallback) { keepass.setcurrentKeePassXCVersion(parsed.version); if (keepass.verifyResponse(parsed, response.nonce)) { - const rIv = response.nonce; if (parsed.entries) { passwords = parsed.entries; keepass.updateLastUsed(keepass.databaseHash); @@ -275,7 +276,7 @@ keepass.generatePassword = function (callback, tab, forceCallback) { }); keepass.nativePort.postMessage(request); }, tab); -} +}; keepass.associate = function(callback, tab) { if (keepass.isAssociated()) { @@ -303,7 +304,8 @@ keepass.associate = function(callback, tab) { const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce) + nonce: keepass.b64e(nonce), + clientID: keepass.clientID }; keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, (response) => { @@ -333,7 +335,7 @@ keepass.associate = function(callback, tab) { }); keepass.nativePort.postMessage(request); }, tab); -} +}; keepass.testAssociation = function (callback, tab, triggerUnlock) { if (tab && page.tabs[tab.id]) { @@ -358,7 +360,7 @@ keepass.testAssociation = function (callback, tab, triggerUnlock) { if (!keepass.serverPublicKey) { if (tab && page.tabs[tab.id]) { - handleError(tab, kpErrors.PUBLIC_KEY_NOT_FOUND); + keepass.handleError(tab, kpErrors.PUBLIC_KEY_NOT_FOUND); } callback(false); return false; @@ -385,7 +387,8 @@ keepass.testAssociation = function (callback, tab, triggerUnlock) { const request = { action: kpAction, message: keepass.encrypt(messageData, nonce), - nonce: keepass.b64e(nonce) + nonce: keepass.b64e(nonce), + clientID: keepass.clientID }; keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, (response) => { @@ -395,7 +398,6 @@ keepass.testAssociation = function (callback, tab, triggerUnlock) { const message = nacl.util.encodeUTF8(res); const parsed = JSON.parse(message); keepass.setcurrentKeePassXCVersion(parsed.version); - const id = parsed.id; keepass.isEncryptionKeyUnrecognized = false; if (!keepass.verifyResponse(parsed, response.nonce)) { @@ -423,7 +425,7 @@ keepass.testAssociation = function (callback, tab, triggerUnlock) { }); keepass.nativePort.postMessage(request); }, tab, triggerUnlock); -} +}; keepass.getDatabaseHash = function (callback, tab, triggerUnlock) { if (!keepass.isConnected) { @@ -453,7 +455,8 @@ keepass.getDatabaseHash = function (callback, tab, triggerUnlock) { const request = { action: kpAction, message: encrypted, - nonce: keepass.b64e(nonce) + nonce: keepass.b64e(nonce), + clientID: keepass.clientID }; keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, (response) => { @@ -493,7 +496,7 @@ keepass.getDatabaseHash = function (callback, tab, triggerUnlock) { } }); keepass.nativePort.postMessage(request); -} +}; keepass.changePublicKeys = function(tab, callback) { if (!keepass.isConnected) { @@ -504,14 +507,16 @@ keepass.changePublicKeys = function(tab, callback) { const kpAction = kpActions.CHANGE_PUBLIC_KEYS; const key = keepass.b64e(keepass.keyPair.publicKey); let nonce = nacl.randomBytes(keepass.keySize); - nonce = keepass.b64e(nonce) + nonce = keepass.b64e(nonce); + keepass.clientID = keepass.b64e(nacl.randomBytes(keepass.keySize)); const message = { action: kpAction, publicKey: key, proxyPort: (page.settings.port ? page.settings.port : 19700), - nonce: nonce - } + nonce: nonce, + clientID: keepass.clientID + }; keepass.callbackOnId(keepass.nativePort.onMessage, kpAction, (response) => { keepass.setcurrentKeePassXCVersion(response.version); @@ -529,12 +534,12 @@ keepass.changePublicKeys = function(tab, callback) { callback(true); }); keepass.nativePort.postMessage(message); -} +}; keepass.generateNewKeyPair = function() { keepass.keyPair = nacl.box.keyPair(); //console.log(keepass.b64e(keepass.keyPair.publicKey) + ' ' + keepass.b64e(keepass.keyPair.secretKey)); -} +}; keepass.isConfigured = function(callback) { if (typeof(keepass.databaseHash) === 'undefined') { @@ -545,11 +550,11 @@ keepass.isConfigured = function(callback) { else { callback(keepass.databaseHash in keepass.keyRing); } -} +}; keepass.isAssociated = function() { return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash === keepass.databaseHash); -} +}; keepass.convertKeyToKeyRing = function() { if (keepass.keyId in localStorage && keepass.keyBody in localStorage && !('keyRing' in localStorage)) { @@ -567,7 +572,7 @@ keepass.convertKeyToKeyRing = function() { delete localStorage[keepass.keyId]; delete localStorage[keepass.keyBody]; } -} +}; keepass.saveKey = function(hash, id, key) { if (!(hash in keepass.keyRing)) { @@ -577,7 +582,7 @@ keepass.saveKey = function(hash, id, key) { hash: hash, created: new Date(), lastUsed: new Date() - } + }; } else { keepass.keyRing[hash].id = id; @@ -585,19 +590,19 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].hash = hash; } localStorage.keyRing = JSON.stringify(keepass.keyRing); -} +}; keepass.updateLastUsed = function(hash) { if ((hash in keepass.keyRing)) { keepass.keyRing[hash].lastUsed = new Date(); localStorage.keyRing = JSON.stringify(keepass.keyRing); } -} +}; keepass.deleteKey = function(hash) { delete keepass.keyRing[hash]; localStorage.keyRing = JSON.stringify(keepass.keyRing); -} +}; keepass.setcurrentKeePassXCVersion = function(version) { if (version) { @@ -606,7 +611,7 @@ keepass.setcurrentKeePassXCVersion = function(version) { versionParsed: Number(version.replace(/\./g, '')) }; } -} +}; keepass.keePassXCUpdateAvailable = function() { if (page.settings.checkUpdateKeePassXC && page.settings.checkUpdateKeePassXC > 0) { @@ -618,7 +623,7 @@ keepass.keePassXCUpdateAvailable = function() { } return (keepass.currentKeePassXC.versionParsed > 0 && keepass.currentKeePassXC.versionParsed < keepass.latestKeePassXC.versionParsed); -} +}; keepass.checkForNewKeePassXCVersion = function() { let xhr = new XMLHttpRequest(); @@ -641,7 +646,7 @@ keepass.checkForNewKeePassXCVersion = function() { xhr.onerror = function(e) { console.log('checkForNewKeePassXCVersion error:' + e); - } + }; try { xhr.open('GET', keepass.latestVersionUrl, true); @@ -651,17 +656,17 @@ keepass.checkForNewKeePassXCVersion = function() { console.log(ex); } keepass.latestKeePassXC.lastChecked = new Date(); -} +}; keepass.connectToNative = function() { if (!keepass.isConnected) { keepass.nativeConnect(); } -} +}; keepass.onNativeMessage = function (response) { //console.log('Received message: ' + JSON.stringify(response)); -} +}; function onDisconnected() { keepass.nativePort = null; @@ -674,12 +679,12 @@ function onDisconnected() { } keepass.nativeConnect = function() { - console.log('Connecting to native messaging host ' + keepass.nativeHostName) + console.log('Connecting to native messaging host ' + keepass.nativeHostName); keepass.nativePort = browser.runtime.connectNative(keepass.nativeHostName); keepass.nativePort.onMessage.addListener(keepass.onNativeMessage); keepass.nativePort.onDisconnect.addListener(onDisconnected); keepass.isConnected = true; -} +}; keepass.verifyKeyResponse = function(response, key, nonce) { if (!response.success || !response.publicKey) { @@ -699,8 +704,7 @@ keepass.verifyKeyResponse = function(response, key, nonce) { } return reply; - -} +}; keepass.verifyResponse = function(response, nonce, id) { keepass.associated.value = response.success; @@ -723,8 +727,7 @@ keepass.verifyResponse = function(response, nonce, id) { keepass.associated.hash = (keepass.associated.value) ? keepass.databaseHash : null; return keepass.isAssociated(); - -} +}; keepass.handleError = function(tab, errorCode, errorMessage = '') { if (errorMessage.length === 0) { @@ -734,15 +737,15 @@ keepass.handleError = function(tab, errorCode, errorMessage = '') { if (tab && page.tabs[tab.id]) { page.tabs[tab.id].errorMessage = errorMessage; } -} +}; keepass.b64e = function(d) { return nacl.util.encodeBase64(d); -} +}; keepass.b64d = function(d) { return nacl.util.decodeBase64(d); -} +}; keepass.getCryptoKey = function() { let dbkey = null; @@ -758,11 +761,11 @@ keepass.getCryptoKey = function() { } return {dbid, dbkey}; -} +}; keepass.setCryptoKey = function(id, key) { keepass.saveKey(keepass.databaseHash, id, key); -} +}; keepass.encrypt = function(input, nonce) { const messageData = nacl.util.decodeUTF8(JSON.stringify(input)); @@ -774,11 +777,11 @@ keepass.encrypt = function(input, nonce) { } } return ''; -} +}; keepass.decrypt = function(input, nonce, toStr) { const m = keepass.b64d(input); const n = keepass.b64d(nonce); const res = nacl.box.open(m, n, keepass.serverPublicKey, keepass.keyPair.secretKey); return res; -} +}; diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 4f82bc1..0a6baba 100644 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -6,7 +6,7 @@ const defaultSettings = { autoFillSingleEntry: false, autoRetrieveCredentials: true, proxyPort: '19700' -} +}; var page = {}; page.tabs = {}; @@ -39,7 +39,7 @@ page.initSettings = function() { page.settings.port = defaultSettings.proxyPort; } localStorage.settings = JSON.stringify(page.settings); -} +}; page.initOpenedTabs = function() { browser.tabs.query({}).then((tabs) => { @@ -56,18 +56,18 @@ page.initOpenedTabs = function() { browserAction.show(null, tabs[0]); }); }); -} +}; page.isValidProtocol = function(url) { let protocol = url.substring(0, url.indexOf(':')); protocol = protocol.toLowerCase(); return !(url.indexOf('.') === -1 || (protocol !== 'http' && protocol !== 'https' && protocol !== 'ftp' && protocol !== 'sftp')); -} +}; page.switchTab = function(callback, tab) { browserAction.showDefault(null, tab); browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {console.log(e);}); -} +}; page.clearCredentials = function(tabId, complete) { if (!page.tabs[tabId]) { @@ -84,11 +84,11 @@ page.clearCredentials = function(tabId, complete) { action: 'clear_credentials' }).catch((e) => {console.log(e);}); } -} +}; page.clearLogins = function(tabId) { page.tabs[tabId].loginList = []; -} +}; page.createTabEntry = function(tabId) { page.tabs[tabId] = { @@ -96,7 +96,7 @@ page.createTabEntry = function(tabId) { 'errorMessage': null, 'loginList': {} }; -} +}; page.removePageInformationFromNotExistingTabs = function() { let rand = Math.floor(Math.random()*1001); @@ -129,12 +129,9 @@ page.debugConsole = function() { page.sprintf = function(input, args) { return input.replace(/{(\d+)}/g, (match, number) => { - return typeof args[number] !== 'undefined' - ? (typeof args[number] === 'object' ? JSON.stringify(args[number]) : args[number]) - : match - ; + return typeof args[number] !== 'undefined' ? (typeof args[number] === 'object' ? JSON.stringify(args[number]) : args[number]) : match; }); -} +}; page.debugDummy = function() {}; diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index 7975192..8fab0a0 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -94,17 +94,17 @@ cipAutocomplete.init = function(field) { .click(cipAutocomplete.onClick) .blur(cipAutocomplete.onBlur) .focus(cipAutocomplete.onFocus); -} +}; cipAutocomplete.onClick = function() { jQuery(this).autocomplete('search', jQuery(this).val()); -} +}; cipAutocomplete.onOpen = function(event, ui) { // NOT BEAUTIFUL! // modifies ALL ui-autocomplete menus of class .cip-ui-menu jQuery('ul.ui-autocomplete.ui-menu').css('z-index', 2147483636); -} +}; cipAutocomplete.onSource = function (request, callback) { const matches = jQuery.map(cipAutocomplete.elements, (tag) => { @@ -113,7 +113,7 @@ cipAutocomplete.onSource = function (request, callback) { } }); callback(matches); -} +}; cipAutocomplete.onSelect = function (e, ui) { e.preventDefault(); @@ -123,7 +123,7 @@ cipAutocomplete.onSelect = function (e, ui) { combination.loginId = ui.item.loginId; cip.fillInCredentials(combination, true, false); jQuery(this).data('fetched', true); -} +}; cipAutocomplete.onBlur = function() { if (jQuery(this).data('fetched') === true) { @@ -136,7 +136,7 @@ cipAutocomplete.onBlur = function() { cip.fillInCredentials(fields, true, true); } } -} +}; cipAutocomplete.onFocus = function() { cip.u = jQuery(this); @@ -144,7 +144,7 @@ cipAutocomplete.onFocus = function() { if (jQuery(this).val() === '') { jQuery(this).autocomplete('search', ''); } -} +}; @@ -162,7 +162,7 @@ cipPassword.init = function() { window.setInterval(function() { cipPassword.checkObservedElements(); }, 400); -} +}; cipPassword.initField = function(field, inputs, pos) { if (!field || field.length !== 1) { @@ -190,7 +190,7 @@ cipPassword.initField = function(field, inputs, pos) { } field.data('cip-genpw-next-field-exists', $found); -} +}; cipPassword.createDialog = function() { if ('passwordCreateDialog' in _called) { @@ -276,7 +276,7 @@ cipPassword.createDialog = function() { const fieldId = jQuery('#cip-genpw-dialog:first').data('cip-genpw-field-id'); const field = jQuery('input[data-cip-id=\''+fieldId+'\']:first'); if (field.length === 1) { - const $password = jQuery('input#cip-genpw-textfield-password:first').val(); + let $password = jQuery('input#cip-genpw-textfield-password:first').val(); if (field.attr('maxlength')) { if ($password.length > field.attr('maxlength')) { @@ -313,7 +313,7 @@ cipPassword.createDialog = function() { } } }); -} +}; cipPassword.createIcon = function(field) { const $className = (isFirefox ? 'key-moz' : 'key'); @@ -359,12 +359,12 @@ cipPassword.createIcon = function(field) { cipPassword.observedIcons.push($icon); jQuery('body').append($icon); -} +}; cipPassword.setIconPosition = function($icon, $field) { $icon.css('top', $field.offset().top + $icon.data('offset') + 1) - .css('left', $field.offset().left + $field.outerWidth() - $icon.data('size') - $icon.data('offset')) -} + .css('left', $field.offset().left + $field.outerWidth() - $icon.data('size') - $icon.data('offset')); +}; cipPassword.copyPasswordToClipboard = function(e) { if (e) { @@ -372,7 +372,7 @@ cipPassword.copyPasswordToClipboard = function(e) { } const input = jQuery("input#cip-genpw-textfield-password"); - input.select() + input.select(); try { const success = document.execCommand('copy'); if (success) { @@ -384,13 +384,13 @@ cipPassword.copyPasswordToClipboard = function(e) { catch (err) { console.log('Could not copy password to clipboard: ' + err); } -} +}; cipPassword.callbackPasswordCopied = function(bool) { if (bool) { jQuery('#cip-genpw-btn-clipboard').addClass('btn-success'); } -} +}; cipPassword.callbackGeneratedPassword = function(entries) { if (entries && entries.length >= 1) { @@ -414,13 +414,13 @@ cipPassword.callbackGeneratedPassword = function(entries) { jQuery('button#cip-genpw-btn-fillin').hide(); } } -} +}; cipPassword.onRequestPassword = function() { browser.runtime.sendMessage({ action: 'generate_password' }).then(cipPassword.callbackGeneratedPassword); -} +}; cipPassword.checkObservedElements = function() { if (cipPassword.observingLock) { @@ -451,7 +451,7 @@ cipPassword.checkObservedElements = function() { } }); cipPassword.observingLock = false; -} +}; @@ -466,7 +466,7 @@ cipForm.init = function(form, credentialFields) { cipForm.setInputFields(form, credentialFields); form.submit(cipForm.onSubmit); } -} +}; cipForm.destroy = function(form, credentialFields) { if (form === false && credentialFields) { @@ -479,12 +479,12 @@ cipForm.destroy = function(form, credentialFields) { if (form && jQuery(form).length > 0) { jQuery(form).unbind('submit', cipForm.onSubmit); } -} +}; cipForm.setInputFields = function(form, credentialFields) { form.data('cipUsername', credentialFields.username); form.data('cipPassword', credentialFields.password); -} +}; cipForm.onSubmit = function() { const usernameId = jQuery(this).data('cipUsername'); @@ -535,7 +535,7 @@ cipDefine.init = function () { cipDefine.resetSelection(); cipDefine.prepareStep1(); cipDefine.markAllUsernameFields($chooser); -} +}; cipDefine.initDescription = function() { const $description = jQuery('div#b2c-cipDefine-description'); @@ -586,7 +586,6 @@ cipDefine.initDescription = function() { cipDefine.selection.username = cipFields.prepareId(cipDefine.selection.username); } - const passwordId = jQuery('div#b2c-cipDefine-fields').data('password'); if (cipDefine.selection.password) { cipDefine.selection.password = cipFields.prepareId(cipDefine.selection.password); } @@ -645,7 +644,7 @@ cipDefine.initDescription = function() { } jQuery('div#b2c-cipDefine-description').draggable(); -} +}; cipDefine.resetSelection = function() { cipDefine.selection = { @@ -653,7 +652,7 @@ cipDefine.resetSelection = function() { password: null, fields: {} }; -} +}; cipDefine.isFieldSelected = function($cipId) { return ( @@ -661,7 +660,7 @@ cipDefine.isFieldSelected = function($cipId) { $cipId === cipDefine.selection.password || $cipId in cipDefine.selection.fields ); -} +}; cipDefine.markAllUsernameFields = function($chooser) { cipDefine.eventFieldClick = function(e) { @@ -671,7 +670,7 @@ cipDefine.markAllUsernameFields = function($chooser) { cipDefine.markAllPasswordFields(jQuery('#b2c-cipDefine-fields')); }; cipDefine.markFields($chooser, cipFields.inputQueryPattern); -} +}; cipDefine.markAllPasswordFields = function($chooser) { cipDefine.eventFieldClick = function(e) { @@ -681,7 +680,7 @@ cipDefine.markAllPasswordFields = function($chooser) { cipDefine.markAllStringFields(jQuery('#b2c-cipDefine-fields')); }; cipDefine.markFields($chooser, 'input[type=\'password\']'); -} +}; cipDefine.markAllStringFields = function($chooser) { cipDefine.eventFieldClick = function(e) { @@ -691,7 +690,7 @@ cipDefine.markAllStringFields = function($chooser) { jQuery('button#b2c-btn-confirm:first').addClass('b2c-btn-primary').attr('disabled', false); }; cipDefine.markFields($chooser, cipFields.inputQueryPattern + ', select'); -} +}; cipDefine.markFields = function ($chooser, $pattern) { //var $found = false; @@ -721,7 +720,7 @@ cipDefine.markFields = function ($chooser, $pattern) { jQuery('button#b2c-btn-skip').click(); } */ -} +}; cipDefine.prepareStep1 = function() { jQuery('div#b2c-help').text('').css('margin-bottom', 0); @@ -732,7 +731,7 @@ cipDefine.prepareStep1 = function() { jQuery('button#b2c-btn-skip:first').data('step', '1').show(); jQuery('button#b2c-btn-confirm:first').hide(); jQuery('button#b2c-btn-again:first').hide(); -} +}; cipDefine.prepareStep2 = function() { jQuery('div#b2c-help').text('').css('margin-bottom', 0); @@ -740,7 +739,7 @@ cipDefine.prepareStep2 = function() { jQuery('div:first', jQuery('div#b2c-cipDefine-description')).text('2. Now choose a password field'); jQuery('button#b2c-btn-skip:first').data('step', '2'); jQuery('button#b2c-btn-again:first').show(); -} +}; cipDefine.prepareStep3 = function() { /* skip step if no entry was found @@ -760,11 +759,11 @@ cipDefine.prepareStep3 = function() { jQuery('button#b2c-btn-confirm:first').show(); jQuery('button#b2c-btn-skip:first').data('step', '3').hide(); jQuery('div:first', jQuery('div#b2c-cipDefine-description')).text('3. Confirm selection'); -} +}; -var cipFields = {} +var cipFields = {}; cipFields.inputQueryPattern = 'input[type=\'text\'], input[type=\'email\'], input[type=\'password\'], input[type=\'tel\'], input[type=\'number\'], input:not([type])'; // unique number as new IDs for input fields @@ -789,11 +788,11 @@ cipFields.setUniqueId = function(field) { cipFields.uniqueNumber += 1; field.attr('data-cip-id', 'jQuery'+String(cipFields.uniqueNumber)); } -} +}; cipFields.prepareId = function(id) { - return id.replace(/[:#.,\[\]\(\)' "]/g, function(m) { return '\\'+m }); -} + return id.replace(/[:#.,\[\]\(\)' "]/g, function(m) { return '\\'+m; }); +}; cipFields.getAllFields = function() { let fields = []; @@ -807,7 +806,19 @@ cipFields.getAllFields = function() { }); return fields; -} +}; + +cipFields.getHiddenFieldCount = function() { + let count = 0; + + jQuery(cipFields.inputQueryPattern).each(function() { + if (jQuery(this).is(':hidden')) { + count++; + } + }); + + return count; +}; cipFields.prepareVisibleFieldsWithID = function($pattern) { jQuery($pattern).each(function() { @@ -815,7 +826,7 @@ cipFields.prepareVisibleFieldsWithID = function($pattern) { cipFields.setUniqueId(jQuery(this)); } }); -} +}; cipFields.getAllCombinations = function(inputs) { let fields = []; @@ -843,7 +854,7 @@ cipFields.getAllCombinations = function(inputs) { } return fields; -} +}; cipFields.getCombination = function(givenType, fieldId) { if (cipFields.combinations.length === 0) { @@ -908,7 +919,7 @@ cipFields.getCombination = function(givenType, fieldId) { combination.isNew = true; } return combination; -} +}; /** * return the username field or null if it not exists @@ -969,7 +980,7 @@ cipFields.getUsernameField = function(passwordId, checkDisabled) { cipFields.setUniqueId(usernameField); return usernameField; -} +}; /** * return the password field or null if it not exists @@ -1026,7 +1037,7 @@ cipFields.getPasswordField = function(usernameId, checkDisabled) { cipFields.setUniqueId(passwordField); return passwordField; -} +}; cipFields.prepareCombinations = function(combinations) { for (const c of combinations) { @@ -1049,7 +1060,7 @@ cipFields.prepareCombinations = function(combinations) { } } } -} +}; cipFields.useDefinedCredentialFields = function() { if (cip.settings['defined-credential-fields'] && cip.settings['defined-credential-fields'][document.location.origin]) { @@ -1077,7 +1088,7 @@ cipFields.useDefinedCredentialFields = function() { } return false; -} +}; @@ -1098,15 +1109,7 @@ cip.credentials = []; jQuery(function() { cip.init(); - - // Detect div's that include forms and are visible - const divDetect = setInterval(function() { - const fields = cipFields.getAllFields(); - if (fields.length > 0) { - cip.initCredentialFields(true); - clearInterval(divDetect); - } - }, 1000); + cip.detectNewActiveFields(); }); cip.init = function() { @@ -1116,7 +1119,21 @@ cip.init = function() { cip.settings = response.data; cip.initCredentialFields(); }); -} +}; + +cip.detectNewActiveFields = function() { + const hiddenFields = cipFields.getHiddenFieldCount(); + + if (hiddenFields > 0) { + const divDetect = setInterval(function() { + const fields = cipFields.getAllFields(); + if (fields.length > 0) { + cip.initCredentialFields(true); + clearInterval(divDetect); + } + }, 1000); + } +}; cip.initCredentialFields = function(forceCall) { if (_called.initCredentialFields && !forceCall) { @@ -1152,7 +1169,7 @@ cip.initCredentialFields = function(forceCall) { }).then(cip.retrieveCredentialsCallback); } }); -} // end function init +}; cip.initPasswordGenerator = function(inputs) { if (cip.settings.usePasswordGenerator) { @@ -1164,7 +1181,7 @@ cip.initPasswordGenerator = function(inputs) { } } } -} +}; cip.receiveCredentialsIfNecessary = function () { if (cip.credentials.length === 0) { @@ -1173,7 +1190,7 @@ cip.receiveCredentialsIfNecessary = function () { args: [ cip.url, cip.submitUrl ] }).then(cip.retrieveCredentialsCallback); } -} +}; cip.retrieveCredentialsCallback = function (credentials, dontAutoFillIn) { if (cipFields.combinations.length > 0) { @@ -1185,7 +1202,7 @@ cip.retrieveCredentialsCallback = function (credentials, dontAutoFillIn) { cip.credentials = credentials; cip.prepareFieldsForCredentials(!Boolean(dontAutoFillIn)); } -} +}; cip.prepareFieldsForCredentials = function(autoFillInForSingle) { // only one login for this site @@ -1222,7 +1239,7 @@ cip.prepareFieldsForCredentials = function(autoFillInForSingle) { else if (cip.credentials.length > 1 || (cip.credentials.length > 0 && (!cip.settings.autoFillSingleEntry || !autoFillInForSingle))) { cip.preparePageForMultipleCredentials(cip.credentials); } -} +}; cip.preparePageForMultipleCredentials = function(credentials) { // add usernames + descriptions to autocomplete-list and popup-list @@ -1254,7 +1271,7 @@ cip.preparePageForMultipleCredentials = function(credentials) { } } } -} +}; cip.getFormActionUrl = function(combination) { const field = _f(combination.password) || _f(combination.username); @@ -1275,7 +1292,7 @@ cip.getFormActionUrl = function(combination) { } return action; -} +}; cip.fillInCredentials = function(combination, onlyPassword, suppressWarnings) { const action = cip.getFormActionUrl(combination); @@ -1317,7 +1334,7 @@ cip.fillInCredentials = function(combination, onlyPassword, suppressWarnings) { cip.fillIn(combination, onlyPassword, suppressWarnings); }); } -} +}; cip.fillInFromActiveElement = function(suppressWarnings) { const el = document.activeElement; @@ -1340,7 +1357,7 @@ cip.fillInFromActiveElement = function(suppressWarnings) { delete combination.loginId; cip.fillInCredentials(combination, false, suppressWarnings); -} +}; cip.fillInFromActiveElementPassOnly = function(suppressWarnings) { const el = document.activeElement; @@ -1373,7 +1390,7 @@ cip.fillInFromActiveElementPassOnly = function(suppressWarnings) { delete combination.loginId; cip.fillInCredentials(combination, true, suppressWarnings); -} +}; cip.setValue = function(field, value) { if (field.is('select')) { @@ -1389,7 +1406,7 @@ cip.setValue = function(field, value) { cip.setValueWithChange(field, value); field.trigger('input'); } -} +}; cip.fillInStringFields = function(fields, StringFields, filledInFields) { let $filledIn = false; @@ -1408,7 +1425,7 @@ cip.fillInStringFields = function(fields, StringFields, filledInFields) { } return $filledIn; -} +}; cip.setValueWithChange = function(field, value) { @@ -1425,7 +1442,7 @@ cip.setValueWithChange = function(field, value) { field.val(value); field[0].dispatchEvent(new Event('input', {'bubbles': true})); field[0].dispatchEvent(new Event('change', {'bubbles': true})); -} +}; cip.fillIn = function(combination, onlyPassword, suppressWarnings) { // no credentials available @@ -1576,7 +1593,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { } } } -} +}; cip.contextMenuRememberCredentials = function() { const el = document.activeElement; @@ -1691,7 +1708,7 @@ cipEvents.clearCredentials = function() { } } } -} +}; cipEvents.triggerActivatedTab = function() { // doesn't run a second time because of _called.initCredentialFields set to true @@ -1705,4 +1722,4 @@ cipEvents.triggerActivatedTab = function() { args: [ cip.url, cip.submitUrl ] }).then(cip.retrieveCredentialsCallback); } -} +}; diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 2b94fd6..384b821 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -25,33 +25,33 @@ options.initMenu = function() { }); $('div.tab:first').show(); -} +}; options.saveSetting = function(name) { const $id = '#' + name; $($id).closest('.control-group').removeClass('error').addClass('success'); - setTimeout(() => { $($id).closest('.control-group').removeClass('success') }, 2500); + setTimeout(() => { $($id).closest('.control-group').removeClass('success'); }, 2500); localStorage.settings = JSON.stringify(options.settings); browser.runtime.sendMessage({ action: 'load_settings' }); -} +}; options.saveSettings = function() { localStorage.settings = JSON.stringify(options.settings); browser.runtime.sendMessage({ action: 'load_settings' }); -} +}; options.saveKeyRing = function() { localStorage.keyRing = JSON.stringify(options.keyRing); browser.runtime.sendMessage({ action: 'load_keyring' }); -} +}; options.initGeneralSettings = function() { $('#tab-general-settings input[type=checkbox]').each(function() { @@ -140,7 +140,7 @@ options.showKeePassXCVersions = function(response) { $('#tab-general-settings .kphVersion:first em.latestVersion:first').text(response.latest); $('#tab-about em.versionKPH').text(response.current); $('#tab-general-settings button.checkUpdateKeePassXC:first').attr('disabled', false); -} +}; options.initConnectedDatabases = function() { $('#dialogDeleteConnectedDatabase').modal({keyboard: true, show: false, backdrop: true}); @@ -200,7 +200,7 @@ options.initConnectedDatabases = function() { action: 'associate' }); }); -} +}; options.initSpecifiedCredentialFields = function() { $('#dialogDeleteSpecifiedCredentialFields').modal({keyboard: true, show: false, backdrop: true}); @@ -249,11 +249,11 @@ options.initSpecifiedCredentialFields = function() { else { $('#tab-specified-fields table tbody:first tr.empty:first').show(); } -} +}; options.initAbout = function() { $('#tab-about em.versionCIP').text(browser.runtime.getManifest().version); if (isFirefox) { $('#chrome-only').remove(); } -} +}; diff --git a/keepassxc-browser/popups/popup_httpauth.js b/keepassxc-browser/popups/popup_httpauth.js index b5f15ff..2e17a47 100644 --- a/keepassxc-browser/popups/popup_httpauth.js +++ b/keepassxc-browser/popups/popup_httpauth.js @@ -1,6 +1,6 @@ $(function() { browser.runtime.getBackgroundPage().then((global) => { - browser.tabs.query({"active": true, "currentWindow": true}.then((tab) => { + browser.tabs.query({"active": true, "currentWindow": true}).then((tab) => { const data = global.page.tabs[tab.id].loginList; let ul = document.getElementById('login-list'); for (let i = 0; i < data.logins.length; i++) { diff --git a/keepassxc-browser/popups/popup_login.js b/keepassxc-browser/popups/popup_login.js index 23a6e1e..8da4930 100644 --- a/keepassxc-browser/popups/popup_login.js +++ b/keepassxc-browser/popups/popup_login.js @@ -1,8 +1,9 @@ $(function() { browser.runtime.getBackgroundPage().then((global) => { browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { - if (tabs.length === 0) + if (tabs.length === 0) { return; // For example: only the background devtools or a popup are opened + } const tab = tabs[0]; const logins = global.page.tabs[tab.id].loginList; From 6c434e372b37f39a89bab6d89c430c315789c9aa Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sun, 17 Sep 2017 10:50:45 +0300 Subject: [PATCH 11/12] If a new login div is created it is not detected at hidden first.. let the loop be --- keepassxc-browser/keepassxc-browser.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index 8fab0a0..f700ce7 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -810,7 +810,6 @@ cipFields.getAllFields = function() { cipFields.getHiddenFieldCount = function() { let count = 0; - jQuery(cipFields.inputQueryPattern).each(function() { if (jQuery(this).is(':hidden')) { count++; @@ -1122,17 +1121,18 @@ cip.init = function() { }; cip.detectNewActiveFields = function() { - const hiddenFields = cipFields.getHiddenFieldCount(); + //const hiddenFields = cipFields.getHiddenFieldCount(); - if (hiddenFields > 0) { + //if (hiddenFields > 0) { const divDetect = setInterval(function() { const fields = cipFields.getAllFields(); - if (fields.length > 0) { + console.log(fields.length); + if (fields.length > 1) { cip.initCredentialFields(true); clearInterval(divDetect); } }, 1000); - } + //} }; cip.initCredentialFields = function(forceCall) { From d7a8762f349901598f17880d093ee23c694a6ff8 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Mon, 18 Sep 2017 09:25:20 +0300 Subject: [PATCH 12/12] Last changes for version 0.30 --- CHANGELOG | 10 +++++----- keepassxc-browser/keepassxc-browser.js | 10 ++-------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2ee000a..7ed60a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,9 @@ -0.3.0 (2017-??-??) +0.3.0 (2017-09-18) ========================= -- Added Mozilla's browser-polyfill -- Merged changes from the latest passifox (credits to smorks/passifox) -- HTTP auth works with all browsers -- Fixed showing credentials from previous logins in the popup (credits to smorks/passifox) +- Added Mozilla's browser-polyfill for making WebExtension compatibility easier +- Merged changes from the latest passifox (credits to smorks/keepasshttp-connector) +- HTTP auth works with all browsers (credits to smorks/keepasshttp-connector) +- Fixed showing credentials from previous logins in the popup (credits to smorks/keepasshttp-connector) - Automatic detection of div's with forms that are non-hidden by user interaction - Verified the source code via JSHint diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index f700ce7..5d57b75 100644 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -1092,18 +1092,11 @@ cipFields.useDefinedCredentialFields = function() { var cip = {}; - -// settings of keepassxc-browser cip.settings = {}; -// username field which will be set on focus cip.u = null; -// password field which will be set on focus cip.p = null; -// document.location cip.url = null; -// request-url of the form in which the field is located cip.submitUrl = null; -// received credentials from KeePassXC cip.credentials = []; jQuery(function() { @@ -1121,8 +1114,9 @@ cip.init = function() { }; cip.detectNewActiveFields = function() { - //const hiddenFields = cipFields.getHiddenFieldCount(); + const hiddenFields = cipFields.getHiddenFieldCount(); + // If hidden fields aren't detected, setInterval is being looped in each frame of the page //if (hiddenFields > 0) { const divDetect = setInterval(function() { const fields = cipFields.getAllFields();