Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 46 additions & 29 deletions firefox-ios/Client/Assets/CC_Script/FormLikeFactory.sys.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,42 +37,28 @@ export let FormLikeFactory = {
},

/**
* Create a FormLike object from an <input>/<select> in a document.
*
* If the field is in a <form>, construct the FormLike from the form.
* Otherwise, create a FormLike with a rootElement (wrapper) according to
* heuristics. Currently all <input>/<select> not in a <form> are one FormLike
* but this shouldn't be relied upon as the heuristics may change to detect
* multiple "forms" (e.g. registration and login) on one page with a <form>.
* Create a FormLike object from an HTMLHtmlElement that is the root of the document
*
* Note that two FormLikes created from the same field won't return the same FormLike object.
* Use the `rootElement` property on the FormLike as a key instead.
* Currently all <input> not in a <form> are one LoginForm but this
* shouldn't be relied upon as the heuristics may change to detect multiple
* "forms" (e.g. registration and login) on one page with a <form>.
*
* @param {HTMLInputElement|HTMLSelectElement} aField - an <input> or <select> field in a document
* @param {HTMLHtmlElement} aDocumentRoot
* @return {FormLike}
* @throws Error if aField isn't a password or username field in a document
* @throws Error if aDocumentRoot isn't an HTMLHtmlElement
*/
createFromField(aField) {
if (
(!HTMLInputElement.isInstance(aField) &&
!HTMLSelectElement.isInstance(aField)) ||
!aField.ownerDocument
) {
throw new Error("createFromField requires a field in a document");
createFromDocumentRoot(aDocumentRoot) {
if (!HTMLHtmlElement.isInstance(aDocumentRoot)) {
throw new Error(
"createFromDocumentRoot: aDocumentRoot must be an HTMLHtmlElement"
);
}

let rootElement = this.findRootForField(aField);
if (HTMLFormElement.isInstance(rootElement)) {
return this.createFromForm(rootElement);
}

let doc = aField.ownerDocument;

let formLike = {
action: doc.baseURI,
action: aDocumentRoot.baseURI,
autocomplete: "on",
ownerDocument: doc,
rootElement,
ownerDocument: aDocumentRoot.ownerDocument,
rootElement: aDocumentRoot,
};

// FormLikes can be created when fields are inserted into the DOM. When
Expand All @@ -82,7 +68,7 @@ export let FormLikeFactory = {
// be computed when it's eventually needed (if ever).
ChromeUtils.defineLazyGetter(formLike, "elements", function () {
let elements = [];
for (let el of this.rootElement.querySelectorAll("input, select")) {
for (let el of aDocumentRoot.querySelectorAll("input, select")) {
// Exclude elements inside the rootElement that are already in a <form> as
// they will be handled by their own FormLike.
if (!el.form) {
Expand All @@ -97,6 +83,37 @@ export let FormLikeFactory = {
return formLike;
},

/**
* Create a FormLike object from an <input>/<select> in a document.
*
* If the field is in a <form>, construct the FormLike from the form.
* Otherwise, create a FormLike with a rootElement (wrapper) according to
* heuristics. Currently all <input>/<select> not in a <form> are one FormLike
* but this shouldn't be relied upon as the heuristics may change to detect
* multiple "forms" (e.g. registration and login) on one page with a <form>.
*
* Note that two FormLikes created from the same field won't return the same FormLike object.
* Use the `rootElement` property on the FormLike as a key instead.
*
* @param {HTMLInputElement|HTMLSelectElement} aField - an <input> or <select> field in a document
* @return {FormLike}
* @throws Error if aField isn't a password or username field in a document
*/
createFromField(aField) {
if (
(!HTMLInputElement.isInstance(aField) &&
!HTMLSelectElement.isInstance(aField)) ||
!aField.ownerDocument
) {
throw new Error("createFromField requires a field in a document");
}

const rootElement = this.findRootForField(aField);
return HTMLFormElement.isInstance(rootElement)
? this.createFromForm(rootElement)
: this.createFromDocumentRoot(rootElement);
},

/**
* Find the closest <form> if any when aField is inside a ShadowRoot.
*
Expand Down
1 change: 1 addition & 0 deletions firefox-ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,4 @@ To create a production build of the User Scripts run the following `npm` command
```shell
npm run build
```