diff --git a/keepassxc-browser/content/keepassxc-browser.js b/keepassxc-browser/content/keepassxc-browser.js index f9b7513..ea665a5 100755 --- a/keepassxc-browser/content/keepassxc-browser.js +++ b/keepassxc-browser/content/keepassxc-browser.js @@ -632,7 +632,9 @@ kpxcFields.useDefinedCredentialFields = function() { // Handle custom TOTP field if (_f(creds.totp)) { - kpxcTOTPIcons.newIcon(_f(creds.totp), _databaseState); + const totpField = _f(creds.totp); + totpField.setAttribute('kpxc-defined', 'totp'); + kpxcTOTPIcons.newIcon(totpField, _databaseState, true); } let found = _f(creds.username) || _f(creds.password); @@ -644,6 +646,14 @@ kpxcFields.useDefinedCredentialFields = function() { } if (found) { + if (creds.username) { + _f(creds.username).setAttribute('kpxc-defined', 'username'); + } + + if (creds.password) { + _f(creds.password).setAttribute('kpxc-defined', 'password'); + } + const fields = { username: creds.username, password: creds.password, @@ -1036,6 +1046,12 @@ kpxc.initCredentialFields = async function(forceCall, inputs) { _databaseState = !res.keePassXCAvailable ? DatabaseState.DISCONNECTED : DatabaseState.LOCKED; + if (!kpxcFields.useDefinedCredentialFields()) { + // Get all combinations of username + password fields + kpxcFields.combinations = kpxcFields.getAllCombinations(inputs); + } + kpxcFields.prepareCombinations(kpxcFields.combinations); + kpxcFields.prepareVisibleFieldsWithID('select'); kpxc.initPasswordGenerator(inputs); @@ -1043,12 +1059,6 @@ kpxc.initCredentialFields = async function(forceCall, inputs) { kpxc.initOTPFields(inputs); } - if (!kpxcFields.useDefinedCredentialFields()) { - // Get all combinations of username + password fields - kpxcFields.combinations = kpxcFields.getAllCombinations(inputs); - } - kpxcFields.prepareCombinations(kpxcFields.combinations); - if (kpxcFields.combinations.length === 0 && inputs.length === 0) { browser.runtime.sendMessage({ action: 'show_default_browseraction' diff --git a/keepassxc-browser/content/pwgen.js b/keepassxc-browser/content/pwgen.js index 8fa0687..e6de428 100644 --- a/keepassxc-browser/content/pwgen.js +++ b/keepassxc-browser/content/pwgen.js @@ -28,7 +28,8 @@ PasswordIcon.prototype.initField = function(field, inputs, pos) { return; } - if (field.getAttribute('kpxc-password-generator')) { + if (field.getAttribute('kpxc-password-generator') + || (field.hasAttribute('kpxc-defined') && field.getAttribute('kpxc-defined') !== 'password')) { return; } @@ -62,8 +63,7 @@ PasswordIcon.prototype.initField = function(field, inputs, pos) { PasswordIcon.prototype.createIcon = function(field) { const className = (isFirefox() ? 'key-moz' : 'key'); const size = (field.offsetHeight > 28) ? 24 : 16; - let offset = Math.floor((field.offsetHeight - size) / 3); - offset = (offset < 0) ? 0 : offset; + const offset = kpxcUI.calculateIconOffset(field, size); const icon = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-icon ' + className, { diff --git a/keepassxc-browser/content/totp-field.js b/keepassxc-browser/content/totp-field.js index 2de8d1d..84b4b83 100644 --- a/keepassxc-browser/content/totp-field.js +++ b/keepassxc-browser/content/totp-field.js @@ -7,8 +7,8 @@ const ignoredTypes = [ 'email', 'password', 'username' ]; var kpxcTOTPIcons = {}; kpxcTOTPIcons.icons = []; -kpxcTOTPIcons.newIcon = function(field, databaseState = DatabaseState.DISCONNECTED) { - kpxcTOTPIcons.icons.push(new TOTPFieldIcon(field, databaseState)); +kpxcTOTPIcons.newIcon = function(field, databaseState = DatabaseState.DISCONNECTED, forced = false) { + kpxcTOTPIcons.icons.push(new TOTPFieldIcon(field, databaseState, forced)); }; kpxcTOTPIcons.switchIcon = function(state) { @@ -17,29 +17,40 @@ kpxcTOTPIcons.switchIcon = function(state) { class TOTPFieldIcon extends Icon { - constructor(field, databaseState = DatabaseState.DISCONNECTED) { + constructor(field, databaseState = DatabaseState.DISCONNECTED, forced = false) { super(); this.icon = null; this.inputField = null; this.databaseState = databaseState; - this.initField(field); + this.initField(field, forced); kpxcUI.monitorIconPosition(this); } } -TOTPFieldIcon.prototype.initField = function(field) { - if (!field - || ignoredTypes.some(t => t === field.type) - || field.getAttribute('kpxc-totp-field') === 'true' - || field.offsetWidth < MINIMUM_SIZE - || field.size < 2 - || (field.maxLength > 0 && (field.maxLength < 6 || field.maxLength > 8)) - || field.id.match(ignoreRegex) - || field.name.match(ignoreRegex)) { +TOTPFieldIcon.prototype.initField = function(field, forced) { + if (!field) { return; } + if (!forced) { + if (ignoredTypes.some(t => t === field.type) + || ignoredTypes.some(t => t === field.autocomplete) + || field.getAttribute('kpxc-totp-field') === 'true' + || (field.hasAttribute('kpxc-defined') && field.getAttribute('kpxc-defined') !== 'totp') + || field.offsetWidth < MINIMUM_SIZE + || field.size < 2 + || (field.maxLength > 0 && (field.maxLength < 6 || field.maxLength > 8)) + || field.id.match(ignoreRegex) + || field.name.match(ignoreRegex)) { + return; + } + } else { + if (field.getAttribute('kpxc-totp-field') === 'true') { + return; + } + } + field.setAttribute('kpxc-totp-field', 'true'); // Observer the visibility @@ -56,8 +67,7 @@ TOTPFieldIcon.prototype.createIcon = function(field) { // Size the icon dynamically, but not greater than 24 or smaller than 14 const size = Math.max(Math.min(24, field.offsetHeight - 4), 14); - let offset = Math.floor((field.offsetHeight - size) / 3); - offset = (offset < 0) ? 0 : offset; + const offset = kpxcUI.calculateIconOffset(field, size); const icon = kpxcUI.createElement('div', 'kpxc kpxc-totp-icon ' + className, { diff --git a/keepassxc-browser/content/ui.js b/keepassxc-browser/content/ui.js index 83a78f5..923e7e1 100644 --- a/keepassxc-browser/content/ui.js +++ b/keepassxc-browser/content/ui.js @@ -80,12 +80,17 @@ kpxcUI.updateIconPosition = function(iconClass) { } }; +kpxcUI.calculateIconOffset = function(field, size) { + const offset = Math.floor((field.offsetHeight - size) / 3); + return (offset < 0) ? 0 : offset; +}; + kpxcUI.setIconPosition = function(icon, field) { const rect = field.getBoundingClientRect(); const bodyRect = document.body.getBoundingClientRect(); const bodyStyle = getComputedStyle(document.body); - const offset = Number(icon.getAttribute('offset')); const size = (document.dir !== 'rtl') ? Number(icon.getAttribute('size')) : 0; + const offset = kpxcUI.calculateIconOffset(field, size); if (bodyStyle.position.toLowerCase() === 'relative') { icon.style.top = Pixels(rect.top - bodyRect.top + document.scrollingElement.scrollTop + offset + 1); diff --git a/keepassxc-browser/content/username-field.js b/keepassxc-browser/content/username-field.js index 86b0296..5f8eb36 100644 --- a/keepassxc-browser/content/username-field.js +++ b/keepassxc-browser/content/username-field.js @@ -38,6 +38,7 @@ UsernameFieldIcon.prototype.initField = function(field) { if (!field || field.getAttribute('kpxc-username-field') === 'true' || field.getAttribute('kpxc-totp-field') === 'true' + || (field.hasAttribute('kpxc-defined') && field.getAttribute('kpxc-defined') !== 'username') || !kpxcFields.isVisible(field)) { return; } @@ -71,8 +72,7 @@ UsernameFieldIcon.prototype.createIcon = function(target) { return; } - let offset = Math.floor((field.offsetHeight - size) / 3); - offset = (offset < 0) ? 0 : offset; + const offset = kpxcUI.calculateIconOffset(field, size); const icon = kpxcUI.createElement('div', 'kpxc kpxc-username-icon ' + className, {