Improve TOTP detection and custom field overriding

This commit is contained in:
varjolintu 2020-06-04 21:25:22 +03:00
parent bfb3c77b6e
commit ce31969160
5 changed files with 53 additions and 28 deletions

View file

@ -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'

View file

@ -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,
{

View file

@ -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,
{

View file

@ -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);

View file

@ -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,
{