mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 17:23:37 +00:00
[PM-5189] Extracting the getAttributeBoolean method to a separate util method
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
|||||||
import { AutofillExtensionMessage } from "../content/abstractions/autofill-init";
|
import { AutofillExtensionMessage } from "../content/abstractions/autofill-init";
|
||||||
import AutofillField from "../models/autofill-field";
|
import AutofillField from "../models/autofill-field";
|
||||||
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
||||||
import { elementIsFillableFormField, sendExtensionMessage } from "../utils";
|
import { elementIsFillableFormField, getAttributeBoolean, sendExtensionMessage } from "../utils";
|
||||||
import { AutofillOverlayElement, RedirectFocusDirection } from "../utils/autofill-overlay.enum";
|
import { AutofillOverlayElement, RedirectFocusDirection } from "../utils/autofill-overlay.enum";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -708,6 +708,8 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
|||||||
const formFieldElement = event.target as ElementWithOpId<FormFieldElement>;
|
const formFieldElement = event.target as ElementWithOpId<FormFieldElement>;
|
||||||
const autofillFieldData = this.hiddenFormFieldElements.get(formFieldElement);
|
const autofillFieldData = this.hiddenFormFieldElements.get(formFieldElement);
|
||||||
if (autofillFieldData) {
|
if (autofillFieldData) {
|
||||||
|
autofillFieldData.readonly = getAttributeBoolean(formFieldElement, "disabled");
|
||||||
|
autofillFieldData.disabled = getAttributeBoolean(formFieldElement, "disabled");
|
||||||
autofillFieldData.viewable = true;
|
autofillFieldData.viewable = true;
|
||||||
void this.setupAutofillOverlayListenerOnField(formFieldElement, autofillFieldData);
|
void this.setupAutofillOverlayListenerOnField(formFieldElement, autofillFieldData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import AutofillField from "../models/autofill-field";
|
import AutofillField from "../models/autofill-field";
|
||||||
import AutofillForm from "../models/autofill-form";
|
import AutofillForm from "../models/autofill-form";
|
||||||
import AutofillPageDetails from "../models/autofill-page-details";
|
import AutofillPageDetails from "../models/autofill-page-details";
|
||||||
import {
|
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
||||||
ElementWithOpId,
|
|
||||||
FillableFormFieldElement,
|
|
||||||
FormFieldElement,
|
|
||||||
FormElementWithAttribute,
|
|
||||||
} from "../types";
|
|
||||||
import {
|
import {
|
||||||
elementIsDescriptionDetailsElement,
|
elementIsDescriptionDetailsElement,
|
||||||
elementIsDescriptionTermElement,
|
elementIsDescriptionTermElement,
|
||||||
@@ -19,6 +14,8 @@ import {
|
|||||||
nodeIsElement,
|
nodeIsElement,
|
||||||
elementIsInputElement,
|
elementIsInputElement,
|
||||||
elementIsTextAreaElement,
|
elementIsTextAreaElement,
|
||||||
|
getAttributeBoolean,
|
||||||
|
getPropertyOrAttribute,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
import { AutofillOverlayContentService } from "./abstractions/autofill-overlay-content.service";
|
import { AutofillOverlayContentService } from "./abstractions/autofill-overlay-content.service";
|
||||||
@@ -33,6 +30,8 @@ import { DomElementVisibilityService } from "./abstractions/dom-element-visibili
|
|||||||
class CollectAutofillContentService implements CollectAutofillContentServiceInterface {
|
class CollectAutofillContentService implements CollectAutofillContentServiceInterface {
|
||||||
private readonly domElementVisibilityService: DomElementVisibilityService;
|
private readonly domElementVisibilityService: DomElementVisibilityService;
|
||||||
private readonly autofillOverlayContentService: AutofillOverlayContentService;
|
private readonly autofillOverlayContentService: AutofillOverlayContentService;
|
||||||
|
private readonly getAttributeBoolean = getAttributeBoolean;
|
||||||
|
private readonly getPropertyOrAttribute = getPropertyOrAttribute;
|
||||||
private noFieldsFound = false;
|
private noFieldsFound = false;
|
||||||
private domRecentlyMutated = true;
|
private domRecentlyMutated = true;
|
||||||
private autofillFormElements: AutofillFormElements = new Map();
|
private autofillFormElements: AutofillFormElements = new Map();
|
||||||
@@ -467,26 +466,6 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
|||||||
return autoCompleteType !== "off" ? autoCompleteType : null;
|
return autoCompleteType !== "off" ? autoCompleteType : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a boolean representing the attribute value of an element.
|
|
||||||
* @param {ElementWithOpId<FormFieldElement>} element
|
|
||||||
* @param {string} attributeName
|
|
||||||
* @param {boolean} checkString
|
|
||||||
* @returns {boolean}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private getAttributeBoolean(
|
|
||||||
element: ElementWithOpId<FormFieldElement>,
|
|
||||||
attributeName: string,
|
|
||||||
checkString = false,
|
|
||||||
): boolean {
|
|
||||||
if (checkString) {
|
|
||||||
return this.getPropertyOrAttribute(element, attributeName) === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Boolean(this.getPropertyOrAttribute(element, attributeName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the attribute of an element as a lowercase value.
|
* Returns the attribute of an element as a lowercase value.
|
||||||
* @param {ElementWithOpId<FormFieldElement>} element
|
* @param {ElementWithOpId<FormFieldElement>} element
|
||||||
@@ -798,21 +777,6 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
|||||||
return this.recursivelyGetTextFromPreviousSiblings(siblingElement);
|
return this.recursivelyGetTextFromPreviousSiblings(siblingElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of a property or attribute from a FormFieldElement.
|
|
||||||
* @param {HTMLElement} element
|
|
||||||
* @param {string} attributeName
|
|
||||||
* @returns {string | null}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private getPropertyOrAttribute(element: HTMLElement, attributeName: string): string | null {
|
|
||||||
if (attributeName in element) {
|
|
||||||
return (element as FormElementWithAttribute)[attributeName];
|
|
||||||
}
|
|
||||||
|
|
||||||
return element.getAttribute(attributeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the element. If the element is a checkbox, returns a checkmark if the
|
* Gets the value of the element. If the element is a checkbox, returns a checkmark if the
|
||||||
* checkbox is checked, or an empty string if it is not checked. If the element is a hidden
|
* checkbox is checked, or an empty string if it is not checked. If the element is a hidden
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AutofillPort } from "../enums/autofill-port.enums";
|
import { AutofillPort } from "../enums/autofill-port.enums";
|
||||||
import { FillableFormFieldElement, FormFieldElement } from "../types";
|
import { FillableFormFieldElement, FormElementWithAttribute, FormFieldElement } from "../types";
|
||||||
|
|
||||||
function generateRandomChars(length: number): string {
|
export function generateRandomChars(length: number): string {
|
||||||
const chars = "abcdefghijklmnopqrstuvwxyz";
|
const chars = "abcdefghijklmnopqrstuvwxyz";
|
||||||
const randomChars = [];
|
const randomChars = [];
|
||||||
const randomBytes = new Uint8Array(length);
|
const randomBytes = new Uint8Array(length);
|
||||||
@@ -18,7 +18,7 @@ function generateRandomChars(length: number): string {
|
|||||||
/**
|
/**
|
||||||
* Generates a random string of characters that formatted as a custom element name.
|
* Generates a random string of characters that formatted as a custom element name.
|
||||||
*/
|
*/
|
||||||
function generateRandomCustomElementName(): string {
|
export function generateRandomCustomElementName(): string {
|
||||||
const length = Math.floor(Math.random() * 5) + 8; // Between 8 and 12 characters
|
const length = Math.floor(Math.random() * 5) + 8; // Between 8 and 12 characters
|
||||||
const numHyphens = Math.min(Math.max(Math.floor(Math.random() * 4), 1), length - 1); // At least 1, maximum of 3 hyphens
|
const numHyphens = Math.min(Math.max(Math.floor(Math.random() * 4), 1), length - 1); // At least 1, maximum of 3 hyphens
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ function generateRandomCustomElementName(): string {
|
|||||||
* @param svgString - The SVG string to build the DOM element from.
|
* @param svgString - The SVG string to build the DOM element from.
|
||||||
* @param ariaHidden - Determines whether the SVG should be hidden from screen readers.
|
* @param ariaHidden - Determines whether the SVG should be hidden from screen readers.
|
||||||
*/
|
*/
|
||||||
function buildSvgDomElement(svgString: string, ariaHidden = true): HTMLElement {
|
export function buildSvgDomElement(svgString: string, ariaHidden = true): HTMLElement {
|
||||||
const domParser = new DOMParser();
|
const domParser = new DOMParser();
|
||||||
const svgDom = domParser.parseFromString(svgString, "image/svg+xml");
|
const svgDom = domParser.parseFromString(svgString, "image/svg+xml");
|
||||||
const domElement = svgDom.documentElement;
|
const domElement = svgDom.documentElement;
|
||||||
@@ -66,7 +66,7 @@ function buildSvgDomElement(svgString: string, ariaHidden = true): HTMLElement {
|
|||||||
* @param command - The command to send.
|
* @param command - The command to send.
|
||||||
* @param options - The options to send with the command.
|
* @param options - The options to send with the command.
|
||||||
*/
|
*/
|
||||||
async function sendExtensionMessage(
|
export async function sendExtensionMessage(
|
||||||
command: string,
|
command: string,
|
||||||
options: Record<string, any> = {},
|
options: Record<string, any> = {},
|
||||||
): Promise<any | void> {
|
): Promise<any | void> {
|
||||||
@@ -88,7 +88,7 @@ async function sendExtensionMessage(
|
|||||||
* @param styles - The styles to set on the element.
|
* @param styles - The styles to set on the element.
|
||||||
* @param priority - Determines whether the styles should be set as important.
|
* @param priority - Determines whether the styles should be set as important.
|
||||||
*/
|
*/
|
||||||
function setElementStyles(
|
export function setElementStyles(
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
styles: Partial<CSSStyleDeclaration>,
|
styles: Partial<CSSStyleDeclaration>,
|
||||||
priority?: boolean,
|
priority?: boolean,
|
||||||
@@ -111,9 +111,9 @@ function setElementStyles(
|
|||||||
* and triggers an onDisconnect event if the extension context
|
* and triggers an onDisconnect event if the extension context
|
||||||
* is invalidated.
|
* is invalidated.
|
||||||
*
|
*
|
||||||
* @param callback - Callback function to run when the extension disconnects
|
* @param callback - Callback export function to run when the extension disconnects
|
||||||
*/
|
*/
|
||||||
function setupExtensionDisconnectAction(callback: (port: chrome.runtime.Port) => void) {
|
export function setupExtensionDisconnectAction(callback: (port: chrome.runtime.Port) => void) {
|
||||||
const port = chrome.runtime.connect({ name: AutofillPort.InjectedScript });
|
const port = chrome.runtime.connect({ name: AutofillPort.InjectedScript });
|
||||||
const onDisconnectCallback = (disconnectedPort: chrome.runtime.Port) => {
|
const onDisconnectCallback = (disconnectedPort: chrome.runtime.Port) => {
|
||||||
callback(disconnectedPort);
|
callback(disconnectedPort);
|
||||||
@@ -128,7 +128,7 @@ function setupExtensionDisconnectAction(callback: (port: chrome.runtime.Port) =>
|
|||||||
*
|
*
|
||||||
* @param windowContext - The global window context
|
* @param windowContext - The global window context
|
||||||
*/
|
*/
|
||||||
function setupAutofillInitDisconnectAction(windowContext: Window) {
|
export function setupAutofillInitDisconnectAction(windowContext: Window) {
|
||||||
if (!windowContext.bitwardenAutofillInit) {
|
if (!windowContext.bitwardenAutofillInit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ function setupAutofillInitDisconnectAction(windowContext: Window) {
|
|||||||
*
|
*
|
||||||
* @param formFieldElement - The form field element to check.
|
* @param formFieldElement - The form field element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsFillableFormField(
|
export function elementIsFillableFormField(
|
||||||
formFieldElement: FormFieldElement,
|
formFieldElement: FormFieldElement,
|
||||||
): formFieldElement is FillableFormFieldElement {
|
): formFieldElement is FillableFormFieldElement {
|
||||||
return !elementIsSpanElement(formFieldElement);
|
return !elementIsSpanElement(formFieldElement);
|
||||||
@@ -158,7 +158,10 @@ function elementIsFillableFormField(
|
|||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
* @param tagName - The tag name to check against.
|
* @param tagName - The tag name to check against.
|
||||||
*/
|
*/
|
||||||
function elementIsInstanceOf<T extends Element>(element: Element, tagName: string): element is T {
|
export function elementIsInstanceOf<T extends Element>(
|
||||||
|
element: Element,
|
||||||
|
tagName: string,
|
||||||
|
): element is T {
|
||||||
return nodeIsElement(element) && element.tagName.toLowerCase() === tagName;
|
return nodeIsElement(element) && element.tagName.toLowerCase() === tagName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +170,7 @@ function elementIsInstanceOf<T extends Element>(element: Element, tagName: strin
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsSpanElement(element: Element): element is HTMLSpanElement {
|
export function elementIsSpanElement(element: Element): element is HTMLSpanElement {
|
||||||
return elementIsInstanceOf<HTMLSpanElement>(element, "span");
|
return elementIsInstanceOf<HTMLSpanElement>(element, "span");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +179,7 @@ function elementIsSpanElement(element: Element): element is HTMLSpanElement {
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsInputElement(element: Element): element is HTMLInputElement {
|
export function elementIsInputElement(element: Element): element is HTMLInputElement {
|
||||||
return elementIsInstanceOf<HTMLInputElement>(element, "input");
|
return elementIsInstanceOf<HTMLInputElement>(element, "input");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +188,7 @@ function elementIsInputElement(element: Element): element is HTMLInputElement {
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsSelectElement(element: Element): element is HTMLSelectElement {
|
export function elementIsSelectElement(element: Element): element is HTMLSelectElement {
|
||||||
return elementIsInstanceOf<HTMLSelectElement>(element, "select");
|
return elementIsInstanceOf<HTMLSelectElement>(element, "select");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +197,7 @@ function elementIsSelectElement(element: Element): element is HTMLSelectElement
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsTextAreaElement(element: Element): element is HTMLTextAreaElement {
|
export function elementIsTextAreaElement(element: Element): element is HTMLTextAreaElement {
|
||||||
return elementIsInstanceOf<HTMLTextAreaElement>(element, "textarea");
|
return elementIsInstanceOf<HTMLTextAreaElement>(element, "textarea");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +206,7 @@ function elementIsTextAreaElement(element: Element): element is HTMLTextAreaElem
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsFormElement(element: Element): element is HTMLFormElement {
|
export function elementIsFormElement(element: Element): element is HTMLFormElement {
|
||||||
return elementIsInstanceOf<HTMLFormElement>(element, "form");
|
return elementIsInstanceOf<HTMLFormElement>(element, "form");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +215,7 @@ function elementIsFormElement(element: Element): element is HTMLFormElement {
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsLabelElement(element: Element): element is HTMLLabelElement {
|
export function elementIsLabelElement(element: Element): element is HTMLLabelElement {
|
||||||
return elementIsInstanceOf<HTMLLabelElement>(element, "label");
|
return elementIsInstanceOf<HTMLLabelElement>(element, "label");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +224,7 @@ function elementIsLabelElement(element: Element): element is HTMLLabelElement {
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsDescriptionDetailsElement(element: Element): element is HTMLElement {
|
export function elementIsDescriptionDetailsElement(element: Element): element is HTMLElement {
|
||||||
return elementIsInstanceOf<HTMLElement>(element, "dd");
|
return elementIsInstanceOf<HTMLElement>(element, "dd");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +233,7 @@ function elementIsDescriptionDetailsElement(element: Element): element is HTMLEl
|
|||||||
*
|
*
|
||||||
* @param element - The element to check.
|
* @param element - The element to check.
|
||||||
*/
|
*/
|
||||||
function elementIsDescriptionTermElement(element: Element): element is HTMLElement {
|
export function elementIsDescriptionTermElement(element: Element): element is HTMLElement {
|
||||||
return elementIsInstanceOf<HTMLElement>(element, "dt");
|
return elementIsInstanceOf<HTMLElement>(element, "dt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +242,7 @@ function elementIsDescriptionTermElement(element: Element): element is HTMLEleme
|
|||||||
*
|
*
|
||||||
* @param node - The node to check.
|
* @param node - The node to check.
|
||||||
*/
|
*/
|
||||||
function nodeIsElement(node: Node): node is Element {
|
export function nodeIsElement(node: Node): node is Element {
|
||||||
return node?.nodeType === Node.ELEMENT_NODE;
|
return node?.nodeType === Node.ELEMENT_NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +251,7 @@ function nodeIsElement(node: Node): node is Element {
|
|||||||
*
|
*
|
||||||
* @param node - The node to check.
|
* @param node - The node to check.
|
||||||
*/
|
*/
|
||||||
function nodeIsInputElement(node: Node): node is HTMLInputElement {
|
export function nodeIsInputElement(node: Node): node is HTMLInputElement {
|
||||||
return nodeIsElement(node) && elementIsInputElement(node);
|
return nodeIsElement(node) && elementIsInputElement(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,29 +260,39 @@ function nodeIsInputElement(node: Node): node is HTMLInputElement {
|
|||||||
*
|
*
|
||||||
* @param node - The node to check.
|
* @param node - The node to check.
|
||||||
*/
|
*/
|
||||||
function nodeIsFormElement(node: Node): node is HTMLFormElement {
|
export function nodeIsFormElement(node: Node): node is HTMLFormElement {
|
||||||
return nodeIsElement(node) && elementIsFormElement(node);
|
return nodeIsElement(node) && elementIsFormElement(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
/**
|
||||||
generateRandomChars,
|
* Returns a boolean representing the attribute value of an element.
|
||||||
generateRandomCustomElementName,
|
*
|
||||||
buildSvgDomElement,
|
* @param element
|
||||||
sendExtensionMessage,
|
* @param attributeName
|
||||||
setElementStyles,
|
* @param checkString
|
||||||
setupExtensionDisconnectAction,
|
*/
|
||||||
setupAutofillInitDisconnectAction,
|
export function getAttributeBoolean(
|
||||||
elementIsFillableFormField,
|
element: HTMLElement,
|
||||||
elementIsInstanceOf,
|
attributeName: string,
|
||||||
elementIsSpanElement,
|
checkString = false,
|
||||||
elementIsInputElement,
|
): boolean {
|
||||||
elementIsSelectElement,
|
if (checkString) {
|
||||||
elementIsTextAreaElement,
|
return getPropertyOrAttribute(element, attributeName) === "true";
|
||||||
elementIsFormElement,
|
}
|
||||||
elementIsLabelElement,
|
|
||||||
elementIsDescriptionDetailsElement,
|
return Boolean(getPropertyOrAttribute(element, attributeName));
|
||||||
elementIsDescriptionTermElement,
|
}
|
||||||
nodeIsElement,
|
|
||||||
nodeIsInputElement,
|
/**
|
||||||
nodeIsFormElement,
|
* Get the value of a property or attribute from a FormFieldElement.
|
||||||
};
|
*
|
||||||
|
* @param element
|
||||||
|
* @param attributeName
|
||||||
|
*/
|
||||||
|
export function getPropertyOrAttribute(element: HTMLElement, attributeName: string): string | null {
|
||||||
|
if (attributeName in element) {
|
||||||
|
return (element as FormElementWithAttribute)[attributeName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return element.getAttribute(attributeName);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user