mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 09:13:33 +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 AutofillField from "../models/autofill-field";
|
||||
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 {
|
||||
@@ -708,6 +708,8 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
||||
const formFieldElement = event.target as ElementWithOpId<FormFieldElement>;
|
||||
const autofillFieldData = this.hiddenFormFieldElements.get(formFieldElement);
|
||||
if (autofillFieldData) {
|
||||
autofillFieldData.readonly = getAttributeBoolean(formFieldElement, "disabled");
|
||||
autofillFieldData.disabled = getAttributeBoolean(formFieldElement, "disabled");
|
||||
autofillFieldData.viewable = true;
|
||||
void this.setupAutofillOverlayListenerOnField(formFieldElement, autofillFieldData);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import AutofillField from "../models/autofill-field";
|
||||
import AutofillForm from "../models/autofill-form";
|
||||
import AutofillPageDetails from "../models/autofill-page-details";
|
||||
import {
|
||||
ElementWithOpId,
|
||||
FillableFormFieldElement,
|
||||
FormFieldElement,
|
||||
FormElementWithAttribute,
|
||||
} from "../types";
|
||||
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
||||
import {
|
||||
elementIsDescriptionDetailsElement,
|
||||
elementIsDescriptionTermElement,
|
||||
@@ -19,6 +14,8 @@ import {
|
||||
nodeIsElement,
|
||||
elementIsInputElement,
|
||||
elementIsTextAreaElement,
|
||||
getAttributeBoolean,
|
||||
getPropertyOrAttribute,
|
||||
} from "../utils";
|
||||
|
||||
import { AutofillOverlayContentService } from "./abstractions/autofill-overlay-content.service";
|
||||
@@ -33,6 +30,8 @@ import { DomElementVisibilityService } from "./abstractions/dom-element-visibili
|
||||
class CollectAutofillContentService implements CollectAutofillContentServiceInterface {
|
||||
private readonly domElementVisibilityService: DomElementVisibilityService;
|
||||
private readonly autofillOverlayContentService: AutofillOverlayContentService;
|
||||
private readonly getAttributeBoolean = getAttributeBoolean;
|
||||
private readonly getPropertyOrAttribute = getPropertyOrAttribute;
|
||||
private noFieldsFound = false;
|
||||
private domRecentlyMutated = true;
|
||||
private autofillFormElements: AutofillFormElements = new Map();
|
||||
@@ -467,26 +466,6 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
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.
|
||||
* @param {ElementWithOpId<FormFieldElement>} element
|
||||
@@ -798,21 +777,6 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
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
|
||||
* 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 { 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 randomChars = [];
|
||||
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.
|
||||
*/
|
||||
function generateRandomCustomElementName(): string {
|
||||
export function generateRandomCustomElementName(): string {
|
||||
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
|
||||
|
||||
@@ -51,7 +51,7 @@ function generateRandomCustomElementName(): string {
|
||||
* @param svgString - The SVG string to build the DOM element from.
|
||||
* @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 svgDom = domParser.parseFromString(svgString, "image/svg+xml");
|
||||
const domElement = svgDom.documentElement;
|
||||
@@ -66,7 +66,7 @@ function buildSvgDomElement(svgString: string, ariaHidden = true): HTMLElement {
|
||||
* @param command - The command to send.
|
||||
* @param options - The options to send with the command.
|
||||
*/
|
||||
async function sendExtensionMessage(
|
||||
export async function sendExtensionMessage(
|
||||
command: string,
|
||||
options: Record<string, any> = {},
|
||||
): Promise<any | void> {
|
||||
@@ -88,7 +88,7 @@ async function sendExtensionMessage(
|
||||
* @param styles - The styles to set on the element.
|
||||
* @param priority - Determines whether the styles should be set as important.
|
||||
*/
|
||||
function setElementStyles(
|
||||
export function setElementStyles(
|
||||
element: HTMLElement,
|
||||
styles: Partial<CSSStyleDeclaration>,
|
||||
priority?: boolean,
|
||||
@@ -111,9 +111,9 @@ function setElementStyles(
|
||||
* and triggers an onDisconnect event if the extension context
|
||||
* 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 onDisconnectCallback = (disconnectedPort: chrome.runtime.Port) => {
|
||||
callback(disconnectedPort);
|
||||
@@ -128,7 +128,7 @@ function setupExtensionDisconnectAction(callback: (port: chrome.runtime.Port) =>
|
||||
*
|
||||
* @param windowContext - The global window context
|
||||
*/
|
||||
function setupAutofillInitDisconnectAction(windowContext: Window) {
|
||||
export function setupAutofillInitDisconnectAction(windowContext: Window) {
|
||||
if (!windowContext.bitwardenAutofillInit) {
|
||||
return;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ function setupAutofillInitDisconnectAction(windowContext: Window) {
|
||||
*
|
||||
* @param formFieldElement - The form field element to check.
|
||||
*/
|
||||
function elementIsFillableFormField(
|
||||
export function elementIsFillableFormField(
|
||||
formFieldElement: FormFieldElement,
|
||||
): formFieldElement is FillableFormFieldElement {
|
||||
return !elementIsSpanElement(formFieldElement);
|
||||
@@ -158,7 +158,10 @@ function elementIsFillableFormField(
|
||||
* @param element - The element to check.
|
||||
* @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;
|
||||
}
|
||||
|
||||
@@ -167,7 +170,7 @@ function elementIsInstanceOf<T extends Element>(element: Element, tagName: strin
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -176,7 +179,7 @@ function elementIsSpanElement(element: Element): element is HTMLSpanElement {
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -185,7 +188,7 @@ function elementIsInputElement(element: Element): element is HTMLInputElement {
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -194,7 +197,7 @@ function elementIsSelectElement(element: Element): element is HTMLSelectElement
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -203,7 +206,7 @@ function elementIsTextAreaElement(element: Element): element is HTMLTextAreaElem
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -212,7 +215,7 @@ function elementIsFormElement(element: Element): element is HTMLFormElement {
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -221,7 +224,7 @@ function elementIsLabelElement(element: Element): element is HTMLLabelElement {
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -230,7 +233,7 @@ function elementIsDescriptionDetailsElement(element: Element): element is HTMLEl
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
@@ -239,7 +242,7 @@ function elementIsDescriptionTermElement(element: Element): element is HTMLEleme
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
@@ -248,7 +251,7 @@ function nodeIsElement(node: Node): node is Element {
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
@@ -257,29 +260,39 @@ function nodeIsInputElement(node: Node): node is HTMLInputElement {
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
export {
|
||||
generateRandomChars,
|
||||
generateRandomCustomElementName,
|
||||
buildSvgDomElement,
|
||||
sendExtensionMessage,
|
||||
setElementStyles,
|
||||
setupExtensionDisconnectAction,
|
||||
setupAutofillInitDisconnectAction,
|
||||
elementIsFillableFormField,
|
||||
elementIsInstanceOf,
|
||||
elementIsSpanElement,
|
||||
elementIsInputElement,
|
||||
elementIsSelectElement,
|
||||
elementIsTextAreaElement,
|
||||
elementIsFormElement,
|
||||
elementIsLabelElement,
|
||||
elementIsDescriptionDetailsElement,
|
||||
elementIsDescriptionTermElement,
|
||||
nodeIsElement,
|
||||
nodeIsInputElement,
|
||||
nodeIsFormElement,
|
||||
};
|
||||
/**
|
||||
* Returns a boolean representing the attribute value of an element.
|
||||
*
|
||||
* @param element
|
||||
* @param attributeName
|
||||
* @param checkString
|
||||
*/
|
||||
export function getAttributeBoolean(
|
||||
element: HTMLElement,
|
||||
attributeName: string,
|
||||
checkString = false,
|
||||
): boolean {
|
||||
if (checkString) {
|
||||
return getPropertyOrAttribute(element, attributeName) === "true";
|
||||
}
|
||||
|
||||
return Boolean(getPropertyOrAttribute(element, attributeName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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