summaryrefslogtreecommitdiffstats
path: root/dom/html/nsGenericHTMLElement.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/html/nsGenericHTMLElement.h')
-rw-r--r--dom/html/nsGenericHTMLElement.h1724
1 files changed, 1724 insertions, 0 deletions
diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h
new file mode 100644
index 000000000..3cca41c3d
--- /dev/null
+++ b/dom/html/nsGenericHTMLElement.h
@@ -0,0 +1,1724 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsGenericHTMLElement_h___
+#define nsGenericHTMLElement_h___
+
+#include "mozilla/Attributes.h"
+#include "mozilla/EventForwards.h"
+#include "nsMappedAttributeElement.h"
+#include "nsIDOMHTMLElement.h"
+#include "nsNameSpaceManager.h" // for kNameSpaceID_None
+#include "nsIFormControl.h"
+#include "nsGkAtoms.h"
+#include "nsContentCreatorFunctions.h"
+#include "mozilla/ErrorResult.h"
+#include "nsIDOMHTMLMenuElement.h"
+#include "mozilla/dom/DOMRect.h"
+#include "mozilla/dom/ValidityState.h"
+#include "mozilla/dom/ElementInlines.h"
+
+class nsDOMTokenList;
+class nsIDOMHTMLMenuElement;
+class nsIEditor;
+class nsIFormControlFrame;
+class nsIFrame;
+class nsILayoutHistoryState;
+class nsIURI;
+class nsPresState;
+struct nsSize;
+
+namespace mozilla {
+class EventChainPostVisitor;
+class EventChainPreVisitor;
+class EventChainVisitor;
+class EventListenerManager;
+class EventStates;
+namespace dom {
+class HTMLFormElement;
+class HTMLMenuElement;
+} // namespace dom
+} // namespace mozilla
+
+typedef nsMappedAttributeElement nsGenericHTMLElementBase;
+
+/**
+ * A common superclass for HTML elements
+ */
+class nsGenericHTMLElement : public nsGenericHTMLElementBase,
+ public nsIDOMHTMLElement
+{
+public:
+ using Element::SetTabIndex;
+ using Element::Focus;
+ explicit nsGenericHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
+ : nsGenericHTMLElementBase(aNodeInfo)
+ {
+ NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
+ "Unexpected namespace");
+ AddStatesSilently(NS_EVENT_STATE_LTR);
+ SetFlags(NODE_HAS_DIRECTION_LTR);
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_IMPL_FROMCONTENT(nsGenericHTMLElement, kNameSpaceID_XHTML)
+
+ // From Element
+ nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+
+ void GetTitle(mozilla::dom::DOMString& aTitle)
+ {
+ GetHTMLAttr(nsGkAtoms::title, aTitle);
+ }
+ NS_IMETHOD SetTitle(const nsAString& aTitle) override
+ {
+ SetHTMLAttr(nsGkAtoms::title, aTitle);
+ return NS_OK;
+ }
+ void GetLang(mozilla::dom::DOMString& aLang)
+ {
+ GetHTMLAttr(nsGkAtoms::lang, aLang);
+ }
+ NS_IMETHOD SetLang(const nsAString& aLang) override
+ {
+ SetHTMLAttr(nsGkAtoms::lang, aLang);
+ return NS_OK;
+ }
+ void GetDir(mozilla::dom::DOMString& aDir)
+ {
+ GetHTMLEnumAttr(nsGkAtoms::dir, aDir);
+ }
+ void SetDir(const nsAString& aDir, mozilla::ErrorResult& aError)
+ {
+ SetHTMLAttr(nsGkAtoms::dir, aDir, aError);
+ }
+ bool Hidden() const
+ {
+ return GetBoolAttr(nsGkAtoms::hidden);
+ }
+ void SetHidden(bool aHidden, mozilla::ErrorResult& aError)
+ {
+ SetHTMLBoolAttr(nsGkAtoms::hidden, aHidden, aError);
+ }
+ virtual void Click();
+ void GetAccessKey(nsString& aAccessKey)
+ {
+ GetHTMLAttr(nsGkAtoms::accesskey, aAccessKey);
+ }
+ void SetAccessKey(const nsAString& aAccessKey, mozilla::ErrorResult& aError)
+ {
+ SetHTMLAttr(nsGkAtoms::accesskey, aAccessKey, aError);
+ }
+ void GetAccessKeyLabel(nsString& aAccessKeyLabel);
+ virtual bool Draggable() const
+ {
+ return AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
+ nsGkAtoms::_true, eIgnoreCase);
+ }
+ void SetDraggable(bool aDraggable, mozilla::ErrorResult& aError)
+ {
+ SetHTMLAttr(nsGkAtoms::draggable,
+ aDraggable ? NS_LITERAL_STRING("true")
+ : NS_LITERAL_STRING("false"),
+ aError);
+ }
+ void GetContentEditable(nsString& aContentEditable)
+ {
+ ContentEditableTristate value = GetContentEditableValue();
+ if (value == eTrue) {
+ aContentEditable.AssignLiteral("true");
+ } else if (value == eFalse) {
+ aContentEditable.AssignLiteral("false");
+ } else {
+ aContentEditable.AssignLiteral("inherit");
+ }
+ }
+ void SetContentEditable(const nsAString& aContentEditable,
+ mozilla::ErrorResult& aError)
+ {
+ if (aContentEditable.LowerCaseEqualsLiteral("inherit")) {
+ UnsetHTMLAttr(nsGkAtoms::contenteditable, aError);
+ } else if (aContentEditable.LowerCaseEqualsLiteral("true")) {
+ SetHTMLAttr(nsGkAtoms::contenteditable, NS_LITERAL_STRING("true"), aError);
+ } else if (aContentEditable.LowerCaseEqualsLiteral("false")) {
+ SetHTMLAttr(nsGkAtoms::contenteditable, NS_LITERAL_STRING("false"), aError);
+ } else {
+ aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+ }
+ bool IsContentEditable()
+ {
+ for (nsIContent* node = this; node; node = node->GetParent()) {
+ nsGenericHTMLElement* element = FromContent(node);
+ if (element) {
+ ContentEditableTristate value = element->GetContentEditableValue();
+ if (value != eInherit) {
+ return value == eTrue;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the count of descendants (inclusive of this node) in
+ * the uncomposed document that are explicitly set as editable.
+ */
+ uint32_t EditableInclusiveDescendantCount();
+
+ mozilla::dom::HTMLMenuElement* GetContextMenu() const;
+ bool Spellcheck();
+ void SetSpellcheck(bool aSpellcheck, mozilla::ErrorResult& aError)
+ {
+ SetHTMLAttr(nsGkAtoms::spellcheck,
+ aSpellcheck ? NS_LITERAL_STRING("true")
+ : NS_LITERAL_STRING("false"),
+ aError);
+ }
+ bool Scrollgrab() const
+ {
+ return HasFlag(ELEMENT_HAS_SCROLLGRAB);
+ }
+ void SetScrollgrab(bool aValue)
+ {
+ if (aValue) {
+ SetFlags(ELEMENT_HAS_SCROLLGRAB);
+ } else {
+ UnsetFlags(ELEMENT_HAS_SCROLLGRAB);
+ }
+ }
+
+ void GetInnerText(mozilla::dom::DOMString& aValue, mozilla::ErrorResult& aError);
+ void SetInnerText(const nsAString& aValue);
+
+ /**
+ * Determine whether an attribute is an event (onclick, etc.)
+ * @param aName the attribute
+ * @return whether the name is an event handler name
+ */
+ virtual bool IsEventAttributeName(nsIAtom* aName) override;
+
+#define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */
+// The using nsINode::Get/SetOn* are to avoid warnings about shadowing the XPCOM
+// getter and setter on nsINode.
+#define FORWARDED_EVENT(name_, id_, type_, struct_) \
+ using nsINode::GetOn##name_; \
+ using nsINode::SetOn##name_; \
+ mozilla::dom::EventHandlerNonNull* GetOn##name_(); \
+ void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler);
+#define ERROR_EVENT(name_, id_, type_, struct_) \
+ using nsINode::GetOn##name_; \
+ using nsINode::SetOn##name_; \
+ already_AddRefed<mozilla::dom::EventHandlerNonNull> GetOn##name_(); \
+ void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler);
+#include "mozilla/EventNameList.h" // IWYU pragma: keep
+#undef ERROR_EVENT
+#undef FORWARDED_EVENT
+#undef EVENT
+ mozilla::dom::Element* GetOffsetParent()
+ {
+ mozilla::CSSIntRect rcFrame;
+ return GetOffsetRect(rcFrame);
+ }
+ int32_t OffsetTop()
+ {
+ mozilla::CSSIntRect rcFrame;
+ GetOffsetRect(rcFrame);
+
+ return rcFrame.y;
+ }
+ int32_t OffsetLeft()
+ {
+ mozilla::CSSIntRect rcFrame;
+ GetOffsetRect(rcFrame);
+
+ return rcFrame.x;
+ }
+ int32_t OffsetWidth()
+ {
+ mozilla::CSSIntRect rcFrame;
+ GetOffsetRect(rcFrame);
+
+ return rcFrame.width;
+ }
+ int32_t OffsetHeight()
+ {
+ mozilla::CSSIntRect rcFrame;
+ GetOffsetRect(rcFrame);
+
+ return rcFrame.height;
+ }
+
+ // These methods are already implemented in nsIContent but we want something
+ // faster for HTMLElements ignoring the namespace checking.
+ // This is safe because we already know that we are in the HTML namespace.
+ inline bool IsHTMLElement() const
+ {
+ return true;
+ }
+
+ inline bool IsHTMLElement(nsIAtom* aTag) const
+ {
+ return mNodeInfo->Equals(aTag);
+ }
+
+ template<typename First, typename... Args>
+ inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const
+ {
+ return IsNodeInternal(aFirst, aArgs...);
+ }
+
+protected:
+ virtual ~nsGenericHTMLElement() {}
+
+public:
+ /**
+ * Get width and height, using given image request if attributes are unset.
+ * Pass a reference to the image request, since the method may change the
+ * value and we want to use the updated value.
+ */
+ nsSize GetWidthHeightForImage(RefPtr<imgRequestProxy>& aImageRequest);
+
+ // XPIDL methods
+ NS_FORWARD_NSIDOMNODE_TO_NSINODE
+
+ NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+ NS_IMETHOD GetTitle(nsAString& aTitle) final override {
+ mozilla::dom::DOMString title;
+ GetTitle(title);
+ title.ToString(aTitle);
+ return NS_OK;
+ }
+ NS_IMETHOD GetLang(nsAString& aLang) final override {
+ mozilla::dom::DOMString lang;
+ GetLang(lang);
+ lang.ToString(aLang);
+ return NS_OK;
+ }
+ NS_IMETHOD GetDir(nsAString& aDir) final override {
+ mozilla::dom::DOMString dir;
+ GetDir(dir);
+ dir.ToString(aDir);
+ return NS_OK;
+ }
+ NS_IMETHOD SetDir(const nsAString& aDir) final override {
+ mozilla::ErrorResult rv;
+ SetDir(aDir, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetDOMClassName(nsAString& aClassName) final {
+ GetHTMLAttr(nsGkAtoms::_class, aClassName);
+ return NS_OK;
+ }
+ NS_IMETHOD SetDOMClassName(const nsAString& aClassName) final {
+ SetClassName(aClassName);
+ return NS_OK;
+ }
+ NS_IMETHOD GetDataset(nsISupports** aDataset) final override;
+ NS_IMETHOD GetHidden(bool* aHidden) final override {
+ *aHidden = Hidden();
+ return NS_OK;
+ }
+ NS_IMETHOD SetHidden(bool aHidden) final override {
+ mozilla::ErrorResult rv;
+ SetHidden(aHidden, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD DOMBlur() final override {
+ mozilla::ErrorResult rv;
+ Blur(rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetAccessKey(nsAString& aAccessKey) final override {
+ nsString accessKey;
+ GetAccessKey(accessKey);
+ aAccessKey.Assign(accessKey);
+ return NS_OK;
+ }
+ NS_IMETHOD SetAccessKey(const nsAString& aAccessKey) final override {
+ mozilla::ErrorResult rv;
+ SetAccessKey(aAccessKey, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetAccessKeyLabel(nsAString& aAccessKeyLabel)
+ final override {
+ nsString accessKeyLabel;
+ GetAccessKeyLabel(accessKeyLabel);
+ aAccessKeyLabel.Assign(accessKeyLabel);
+ return NS_OK;
+ }
+ NS_IMETHOD SetDraggable(bool aDraggable) final override {
+ mozilla::ErrorResult rv;
+ SetDraggable(aDraggable, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetContentEditable(nsAString& aContentEditable)
+ final override {
+ nsString contentEditable;
+ GetContentEditable(contentEditable);
+ aContentEditable.Assign(contentEditable);
+ return NS_OK;
+ }
+ NS_IMETHOD SetContentEditable(const nsAString& aContentEditable)
+ final override {
+ mozilla::ErrorResult rv;
+ SetContentEditable(aContentEditable, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetIsContentEditable(bool* aIsContentEditable)
+ final override {
+ *aIsContentEditable = IsContentEditable();
+ return NS_OK;
+ }
+ NS_IMETHOD GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu)
+ final override;
+ NS_IMETHOD GetSpellcheck(bool* aSpellcheck) final override {
+ *aSpellcheck = Spellcheck();
+ return NS_OK;
+ }
+ NS_IMETHOD SetSpellcheck(bool aSpellcheck) final override {
+ mozilla::ErrorResult rv;
+ SetSpellcheck(aSpellcheck, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetOuterHTML(nsAString& aOuterHTML) final override {
+ mozilla::dom::Element::GetOuterHTML(aOuterHTML);
+ return NS_OK;
+ }
+ NS_IMETHOD SetOuterHTML(const nsAString& aOuterHTML) final override {
+ mozilla::ErrorResult rv;
+ mozilla::dom::Element::SetOuterHTML(aOuterHTML, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD InsertAdjacentHTML(const nsAString& position,
+ const nsAString& text) final override;
+ NS_IMETHOD ScrollIntoView(bool top, uint8_t _argc) final override {
+ if (!_argc) {
+ top = true;
+ }
+ mozilla::dom::Element::ScrollIntoView(top);
+ return NS_OK;
+ }
+ NS_IMETHOD GetOffsetParent(nsIDOMElement** aOffsetParent)
+ final override {
+ mozilla::dom::Element* offsetParent = GetOffsetParent();
+ if (!offsetParent) {
+ *aOffsetParent = nullptr;
+ return NS_OK;
+ }
+ return CallQueryInterface(offsetParent, aOffsetParent);
+ }
+ NS_IMETHOD GetOffsetTop(int32_t* aOffsetTop) final override {
+ *aOffsetTop = OffsetTop();
+ return NS_OK;
+ }
+ NS_IMETHOD GetOffsetLeft(int32_t* aOffsetLeft) final override {
+ *aOffsetLeft = OffsetLeft();
+ return NS_OK;
+ }
+ NS_IMETHOD GetOffsetWidth(int32_t* aOffsetWidth) final override {
+ *aOffsetWidth = OffsetWidth();
+ return NS_OK;
+ }
+ NS_IMETHOD GetOffsetHeight(int32_t* aOffsetHeight) final override {
+ *aOffsetHeight = OffsetHeight();
+ return NS_OK;
+ }
+ NS_IMETHOD DOMClick() final override {
+ Click();
+ return NS_OK;
+ }
+ NS_IMETHOD GetTabIndex(int32_t* aTabIndex) final override {
+ *aTabIndex = TabIndex();
+ return NS_OK;
+ }
+ NS_IMETHOD SetTabIndex(int32_t aTabIndex) final override {
+ mozilla::ErrorResult rv;
+ SetTabIndex(aTabIndex, rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD Focus() final override {
+ mozilla::ErrorResult rv;
+ Focus(rv);
+ return rv.StealNSResult();
+ }
+ NS_IMETHOD GetDraggable(bool* aDraggable) final override {
+ *aDraggable = Draggable();
+ return NS_OK;
+ }
+ NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) override {
+ return mozilla::dom::Element::GetInnerHTML(aInnerHTML);
+ }
+ using mozilla::dom::Element::SetInnerHTML;
+ NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML) final override {
+ mozilla::ErrorResult rv;
+ SetInnerHTML(aInnerHTML, rv);
+ return rv.StealNSResult();
+ }
+
+ using nsGenericHTMLElementBase::GetOwnerDocument;
+
+ virtual nsIDOMNode* AsDOMNode() override { return this; }
+
+public:
+ // Implementation for nsIContent
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers) override;
+ virtual void UnbindFromTree(bool aDeep = true,
+ bool aNullParent = true) override;
+
+ MOZ_ALWAYS_INLINE // Avoid a crashy hook from Avast 10 Beta
+ nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAString& aValue, bool aNotify)
+ {
+ return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
+ }
+ virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ nsIAtom* aPrefix, const nsAString& aValue,
+ bool aNotify) override;
+ virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ bool aNotify) override;
+ virtual bool IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse) override
+ {
+ bool isFocusable = false;
+ IsHTMLFocusable(aWithMouse, &isFocusable, aTabIndex);
+ return isFocusable;
+ }
+ /**
+ * Returns true if a subclass is not allowed to override the value returned
+ * in aIsFocusable.
+ */
+ virtual bool IsHTMLFocusable(bool aWithMouse,
+ bool *aIsFocusable,
+ int32_t *aTabIndex);
+ virtual bool PerformAccesskey(bool aKeyCausesActivation,
+ bool aIsTrustedEvent) override;
+
+ /**
+ * Check if an event for an anchor can be handled
+ * @return true if the event can be handled, false otherwise
+ */
+ bool CheckHandleEventForAnchorsPreconditions(
+ mozilla::EventChainVisitor& aVisitor);
+ nsresult PreHandleEventForAnchors(mozilla::EventChainPreVisitor& aVisitor);
+ nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor);
+ bool IsHTMLLink(nsIURI** aURI) const;
+
+ // HTML element methods
+ void Compact() { mAttrsAndChildren.Compact(); }
+
+ virtual void UpdateEditableState(bool aNotify) override;
+
+ virtual mozilla::EventStates IntrinsicState() const override;
+
+ // Helper for setting our editable flag and notifying
+ void DoSetEditableFlag(bool aEditable, bool aNotify) {
+ SetEditableFlag(aEditable);
+ UpdateState(aNotify);
+ }
+
+ virtual bool ParseAttribute(int32_t aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult) override;
+
+ bool ParseBackgroundAttribute(int32_t aNamespaceID,
+ nsIAtom* aAttribute,
+ const nsAString& aValue,
+ nsAttrValue& aResult);
+
+ NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
+ virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
+
+ /**
+ * Get the base target for any links within this piece
+ * of content. Generally, this is the document's base target,
+ * but certain content carries a local base for backward
+ * compatibility.
+ *
+ * @param aBaseTarget the base target [OUT]
+ */
+ void GetBaseTarget(nsAString& aBaseTarget) const;
+
+ /**
+ * Get the primary form control frame for this element. Same as
+ * GetPrimaryFrame(), except it QI's to nsIFormControlFrame.
+ *
+ * @param aFlush whether to flush out frames so that they're up to date.
+ * @return the primary frame as nsIFormControlFrame
+ */
+ nsIFormControlFrame* GetFormControlFrame(bool aFlushFrames);
+
+ //----------------------------------------
+
+ /**
+ * Parse an alignment attribute (top/middle/bottom/baseline)
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseAlignValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Parse a div align string to value (left/right/center/middle/justify)
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseDivAlignValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Convert a table halign string to value (left/right/center/char/justify)
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseTableHAlignValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Convert a table cell halign string to value
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseTableCellHAlignValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Convert a table valign string to value (left/right/center/char/justify/
+ * abscenter/absmiddle/middle)
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseTableVAlignValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Convert an image attribute to value (width, height, hspace, vspace, border)
+ *
+ * @param aAttribute the attribute to parse
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseImageAttribute(nsIAtom* aAttribute,
+ const nsAString& aString,
+ nsAttrValue& aResult);
+
+ static bool ParseReferrerAttribute(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Convert a frameborder string to value (yes/no/1/0)
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseFrameborderValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /**
+ * Convert a scrolling string to value (yes/no/on/off/scroll/noscroll/auto)
+ *
+ * @param aString the string to parse
+ * @param aResult the resulting HTMLValue
+ * @return whether the value was parsed
+ */
+ static bool ParseScrollingValue(const nsAString& aString,
+ nsAttrValue& aResult);
+
+ /*
+ * Attribute Mapping Helpers
+ */
+
+ /**
+ * A style attribute mapping function for the most common attributes, to be
+ * called by subclasses' attribute mapping functions. Currently handles
+ * dir, lang and hidden, could handle others.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aRuleData);
+ /**
+ * Same as MapCommonAttributesInto except that it does not handle hidden.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapCommonAttributesIntoExceptHidden(const nsMappedAttributes* aAttributes,
+ nsRuleData* aRuleData);
+
+ static const MappedAttributeEntry sCommonAttributeMap[];
+ static const MappedAttributeEntry sImageMarginSizeAttributeMap[];
+ static const MappedAttributeEntry sImageBorderAttributeMap[];
+ static const MappedAttributeEntry sImageAlignAttributeMap[];
+ static const MappedAttributeEntry sDivAlignAttributeMap[];
+ static const MappedAttributeEntry sBackgroundAttributeMap[];
+ static const MappedAttributeEntry sBackgroundColorAttributeMap[];
+
+ /**
+ * Helper to map the align attribute into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+
+ /**
+ * Helper to map the align attribute into a style struct for things
+ * like <div>, <h1>, etc.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+
+ /**
+ * Helper to map the image border attribute into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Helper to map the image margin attribute into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Helper to map the image position attribute into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Helper to map the background attribute
+ * into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapBackgroundInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Helper to map the bgcolor attribute
+ * into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapBGColorInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Helper to map the background attributes (currently background and bgcolor)
+ * into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Helper to map the scrolling attribute on FRAME and IFRAME
+ * into a style struct.
+ *
+ * @param aAttributes the list of attributes to map
+ * @param aData the returned rule data [INOUT]
+ * @see GetAttributeMappingFunction
+ */
+ static void MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
+ nsRuleData* aData);
+ /**
+ * Get the presentation context for this content node.
+ * @return the presentation context
+ */
+ enum PresContextFor
+ {
+ eForComposedDoc,
+ eForUncomposedDoc
+ };
+ nsPresContext* GetPresContext(PresContextFor aFor);
+
+ // Form Helper Routines
+ /**
+ * Find an ancestor of this content node which is a form (could be null)
+ * @param aCurrentForm the current form for this node. If this is
+ * non-null, and no ancestor form is found, and the current form is in
+ * a connected subtree with the node, the current form will be
+ * returned. This is needed to handle cases when HTML elements have a
+ * current form that they're not descendants of.
+ * @note This method should not be called if the element has a form attribute.
+ */
+ mozilla::dom::HTMLFormElement*
+ FindAncestorForm(mozilla::dom::HTMLFormElement* aCurrentForm = nullptr);
+
+ virtual void RecompileScriptEventListeners() override;
+
+ /**
+ * See if the document being tested has nav-quirks mode enabled.
+ * @param doc the document
+ */
+ static bool InNavQuirksMode(nsIDocument* aDoc);
+
+ /**
+ * Locate an nsIEditor rooted at this content node, if there is one.
+ */
+ nsresult GetEditor(nsIEditor** aEditor);
+
+ /**
+ * Helper method for NS_IMPL_URI_ATTR macro.
+ * Gets the absolute URI value of an attribute, by resolving any relative
+ * URIs in the attribute against the baseuri of the element. If the attribute
+ * isn't a relative URI the value of the attribute is returned as is. Only
+ * works for attributes in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aBaseAttr name of base attribute.
+ * @param aResult result value [out]
+ */
+ void GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult) const;
+
+ /**
+ * Gets the absolute URI values of an attribute, by resolving any relative
+ * URIs in the attribute against the baseuri of the element. If a substring
+ * isn't a relative URI, the substring is returned as is. Only works for
+ * attributes in null namespace.
+ */
+ bool GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsIURI** aURI) const;
+
+ /**
+ * Returns the current disabled state of the element.
+ */
+ virtual bool IsDisabled() const {
+ return false;
+ }
+
+ bool IsHidden() const
+ {
+ return HasAttr(kNameSpaceID_None, nsGkAtoms::hidden);
+ }
+
+ virtual bool IsLabelable() const override;
+ virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
+
+ static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */);
+
+ static inline bool
+ CanHaveName(nsIAtom* aTag)
+ {
+ return aTag == nsGkAtoms::img ||
+ aTag == nsGkAtoms::form ||
+ aTag == nsGkAtoms::applet ||
+ aTag == nsGkAtoms::embed ||
+ aTag == nsGkAtoms::object;
+ }
+ static inline bool
+ ShouldExposeNameAsHTMLDocumentProperty(Element* aElement)
+ {
+ return aElement->IsHTMLElement() &&
+ CanHaveName(aElement->NodeInfo()->NameAtom());
+ }
+ static inline bool
+ ShouldExposeIdAsHTMLDocumentProperty(Element* aElement)
+ {
+ if (aElement->IsAnyOfHTMLElements(nsGkAtoms::applet,
+ nsGkAtoms::embed,
+ nsGkAtoms::object)) {
+ return true;
+ }
+
+ // Per spec, <img> is exposed by id only if it also has a nonempty
+ // name (which doesn't have to match the id or anything).
+ // HasName() is true precisely when name is nonempty.
+ return aElement->IsHTMLElement(nsGkAtoms::img) && aElement->HasName();
+ }
+
+ static bool
+ IsScrollGrabAllowed(JSContext*, JSObject*);
+
+protected:
+ /**
+ * Add/remove this element to the documents name cache
+ */
+ void AddToNameTable(nsIAtom* aName) {
+ NS_ASSERTION(HasName(), "Node doesn't have name?");
+ nsIDocument* doc = GetUncomposedDoc();
+ if (doc && !IsInAnonymousSubtree()) {
+ doc->AddToNameTable(this, aName);
+ }
+ }
+ void RemoveFromNameTable() {
+ if (HasName()) {
+ nsIDocument* doc = GetUncomposedDoc();
+ if (doc) {
+ doc->RemoveFromNameTable(this, GetParsedAttr(nsGkAtoms::name)->
+ GetAtomValue());
+ }
+ }
+ }
+
+ /**
+ * Register or unregister an access key to this element based on the
+ * accesskey attribute.
+ */
+ void RegAccessKey()
+ {
+ if (HasFlag(NODE_HAS_ACCESSKEY)) {
+ RegUnRegAccessKey(true);
+ }
+ }
+
+ void UnregAccessKey()
+ {
+ if (HasFlag(NODE_HAS_ACCESSKEY)) {
+ RegUnRegAccessKey(false);
+ }
+ }
+
+private:
+ void RegUnRegAccessKey(bool aDoReg);
+
+protected:
+ virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify) override;
+
+ virtual mozilla::EventListenerManager*
+ GetEventListenerManagerForAttr(nsIAtom* aAttrName,
+ bool* aDefer) override;
+
+ /**
+ * Dispatch a simulated mouse click by keyboard to the given element.
+ */
+ nsresult DispatchSimulatedClick(nsGenericHTMLElement* aElement,
+ bool aIsTrusted,
+ nsPresContext* aPresContext);
+
+ /**
+ * Create a URI for the given aURISpec string.
+ * Returns INVALID_STATE_ERR and nulls *aURI if aURISpec is empty
+ * and the document's URI matches the element's base URI.
+ */
+ nsresult NewURIFromString(const nsAString& aURISpec, nsIURI** aURI);
+
+ void GetHTMLAttr(nsIAtom* aName, nsAString& aResult) const
+ {
+ GetAttr(kNameSpaceID_None, aName, aResult);
+ }
+ void GetHTMLAttr(nsIAtom* aName, mozilla::dom::DOMString& aResult) const
+ {
+ GetAttr(kNameSpaceID_None, aName, aResult);
+ }
+ void GetHTMLEnumAttr(nsIAtom* aName, nsAString& aResult) const
+ {
+ GetEnumAttr(aName, nullptr, aResult);
+ }
+ void GetHTMLURIAttr(nsIAtom* aName, nsAString& aResult) const
+ {
+ GetURIAttr(aName, nullptr, aResult);
+ }
+
+ void SetHTMLAttr(nsIAtom* aName, const nsAString& aValue)
+ {
+ SetAttr(kNameSpaceID_None, aName, aValue, true);
+ }
+ void SetHTMLAttr(nsIAtom* aName, const nsAString& aValue, mozilla::ErrorResult& aError)
+ {
+ mozilla::dom::Element::SetAttr(aName, aValue, aError);
+ }
+ void UnsetHTMLAttr(nsIAtom* aName, mozilla::ErrorResult& aError)
+ {
+ mozilla::dom::Element::UnsetAttr(aName, aError);
+ }
+ void SetHTMLBoolAttr(nsIAtom* aName, bool aValue, mozilla::ErrorResult& aError)
+ {
+ if (aValue) {
+ SetHTMLAttr(aName, EmptyString(), aError);
+ } else {
+ UnsetHTMLAttr(aName, aError);
+ }
+ }
+ template<typename T>
+ void SetHTMLIntAttr(nsIAtom* aName, T aValue, mozilla::ErrorResult& aError)
+ {
+ nsAutoString value;
+ value.AppendInt(aValue);
+
+ SetHTMLAttr(aName, value, aError);
+ }
+
+ /**
+ * Helper method for NS_IMPL_STRING_ATTR macro.
+ * Sets the value of an attribute, returns specified default value if the
+ * attribute isn't set. Only works for attributes in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aDefault default-value to return if attribute isn't set.
+ * @param aResult result value [out]
+ */
+ nsresult SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue);
+
+ /**
+ * Helper method for NS_IMPL_INT_ATTR macro.
+ * Gets the integer-value of an attribute, returns specified default value
+ * if the attribute isn't set or isn't set to an integer. Only works for
+ * attributes in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aDefault default-value to return if attribute isn't set.
+ */
+ int32_t GetIntAttr(nsIAtom* aAttr, int32_t aDefault) const;
+
+ /**
+ * Helper method for NS_IMPL_INT_ATTR macro.
+ * Sets value of attribute to specified integer. Only works for attributes
+ * in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aValue Integer value of attribute.
+ */
+ nsresult SetIntAttr(nsIAtom* aAttr, int32_t aValue);
+
+ /**
+ * Helper method for NS_IMPL_UINT_ATTR macro.
+ * Gets the unsigned integer-value of an attribute, returns specified default
+ * value if the attribute isn't set or isn't set to an integer. Only works for
+ * attributes in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aDefault default-value to return if attribute isn't set.
+ */
+ uint32_t GetUnsignedIntAttr(nsIAtom* aAttr, uint32_t aDefault) const;
+
+ /**
+ * Helper method for NS_IMPL_UINT_ATTR macro.
+ * Sets value of attribute to specified unsigned integer. Only works for
+ * attributes in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aValue Integer value of attribute.
+ * @param aDefault Default value (in case value is out of range). If the spec
+ * doesn't provide one, should be 1 if the value is limited to
+ * nonzero values, and 0 otherwise.
+ */
+ void SetUnsignedIntAttr(nsIAtom* aName, uint32_t aValue, uint32_t aDefault,
+ mozilla::ErrorResult& aError)
+ {
+ nsAutoString value;
+ if (aValue > INT32_MAX) {
+ value.AppendInt(aDefault);
+ } else {
+ value.AppendInt(aValue);
+ }
+
+ SetHTMLAttr(aName, value, aError);
+ }
+
+ /**
+ * Sets value of attribute to specified double. Only works for attributes
+ * in null namespace.
+ *
+ * @param aAttr name of attribute.
+ * @param aValue Double value of attribute.
+ */
+ void SetDoubleAttr(nsIAtom* aAttr, double aValue, mozilla::ErrorResult& aRv)
+ {
+ nsAutoString value;
+ value.AppendFloat(aValue);
+
+ SetHTMLAttr(aAttr, value, aRv);
+ }
+
+ /**
+ * Locates the nsIEditor associated with this node. In general this is
+ * equivalent to GetEditorInternal(), but for designmode or contenteditable,
+ * this may need to get an editor that's not actually on this element's
+ * associated TextControlFrame. This is used by the spellchecking routines
+ * to get the editor affected by changing the spellcheck attribute on this
+ * node.
+ */
+ virtual already_AddRefed<nsIEditor> GetAssociatedEditor();
+
+ /**
+ * Get the frame's offset information for offsetTop/Left/Width/Height.
+ * Returns the parent the offset is relative to.
+ * @note This method flushes pending notifications (Flush_Layout).
+ * @param aRect the offset information [OUT]
+ */
+ mozilla::dom::Element* GetOffsetRect(mozilla::CSSIntRect& aRect);
+
+ /**
+ * Returns true if this is the current document's body element
+ */
+ bool IsCurrentBodyElement();
+
+ /**
+ * Ensures all editors associated with a subtree are synced, for purposes of
+ * spellchecking.
+ */
+ static void SyncEditorsOnSubtree(nsIContent* content);
+
+ enum ContentEditableTristate {
+ eInherit = -1,
+ eFalse = 0,
+ eTrue = 1
+ };
+
+ /**
+ * Returns eTrue if the element has a contentEditable attribute and its value
+ * is "true" or an empty string. Returns eFalse if the element has a
+ * contentEditable attribute and its value is "false". Otherwise returns
+ * eInherit.
+ */
+ ContentEditableTristate GetContentEditableValue() const
+ {
+ static const nsIContent::AttrValuesArray values[] =
+ { &nsGkAtoms::_false, &nsGkAtoms::_true, &nsGkAtoms::_empty, nullptr };
+
+ if (!MayHaveContentEditableAttr())
+ return eInherit;
+
+ int32_t value = FindAttrValueIn(kNameSpaceID_None,
+ nsGkAtoms::contenteditable, values,
+ eIgnoreCase);
+
+ return value > 0 ? eTrue : (value == 0 ? eFalse : eInherit);
+ }
+
+ // Used by A, AREA, LINK, and STYLE.
+ already_AddRefed<nsIURI> GetHrefURIForAnchors() const;
+
+ /**
+ * Returns whether this element is an editable root. There are two types of
+ * editable roots:
+ * 1) the documentElement if the whole document is editable (for example for
+ * desginMode=on)
+ * 2) an element that is marked editable with contentEditable=true and that
+ * doesn't have a parent or whose parent is not editable.
+ * Note that this doesn't return input and textarea elements that haven't been
+ * made editable through contentEditable or designMode.
+ */
+ bool IsEditableRoot() const;
+
+private:
+ void ChangeEditableState(int32_t aChange);
+};
+
+namespace mozilla {
+namespace dom {
+class HTMLFieldSetElement;
+} // namespace dom
+} // namespace mozilla
+
+#define FORM_ELEMENT_FLAG_BIT(n_) NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
+
+// Form element specific bits
+enum {
+ // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement,
+ // that means that we have added ourselves to our mForm. It's possible to
+ // have a non-null mForm, but not have this flag set. That happens when the
+ // form is set via the content sink.
+ ADDED_TO_FORM = FORM_ELEMENT_FLAG_BIT(0),
+
+ // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement,
+ // that means that its form is in the process of being unbound from the tree,
+ // and this form element hasn't re-found its form in
+ // nsGenericHTMLFormElement::UnbindFromTree yet.
+ MAYBE_ORPHAN_FORM_ELEMENT = FORM_ELEMENT_FLAG_BIT(1)
+};
+
+// NOTE: I don't think it's possible to have the above two flags set at the
+// same time, so if it becomes an issue we can probably merge them into the
+// same bit. --bz
+
+ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
+
+#undef FORM_ELEMENT_FLAG_BIT
+
+/**
+ * A helper class for form elements that can contain children
+ */
+class nsGenericHTMLFormElement : public nsGenericHTMLElement,
+ public nsIFormControl
+{
+public:
+ explicit nsGenericHTMLFormElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ nsINode* GetScopeChainParent() const override;
+
+ virtual bool IsNodeOfType(uint32_t aFlags) const override;
+ virtual void SaveSubtreeState() override;
+
+ // nsIFormControl
+ virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() override;
+ virtual mozilla::dom::Element* GetFormElement() override;
+ mozilla::dom::HTMLFormElement* GetForm() const
+ {
+ return mForm;
+ }
+ virtual void SetForm(nsIDOMHTMLFormElement* aForm) override;
+ virtual void ClearForm(bool aRemoveFromForm) override;
+
+ nsresult GetForm(nsIDOMHTMLFormElement** aForm);
+
+ NS_IMETHOD SaveState() override
+ {
+ return NS_OK;
+ }
+
+ virtual bool RestoreState(nsPresState* aState) override
+ {
+ return false;
+ }
+ virtual bool AllowDrop() override
+ {
+ return true;
+ }
+
+ // nsIContent
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers) override;
+ virtual void UnbindFromTree(bool aDeep = true,
+ bool aNullParent = true) override;
+ virtual IMEState GetDesiredIMEState() override;
+ virtual mozilla::EventStates IntrinsicState() const override;
+
+ virtual nsresult PreHandleEvent(
+ mozilla::EventChainPreVisitor& aVisitor) override;
+
+ virtual bool IsDisabled() const override;
+
+ /**
+ * This callback is called by a fieldest on all its elements whenever its
+ * disabled attribute is changed so the element knows its disabled state
+ * might have changed.
+ *
+ * @note Classes redefining this method should not do any content
+ * state updates themselves but should just make sure to call into
+ * nsGenericHTMLFormElement::FieldSetDisabledChanged.
+ */
+ virtual void FieldSetDisabledChanged(bool aNotify);
+
+ void FieldSetFirstLegendChanged(bool aNotify) {
+ UpdateFieldSet(aNotify);
+ }
+
+ /**
+ * This callback is called by a fieldset on all it's elements when it's being
+ * destroyed. When called, the elements should check that aFieldset is there
+ * first parent fieldset and null mFieldset in that case only.
+ *
+ * @param aFieldSet The fieldset being removed.
+ */
+ void ForgetFieldSet(nsIContent* aFieldset);
+
+ /**
+ * Returns if the control can be disabled.
+ */
+ bool CanBeDisabled() const;
+
+ virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
+ int32_t* aTabIndex) override;
+
+ virtual bool IsLabelable() const override;
+
+protected:
+ virtual ~nsGenericHTMLFormElement();
+
+ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ nsAttrValueOrString* aValue,
+ bool aNotify) override;
+
+ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify) override;
+
+ /**
+ * This method will update the form owner, using @form or looking to a parent.
+ *
+ * @param aBindToTree Whether the element is being attached to the tree.
+ * @param aFormIdElement The element associated with the id in @form. If
+ * aBindToTree is false, aFormIdElement *must* contain the element associated
+ * with the id in @form. Otherwise, it *must* be null.
+ *
+ * @note Callers of UpdateFormOwner have to be sure the element is in a
+ * document (GetUncomposedDoc() != nullptr).
+ */
+ void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement);
+
+ /**
+ * This method will update mFieldset and set it to the first fieldset parent.
+ */
+ void UpdateFieldSet(bool aNotify);
+
+ /**
+ * Add a form id observer which will observe when the element with the id in
+ * @form will change.
+ *
+ * @return The element associated with the current id in @form (may be null).
+ */
+ Element* AddFormIdObserver();
+
+ /**
+ * Remove the form id observer.
+ */
+ void RemoveFormIdObserver();
+
+ /**
+ * This method is a a callback for IDTargetObserver (from nsIDocument).
+ * It will be called each time the element associated with the id in @form
+ * changes.
+ */
+ static bool FormIdUpdated(Element* aOldElement, Element* aNewElement,
+ void* aData);
+
+ // Returns true if the event should not be handled from PreHandleEvent
+ bool IsElementDisabledForEvents(mozilla::EventMessage aMessage,
+ nsIFrame* aFrame);
+
+ // The focusability state of this form control. eUnfocusable means that it
+ // shouldn't be focused at all, eInactiveWindow means it's in an inactive
+ // window, eActiveWindow means it's in an active window.
+ enum FocusTristate {
+ eUnfocusable,
+ eInactiveWindow,
+ eActiveWindow
+ };
+
+ // Get our focus state. If this returns eInactiveWindow, it will set this
+ // element as the focused element for that window.
+ FocusTristate FocusState();
+
+ /** The form that contains this control */
+ mozilla::dom::HTMLFormElement* mForm;
+
+ /* This is a pointer to our closest fieldset parent if any */
+ mozilla::dom::HTMLFieldSetElement* mFieldSet;
+};
+
+class nsGenericHTMLFormElementWithState : public nsGenericHTMLFormElement
+{
+public:
+ explicit nsGenericHTMLFormElementWithState(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
+
+ /**
+ * Get the presentation state for a piece of content, or create it if it does
+ * not exist. Generally used by SaveState().
+ */
+ nsPresState* GetPrimaryPresState();
+
+ /**
+ * Get the layout history object for a particular piece of content.
+ *
+ * @param aRead if true, won't return a layout history state if the
+ * layout history state is empty.
+ * @return the history state object
+ */
+ already_AddRefed<nsILayoutHistoryState>
+ GetLayoutHistory(bool aRead);
+
+ /**
+ * Restore the state for a form control. Ends up calling
+ * nsIFormControl::RestoreState().
+ *
+ * @return false if RestoreState() was not called, the return
+ * value of RestoreState() otherwise.
+ */
+ bool RestoreFormControlState();
+
+ /**
+ * Called when we have been cloned and adopted, and the information of the
+ * node has been changed.
+ */
+ virtual void NodeInfoChanged() override;
+
+protected:
+ /* Generates the state key for saving the form state in the session if not
+ computed already. The result is stored in mStateKey on success */
+ nsresult GenerateStateKey();
+
+ /* Used to store the key to that element in the session. Is void until
+ GenerateStateKey has been used */
+ nsCString mStateKey;
+};
+
+//----------------------------------------------------------------------
+
+/**
+ * This macro is similar to NS_IMPL_STRING_ATTR except that the getter method
+ * falls back to an alternative method if the content attribute isn't set.
+ */
+#define NS_IMPL_STRING_ATTR_WITH_FALLBACK(_class, _method, _atom, _fallback) \
+ NS_IMETHODIMP \
+ _class::Get##_method(nsAString& aValue) \
+ { \
+ if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue)) { \
+ _fallback(aValue); \
+ } \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(const nsAString& aValue) \
+ { \
+ return SetAttrHelper(nsGkAtoms::_atom, aValue); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given integer
+ * valued content property. The method uses the generic GetAttr and
+ * SetAttr methods.
+ */
+#define NS_IMPL_INT_ATTR(_class, _method, _atom) \
+ NS_IMPL_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, 0)
+
+#define NS_IMPL_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default) \
+ NS_IMETHODIMP \
+ _class::Get##_method(int32_t* aValue) \
+ { \
+ *aValue = GetIntAttr(nsGkAtoms::_atom, _default); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(int32_t aValue) \
+ { \
+ return SetIntAttr(nsGkAtoms::_atom, aValue); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given unsigned integer
+ * valued content property. The method uses GetUnsignedIntAttr and
+ * SetUnsignedIntAttr methods.
+ */
+#define NS_IMPL_UINT_ATTR(_class, _method, _atom) \
+ NS_IMPL_UINT_ATTR_DEFAULT_VALUE(_class, _method, _atom, 0)
+
+#define NS_IMPL_UINT_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default) \
+ NS_IMETHODIMP \
+ _class::Get##_method(uint32_t* aValue) \
+ { \
+ *aValue = GetUnsignedIntAttr(nsGkAtoms::_atom, _default); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(uint32_t aValue) \
+ { \
+ mozilla::ErrorResult rv; \
+ SetUnsignedIntAttr(nsGkAtoms::_atom, aValue, _default, rv); \
+ return rv.StealNSResult(); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given unsigned integer
+ * valued content property. The method uses GetUnsignedIntAttr and
+ * SetUnsignedIntAttr methods. This macro is similar to NS_IMPL_UINT_ATTR except
+ * that it throws an exception if the set value is null.
+ */
+#define NS_IMPL_UINT_ATTR_NON_ZERO(_class, _method, _atom) \
+ NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(_class, _method, _atom, 1)
+
+#define NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(_class, _method, _atom, _default) \
+ NS_IMETHODIMP \
+ _class::Get##_method(uint32_t* aValue) \
+ { \
+ *aValue = GetUnsignedIntAttr(nsGkAtoms::_atom, _default); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(uint32_t aValue) \
+ { \
+ if (aValue == 0) { \
+ return NS_ERROR_DOM_INDEX_SIZE_ERR; \
+ } \
+ mozilla::ErrorResult rv; \
+ SetUnsignedIntAttr(nsGkAtoms::_atom, aValue, _default, rv); \
+ return rv.StealNSResult(); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given content
+ * property that needs to return a URI in string form. The method
+ * uses the generic GetAttr and SetAttr methods. This macro is much
+ * like the NS_IMPL_STRING_ATTR macro, except we make sure the URI is
+ * absolute.
+ */
+#define NS_IMPL_URI_ATTR(_class, _method, _atom) \
+ NS_IMETHODIMP \
+ _class::Get##_method(nsAString& aValue) \
+ { \
+ GetURIAttr(nsGkAtoms::_atom, nullptr, aValue); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(const nsAString& aValue) \
+ { \
+ return SetAttrHelper(nsGkAtoms::_atom, aValue); \
+ }
+
+#define NS_IMPL_URI_ATTR_WITH_BASE(_class, _method, _atom, _base_atom) \
+ NS_IMETHODIMP \
+ _class::Get##_method(nsAString& aValue) \
+ { \
+ GetURIAttr(nsGkAtoms::_atom, nsGkAtoms::_base_atom, aValue); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(const nsAString& aValue) \
+ { \
+ return SetAttrHelper(nsGkAtoms::_atom, aValue); \
+ }
+
+/**
+ * A macro to implement getter and setter for action and form action content
+ * attributes. It's very similar to NS_IMPL_URI_ATTR excepted that if the
+ * content attribute is the empty string, the empty string is returned.
+ */
+#define NS_IMPL_ACTION_ATTR(_class, _method, _atom) \
+ NS_IMETHODIMP \
+ _class::Get##_method(nsAString& aValue) \
+ { \
+ GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue); \
+ if (!aValue.IsEmpty()) { \
+ GetURIAttr(nsGkAtoms::_atom, nullptr, aValue); \
+ } \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(const nsAString& aValue) \
+ { \
+ return SetAttrHelper(nsGkAtoms::_atom, aValue); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given content
+ * property that needs to set a non-negative integer. The method
+ * uses the generic GetAttr and SetAttr methods. This macro is much
+ * like the NS_IMPL_INT_ATTR macro except we throw an exception if
+ * the set value is negative.
+ */
+#define NS_IMPL_NON_NEGATIVE_INT_ATTR(_class, _method, _atom) \
+ NS_IMPL_NON_NEGATIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, -1)
+
+#define NS_IMPL_NON_NEGATIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default) \
+ NS_IMETHODIMP \
+ _class::Get##_method(int32_t* aValue) \
+ { \
+ *aValue = GetIntAttr(nsGkAtoms::_atom, _default); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(int32_t aValue) \
+ { \
+ if (aValue < 0) { \
+ return NS_ERROR_DOM_INDEX_SIZE_ERR; \
+ } \
+ return SetIntAttr(nsGkAtoms::_atom, aValue); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given content
+ * property that needs to set an enumerated string. The method
+ * uses a specific GetEnumAttr and the generic SetAttrHelper methods.
+ */
+#define NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default) \
+ NS_IMETHODIMP \
+ _class::Get##_method(nsAString& aValue) \
+ { \
+ GetEnumAttr(nsGkAtoms::_atom, _default, aValue); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(const nsAString& aValue) \
+ { \
+ return SetAttrHelper(nsGkAtoms::_atom, aValue); \
+ }
+
+/**
+ * A macro to implement the getter and setter for a given content
+ * property that needs to set an enumerated string that has different
+ * default values for missing and invalid values. The method uses a
+ * specific GetEnumAttr and the generic SetAttrHelper methods.
+ */
+#define NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(_class, _method, _atom, _defaultMissing, _defaultInvalid) \
+ NS_IMETHODIMP \
+ _class::Get##_method(nsAString& aValue) \
+ { \
+ GetEnumAttr(nsGkAtoms::_atom, _defaultMissing, _defaultInvalid, aValue); \
+ return NS_OK; \
+ } \
+ NS_IMETHODIMP \
+ _class::Set##_method(const nsAString& aValue) \
+ { \
+ return SetAttrHelper(nsGkAtoms::_atom, aValue); \
+ }
+
+#define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag) \
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \
+ mNodeInfo->Equals(nsGkAtoms::_tag))
+
+
+/**
+ * A macro to declare the NS_NewHTMLXXXElement() functions.
+ */
+#define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName) \
+namespace mozilla { \
+namespace dom { \
+class HTML##_elementName##Element; \
+} \
+} \
+nsGenericHTMLElement* \
+NS_NewHTML##_elementName##Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
+
+#define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName) \
+inline nsGenericHTMLElement* \
+NS_NewHTML##_elementName##Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER) \
+{ \
+ return NS_NewHTMLSharedElement(mozilla::Move(aNodeInfo), aFromParser); \
+}
+
+/**
+ * A macro to implement the NS_NewHTMLXXXElement() functions.
+ */
+#define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName) \
+nsGenericHTMLElement* \
+NS_NewHTML##_elementName##Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ mozilla::dom::FromParser aFromParser) \
+{ \
+ return new mozilla::dom::HTML##_elementName##Element(aNodeInfo); \
+}
+
+#define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \
+nsGenericHTMLElement* \
+NS_NewHTML##_elementName##Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \
+ mozilla::dom::FromParser aFromParser) \
+{ \
+ return new mozilla::dom::HTML##_elementName##Element(aNodeInfo, \
+ aFromParser); \
+}
+
+// Here, we expand 'NS_DECLARE_NS_NEW_HTML_ELEMENT()' by hand.
+// (Calling the macro directly (with no args) produces compiler warnings.)
+nsGenericHTMLElement*
+NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
+
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedObject)
+
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Anchor)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Area)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Audio)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(BR)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Body)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Button)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Canvas)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Content)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Mod)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Data)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(DataList)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Details)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Div)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(FieldSet)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Font)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Form)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Frame)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(FrameSet)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(HR)
+NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Head)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Heading)
+NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Html)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(IFrame)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Image)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Input)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(LI)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Label)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Link)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Map)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Menu)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(MenuItem)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Meter)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Object)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Option)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Output)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Picture)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Script)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Select)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Shadow)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Source)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Span)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Style)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Summary)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCaption)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCell)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCol)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Table)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(TableRow)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(TableSection)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Tbody)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Template)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(TextArea)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Tfoot)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Thead)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Time)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Title)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Track)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Unknown)
+NS_DECLARE_NS_NEW_HTML_ELEMENT(Video)
+
+inline nsISupports*
+ToSupports(nsGenericHTMLElement* aHTMLElement)
+{
+ return static_cast<nsIContent*>(aHTMLElement);
+}
+
+inline nsISupports*
+ToCanonicalSupports(nsGenericHTMLElement* aHTMLElement)
+{
+ return static_cast<nsIContent*>(aHTMLElement);
+}
+
+#endif /* nsGenericHTMLElement_h___ */