Remove internal password generator

This commit is contained in:
varjolintu 2023-08-21 19:08:55 +03:00
parent 91cc1d17dc
commit 25975d1558
8 changed files with 21 additions and 431 deletions

View file

@ -133,7 +133,7 @@
"kpxcForm": true,
"kpxcIcons": true,
"kpxcObserverHelper": true,
"kpxcPasswordDialog": true,
"kpxcPasswordGenerator": true,
"kpxcPasswordIcons": true,
"kpxcSites": true,
"kpxcTOTPAutocomplete": true,

View file

@ -159,34 +159,6 @@
"message": "Password generator icon",
"description": "Alt attribute text of the password generator icon."
},
"passwordGeneratorPlaceholder": {
"message": "Generated password",
"description": "Input field placeholder for generated password."
},
"passwordGeneratorLabel": {
"message": "Also fill in the next password-field",
"description": "Checkbox text below the password generator input field."
},
"passwordGeneratorTitle": {
"message": "Password Generator",
"description": "Password generator dialog title."
},
"passwordGeneratorGenerate": {
"message": "Generate",
"description": "Generate button text in password generator."
},
"passwordGeneratorTryAgain": {
"message": "Try again",
"description": "Generate button text in password generator when not connected."
},
"passwordGeneratorCopy": {
"message": "Copy",
"description": "Copy button text in password generator."
},
"passwordGeneratorFill": {
"message": "Fill password",
"description": "Fill a password in password generator."
},
"passwordGeneratorErrorTooLong": {
"message": "Error: The generated password is longer than the allowed length!",
"description": "A warning text shown in the password generator."
@ -203,13 +175,8 @@
"message": "Generate password",
"description": "Password icon title text."
},
"passwordGeneratorError": {
"message": "Cannot receive generated password.",
"description": "Password generator error text when KeePassXC is closed."
},
"passwordGeneratorErrorIsRunning": {
"message": "Is KeePassXC running and connected?",
"description": "Password generator error text when KeePassXC is closed."
"passwordGeneratorNotSupported": {
"message": "Launching the password generator is not supported in this KeePassXC version. Please update KeePassXC to a newer version."
},
"usernameFieldText": {
"message": "Fill credentials from KeePassXC",

View file

@ -961,7 +961,7 @@ browser.runtime.onMessage.addListener(async function(req, sender) {
} else if (req.action === 'retrive_credentials_forced') {
await kpxc.retrieveCredentials(true);
} else if (req.action === 'show_password_generator') {
kpxcPasswordDialog.trigger();
kpxcPasswordGenerator.showPasswordGenerator();
} else if (req.action === 'request_autotype') {
sendMessage('request_autotype', [ window.location.hostname ]);
}

View file

@ -12,7 +12,7 @@ kpxcPasswordIcons.switchIcon = function(state) {
};
kpxcPasswordIcons.deleteHiddenIcons = function() {
kpxcUI.deleteHiddenIcons(kpxcPasswordIcons.icons, 'kpxc-password-field');
kpxcUI.deleteHiddenIcons(kpxcPasswordIcons.icons);
};
kpxcPasswordIcons.isValid = function(field) {
@ -59,7 +59,7 @@ PasswordIcon.prototype.createIcon = function(field) {
'alt': tr('passwordGeneratorIcon'),
'size': size,
'offset': offset,
'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id')
'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id') // Needed?
});
icon.style.zIndex = '10000000';
@ -76,13 +76,7 @@ PasswordIcon.prototype.createIcon = function(field) {
}
e.stopPropagation();
if (await useKeePassXCPasswordGenerator()) {
kpxcPasswordDialog.generate(null, field);
return;
}
kpxcPasswordDialog.showDialog(field, icon);
kpxcPasswordGenerator.showPasswordGenerator(field);
});
icon.addEventListener('mousedown', ev => ev.stopPropagation());
@ -100,226 +94,23 @@ PasswordIcon.prototype.createIcon = function(field) {
document.body.append(wrapper);
};
/**
* @Object kpxcPasswordDialog
* Provides a password dialog for content scripts.
* TODO: To be removed when KeePassXC 2.8.0 is released. 2.7.0 already uses KeePassXC's own password generator instead.
*/
const kpxcPasswordDialog = {};
kpxcPasswordDialog.created = false;
kpxcPasswordDialog.icon = null;
kpxcPasswordDialog.input = null;
kpxcPasswordDialog.nextField = null;
kpxcPasswordDialog.selected = null;
kpxcPasswordDialog.startPosX = 0;
kpxcPasswordDialog.startPosY = 0;
kpxcPasswordDialog.diffX = 0;
kpxcPasswordDialog.diffY = 0;
kpxcPasswordDialog.dialog = null;
kpxcPasswordDialog.titleBar = null;
kpxcPasswordDialog.createDialog = function() {
if (kpxcPasswordDialog.created) {
// If database is open again, generate a new password right away
const input = kpxcPasswordDialog.shadowSelector('.kpxc-pwgen-input');
if (input.style.display === 'none') {
kpxcPasswordDialog.generate();
}
return;
}
kpxcPasswordDialog.created = true;
const kpxcPasswordGenerator = {};
const wrapper = kpxcUI.createElement('div');
kpxcPasswordDialog.shadowRoot = wrapper.attachShadow({ mode: 'closed' });
const dialog = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-dialog');
const titleBar = kpxcUI.createElement('div', 'kpxc-pwgen-titlebar', {}, tr('passwordGeneratorTitle'));
const closeButton = kpxcUI.createElement('div', 'kpxc-pwgen-close', {}, '×');
closeButton.addEventListener('click', function(e) {
if (!e.isTrusted) {
return;
}
kpxcPasswordDialog.openDialog();
});
titleBar.append(closeButton);
const passwordRow = kpxcUI.createElement('div', 'kpxc-pwgen-password-row');
const input = kpxcUI.createElement('input', 'kpxc-pwgen-input', { 'placeholder': tr('passwordGeneratorPlaceholder'), 'type': 'text', 'tabindex': '-1' });
passwordRow.appendMultiple(input);
// Buttons
const buttonsRow = kpxcUI.createElement('div', 'kpxc-pwgen-buttons');
const generateButton = kpxcUI.createElement('button', 'kpxc-button kpxc-orange-button', { 'id': 'kpxc-pwgen-btn-generate' }, tr('passwordGeneratorGenerate'));
const copyButton = kpxcUI.createElement('button', 'kpxc-button kpxc-orange-button', { 'id': 'kpxc-pwgen-btn-copy' }, tr('passwordGeneratorCopy'));
const fillButton = kpxcUI.createElement('button', 'kpxc-button kpxc-green-button', { 'id': 'kpxc-pwgen-btn-fill' }, tr('passwordGeneratorFill'));
generateButton.addEventListener('click', function(e) {
kpxcPasswordDialog.generate(e);
});
fillButton.addEventListener('click', function(e) {
kpxcPasswordDialog.fill(e);
kpxcPasswordDialog.openDialog();
});
copyButton.addEventListener('click', function(e) {
kpxcPasswordDialog.copy(e);
});
buttonsRow.appendMultiple(generateButton, copyButton, fillButton);
dialog.appendMultiple(titleBar, passwordRow, buttonsRow);
const styleSheet = createStylesheet('css/pwgen.css');
const buttonStyle = createStylesheet('css/button.css');
const colorStyleSheet = createStylesheet('css/colors.css');
kpxcPasswordDialog.shadowRoot.append(colorStyleSheet);
kpxcPasswordDialog.shadowRoot.append(styleSheet);
kpxcPasswordDialog.shadowRoot.append(buttonStyle);
kpxcPasswordDialog.shadowRoot.append(dialog);
const icon = $('.kpxc-pwgen-icon');
if (icon) {
dialog.style.top = Pixels(icon.offsetTop + icon.offsetHeight);
dialog.style.left = icon.style.left;
} else {
const rect = document.activeElement.getBoundingClientRect();
dialog.style.top = Pixels(rect.top + rect.height);
dialog.style.left = Pixels(rect.left);
}
document.body.append(wrapper);
kpxcPasswordDialog.dialog = dialog;
kpxcPasswordDialog.titleBar = titleBar;
kpxcPasswordDialog.titleBar.addEventListener('mousedown', function(e) {
kpxcPasswordDialog.mouseDown(e);
});
kpxcPasswordDialog.generate();
kpxcPasswordGenerator.showPasswordGenerator = async function(field) {
kpxcPasswordGenerator.generate(field ?? document.activeElement);
};
kpxcPasswordDialog.mouseDown = function(e) {
kpxcPasswordDialog.selected = kpxcPasswordDialog.titleBar;
kpxcPasswordDialog.startPosX = e.clientX;
kpxcPasswordDialog.startPosY = e.clientY;
kpxcPasswordDialog.diffX = kpxcPasswordDialog.startPosX - kpxcPasswordDialog.dialog.offsetLeft;
kpxcPasswordDialog.diffY = kpxcPasswordDialog.startPosY - kpxcPasswordDialog.dialog.offsetTop;
return false;
};
kpxcPasswordDialog.openDialog = function() {
if (kpxcPasswordDialog.dialog.style.display === '' || kpxcPasswordDialog.dialog.style.display === 'none') {
kpxcPasswordDialog.dialog.style.display = 'block';
} else {
kpxcPasswordDialog.dialog.style.display = 'none';
}
};
kpxcPasswordDialog.trigger = async function() {
if (await useKeePassXCPasswordGenerator()) {
kpxcPasswordDialog.generate(null, document.activeElement);
kpxcPasswordGenerator.generate = async function(field) {
if (!await isPasswordGeneratorSupported()) {
kpxcUI.createNotification('error', tr('passwordGeneratorNotSupported'));
return;
}
kpxcPasswordDialog.showDialog(document.activeElement, kpxcPasswordDialog.icon);
kpxcPasswordGenerator.fill(field, await sendMessage('generate_password'));
};
kpxcPasswordDialog.showDialog = function(field, icon) {
if (!kpxcFields.isVisible(field)) {
icon.parentNode.removeChild(icon);
field.removeAttribute('kpxc-password-field');
return;
}
kpxcPasswordDialog.input = field;
// Save next password field if found
if (kpxc.inputs.length > 0) {
const index = kpxc.inputs.indexOf(field);
const nextField = kpxc.inputs[index + 1];
kpxcPasswordDialog.nextField = (nextField && nextField.getLowerCaseAttribute('type') === 'password') ? nextField : undefined;
}
kpxcPasswordDialog.createDialog();
initColorTheme(kpxcPasswordDialog.dialog);
kpxcPasswordDialog.openDialog();
// Adjust the dialog location
if (kpxcPasswordDialog.dialog) {
if (icon) {
kpxcPasswordDialog.dialog.style.top = Pixels(icon.offsetTop + icon.offsetHeight);
kpxcPasswordDialog.dialog.style.left = icon.style.left;
} else {
const rect = document.activeElement.getBoundingClientRect();
kpxcPasswordDialog.dialog.style.top = Pixels(rect.top + rect.height);
kpxcPasswordDialog.dialog.style.left = Pixels(rect.left);
}
}
};
kpxcPasswordDialog.generate = async function(e, field) {
// This function can be also called from non-events
if (e) {
if (!e.isTrusted) {
return;
}
e.preventDefault();
}
if (await useKeePassXCPasswordGenerator()) {
kpxcPasswordDialog.newFill(field, await sendMessage('generate_password'));
return;
}
callbackGeneratedPassword(await sendMessage('generate_password'));
};
kpxcPasswordDialog.copy = function(e) {
if (!e.isTrusted) {
return;
}
e.preventDefault();
kpxcPasswordDialog.copyPasswordToClipboard();
};
kpxcPasswordDialog.fill = function(e) {
if (!e.isTrusted || !kpxcPasswordDialog.input) {
return;
}
e.preventDefault();
const password = kpxcPasswordDialog.shadowSelector('.kpxc-pwgen-input');
if (kpxcPasswordDialog.input.getAttribute('maxlength')) {
if (password.value.length > kpxcPasswordDialog.input.getAttribute('maxlength')) {
const message = tr('passwordGeneratorErrorTooLong') + '\r\n'
+ tr('passwordGeneratorErrorTooLongCut') + '\r\n' + tr('passwordGeneratorErrorTooLongRemember');
message.style.whiteSpace = 'pre';
kpxcUI.createNotification('error', message);
return;
}
}
kpxcPasswordDialog.input.value = password.value;
kpxcPasswordDialog.input.dispatchEvent(new Event('keydown', { bubbles: true }));
kpxcPasswordDialog.input.dispatchEvent(new Event('keyup', { bubbles: true }));
kpxcPasswordDialog.input.dispatchEvent(new Event('input', { bubbles: true }));
kpxcPasswordDialog.input.dispatchEvent(new Event('change', { bubbles: true }));
if (kpxcPasswordDialog.nextField) {
kpxcPasswordDialog.nextField.value = password.value;
kpxcPasswordDialog.nextField.dispatchEvent(new Event('keydown', { bubbles: true }));
kpxcPasswordDialog.nextField.dispatchEvent(new Event('keyup', { bubbles: true }));
kpxcPasswordDialog.nextField.dispatchEvent(new Event('input', { bubbles: true }));
kpxcPasswordDialog.nextField.dispatchEvent(new Event('change', { bubbles: true }));
}
};
// New way to fill the password
kpxcPasswordDialog.newFill = function(elem, password) {
kpxcPasswordGenerator.fill = function(elem, password) {
if (!elem || !password) {
return;
}
@ -358,56 +149,7 @@ kpxcPasswordDialog.newFill = function(elem, password) {
}
};
kpxcPasswordDialog.copyPasswordToClipboard = function() {
kpxcPasswordDialog.shadowSelector('.kpxc-pwgen-input').select();
try {
return document.execCommand('copy');
} catch (err) {
console.log('Could not copy password to clipboard: ' + err);
}
return false;
};
const callbackGeneratedPassword = function(passwords) {
if (passwords && passwords.length >= 1) {
const errorMessage = kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-error');
if (errorMessage) {
enableButtons();
const input = kpxcPasswordDialog.shadowSelector('.kpxc-pwgen-input');
input.style.display = 'block';
errorMessage.remove();
}
kpxcPasswordDialog.shadowSelector('.kpxc-pwgen-input').value = passwords[0].password;
} else {
if (kpxcPasswordDialog.shadowSelectorAll('div#kpxc-pwgen-error').length === 0) {
const input = kpxcPasswordDialog.shadowSelector('.kpxc-pwgen-input');
input.style.display = 'none';
const errorMessage = kpxcUI.createElement('div', '', { 'id': 'kpxc-pwgen-error' },
tr('passwordGeneratorError') + '\r\n' + tr('passwordGeneratorErrorIsRunning'));
errorMessage.style.whiteSpace = 'pre';
input.parentElement.append(errorMessage);
disableButtons();
}
}
};
const enableButtons = function() {
kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-btn-generate').textContent = tr('passwordGeneratorGenerate');
kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-btn-copy').style.display = 'inline-block';
kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-btn-fill').style.display = 'inline-block';
};
const disableButtons = function() {
kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-btn-generate').textContent = tr('passwordGeneratorTryAgain');
kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-btn-copy').style.display = 'none';
kpxcPasswordDialog.shadowSelector('#kpxc-pwgen-btn-fill').style.display = 'none';
};
const useKeePassXCPasswordGenerator = async function() {
const isPasswordGeneratorSupported = async function() {
const response = await browser.runtime.sendMessage({
action: 'get_keepassxc_versions'
});

View file

@ -36,7 +36,7 @@ kpxcTOTPIcons.switchIcon = function(state, uuid) {
};
kpxcTOTPIcons.deleteHiddenIcons = function() {
kpxcUI.deleteHiddenIcons(kpxcTOTPIcons.icons, 'kpxc-totp-field');
kpxcUI.deleteHiddenIcons(kpxcTOTPIcons.icons);
};
kpxcTOTPIcons.autoCompleteIsOneTimeCode = function(field) {
@ -90,10 +90,6 @@ kpxcTOTPIcons.isValid = function(field, forced) {
logDebug('Error: TOTP field found but it is not valid:', field);
return false;
}
} else {
if (field.getAttribute('kpxc-totp-field') === 'true') {
return false;
}
}
return true;

View file

@ -62,8 +62,7 @@ class Icon {
}
}
removeIcon(attr) {
this.inputField.removeAttribute(attr);
removeIcon() {
this.shadowRoot.removeChild(this.icon);
document.body.removeChild(this.shadowRoot.host);
}
@ -173,12 +172,12 @@ kpxcUI.getRelativeTopPosition = function(rect) {
return kpxcUI.bodyStyle.position.toLowerCase() === 'relative' ? rect.top - kpxcUI.bodyRect.top : rect.top;
};
kpxcUI.deleteHiddenIcons = function(iconList, attr) {
kpxcUI.deleteHiddenIcons = function(iconList) {
const deletedIcons = [];
for (const icon of iconList) {
if (icon.inputField && !kpxcFields.isVisible(icon.inputField)) {
const index = iconList.indexOf(icon);
icon.removeIcon(attr);
icon.removeIcon();
iconList.splice(index, 1);
deletedIcons.push(icon.inputField);
@ -345,23 +344,6 @@ const logDebug = function(message, extra) {
}
};
// Enables dragging
document.addEventListener('mousemove', function(e) {
if (!kpxcUI.mouseDown) {
return;
}
if (kpxcPasswordDialog.selected === kpxcPasswordDialog.titleBar) {
const xPos = e.clientX - kpxcPasswordDialog.diffX;
const yPos = e.clientY - kpxcPasswordDialog.diffY;
if (kpxcPasswordDialog.selected !== null) {
kpxcPasswordDialog.dialog.style.left = Pixels(xPos);
kpxcPasswordDialog.dialog.style.top = Pixels(yPos);
}
}
});
document.addEventListener('mousedown', function(e) {
if (!e.isTrusted) {
return;
@ -375,7 +357,6 @@ document.addEventListener('mouseup', function(e) {
return;
}
kpxcPasswordDialog.selected = null;
kpxcUI.mouseDown = false;
});

View file

@ -13,7 +13,7 @@ kpxcUsernameIcons.switchIcon = function(state) {
};
kpxcUsernameIcons.deleteHiddenIcons = function() {
kpxcUI.deleteHiddenIcons(kpxcUsernameIcons.icons, 'kpxc-username-field');
kpxcUI.deleteHiddenIcons(kpxcUsernameIcons.icons);
};
kpxcUsernameIcons.isValid = function(field) {
@ -122,7 +122,6 @@ UsernameFieldIcon.prototype.createIcon = function(field) {
const iconClicked = async function(field, icon) {
if (!kpxcFields.isCustomLoginFieldsUsed() && !kpxcFields.isVisible(field)) {
icon.parentNode.removeChild(icon);
field.removeAttribute('kpxc-username-field');
return;
}

View file

@ -1,80 +1,3 @@
.kpxc-pwgen-dialog {
background-color: var(--kpxc-background-color);
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 4px 6px 0 hsla(0, 0%, 0%, 0.2);
color: var(--kpxc-text-color);
font-family: 'Lato', sans-serif !important;
min-height: 80px;
padding: .1em .2em .1em .2em;
position: absolute !important;
width: 350px;
z-index: 10000000 !important;
}
.kpxc-pwgen-titlebar {
background-color: #6cac4d;
color: #fff;
cursor: move;
font-size: 12px !important;
margin: .2em 0 .2em 0;
padding: .4em .2em .4em .8em;
position: relative;
user-select: none;
}
.kpxc-pwgen-password-row {
color: #fff;
display: flex;
margin: .2em 0 .2em 0;
padding: .4em 1em;
}
.kpxc-pwgen-buttons {
align-items: center;
border-top: 1px solid #ccc;
color: #fff;
display: flex;
justify-content: left;
padding: .4em 1em;
margin: .2em 0 .2em 0;
}
.kpxc-pwgen-close {
color: #fff;
float: right;
font-size: inherit;
font-weight: bold;
text-align: center;
min-width: 20px;
}
.kpxc-pwgen-close:hover {
background-color: #6cac4d !important;
color: #fff;
cursor: pointer;
}
.kpxc-pwgen-input {
background: none !important;
border-radius: 4px !important;
color: var(--kpxc-text-color) !important;
font-size: 12px !important;
font-weight: normal !important;
height: auto !important;
padding: 4px !important;
width: 100% !important;
}
.kpxc #kpxc-pwgen-error {
color: var(--kpxc-text-color);
font-size: 12px !important;
font-style: normal !important;
font-weight: normal !important;
text-align: center;
width: 100%;
}
.kpxc-pwgen-icon {
cursor: pointer;
position: absolute;
@ -89,21 +12,3 @@
background: url('moz-extension://__MSG_@@extension_id__/icons/key.svg') right no-repeat;
background-size: contain;
}
@media (prefers-color-scheme: dark) {
.kpxc-pwgen-dialog {
background: var(--kpxc-background-color) !important;
color: var(--kpxc-text-color) !important;
}
.kpxc-pwgen-input {
background-color: var(--kpxc-input-background-color) !important;
border: var(--kpxc-input-border);
border-color: var(--kpxc-input-border-color);
color: var(--kpxc-text-color) !important;
}
.kpxc #kpxc-pwgen-error {
color: var(--kpxc-text-color) !important;
}
}