mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Merge pull request #1010 from keepassxreboot/feature/predefined_sites
Add predefined sites option
This commit is contained in:
commit
82e32d4e78
17 changed files with 168 additions and 84 deletions
|
|
@ -112,6 +112,7 @@
|
|||
"slashNeededForUrl": true,
|
||||
"statusResponse": true,
|
||||
"tr": true,
|
||||
"trimURL", true
|
||||
"trimURL": true,
|
||||
"PREDEFINED_SITELIST": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
63
keepassxc-browser/common/sites.js
Normal file
63
keepassxc-browser/common/sites.js
Normal file
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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 @@
|
|||
"<all_urls>"
|
||||
],
|
||||
"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"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,12 +11,13 @@
|
|||
<link rel="icon" type="image/png" href="../icons/keepassxc_32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="../icons/keepassxc_64x64.png" sizes="64x64">
|
||||
<link rel="icon" type="image/png" href="../icons/keepassxc_96x96.png" sizes="96x96">
|
||||
<script src="../browser-polyfill.min.js"></script>
|
||||
<script src="../global.js"></script>
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../common/global.js"></script>
|
||||
<script src="../common/sites.js"></script>
|
||||
<script src="../bootstrap/jquery-3.4.1.min.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script src="options.js"></script>
|
||||
<script src="../translate.js" defer></script>
|
||||
<script src="../common/translate.js" defer></script>
|
||||
</head>
|
||||
<body class="pt-3 pb-5">
|
||||
<div class="container-fluid">
|
||||
|
|
@ -307,6 +308,17 @@
|
|||
<span class="form-text text-muted" data-i18n="optionsSaveDomainOnlyCustomLoginHelpText"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="usePredefinedSites" id="usePredefinedSites" value="true" />
|
||||
<label class="form-check-label" for="usePredefinedSites" data-i18n="optionsUsePredefinedSites"></label>
|
||||
<span class="form-text text-muted" data-i18n="optionsUsePredefinedSitesHelpText"></span>
|
||||
<details id="predefinedSiteList">
|
||||
<summary><span data-i18n="optionsPredefinedSiteList"></span></summary>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -243,6 +243,18 @@ options.initGeneralSettings = function() {
|
|||
const copyText = document.getElementById('versionInfo').innerText;
|
||||
navigator.clipboard.writeText(copyText);
|
||||
});
|
||||
|
||||
// Add predefined sites to the <details> 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) {
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@
|
|||
<link rel="icon" type="image/png" href="../icons/keepassxc_32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="../icons/keepassxc_64x64.png" sizes="64x64">
|
||||
<link rel="icon" type="image/png" href="../icons/keepassxc_96x96.png" sizes="96x96">
|
||||
<script src="../browser-polyfill.min.js"></script>
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../bootstrap/jquery-3.4.1.min.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script defer src="shortcuts.js"></script>
|
||||
<script defer src="../global.js"></script>
|
||||
<script defer src="../translate.js"></script>
|
||||
<script defer src="../common/global.js"></script>
|
||||
<script defer src="../common/translate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="conf-container">
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
<link rel="stylesheet" href="popup.css" />
|
||||
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="../fonts/fork-awesome.min.css" />
|
||||
<script src="../browser-polyfill.min.js"></script>
|
||||
<script src="../global.js"></script>
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../common/global.js"></script>
|
||||
<script src="../bootstrap/jquery-3.4.1.min.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script src="popup_functions.js"></script>
|
||||
<script src="popup.js"></script>
|
||||
<script defer src="../translate.js"></script>
|
||||
<script defer src="../common/translate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
<link rel="stylesheet" href="popup.css" />
|
||||
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="../fonts/fork-awesome.min.css" />
|
||||
<script src="../browser-polyfill.min.js"></script>
|
||||
<script src="../global.js"></script>
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../common/global.js"></script>
|
||||
<script src="../bootstrap/jquery-3.4.1.min.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script src="popup_functions.js"></script>
|
||||
<script src="popup_httpauth.js"></script>
|
||||
<script defer src="../translate.js"></script>
|
||||
<script defer src="../common/translate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
<link rel="stylesheet" href="popup.css" />
|
||||
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="../fonts/fork-awesome.min.css" />
|
||||
<script src="../browser-polyfill.min.js"></script>
|
||||
<script src="../global.js"></script>
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../common/global.js"></script>
|
||||
<script src="../bootstrap/jquery-3.4.1.min.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script src="popup_functions.js"></script>
|
||||
<script src="popup_login.js"></script>
|
||||
<script defer src="../translate.js"></script>
|
||||
<script defer src="../common/translate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
|
|
|||
Loading…
Reference in a new issue