Fix Copy Custom Field Name on pages with iframes (#2091)

* Improve error messages

* Send getClickedElement msg to specific frameId

* Add support for finding input element from label

* Use i18n for error messages

* Fix unrelated linting
This commit is contained in:
Thomas Rittson 2021-10-07 09:52:33 +10:00 committed by GitHub
parent bbcbcf2b40
commit cffd4b3515
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 9 deletions

View File

@ -1807,5 +1807,11 @@
},
"personalVaultExportPolicyInEffect": {
"message": "One or more organization policies prevents you from exporting your personal vault."
},
"copyCustomFieldNameInvalidElement": {
"message": "Unable to identify a valid form element. Try inspecting the HTML instead."
},
"copyCustomFieldNameNotUnique": {
"message": "No unique identifier found."
}
}

View File

@ -30,7 +30,7 @@ export default class ContextMenusBackground {
if (info.menuItemId === 'generate-password') {
await this.generatePasswordToClipboard();
} else if (info.menuItemId === 'copy-identifier') {
await this.getClickedElement();
await this.getClickedElement(info.frameId);
} else if (info.parentMenuItemId === 'autofill' ||
info.parentMenuItemId === 'copy-username' ||
info.parentMenuItemId === 'copy-password' ||
@ -47,13 +47,13 @@ export default class ContextMenusBackground {
this.passwordGenerationService.addHistory(password);
}
private async getClickedElement() {
private async getClickedElement(frameId: number) {
const tab = await BrowserApi.getTabFromCurrentWindow();
if (tab == null) {
return;
}
BrowserApi.tabSendMessageData(tab, 'getClickedElement');
BrowserApi.tabSendMessage(tab, { command: 'getClickedElement' }, { frameId: frameId });
}
private async cipherAction(info: any) {

View File

@ -1,25 +1,49 @@
const inputTags = ['input', 'textarea', 'select'];
const labelTags = ['label', 'span'];
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
const invalidElement = chrome.i18n.getMessage('copyCustomFieldNameInvalidElement');
const noUniqueIdentifier = chrome.i18n.getMessage('copyCustomFieldNameNotUnique');
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.';
return invalidElement;
}
if (!inputTags.includes(clickedEl.nodeName.toLowerCase())) {
return 'Invalid element type.';
const tagName = clickedEl.nodeName.toLowerCase();
let inputEl = null;
// Try to identify the input element (which may not be the clicked element)
if (inputTags.includes(tagName)) {
inputEl = clickedEl;
} else if (labelTags.includes(tagName)) {
let inputName = null;
if (tagName === 'label') {
inputName = clickedEl.getAttribute('for');
} else {
inputName = clickedEl.closest('label')?.getAttribute('for');
}
if (inputName != null) {
inputEl = document.querySelector('input[name=' + inputName + '], select[name=' + inputName +
'], textarea[name=' + inputName + ']');
}
}
if (inputEl == null) {
return invalidElement;
}
for (const attr of attributes) {
const attributeValue = clickedEl.getAttribute(attr);
const attributeValue = inputEl.getAttribute(attr);
const selector = '[' + attr + '="' + attributeValue + '"]';
if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) {
return attributeValue;
}
}
return 'No unique identifier found.';
return noUniqueIdentifier;
}
function isNullOrEmpty(s: string) {

View File

@ -62,6 +62,7 @@ import { StateService } from 'jslib-common/services/state.service';
import { PopupSearchService } from './popup-search.service';
import { PopupUtilsService } from './popup-utils.service';
import { ThemeType } from 'jslib-common/enums/themeType';
function getBgService<T>(service: string) {

View File

@ -3,6 +3,7 @@ import {
OnInit,
} from '@angular/core';
import { ThemeType } from 'jslib-common/enums/themeType';
import { UriMatchType } from 'jslib-common/enums/uriMatchType';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
@ -12,7 +13,6 @@ import { StorageService } from 'jslib-common/abstractions/storage.service';
import { TotpService } from 'jslib-common/abstractions/totp.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ThemeType } from 'jslib-common/enums/themeType';
@Component({
selector: 'app-options',