diff --git a/keepassxc-browser/common/sites.js b/keepassxc-browser/common/sites.js index c871822..c6081dd 100644 --- a/keepassxc-browser/common/sites.js +++ b/keepassxc-browser/common/sites.js @@ -71,7 +71,7 @@ kpxcSites.detectUsernameFromPage = function() { * @returns {boolean} True if an Element has a match with the identifier and document location */ kpxcSites.exceptionFound = function(identifier, field) { - if (!identifier || identifier.length === 0) { + if ((!identifier || identifier.length === 0) && !field) { return; } @@ -80,7 +80,7 @@ kpxcSites.exceptionFound = function(identifier, field) { || (typeof identifier === 'object' && [ 'password', 'form-row', 'show-password' ].every(c => identifier.contains(c))))) { return true; } else if (document.location.origin.startsWith('https://signin.ebay.') - && (identifier === 'null' || identifier.value === 'null' || identifier === 'pass')) { + && (identifier === 'null' || identifier?.value === 'null' || identifier === 'pass')) { return true; } else if (document.location.origin.startsWith('https://www.fidelity.com')) { if (typeof identifier === 'string') { @@ -108,6 +108,33 @@ kpxcSites.exceptionFound = function(identifier, field) { return true; } else if (document.location.origin === 'https://accounts.google.com' && field?.id === 'password') { return true; + } else if (document.location.origin === 'https://www.epicgames.com' + && ((field?.style?.opacity === '1' && field?.style?.willChange === 'auto') || identifier === 'password')) { + return true; + } else if (document.location.origin === 'https://www.paypal.com' && field?.id === 'splitPassword') { + return true; + } + + return false; +}; + +// Handles exceptions when returning or modifying existing combinations +kpxcSites.combinationExceptionFound = function(existingCombination) { + if (!existingCombination) { + return false; + } + + // Exception for e.g. Google. They replace the username input with password input using identical className. + // If detected, remove the username from the combination. + if (existingCombination?.username?.className?.length > 0 + && existingCombination?.password?.className?.length > 0 + && existingCombination?.username?.className === existingCombination?.password?.className) { + return true; + } + + if (document.location.origin === 'https://www.paypal.com' + && existingCombination.password?.className?.includes('pin-password')) { + return true; } return false; diff --git a/keepassxc-browser/content/fields.js b/keepassxc-browser/content/fields.js index 5c00cd0..8465e89 100644 --- a/keepassxc-browser/content/fields.js +++ b/keepassxc-browser/content/fields.js @@ -108,11 +108,8 @@ kpxcFields.getExistingCombination = function(combination) { existingCombination.passwordInputs.push(combination.password); } - // Exception for Google. They replace the username input with password input using identical className. - // If detected, remove the username from the combination. - if (existingCombination?.username?.className?.length > 0 - && existingCombination?.password?.className?.length > 0 - && existingCombination?.username?.className === existingCombination?.password?.className) { + // Remove username field from combination with certain sites (replaced by password input) + if (kpxcSites.combinationExceptionFound(existingCombination)) { existingCombination.username = null; } diff --git a/keepassxc-browser/content/form.js b/keepassxc-browser/content/form.js index d916be0..210bc76 100644 --- a/keepassxc-browser/content/form.js +++ b/keepassxc-browser/content/form.js @@ -27,7 +27,7 @@ kpxcForm.activateCredentialBanner = async function(usernameValue, passwordInputs return; } - if (passwordField) { + if (passwordField && kpxcFields.isVisible(passwordField)) { await kpxc.setPasswordFilled(true); } diff --git a/keepassxc-browser/content/icon-handler.js b/keepassxc-browser/content/icon-handler.js index 7d5a1c0..9406d9c 100644 --- a/keepassxc-browser/content/icon-handler.js +++ b/keepassxc-browser/content/icon-handler.js @@ -45,7 +45,13 @@ kpxcIcons.addIconsFromForm = async function(form) { // Special case where everything else has been hidden, but a single password field is now displayed. // For example PayPal and Amazon is handled like this. if (c.username && !c.password && c.passwordInputs.length === 1) { - kpxcIcons.addIcon(c.passwordInputs[0], kpxcIcons.iconTypes.DEFAULT); + // Use password input directly from form if found (Epicgames) + const passwordField = c.form?.querySelector('input[type=password]'); + if (c.form && passwordField) { + kpxcIcons.addIcon(passwordField, kpxcIcons.iconTypes.DEFAULT); + } else { + kpxcIcons.addIcon(c.passwordInputs[0], kpxcIcons.iconTypes.DEFAULT); + } } if (c.username && !c.username.readOnly) { diff --git a/keepassxc-browser/content/observer-helper.js b/keepassxc-browser/content/observer-helper.js index 077b7db..a4d09eb 100644 --- a/keepassxc-browser/content/observer-helper.js +++ b/keepassxc-browser/content/observer-helper.js @@ -25,7 +25,6 @@ kpxcObserverHelper.ignoredNodeNames = [ ]; kpxcObserverHelper.ignoredPartialNodeNames = [ - 'FACEPLATE', 'REDDIT-PDP', 'RENDER-TEMPLATE', 'SHREDDIT', @@ -247,8 +246,9 @@ kpxcObserverHelper.findInputsFromShadowDOM = function(target) { // Detects animations and transitions. Triggers handleObserverAdd() again on animationend/transitionend. kpxcObserverHelper.handleTransitions = function(target) { - const targetHasAnimations = target?.classList?.toString()?.includes('animate'); - const targetHasDurations = target?.classList?.toString()?.includes('duration'); + const classList = target?.classList?.toString(); + const targetHasAnimations = classList?.includes('animate'); + const targetHasDurations = classList?.includes('duration') || classList?.includes('transform'); if (targetHasAnimations || targetHasDurations) { const animations = target.getAnimations();