Browse Source

Add new context menu item: Copy Custom Field Name (#2045)

* Add "Copy custom field name" context menu item

* Title case context menu string

* Improve Copy Custom Field Name logic

* Move CopyClickedElement to runtime.background

* Update dependencies

* Add comments, refactor logic, add failure messages

* Fix typo and linting

* Fix typos

* Move null check inside function
fix/chrome-macos-slowdown
Thomas Rittson 2 months ago
committed by GitHub
parent
commit
0bd22dcddc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/_locales/en/messages.json
  2. 11
      src/background/contextMenus.background.ts
  3. 8
      src/background/main.background.ts
  4. 2
      src/background/runtime.background.ts
  5. 45
      src/content/contextMenuHandler.ts
  6. 3
      src/manifest.json
  7. 1
      webpack.config.js

3
src/_locales/en/messages.json

@ -88,6 +88,9 @@
"generatePasswordCopied": {
"message": "Generate Password (copied)"
},
"copyElementIdentifier": {
"message": "Copy Custom Field Name"
},
"noMatchingLogins": {
"message": "No matching logins."
},

11
src/background/contextMenus.background.ts

@ -29,6 +29,8 @@ export default class ContextMenusBackground {
this.contextMenus.onClicked.addListener(async (info: any, tab: any) => {
if (info.menuItemId === 'generate-password') {
await this.generatePasswordToClipboard();
} else if (info.menuItemId === 'copy-identifier') {
await this.getClickedElement();
} else if (info.parentMenuItemId === 'autofill' ||
info.parentMenuItemId === 'copy-username' ||
info.parentMenuItemId === 'copy-password' ||
@ -45,6 +47,15 @@ export default class ContextMenusBackground {
this.passwordGenerationService.addHistory(password);
}
private async getClickedElement() {
const tab = await BrowserApi.getTabFromCurrentWindow();
if (tab == null) {
return;
}
BrowserApi.tabSendMessageData(tab, 'getClickedElement');
}
private async cipherAction(info: any) {
const id = info.menuItemId.split('_')[1];
if (id === 'noop') {

8
src/background/main.background.ts

@ -512,6 +512,14 @@ export default class MainBackground {
title: this.i18nService.t('generatePasswordCopied'),
});
await this.contextMenusCreate({
type: 'normal',
id: 'copy-identifier',
parentId: 'root',
contexts: ['all'],
title: this.i18nService.t('copyElementIdentifier'),
});
this.buildingContextMenu = false;
}

2
src/background/runtime.background.ts

@ -195,6 +195,8 @@ export default class RuntimeBackground {
type: 'info',
});
break;
case 'getClickedElementResponse':
this.platformUtilsService.copyToClipboard(msg.identifier, { window: window });
default:
break;
}

45
src/content/contextMenuHandler.ts

@ -0,0 +1,45 @@
const inputTags = ['input', 'textarea', 'select'];
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
let clickedEl: HTMLElement = null;
// Find the best attribute to be used as the Name for an element in a custom field.
function getClickedElementIdentifier() {
if (clickedEl == null) {
return 'Unable to identify clicked element.'
}
if (!inputTags.includes(clickedEl.nodeName.toLowerCase())) {
return 'Invalid element type.';
}
for (const attr of attributes) {
const attributeValue = clickedEl.getAttribute(attr);
const selector = '[' + attr + '="' + attributeValue + '"]';
if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) {
return attributeValue;
}
}
return 'No unique identifier found.';
}
function isNullOrEmpty(s: string) {
return s == null || s === '';
}
// We only have access to the element that's been clicked when the context menu is first opened.
// Remember it for use later.
document.addEventListener('contextmenu', event => {
clickedEl = event.target as HTMLElement;
});
// Runs when the 'Copy Custom Field Name' context menu item is actually clicked.
chrome.runtime.onMessage.addListener(event => {
if (event.command === 'getClickedElement') {
const identifier = getClickedElementIdentifier();
chrome.runtime.sendMessage({
command: 'getClickedElementResponse',
sender: 'contextMenuHandler',
identifier: identifier,
});
}
});

3
src/manifest.json

@ -20,7 +20,8 @@
"js": [
"content/autofill.js",
"content/autofiller.js",
"content/notificationBar.js"
"content/notificationBar.js",
"content/contextMenuHandler.js"
],
"matches": [
"http://*/*",

1
webpack.config.js

@ -130,6 +130,7 @@ const config = {
'content/autofill': './src/content/autofill.js',
'content/autofiller': './src/content/autofiller.ts',
'content/notificationBar': './src/content/notificationBar.ts',
'content/contextMenuHandler': './src/content/contextMenuHandler.ts',
'content/shortcuts': './src/content/shortcuts.ts',
'content/message_handler': './src/content/message_handler.ts',
'notification/bar': './src/notification/bar.js',

Loading…
Cancel
Save