1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-10-14 06:48:18 +02:00

[PM-13184] Filter out specific-nodes within TreeWalker query (#11415)

This commit is contained in:
Cesar Gonzalez 2024-10-09 18:14:39 -05:00 committed by GitHub
parent 1ca03e7815
commit 877dfeae7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -7,6 +7,27 @@ import { DomQueryService as DomQueryServiceInterface } from "./abstractions/dom-
export class DomQueryService implements DomQueryServiceInterface { export class DomQueryService implements DomQueryServiceInterface {
private pageContainsShadowDom: boolean; private pageContainsShadowDom: boolean;
private useTreeWalkerStrategyFlagSet = true; private useTreeWalkerStrategyFlagSet = true;
private ignoredTreeWalkerNodes = new Set([
"svg",
"script",
"noscript",
"head",
"style",
"link",
"meta",
"title",
"base",
"img",
"picture",
"video",
"audio",
"object",
"source",
"track",
"param",
"map",
"area",
]);
constructor() { constructor() {
void this.init(); void this.init();
@ -21,6 +42,7 @@ export class DomQueryService implements DomQueryServiceInterface {
* @param treeWalkerFilter - The filter callback to use for the treeWalker query * @param treeWalkerFilter - The filter callback to use for the treeWalker query
* @param mutationObserver - The MutationObserver to use for observing shadow roots * @param mutationObserver - The MutationObserver to use for observing shadow roots
* @param forceDeepQueryAttempt - Whether to force a deep query attempt * @param forceDeepQueryAttempt - Whether to force a deep query attempt
* @param ignoredTreeWalkerNodesOverride - An optional set of node names to ignore when using the treeWalker strategy
*/ */
query<T>( query<T>(
root: Document | ShadowRoot | Element, root: Document | ShadowRoot | Element,
@ -28,15 +50,28 @@ export class DomQueryService implements DomQueryServiceInterface {
treeWalkerFilter: CallableFunction, treeWalkerFilter: CallableFunction,
mutationObserver?: MutationObserver, mutationObserver?: MutationObserver,
forceDeepQueryAttempt?: boolean, forceDeepQueryAttempt?: boolean,
ignoredTreeWalkerNodesOverride?: Set<string>,
): T[] { ): T[] {
const ignoredTreeWalkerNodes = ignoredTreeWalkerNodesOverride || this.ignoredTreeWalkerNodes;
if (!forceDeepQueryAttempt && this.pageContainsShadowDomElements()) { if (!forceDeepQueryAttempt && this.pageContainsShadowDomElements()) {
return this.queryAllTreeWalkerNodes<T>(root, treeWalkerFilter, mutationObserver); return this.queryAllTreeWalkerNodes<T>(
root,
treeWalkerFilter,
ignoredTreeWalkerNodes,
mutationObserver,
);
} }
try { try {
return this.deepQueryElements<T>(root, queryString, mutationObserver); return this.deepQueryElements<T>(root, queryString, mutationObserver);
} catch { } catch {
return this.queryAllTreeWalkerNodes<T>(root, treeWalkerFilter, mutationObserver); return this.queryAllTreeWalkerNodes<T>(
root,
treeWalkerFilter,
ignoredTreeWalkerNodes,
mutationObserver,
);
} }
} }
@ -207,11 +242,13 @@ export class DomQueryService implements DomQueryServiceInterface {
* and returns a collection of nodes. * and returns a collection of nodes.
* @param rootNode * @param rootNode
* @param filterCallback * @param filterCallback
* @param ignoredTreeWalkerNodes
* @param mutationObserver * @param mutationObserver
*/ */
private queryAllTreeWalkerNodes<T>( private queryAllTreeWalkerNodes<T>(
rootNode: Node, rootNode: Node,
filterCallback: CallableFunction, filterCallback: CallableFunction,
ignoredTreeWalkerNodes: Set<string>,
mutationObserver?: MutationObserver, mutationObserver?: MutationObserver,
): T[] { ): T[] {
const treeWalkerQueryResults: T[] = []; const treeWalkerQueryResults: T[] = [];
@ -220,6 +257,7 @@ export class DomQueryService implements DomQueryServiceInterface {
rootNode, rootNode,
treeWalkerQueryResults, treeWalkerQueryResults,
filterCallback, filterCallback,
ignoredTreeWalkerNodes,
mutationObserver, mutationObserver,
); );
@ -233,15 +271,21 @@ export class DomQueryService implements DomQueryServiceInterface {
* @param rootNode * @param rootNode
* @param treeWalkerQueryResults * @param treeWalkerQueryResults
* @param filterCallback * @param filterCallback
* @param ignoredTreeWalkerNodes
* @param mutationObserver * @param mutationObserver
*/ */
private buildTreeWalkerNodesQueryResults<T>( private buildTreeWalkerNodesQueryResults<T>(
rootNode: Node, rootNode: Node,
treeWalkerQueryResults: T[], treeWalkerQueryResults: T[],
filterCallback: CallableFunction, filterCallback: CallableFunction,
ignoredTreeWalkerNodes: Set<string>,
mutationObserver?: MutationObserver, mutationObserver?: MutationObserver,
) { ) {
const treeWalker = document?.createTreeWalker(rootNode, NodeFilter.SHOW_ELEMENT); const treeWalker = document?.createTreeWalker(rootNode, NodeFilter.SHOW_ELEMENT, (node) =>
ignoredTreeWalkerNodes.has(node.nodeName?.toLowerCase())
? NodeFilter.FILTER_REJECT
: NodeFilter.FILTER_ACCEPT,
);
let currentNode = treeWalker?.currentNode; let currentNode = treeWalker?.currentNode;
while (currentNode) { while (currentNode) {
@ -263,6 +307,7 @@ export class DomQueryService implements DomQueryServiceInterface {
nodeShadowRoot, nodeShadowRoot,
treeWalkerQueryResults, treeWalkerQueryResults,
filterCallback, filterCallback,
ignoredTreeWalkerNodes,
mutationObserver, mutationObserver,
); );
} }