1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_HTMLFormElement_h
8 #define mozilla_dom_HTMLFormElement_h
9 
10 #include "mozilla/AsyncEventDispatcher.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/UniquePtr.h"
13 #include "mozilla/dom/BrowsingContext.h"
14 #include "mozilla/dom/PopupBlocker.h"
15 #include "mozilla/dom/RadioGroupManager.h"
16 #include "nsCOMPtr.h"
17 #include "nsIFormControl.h"
18 #include "nsGenericHTMLElement.h"
19 #include "nsIRadioGroupContainer.h"
20 #include "nsIWeakReferenceUtils.h"
21 #include "nsThreadUtils.h"
22 #include "nsInterfaceHashtable.h"
23 #include "nsRefPtrHashtable.h"
24 #include "nsTHashMap.h"
25 #include "js/friend/DOMProxy.h"  // JS::ExpandoAndGeneration
26 
27 class nsIMutableArray;
28 class nsIURI;
29 
30 namespace mozilla {
31 class EventChainPostVisitor;
32 class EventChainPreVisitor;
33 namespace dom {
34 class DialogFormSubmission;
35 class HTMLFormControlsCollection;
36 class HTMLFormSubmission;
37 class HTMLImageElement;
38 class FormData;
39 
40 class HTMLFormElement final : public nsGenericHTMLElement,
41                               public nsIRadioGroupContainer,
42                               RadioGroupManager {
43   friend class HTMLFormControlsCollection;
44 
45  public:
46   NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLFormElement, form)
47 
48   explicit HTMLFormElement(
49       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
50 
51   enum { FORM_CONTROL_LIST_HASHTABLE_LENGTH = 8 };
52 
53   // nsISupports
54   NS_DECL_ISUPPORTS_INHERITED
55 
56   int32_t IndexOfContent(nsIContent* aContent);
57   nsGenericHTMLFormElement* GetDefaultSubmitElement() const;
58 
59   // nsIRadioGroupContainer
60   void SetCurrentRadioButton(const nsAString& aName,
61                              HTMLInputElement* aRadio) override;
62   HTMLInputElement* GetCurrentRadioButton(const nsAString& aName) override;
63   NS_IMETHOD GetNextRadioButton(const nsAString& aName, const bool aPrevious,
64                                 HTMLInputElement* aFocusedRadio,
65                                 HTMLInputElement** aRadioOut) override;
66   NS_IMETHOD WalkRadioGroup(const nsAString& aName,
67                             nsIRadioVisitor* aVisitor) override;
68   void AddToRadioGroup(const nsAString& aName,
69                        HTMLInputElement* aRadio) override;
70   void RemoveFromRadioGroup(const nsAString& aName,
71                             HTMLInputElement* aRadio) override;
72   virtual uint32_t GetRequiredRadioCount(const nsAString& aName) const override;
73   virtual void RadioRequiredWillChange(const nsAString& aName,
74                                        bool aRequiredAdded) override;
75   virtual bool GetValueMissingState(const nsAString& aName) const override;
76   virtual void SetValueMissingState(const nsAString& aName,
77                                     bool aValue) override;
78 
79   virtual EventStates IntrinsicState() const override;
80 
81   // EventTarget
82   virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
83 
84   // nsIContent
85   virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
86                               const nsAString& aValue,
87                               nsIPrincipal* aMaybeScriptedPrincipal,
88                               nsAttrValue& aResult) override;
89   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
90   void WillHandleEvent(EventChainPostVisitor& aVisitor) override;
91   virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
92 
93   virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
94   virtual void UnbindFromTree(bool aNullParent = true) override;
95   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
96                                  const nsAttrValueOrString* aValue,
97                                  bool aNotify) override;
98 
99   /**
100    * Forget all information about the current submission (and the fact that we
101    * are currently submitting at all).
102    */
103   void ForgetCurrentSubmission();
104 
105   virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
106 
107   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLFormElement,
108                                            nsGenericHTMLElement)
109 
110   /**
111    * Remove an element from this form's list of elements
112    *
113    * @param aElement the element to remove
114    * @param aUpdateValidity If true, updates the form validity.
115    * @return NS_OK if the element was successfully removed.
116    */
117   nsresult RemoveElement(nsGenericHTMLFormElement* aElement,
118                          bool aUpdateValidity);
119 
120   /**
121    * Remove an element from the lookup table maintained by the form.
122    * We can't fold this method into RemoveElement() because when
123    * RemoveElement() is called it doesn't know if the element is
124    * removed because the id attribute has changed, or because the
125    * name attribute has changed.
126    *
127    * @param aElement the element to remove
128    * @param aName the name or id of the element to remove
129    * @return NS_OK if the element was successfully removed.
130    */
131   nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
132                                   const nsAString& aName);
133 
134   /**
135    * Add an element to end of this form's list of elements
136    *
137    * @param aElement the element to add
138    * @param aUpdateValidity If true, the form validity will be updated.
139    * @param aNotify If true, send DocumentObserver notifications as needed.
140    * @return NS_OK if the element was successfully added
141    */
142   nsresult AddElement(nsGenericHTMLFormElement* aElement, bool aUpdateValidity,
143                       bool aNotify);
144 
145   /**
146    * Add an element to the lookup table maintained by the form.
147    *
148    * We can't fold this method into AddElement() because when
149    * AddElement() is called, the form control has no
150    * attributes.  The name or id attributes of the form control
151    * are used as a key into the table.
152    */
153   nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
154                              const nsAString& aName);
155 
156   /**
157    * Remove an image element from this form's list of image elements
158    *
159    * @param aElement the image element to remove
160    * @return NS_OK if the element was successfully removed.
161    */
162   nsresult RemoveImageElement(HTMLImageElement* aElement);
163 
164   /**
165    * Remove an image element from the lookup table maintained by the form.
166    * We can't fold this method into RemoveImageElement() because when
167    * RemoveImageElement() is called it doesn't know if the element is
168    * removed because the id attribute has changed, or because the
169    * name attribute has changed.
170    *
171    * @param aElement the image element to remove
172    * @param aName the name or id of the element to remove
173    * @return NS_OK if the element was successfully removed.
174    */
175   nsresult RemoveImageElementFromTable(HTMLImageElement* aElement,
176                                        const nsAString& aName);
177   /**
178    * Add an image element to the end of this form's list of image elements
179    *
180    * @param aElement the element to add
181    * @return NS_OK if the element was successfully added
182    */
183   nsresult AddImageElement(HTMLImageElement* aElement);
184 
185   /**
186    * Add an image element to the lookup table maintained by the form.
187    *
188    * We can't fold this method into AddImageElement() because when
189    * AddImageElement() is called, the image attributes can change.
190    * The name or id attributes of the image are used as a key into the table.
191    */
192   nsresult AddImageElementToTable(HTMLImageElement* aChild,
193                                   const nsAString& aName);
194 
195   /**
196    * Returns true if implicit submission of this form is disabled. For more
197    * on implicit submission see:
198    *
199    * http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#implicit-submission
200    */
201   bool ImplicitSubmissionIsDisabled() const;
202 
203   /**
204    * Check whether a given nsGenericHTMLFormElement is the last single line
205    * input control that is not disabled. aElement is expected to not be null.
206    */
207   bool IsLastActiveElement(const nsGenericHTMLFormElement* aElement) const;
208 
209   /**
210    * Check whether a given nsGenericHTMLFormElement is the default submit
211    * element.  This is different from just comparing to
212    * GetDefaultSubmitElement() in certain situations inside an update
213    * when GetDefaultSubmitElement() might not be up to date. aElement
214    * is expected to not be null.
215    */
216   bool IsDefaultSubmitElement(const nsGenericHTMLFormElement* aElement) const;
217 
218   /**
219    * Flag the form to know that a button or image triggered scripted form
220    * submission. In that case the form will defer the submission until the
221    * script handler returns and the return value is known.
222    */
223   void OnSubmitClickBegin(Element* aOriginatingElement);
224   void OnSubmitClickEnd();
225 
226   /**
227    * This method will update the form validity.
228    *
229    * This method has to be called by form elements whenever their validity state
230    * or status regarding constraint validation changes.
231    *
232    * @note This method isn't used for CheckValidity().
233    * @note If an element becomes barred from constraint validation, it has to be
234    * considered as valid.
235    *
236    * @param aElementValidityState the new validity state of the element
237    */
238   void UpdateValidity(bool aElementValidityState);
239 
240   /**
241    * This method check the form validity and make invalid form elements send
242    * invalid event if needed.
243    *
244    * @return Whether the form is valid.
245    *
246    * @note Do not call this method if novalidate/formnovalidate is used.
247    * @note This method might disappear with bug 592124, hopefuly.
248    * @see
249    * https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#interactively-validate-the-constraints
250    */
251   bool CheckValidFormSubmission();
252 
253   /**
254    * Contruct the entry list to get their data pumped into the FormData and
255    * fire a `formdata` event with the entry list in formData attribute.
256    * <https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#constructing-form-data-set>
257    *
258    * @param aFormData the form data object
259    */
260   // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
261   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult ConstructEntryList(FormData* aFormData);
262 
263   /**
264    * Whether the submission of this form has been ever prevented because of
265    * being invalid.
266    *
267    * @return Whether the submission of this form has been prevented because of
268    * being invalid.
269    */
HasEverTriedInvalidSubmit()270   bool HasEverTriedInvalidSubmit() const { return mEverTriedInvalidSubmit; }
271 
272   /**
273    * Implements form[name]. Returns form controls in this form with the correct
274    * value of the name attribute.
275    */
276   already_AddRefed<nsISupports> FindNamedItem(const nsAString& aName,
277                                               nsWrapperCache** aCache);
278 
279   // WebIDL
280 
GetAcceptCharset(DOMString & aValue)281   void GetAcceptCharset(DOMString& aValue) {
282     GetHTMLAttr(nsGkAtoms::acceptcharset, aValue);
283   }
284 
SetAcceptCharset(const nsAString & aValue,ErrorResult & aRv)285   void SetAcceptCharset(const nsAString& aValue, ErrorResult& aRv) {
286     SetHTMLAttr(nsGkAtoms::acceptcharset, aValue, aRv);
287   }
288 
289   void GetAction(nsString& aValue);
SetAction(const nsAString & aValue,ErrorResult & aRv)290   void SetAction(const nsAString& aValue, ErrorResult& aRv) {
291     SetHTMLAttr(nsGkAtoms::action, aValue, aRv);
292   }
293 
294   void GetAutocomplete(nsAString& aValue);
SetAutocomplete(const nsAString & aValue,ErrorResult & aRv)295   void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv) {
296     SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
297   }
298 
299   void GetEnctype(nsAString& aValue);
SetEnctype(const nsAString & aValue,ErrorResult & aRv)300   void SetEnctype(const nsAString& aValue, ErrorResult& aRv) {
301     SetHTMLAttr(nsGkAtoms::enctype, aValue, aRv);
302   }
303 
GetEncoding(nsAString & aValue)304   void GetEncoding(nsAString& aValue) { GetEnctype(aValue); }
SetEncoding(const nsAString & aValue,ErrorResult & aRv)305   void SetEncoding(const nsAString& aValue, ErrorResult& aRv) {
306     SetEnctype(aValue, aRv);
307   }
308 
309   void GetMethod(nsAString& aValue);
SetMethod(const nsAString & aValue,ErrorResult & aRv)310   void SetMethod(const nsAString& aValue, ErrorResult& aRv) {
311     SetHTMLAttr(nsGkAtoms::method, aValue, aRv);
312   }
313 
GetName(DOMString & aValue)314   void GetName(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::name, aValue); }
315 
SetName(const nsAString & aValue,ErrorResult & aRv)316   void SetName(const nsAString& aValue, ErrorResult& aRv) {
317     SetHTMLAttr(nsGkAtoms::name, aValue, aRv);
318   }
319 
NoValidate()320   bool NoValidate() const { return GetBoolAttr(nsGkAtoms::novalidate); }
321 
SetNoValidate(bool aValue,ErrorResult & aRv)322   void SetNoValidate(bool aValue, ErrorResult& aRv) {
323     SetHTMLBoolAttr(nsGkAtoms::novalidate, aValue, aRv);
324   }
325 
GetTarget(DOMString & aValue)326   void GetTarget(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::target, aValue); }
327 
SetTarget(const nsAString & aValue,ErrorResult & aRv)328   void SetTarget(const nsAString& aValue, ErrorResult& aRv) {
329     SetHTMLAttr(nsGkAtoms::target, aValue, aRv);
330   }
331 
332   // it's only out-of-line because the class definition is not available in the
333   // header
334   nsIHTMLCollection* Elements();
335 
336   int32_t Length();
337 
338   /**
339    * Check whether submission can proceed for this form then fire submit event.
340    * This basically implements steps 1-6 (more or less) of
341    * <https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit>.
342    * @param aSubmitter If not null, is the "submitter" from that algorithm.
343    *                   Therefore it must be a valid submit control.
344    */
345   MOZ_CAN_RUN_SCRIPT void MaybeSubmit(Element* aSubmitter);
346   MOZ_CAN_RUN_SCRIPT void MaybeReset(Element* aSubmitter);
347   void Submit(ErrorResult& aRv);
348 
349   /**
350    * Requests to submit the form. Unlike submit(), this method includes
351    * interactive constraint validation and firing a submit event,
352    * either of which can cancel submission.
353    *
354    * @param aSubmitter The submitter argument can be used to point to a specific
355    *                   submit button.
356    * @param aRv        An ErrorResult.
357    * @see
358    * https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
359    */
360   MOZ_CAN_RUN_SCRIPT void RequestSubmit(nsGenericHTMLElement* aSubmitter,
361                                         ErrorResult& aRv);
362 
363   MOZ_CAN_RUN_SCRIPT void Reset();
364 
CheckValidity()365   bool CheckValidity() { return CheckFormValidity(nullptr); }
366 
ReportValidity()367   bool ReportValidity() { return CheckValidFormSubmission(); }
368 
369   Element* IndexedGetter(uint32_t aIndex, bool& aFound);
370 
371   already_AddRefed<nsISupports> NamedGetter(const nsAString& aName,
372                                             bool& aFound);
373 
374   void GetSupportedNames(nsTArray<nsString>& aRetval);
375 
376   static int32_t CompareFormControlPosition(Element* aElement1,
377                                             Element* aElement2,
378                                             const nsIContent* aForm);
379 #ifdef DEBUG
380   static void AssertDocumentOrder(
381       const nsTArray<nsGenericHTMLFormElement*>& aControls, nsIContent* aForm);
382   static void AssertDocumentOrder(
383       const nsTArray<RefPtr<nsGenericHTMLFormElement>>& aControls,
384       nsIContent* aForm);
385 #endif
386 
387   JS::ExpandoAndGeneration mExpandoAndGeneration;
388 
389  protected:
390   virtual JSObject* WrapNode(JSContext* aCx,
391                              JS::Handle<JSObject*> aGivenProto) override;
392 
393   void PostPasswordEvent();
394   void PostPossibleUsernameEvent();
395 
396   RefPtr<AsyncEventDispatcher> mFormPasswordEventDispatcher;
397   RefPtr<AsyncEventDispatcher> mFormPossibleUsernameEventDispatcher;
398 
399   class RemoveElementRunnable;
400   friend class RemoveElementRunnable;
401 
402   class RemoveElementRunnable : public Runnable {
403    public:
RemoveElementRunnable(HTMLFormElement * aForm)404     explicit RemoveElementRunnable(HTMLFormElement* aForm)
405         : Runnable("dom::HTMLFormElement::RemoveElementRunnable"),
406           mForm(aForm) {}
407 
Run()408     NS_IMETHOD Run() override {
409       mForm->HandleDefaultSubmitRemoval();
410       return NS_OK;
411     }
412 
413    private:
414     RefPtr<HTMLFormElement> mForm;
415   };
416 
417   nsresult DoReset();
418 
419   // Async callback to handle removal of our default submit
420   void HandleDefaultSubmitRemoval();
421 
422   //
423   // Submit Helpers
424   //
425   //
426   /**
427    * Attempt to submit (submission might be deferred)
428    *
429    * @param aPresContext the presentation context
430    * @param aEvent the DOM event that was passed to us for the submit
431    */
432   nsresult DoSubmit(Event* aEvent = nullptr);
433 
434   /**
435    * Prepare the submission object (called by DoSubmit)
436    *
437    * @param aFormSubmission the submission object
438    * @param aEvent the DOM event that was passed to us for the submit
439    */
440   nsresult BuildSubmission(HTMLFormSubmission** aFormSubmission, Event* aEvent);
441   /**
442    * Perform the submission (called by DoSubmit and FlushPendingSubmission)
443    *
444    * @param aFormSubmission the submission object
445    */
446   nsresult SubmitSubmission(HTMLFormSubmission* aFormSubmission);
447 
448   /**
449    * Submit a form[method=dialog]
450    * @param aFormSubmission the submission object
451    */
452   nsresult SubmitDialog(DialogFormSubmission* aFormSubmission);
453 
454   /**
455    * Notify any submit observers of the submit.
456    *
457    * @param aActionURL the URL being submitted to
458    * @param aCancelSubmit out param where submit observers can specify that the
459    *        submit should be cancelled.
460    */
461   nsresult NotifySubmitObservers(nsIURI* aActionURL, bool* aCancelSubmit,
462                                  bool aEarlyNotify);
463 
464   /**
465    * If this form submission is secure -> insecure, ask the user if they want
466    * to continue.
467    *
468    * @param aActionURL the URL being submitted to
469    * @param aCancelSubmit out param: will be true if the user wants to cancel
470    */
471   nsresult DoSecureToInsecureSubmitCheck(nsIURI* aActionURL,
472                                          bool* aCancelSubmit);
473 
474   /**
475    * Find form controls in this form with the correct value in the name
476    * attribute.
477    */
478   already_AddRefed<nsISupports> DoResolveName(const nsAString& aName);
479 
480   /**
481    * Check the form validity following this algorithm:
482    * https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#statically-validate-the-constraints
483    *
484    * @param aInvalidElements [out] parameter containing the list of unhandled
485    * invalid controls.
486    *
487    * @return Whether the form is currently valid.
488    */
489   bool CheckFormValidity(nsTArray<RefPtr<Element>>* aInvalidElements) const;
490 
491   // Clear the mImageNameLookupTable and mImageElements.
492   void Clear();
493 
494   // Insert a element into the past names map.
495   void AddToPastNamesMap(const nsAString& aName, nsISupports* aChild);
496 
497   // Remove the given element from the past names map.  The element must be an
498   // nsGenericHTMLFormElement or HTMLImageElement.
499   void RemoveElementFromPastNamesMap(Element* aElement);
500 
501   nsresult AddElementToTableInternal(
502       nsInterfaceHashtable<nsStringHashKey, nsISupports>& aTable,
503       nsIContent* aChild, const nsAString& aName);
504 
505   nsresult RemoveElementFromTableInternal(
506       nsInterfaceHashtable<nsStringHashKey, nsISupports>& aTable,
507       nsIContent* aChild, const nsAString& aName);
508 
509  public:
510   /**
511    * Flush a possible pending submission. If there was a scripted submission
512    * triggered by a button or image, the submission was defered. This method
513    * forces the pending submission to be submitted. (happens when the handler
514    * returns false or there is an action/target change in the script)
515    */
516   void FlushPendingSubmission();
517 
518   /**
519    * Get the full URL to submit to.  Do not submit if the returned URL is null.
520    *
521    * @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
522    * @param aOriginatingElement the originating element of the form submission
523    * [IN]
524    */
525   nsresult GetActionURL(nsIURI** aActionURL, Element* aOriginatingElement);
526 
527   // Returns a number for this form that is unique within its owner document.
528   // This is used by nsContentUtils::GenerateStateKey to identify form controls
529   // that are inserted into the document by the parser.
530   int32_t GetFormNumberForStateKey();
531 
532   /**
533    * Called when we have been cloned and adopted, and the information of the
534    * node has been changed.
535    */
536   void NodeInfoChanged(Document* aOldDoc) override;
537 
538  protected:
539   //
540   // Data members
541   //
542   /** The list of controls (form.elements as well as stuff not in elements) */
543   RefPtr<HTMLFormControlsCollection> mControls;
544 
545   /** The pending submission object */
546   UniquePtr<HTMLFormSubmission> mPendingSubmission;
547 
548   /** The target browsing context, if any. */
549   RefPtr<BrowsingContext> mTargetContext;
550   /** The load identifier for the pending request created for a
551    * submit, used to be able to block double submits. */
552   Maybe<uint64_t> mCurrentLoadId;
553 
554   /** The default submit element -- WEAK */
555   nsGenericHTMLFormElement* mDefaultSubmitElement;
556 
557   /** The first submit element in mElements -- WEAK */
558   nsGenericHTMLFormElement* mFirstSubmitInElements;
559 
560   /** The first submit element in mNotInElements -- WEAK */
561   nsGenericHTMLFormElement* mFirstSubmitNotInElements;
562 
563   // This array holds on to all HTMLImageElement(s).
564   // This is needed to properly clean up the bi-directional references
565   // (both weak and strong) between the form and its HTMLImageElements.
566 
567   nsTArray<HTMLImageElement*> mImageElements;  // Holds WEAK references
568 
569   // A map from an ID or NAME attribute to the HTMLImageElement(s), this
570   // hash holds strong references either to the named HTMLImageElement, or
571   // to a list of named HTMLImageElement(s), in the case where this hash
572   // holds on to a list of named HTMLImageElement(s) the list has weak
573   // references to the HTMLImageElement.
574 
575   nsInterfaceHashtable<nsStringHashKey, nsISupports> mImageNameLookupTable;
576 
577   // A map from names to elements that were gotten by those names from this
578   // form in that past.  See "past names map" in the HTML5 specification.
579 
580   nsInterfaceHashtable<nsStringHashKey, nsISupports> mPastNameLookupTable;
581 
582   /** Keep track of what the popup state was when the submit was initiated */
583   PopupBlocker::PopupControlState mSubmitPopupState;
584 
585   /**
586    * Number of invalid and candidate for constraint validation elements in the
587    * form the last time UpdateValidity has been called.
588    */
589   int32_t mInvalidElementsCount;
590 
591   // See GetFormNumberForStateKey.
592   int32_t mFormNumber;
593 
594   /** Whether we are currently processing a submit event or not */
595   bool mGeneratingSubmit;
596   /** Whether we are currently processing a reset event or not */
597   bool mGeneratingReset;
598   /** Whether the submission is to be deferred in case a script triggers it */
599   bool mDeferSubmission;
600   /** Whether we notified NS_FORMSUBMIT_SUBJECT listeners already */
601   bool mNotifiedObservers;
602   /** If we notified the listeners early, what was the result? */
603   bool mNotifiedObserversResult;
604   /**
605    * Whether the submission of this form has been ever prevented because of
606    * being invalid.
607    */
608   bool mEverTriedInvalidSubmit;
609   /** Whether we are constructing entry list */
610   bool mIsConstructingEntryList;
611   /** Whether we are firing submission event */
612   bool mIsFiringSubmissionEvents;
613 
614  private:
615   bool IsSubmitting() const;
616 
617   NotNull<const Encoding*> GetSubmitEncoding();
618 
619   /**
620    * Fire an event when the form is removed from the DOM tree. This is now only
621    * used by the password manager.
622    */
623   void MaybeFireFormRemoved();
624 
625   ~HTMLFormElement();
626 };
627 
628 }  // namespace dom
629 
630 }  // namespace mozilla
631 
632 #endif  // mozilla_dom_HTMLFormElement_h
633