Skip to content

Commit

Permalink
Merge pull request keepassxreboot#1966 from keepassxreboot/fix/remove…
Browse files Browse the repository at this point in the history
…_internal_password_generator

Remove internal password generator
  • Loading branch information
varjolintu authored Feb 25, 2024
2 parents 41506f8 + 25975d1 commit 66d93f6
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 431 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
"kpxcForm": true,
"kpxcIcons": true,
"kpxcObserverHelper": true,
"kpxcPasswordDialog": true,
"kpxcPasswordGenerator": true,
"kpxcPasswordIcons": true,
"kpxcSites": true,
"kpxcTOTPAutocomplete": true,
Expand Down
37 changes: 2 additions & 35 deletions keepassxc-browser/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand All @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion keepassxc-browser/content/keepassxc-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]);
}
Expand Down
282 changes: 12 additions & 270 deletions keepassxc-browser/content/pwgen.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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';
Expand All @@ -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());
Expand All @@ -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 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();
};

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);
return;
}

kpxcPasswordDialog.showDialog(document.activeElement, kpxcPasswordDialog.icon);
};

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;
}
const kpxcPasswordGenerator = {};

callbackGeneratedPassword(await sendMessage('generate_password'));
kpxcPasswordGenerator.showPasswordGenerator = async function(field) {
kpxcPasswordGenerator.generate(field ?? document.activeElement);
};

kpxcPasswordDialog.copy = function(e) {
if (!e.isTrusted) {
kpxcPasswordGenerator.generate = async function(field) {
if (!await isPasswordGeneratorSupported()) {
kpxcUI.createNotification('error', tr('passwordGeneratorNotSupported'));
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 }));
}
kpxcPasswordGenerator.fill(field, await sendMessage('generate_password'));
};

// New way to fill the password
kpxcPasswordDialog.newFill = function(elem, password) {
kpxcPasswordGenerator.fill = function(elem, password) {
if (!elem || !password) {
return;
}
Expand Down Expand Up @@ -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'
});
Expand Down
Loading

0 comments on commit 66d93f6

Please sign in to comment.