Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc-browser.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keepassxc-browser/_locales/en/messages.json4
-rwxr-xr-xkeepassxc-browser/background/event.js3
-rw-r--r--keepassxc-browser/background/init.js3
-rwxr-xr-xkeepassxc-browser/background/page.js61
-rwxr-xr-xkeepassxc-browser/content/keepassxc-browser.js24
5 files changed, 93 insertions, 2 deletions
diff --git a/keepassxc-browser/_locales/en/messages.json b/keepassxc-browser/_locales/en/messages.json
index d876115..855e003 100644
--- a/keepassxc-browser/_locales/en/messages.json
+++ b/keepassxc-browser/_locales/en/messages.json
@@ -27,6 +27,10 @@
"message": "Show Password Generator",
"description": "Show password generator text."
},
+ "contextMenuFillAttribute": {
+ "message": "Fill attributeā€¦",
+ "description": "Context menu parent item for filling a custom attribute."
+ },
"multipleCredentialsDetected": {
"message": "HTTP authentication with multiple credentials detected. Click on the extension icon to choose the correct one.",
"description": "Notification when HTTP Authentication has multiple credentials detected."
diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js
index 862f0d3..986935a 100755
--- a/keepassxc-browser/background/event.js
+++ b/keepassxc-browser/background/event.js
@@ -236,5 +236,6 @@ kpxcEvent.messageHandlers = {
'update_credentials': keepass.updateCredentials,
'username_field_detected': kpxcEvent.onUsernameFieldDetected,
'save_settings': kpxcEvent.onSaveSettings,
- 'update_available_keepassxc': kpxcEvent.onUpdateAvailableKeePassXC
+ 'update_available_keepassxc': kpxcEvent.onUpdateAvailableKeePassXC,
+ 'update_context_menu': page.updateContextMenu
};
diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js
index 3cea8ab..0e7840e 100644
--- a/keepassxc-browser/background/init.js
+++ b/keepassxc-browser/background/init.js
@@ -107,6 +107,7 @@ const contextMenuItems = [
{ title: tr('contextMenuFillUsernameAndPassword'), action: 'fill_username_password' },
{ title: tr('contextMenuFillPassword'), action: 'fill_password' },
{ title: tr('contextMenuFillTOTP'), action: 'fill_totp' },
+ { title: tr('contextMenuFillAttribute'), id: 'fill_attribute', visible: false },
{ title: tr('contextMenuShowPasswordGenerator'), action: 'show_password_generator' },
{ title: tr('contextMenuSaveCredentials'), action: 'remember_credentials' }
];
@@ -122,6 +123,8 @@ for (const item of contextMenuItems) {
browser.contextMenus.create({
title: item.title,
contexts: menuContexts,
+ visible: item.visible,
+ id: item.id,
onclick: (info, tab) => {
browser.tabs.sendMessage(tab.id, {
action: item.action
diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js
index 0d0df3c..7efac4d 100755
--- a/keepassxc-browser/background/page.js
+++ b/keepassxc-browser/background/page.js
@@ -24,6 +24,7 @@ const defaultSettings = {
};
var page = {};
+page.attributeMenuItemIds = [];
page.blockedTabs = [];
page.currentRequest = {};
page.currentTabId = -1;
@@ -170,7 +171,14 @@ page.initSitePreferences = async function() {
await browser.storage.local.set({ 'settings': page.settings });
};
-page.switchTab = function(tab) {
+page.switchTab = async function(tab) {
+ browser.contextMenus.update('fill_attribute', { visible: false });
+ if (page.tabs[tab.id]
+ && page.tabs[tab.id].credentials.length > 0
+ && page.tabs[tab.id].credentials.some(e => e.stringFields && e.stringFields.length > 0)) {
+ await page.updateContextMenu(tab, page.tabs[tab.id].credentials);
+ }
+
browserAction.showDefault(tab);
browser.tabs.sendMessage(tab.id, { action: 'activated_tab' }).catch((e) => {
console.log('Cannot send activated_tab message: ', e);
@@ -203,6 +211,8 @@ page.clearLogins = function(tabId) {
page.tabs[tabId].loginList = [];
page.currentRequest = {};
page.passwordFilled = false;
+
+ browser.contextMenus.update('fill_attribute', { visible: false });
};
// Clear all logins from all pages and update the content scripts
@@ -234,6 +244,7 @@ page.createTabEntry = function(tabId) {
};
page.clearSubmittedCredentials();
+ browser.contextMenus.update('fill_attribute', { visible: false });
};
page.removePageInformationFromNotExistingTabs = async function() {
@@ -312,3 +323,51 @@ page.setSubmitted = async function(tab, args = []) {
const [ submitted, username, password, url, oldCredentials ] = args;
page.setSubmittedCredentials(submitted, username, password, url, oldCredentials, tab.id);
};
+
+// Update context menu for attribute filling
+page.updateContextMenu = async function(tab, credentials) {
+ // Remove any old attribute items
+ while (page.attributeMenuItemIds.length) {
+ browser.contextMenus.remove(page.attributeMenuItemIds.pop());
+ }
+
+ // Set parent item visibility
+ browser.contextMenus.update('fill_attribute', { visible: true });
+
+ // Add any new attribute items
+ for (const cred of credentials) {
+ if (!cred.stringFields) {
+ continue;
+ }
+
+ for (const attribute of cred.stringFields) {
+ // Show username inside [] if there are KPH attributes inside multiple credentials
+ const attributeName = Object.keys(attribute)[0].slice(5);
+ const finalName = credentials.length > 1
+ ? `[${cred.login}] ${attributeName}`
+ : attributeName;
+
+ page.attributeMenuItemIds.push(createContextMenuItem({
+ action: 'fill_attribute',
+ args: attribute,
+ parentId: 'fill_attribute',
+ title: finalName
+ }));
+ }
+ }
+};
+
+const createContextMenuItem = function({action, args, ...options}) {
+ return browser.contextMenus.create({
+ contexts: menuContexts,
+ onclick: (info, tab) => {
+ browser.tabs.sendMessage(tab.id, {
+ action: action,
+ args: args
+ }).catch((err) => {
+ console.log(err);
+ });
+ },
+ ...options
+ });
+};
diff --git a/keepassxc-browser/content/keepassxc-browser.js b/keepassxc-browser/content/keepassxc-browser.js
index ee38c4f..0201028 100755
--- a/keepassxc-browser/content/keepassxc-browser.js
+++ b/keepassxc-browser/content/keepassxc-browser.js
@@ -720,6 +720,21 @@ kpxc.detectDatabaseChange = async function(response) {
}
};
+// Fill selected attribute from the context menu
+kpxc.fillAttributeToActiveElementWith = async function(attr) {
+ const el = document.activeElement;
+ if (el.nodeName !== 'INPUT' || kpxc.credentials.length === 0) {
+ return;
+ }
+
+ const value = Object.values(attr);
+ if (!value || value.length === 0) {
+ return;
+ }
+
+ kpxc.setValue(el, value[0]);
+};
+
// Fill requested from the context menu. Active element is used for combination detection
kpxc.fillInFromActiveElement = async function(passOnly = false) {
if (kpxc.credentials.length === 0) {
@@ -1292,6 +1307,12 @@ kpxc.retrieveCredentialsCallback = async function(credentials) {
await kpxc.prepareCredentials();
}
+ // Update fill_attribute context menu if String Fields are available
+ const stringFieldsFound = credentials.some(e => e.stringFields && e.stringFields.length > 0);
+ if (stringFieldsFound) {
+ await sendMessage('update_context_menu', credentials);
+ }
+
// Retrieve submitted credentials if available
const creds = await sendMessage('page_get_submitted');
if (creds && creds.submitted) {
@@ -1761,6 +1782,9 @@ browser.runtime.onMessage.addListener(async function(req, sender) {
} else if (req.action === 'fill_totp') {
await kpxc.receiveCredentialsIfNecessary();
kpxc.fillFromTOTP();
+ } else if (req.action === 'fill_attribute' && req.args) {
+ await kpxc.receiveCredentialsIfNecessary();
+ kpxc.fillAttributeToActiveElementWith(req.args);
} else if (req.action === 'ignore_site') {
kpxc.ignoreSite(req.args);
} else if (req.action === 'redetect_fields') {