diff --git a/.eslintrc b/.eslintrc index 6e47b6a..8973140 100644 --- a/.eslintrc +++ b/.eslintrc @@ -112,6 +112,7 @@ "slashNeededForUrl": true, "statusResponse": true, "tr": true, - "trimURL", true + "trimURL": true, + "PREDEFINED_SITELIST": true } } diff --git a/keepassxc-browser/_locales/en/messages.json b/keepassxc-browser/_locales/en/messages.json index 685253d..d876115 100644 --- a/keepassxc-browser/_locales/en/messages.json +++ b/keepassxc-browser/_locales/en/messages.json @@ -707,6 +707,18 @@ "message": "Passwords are generated by KeePassXC using your password generation profile.", "description": "Password Generator option help text, second part." }, + "optionsPredefinedSiteList": { + "message": "Predefined sites", + "description": "Predefined site list details button text." + }, + "optionsUsePredefinedSites": { + "message": "Use predefined sites for compatibility.", + "description": "Use predefined sites checkbox text." + }, + "optionsUsePredefinedSitesHelpText": { + "message": "Adds common sites that have username-only login forms to the site preferences.", + "description": "Use predefined sites option help text." + }, "optionsShowLoginFormIconHelpText": { "message": "Adds an icon to username fields for filling credentials with a single mouse click.", "description": "Username field icon option help text." @@ -916,8 +928,8 @@ "description": "Part of confirmation text when removing saved custom login fields." }, "optionsSitePreferencesNotFound": { - "message": "No ignored sites found.", - "description": "Shown when no ignored sites are saved." + "message": "No site preferences found.", + "description": "Shown when no site preferences are saved." }, "optionsSitePreferencesRemove": { "message": "Remove site?", diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 7400ac8..3cea8ab 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -4,6 +4,7 @@ try { await keepass.migrateKeyRing(); await page.initSettings(); + await page.initSitePreferences(); await page.initOpenedTabs(); await httpAuth.init(); await keepass.reconnect(null, 5000); // 5 second timeout for the first connect diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 0099b1e..0d0df3c 100755 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -19,6 +19,7 @@ const defaultSettings = { showNotifications: true, showOTPIcon: true, useObserver: true, + usePredefinedSites: true, usePasswordGeneratorIcons: false }; @@ -124,6 +125,10 @@ page.initSettings = async function() { page.settings.usePasswordGeneratorIcons = defaultSettings.usePasswordGeneratorIcons; } + if (!('usePredefinedSites' in page.settings)) { + page.settings.usePredefinedSites = defaultSettings.usePredefinedSites; + } + await browser.storage.local.set({ 'settings': page.settings }); return page.settings; } catch (err) { @@ -153,6 +158,18 @@ page.initOpenedTabs = async function() { } }; +page.initSitePreferences = async function() { + if (!page.settings) { + return; + } + + if (!page.settings['sitePreferences']) { + page.settings['sitePreferences'] = []; + } + + await browser.storage.local.set({ 'settings': page.settings }); +}; + page.switchTab = function(tab) { browserAction.showDefault(tab); browser.tabs.sendMessage(tab.id, { action: 'activated_tab' }).catch((e) => { diff --git a/keepassxc-browser/browser-polyfill.min.js b/keepassxc-browser/common/browser-polyfill.min.js similarity index 100% rename from keepassxc-browser/browser-polyfill.min.js rename to keepassxc-browser/common/browser-polyfill.min.js diff --git a/keepassxc-browser/global.js b/keepassxc-browser/common/global.js similarity index 100% rename from keepassxc-browser/global.js rename to keepassxc-browser/common/global.js diff --git a/keepassxc-browser/common/sites.js b/keepassxc-browser/common/sites.js new file mode 100644 index 0000000..4b76703 --- /dev/null +++ b/keepassxc-browser/common/sites.js @@ -0,0 +1,63 @@ +'use strict'; + +const PREDEFINED_SITELIST = [ + 'https://accounts.google.com/*', + 'https://www.paypal.com/*', + 'https://*.live.com/*', + 'https://www.amazon.com/*', + 'https://www.amazon.de/*', + 'https://www.amazon.co.uk/*', + 'https://signin.aws.amazon.com/*', + 'https://www.upwork.com/ab/*', + 'https://home.personalcapital.com/*', + 'https://auth.services.adobe.com/*', + 'https://idmsa.apple.com/*', + 'https://*.soundcloud.com/*', + 'https://icloud.com/*', + 'https://signin.ebay.de/*', + 'https://signin.ebay.com/*', + 'https://signin.ebay.com.au/*', + 'https://signin.ebay.com.cn/*', + 'https://signin.ebay.com.hk/*', + 'https://signin.ebay.com.my/*', + 'https://signin.ebay.com.sg/*', + 'https://signin.ebay.it/*', + 'https://signin.ebay.co.uk/*', + 'https://signin.ebay.ca/*', + 'https://signin.ebay.at/*', + 'https://signin.ebay.be/*', + 'https://signin.ebay.fr/*', + 'https://signin.ebay.ie/*', + 'https://signin.ebay.nl/*', + 'https://signin.ebay.es/*', + 'https://signin.ebay.ch/*', + 'https://signin.ebay.in/*', + 'https://signin.ebay.ph/*', + 'https://login.yahoo.com/*', + 'https://*.atlassian.com/*' +]; + +const kpxcSites = {}; +kpxcSites.googlePasswordFormUrl = 'https://accounts.google.com/signin/v2/challenge/password'; +kpxcSites.googleUrl = 'https://accounts.google.com'; +kpxcSites.savedForm = undefined; + +// Handles a few exceptions for certain sites where password form is inside a div +// or another element that is not detected directly. Triggered by MutationObserver. +// Returns true if an Element has a matching classList. +kpxcSites.exceptionFound = function(classList) { + if (!classList || classList.length === 0) { + return; + } + + // Apple ID + if (document.location.origin === 'https://idmsa.apple.com' + && [ 'password', 'form-row', 'show-password' ].every(c => classList.contains(c))) { + return true; + } else if (document.location.origin.startsWith('https://signin.ebay.com') + && classList.contains('null')) { + return true; + } + + return false; +}; diff --git a/keepassxc-browser/translate.js b/keepassxc-browser/common/translate.js similarity index 100% rename from keepassxc-browser/translate.js rename to keepassxc-browser/common/translate.js diff --git a/keepassxc-browser/content/keepassxc-browser.js b/keepassxc-browser/content/keepassxc-browser.js index bf020a8..a639dac 100755 --- a/keepassxc-browser/content/keepassxc-browser.js +++ b/keepassxc-browser/content/keepassxc-browser.js @@ -158,13 +158,14 @@ kpxcForm.getFormSubmitButton = function(form) { const action = kpxc.submitUrl || form.action; // Special handling for accounts.google.com. The submit button is outside the form. - if (form.action.startsWith('https://accounts.google.com')) { - const findDiv = $('#identifierNext'); + if (form.action.startsWith(kpxcSites.googleUrl)) { + const findDiv = $('#identifierNext, #passwordNext'); if (!findDiv) { return undefined; } const buttons = findDiv.getElementsByTagName('button'); + kpxcSites.savedForm = form; return buttons.length > 0 ? buttons[0] : undefined; } @@ -220,7 +221,8 @@ kpxcForm.getNewPassword = function(passwordInputs = []) { // Initializes form and attaches the submit button to our own callback kpxcForm.init = function(form, credentialFields) { - if (!kpxcForm.formIdentified(form) && (credentialFields.password || credentialFields.username)) { + if (!kpxcForm.formIdentified(form) && (credentialFields.password || credentialFields.username) + || form.action.startsWith(kpxcSites.googlePasswordFormUrl)) { kpxcForm.saveForm(form, credentialFields); form.addEventListener('submit', kpxcForm.onSubmit); @@ -244,7 +246,13 @@ kpxcForm.onSubmit = async function(e) { }; // Traverse parents if the form is not found. - const form = this.nodeName === 'FORM' ? this : kpxcFields.traverseParents(this, searchForm, searchForm, () => null); + let form = this.nodeName === 'FORM' ? this : kpxcFields.traverseParents(this, searchForm, searchForm, () => null); + + // Check for extra forms from sites.js + if (!form) { + form = kpxcSites.savedForm; + } + if (!form) { return; } @@ -612,11 +620,9 @@ kpxc.submitUrl = null; kpxc.url = null; // Add page to Site Preferences with Username-only detection enabled. Set from the popup -kpxc.addToSitePreferences = async function(sites) { - kpxc.initSitePreferences(); - +kpxc.addToSitePreferences = async function() { // Returns a predefined URL for certain sites - let site = kpxcSites.definedURL(trimURL(window.top.location.href)); + let site = trimURL(window.top.location.href); // Check if the site already exists -> update the current settings let siteExists = false; @@ -955,8 +961,6 @@ kpxc.getSite = function(sites) { } let site = trimURL(sites[0]); - kpxc.initSitePreferences(); - if (slashNeededForUrl(site)) { site += '/'; } @@ -1151,17 +1155,6 @@ kpxc.initLoginPopup = function() { sendMessage('popup_login', usernames); }; -// Delete previously created Object if it exists. It will be replaced by an Array -kpxc.initSitePreferences = function() { - if (kpxc.settings['sitePreferences'] !== undefined && kpxc.settings['sitePreferences'].constructor === Object) { - delete kpxc.settings['sitePreferences']; - } - - if (!kpxc.settings['sitePreferences']) { - kpxc.settings['sitePreferences'] = []; - } -}; - kpxc.passwordFilled = async function() { return await sendMessage('password_get_filled'); }; @@ -1356,8 +1349,6 @@ kpxc.setValueWithChange = function(field, value) { // Returns true if site is ignored kpxc.siteIgnored = async function(condition) { - kpxc.initSitePreferences(); - if (kpxc.settings.sitePreferences) { let currentLocation; try { @@ -1378,6 +1369,15 @@ kpxc.siteIgnored = async function(condition) { kpxc.singleInputEnabledForPage = site.usernameOnly; } } + + // Check for predefined sites + if (kpxc.settings.usePredefinedSites) { + for (const url of PREDEFINED_SITELIST) { + if (siteMatch(url, currentLocation) || url === currentLocation) { + kpxc.singleInputEnabledForPage = true; + } + } + } } return false; @@ -1644,7 +1644,7 @@ kpxcObserverHelper.initObserver = async function() { } else if (mut.type === 'attributes' && mut.attributeName === 'class') { // Only accept targets with forms const forms = mut.target.nodeName === 'FORM' ? mut.target : mut.target.getElementsByTagName('form'); - if (forms.length === 0) { + if (forms.length === 0 && !kpxcSites.exceptionFound(mut.target.classList)) { continue; } diff --git a/keepassxc-browser/content/sites.js b/keepassxc-browser/content/sites.js deleted file mode 100644 index e96e787..0000000 --- a/keepassxc-browser/content/sites.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -// List of sites that need special handling. 'rep' is the replacement URL. -const siteList = [ - { - url: 'accounts.google.com', - rep: 'https://accounts.google.com/*' - } -]; - -const kpxcSites = {}; - -// Returns a predefined URL for certain sites to ensure compatibility with Site Preferences -kpxcSites.definedURL = function(url) { - for (const site of siteList) { - if (url.includes(site.url)) { - return site.rep; - } - } - - return url; -}; - -// UNUSED: Adds all common sites with multi-page login to Site Preferences -kpxcSites.addAllCommonSites = function() { - kpxc.initializeSitePreferences(); - - for (const site of siteList) { - kpxc.settings['sitePreferences'].push({ - url: site.rep, - ignore: IGNORE_NOTHING, - usernameOnly: true - }); - } -}; diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index 8184691..5ab8125 100755 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 2, "name": "KeePassXC-Browser", - "version": "1.7.1", - "version_name": "1.7.1", + "version": "1.7.2", + "version_name": "1.7.2", "description": "__MSG_extensionDescription__", "author": "KeePassXC Team", "icons": { @@ -31,8 +31,9 @@ }, "background": { "scripts": [ - "browser-polyfill.min.js", - "global.js", + "common/browser-polyfill.min.js", + "common/global.js", + "common/sites.js", "background/nacl.min.js", "background/nacl-util.min.js", "background/keepass.js", @@ -49,15 +50,15 @@ "" ], "js": [ - "browser-polyfill.min.js", - "global.js", + "common/browser-polyfill.min.js", + "common/global.js", + "common/sites.js", "content/ui.js", "content/banner.js", "content/autocomplete.js", "content/define.js", "content/keepassxc-browser.js", "content/pwgen.js", - "content/sites.js", "content/totp-field.js", "content/username-field.js" ], diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html index 443c979..284b6e0 100644 --- a/keepassxc-browser/options/options.html +++ b/keepassxc-browser/options/options.html @@ -11,12 +11,13 @@ - - + + + - +
@@ -307,6 +308,17 @@
+ +
+
+ + + +
+ +
+
+
diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 79deb08..b2abfed 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -243,6 +243,18 @@ options.initGeneralSettings = function() { const copyText = document.getElementById('versionInfo').innerText; navigator.clipboard.writeText(copyText); }); + + // Add predefined sites to the
list + const siteListing = $('#predefinedSiteList'); + if (siteListing) { + // From sites.js + for (const site of PREDEFINED_SITELIST) { + const elem = document.createElement('span'); + elem.textContent = site; + siteListing.append(document.createElement('br')); + siteListing.append(elem); + } + } }; options.showKeePassXCVersions = function(response) { diff --git a/keepassxc-browser/options/shortcuts.html b/keepassxc-browser/options/shortcuts.html index 3a5a68a..687f948 100644 --- a/keepassxc-browser/options/shortcuts.html +++ b/keepassxc-browser/options/shortcuts.html @@ -10,12 +10,12 @@ - + - - + +
diff --git a/keepassxc-browser/popups/popup.html b/keepassxc-browser/popups/popup.html index 0faf5c6..9754225 100644 --- a/keepassxc-browser/popups/popup.html +++ b/keepassxc-browser/popups/popup.html @@ -7,13 +7,13 @@ - - + + - +
diff --git a/keepassxc-browser/popups/popup_httpauth.html b/keepassxc-browser/popups/popup_httpauth.html index aa0f7c6..8eb2547 100644 --- a/keepassxc-browser/popups/popup_httpauth.html +++ b/keepassxc-browser/popups/popup_httpauth.html @@ -7,13 +7,13 @@ - - + + - +
diff --git a/keepassxc-browser/popups/popup_login.html b/keepassxc-browser/popups/popup_login.html index 2436885..0f3d745 100644 --- a/keepassxc-browser/popups/popup_login.html +++ b/keepassxc-browser/popups/popup_login.html @@ -7,13 +7,13 @@ - - + + - +