content/base/public/Element.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=2 et :
     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/. */
     7 /*
     8  * Base class for all element classes; this provides an implementation
     9  * of DOM Core's nsIDOMElement, implements nsIContent, provides
    10  * utility methods for subclasses, and so forth.
    11  */
    13 #ifndef mozilla_dom_Element_h__
    14 #define mozilla_dom_Element_h__
    16 #include "mozilla/dom/FragmentOrElement.h" // for base class
    17 #include "nsChangeHint.h"                  // for enum
    18 #include "mozilla/EventStates.h"           // for member
    19 #include "mozilla/dom/DirectionalityUtils.h"
    20 #include "nsIDOMElement.h"
    21 #include "nsILinkHandler.h"
    22 #include "nsNodeUtils.h"
    23 #include "nsAttrAndChildArray.h"
    24 #include "mozFlushType.h"
    25 #include "nsDOMAttributeMap.h"
    26 #include "nsIDOMXPathNSResolver.h"
    27 #include "nsPresContext.h"
    28 #include "nsDOMClassInfoID.h" // DOMCI_DATA
    29 #include "mozilla/CORSMode.h"
    30 #include "mozilla/Attributes.h"
    31 #include "nsIScrollableFrame.h"
    32 #include "mozilla/dom/Attr.h"
    33 #include "nsISMILAttr.h"
    34 #include "mozilla/dom/DOMRect.h"
    35 #include "nsAttrValue.h"
    36 #include "mozilla/EventForwards.h"
    37 #include "mozilla/dom/BindingDeclarations.h"
    38 #include "Units.h"
    40 class nsIDOMEventListener;
    41 class nsIFrame;
    42 class nsIDOMMozNamedAttrMap;
    43 class nsIDOMCSSStyleDeclaration;
    44 class nsIURI;
    45 class nsINodeInfo;
    46 class nsIControllers;
    47 class nsEventChainVisitor;
    48 class nsIScrollableFrame;
    49 class nsAttrValueOrString;
    50 class ContentUnbinder;
    51 class nsContentList;
    52 class nsDOMTokenList;
    53 struct nsRect;
    54 class nsFocusManager;
    55 class nsGlobalWindow;
    56 class nsICSSDeclaration;
    57 class nsISMILAttr;
    59 already_AddRefed<nsContentList>
    60 NS_GetContentList(nsINode* aRootNode,
    61                   int32_t  aMatchNameSpaceId,
    62                   const nsAString& aTagname);
    64 #define ELEMENT_FLAG_BIT(n_) NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
    66 // Element-specific flags
    67 enum {
    68   // Set if the element has a pending style change.
    69   ELEMENT_HAS_PENDING_RESTYLE =                 ELEMENT_FLAG_BIT(0),
    71   // Set if the element is a potential restyle root (that is, has a style
    72   // change pending _and_ that style change will attempt to restyle
    73   // descendants).
    74   ELEMENT_IS_POTENTIAL_RESTYLE_ROOT =           ELEMENT_FLAG_BIT(1),
    76   // Set if the element has a pending animation style change.
    77   ELEMENT_HAS_PENDING_ANIMATION_RESTYLE =       ELEMENT_FLAG_BIT(2),
    79   // Set if the element is a potential animation restyle root (that is,
    80   // has an animation style change pending _and_ that style change
    81   // will attempt to restyle descendants).
    82   ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT = ELEMENT_FLAG_BIT(3),
    84   // All of those bits together, for convenience.
    85   ELEMENT_ALL_RESTYLE_FLAGS = ELEMENT_HAS_PENDING_RESTYLE |
    86                               ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
    87                               ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
    88                               ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT,
    90   // Just the HAS_PENDING bits, for convenience
    91   ELEMENT_PENDING_RESTYLE_FLAGS = ELEMENT_HAS_PENDING_RESTYLE |
    92                                   ELEMENT_HAS_PENDING_ANIMATION_RESTYLE,
    94   // Remaining bits are for subclasses
    95   ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 4
    96 };
    98 #undef ELEMENT_FLAG_BIT
   100 // Make sure we have space for our bits
   101 ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
   103 namespace mozilla {
   104 class EventChainPostVisitor;
   105 class EventChainPreVisitor;
   106 class EventChainVisitor;
   107 class EventListenerManager;
   108 class EventStateManager;
   110 namespace dom {
   112 class Link;
   113 class UndoManager;
   114 class DOMRect;
   115 class DOMRectList;
   117 // IID for the dom::Element interface
   118 #define NS_ELEMENT_IID \
   119 { 0xf7c18f0f, 0xa8fd, 0x4a95, \
   120   { 0x91, 0x72, 0xd3, 0xa7, 0x4a, 0xb8, 0xc4, 0xbe } }
   122 class Element : public FragmentOrElement
   123 {
   124 public:
   125 #ifdef MOZILLA_INTERNAL_API
   126   Element(already_AddRefed<nsINodeInfo>& aNodeInfo) :
   127     FragmentOrElement(aNodeInfo),
   128     mState(NS_EVENT_STATE_MOZ_READONLY)
   129   {
   130     NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
   131                       "Bad NodeType in aNodeInfo");
   132     SetIsElement();
   133   }
   134 #endif // MOZILLA_INTERNAL_API
   136   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
   138   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
   140   /**
   141    * Method to get the full state of this element.  See mozilla/EventStates.h
   142    * for the possible bits that could be set here.
   143    */
   144   EventStates State() const
   145   {
   146     // mState is maintained by having whoever might have changed it
   147     // call UpdateState() or one of the other mState mutators.
   148     return mState;
   149   }
   151   /**
   152    * Ask this element to update its state.  If aNotify is false, then
   153    * state change notifications will not be dispatched; in that
   154    * situation it is the caller's responsibility to dispatch them.
   155    *
   156    * In general, aNotify should only be false if we're guaranteed that
   157    * the element can't have a frame no matter what its style is
   158    * (e.g. if we're in the middle of adding it to the document or
   159    * removing it from the document).
   160    */
   161   void UpdateState(bool aNotify);
   163   /**
   164    * Method to update mState with link state information.  This does not notify.
   165    */
   166   void UpdateLinkState(EventStates aState);
   168   /**
   169    * Returns true if this element is either a full-screen element or an
   170    * ancestor of the full-screen element.
   171    */
   172   bool IsFullScreenAncestor() const {
   173     return mState.HasAtLeastOneOfStates(NS_EVENT_STATE_FULL_SCREEN_ANCESTOR |
   174                                         NS_EVENT_STATE_FULL_SCREEN);
   175   }
   177   /**
   178    * The style state of this element. This is the real state of the element
   179    * with any style locks applied for pseudo-class inspecting.
   180    */
   181   EventStates StyleState() const
   182   {
   183     if (!HasLockedStyleStates()) {
   184       return mState;
   185     }
   186     return StyleStateFromLocks();
   187   }
   189   /**
   190    * The style state locks applied to this element.
   191    */
   192   EventStates LockedStyleStates() const;
   194   /**
   195    * Add a style state lock on this element.
   196    */
   197   void LockStyleStates(EventStates aStates);
   199   /**
   200    * Remove a style state lock on this element.
   201    */
   202   void UnlockStyleStates(EventStates aStates);
   204   /**
   205    * Clear all style state locks on this element.
   206    */
   207   void ClearStyleStateLocks();
   209   /**
   210    * Get the inline style rule, if any, for this element.
   211    */
   212   virtual css::StyleRule* GetInlineStyleRule();
   214   /**
   215    * Set the inline style rule for this element. This will send an appropriate
   216    * AttributeChanged notification if aNotify is true.
   217    */
   218   virtual nsresult SetInlineStyleRule(css::StyleRule* aStyleRule,
   219                                       const nsAString* aSerialized,
   220                                       bool aNotify);
   222   /**
   223    * Get the SMIL override style rule for this element. If the rule hasn't been
   224    * created, this method simply returns null.
   225    */
   226   virtual css::StyleRule* GetSMILOverrideStyleRule();
   228   /**
   229    * Set the SMIL override style rule for this element. If aNotify is true, this
   230    * method will notify the document's pres context, so that the style changes
   231    * will be noticed.
   232    */
   233   virtual nsresult SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
   234                                             bool aNotify);
   236   /**
   237    * Returns a new nsISMILAttr that allows the caller to animate the given
   238    * attribute on this element.
   239    *
   240    * The CALLER OWNS the result and is responsible for deleting it.
   241    */
   242   virtual nsISMILAttr* GetAnimatedAttr(int32_t aNamespaceID, nsIAtom* aName)
   243   {
   244     return nullptr;
   245   }
   247   /**
   248    * Get the SMIL override style for this element. This is a style declaration
   249    * that is applied *after* the inline style, and it can be used e.g. to store
   250    * animated style values.
   251    *
   252    * Note: This method is analogous to the 'GetStyle' method in
   253    * nsGenericHTMLElement and nsStyledElement.
   254    */
   255   virtual nsICSSDeclaration* GetSMILOverrideStyle();
   257   /**
   258    * Returns if the element is labelable as per HTML specification.
   259    */
   260   virtual bool IsLabelable() const;
   262   /**
   263    * Is the attribute named stored in the mapped attributes?
   264    *
   265    * // XXXbz we use this method in HasAttributeDependentStyle, so svg
   266    *    returns true here even though it stores nothing in the mapped
   267    *    attributes.
   268    */
   269   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   271   /**
   272    * Get a hint that tells the style system what to do when
   273    * an attribute on this node changes, if something needs to happen
   274    * in response to the change *other* than the result of what is
   275    * mapped into style data via any type of style rule.
   276    */
   277   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
   278                                               int32_t aModType) const;
   280   /**
   281    * Returns an atom holding the name of the "class" attribute on this
   282    * content node (if applicable).  Returns null if there is no
   283    * "class" attribute for this type of content node.
   284    */
   285   virtual nsIAtom *GetClassAttributeName() const;
   287   inline Directionality GetDirectionality() const {
   288     if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
   289       return eDir_RTL;
   290     }
   292     if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
   293       return eDir_LTR;
   294     }
   296     return eDir_NotSet;
   297   }
   299   inline void SetDirectionality(Directionality aDir, bool aNotify) {
   300     UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
   301     if (!aNotify) {
   302       RemoveStatesSilently(DIRECTION_STATES);
   303     }
   305     switch (aDir) {
   306       case (eDir_RTL):
   307         SetFlags(NODE_HAS_DIRECTION_RTL);
   308         if (!aNotify) {
   309           AddStatesSilently(NS_EVENT_STATE_RTL);
   310         }
   311         break;
   313       case(eDir_LTR):
   314         SetFlags(NODE_HAS_DIRECTION_LTR);
   315         if (!aNotify) {
   316           AddStatesSilently(NS_EVENT_STATE_LTR);
   317         }
   318         break;
   320       default:
   321         break;
   322     }
   324     /* 
   325      * Only call UpdateState if we need to notify, because we call
   326      * SetDirectionality for every element, and UpdateState is very very slow
   327      * for some elements.
   328      */
   329     if (aNotify) {
   330       UpdateState(true);
   331     }
   332   }
   334   bool GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult);
   336   // The bdi element defaults to dir=auto if it has no dir attribute set.
   337   // Other elements will only have dir=auto if they have an explicit dir=auto,
   338   // which will mean that HasValidDir() returns true but HasFixedDir() returns
   339   // false
   340   inline bool HasDirAuto() const {
   341     return (!HasFixedDir() &&
   342             (HasValidDir() || IsHTML(nsGkAtoms::bdi)));
   343   }
   345   Directionality GetComputedDirectionality() const;
   347 protected:
   348   /**
   349    * Method to get the _intrinsic_ content state of this element.  This is the
   350    * state that is independent of the element's presentation.  To get the full
   351    * content state, use State().  See mozilla/EventStates.h for
   352    * the possible bits that could be set here.
   353    */
   354   virtual EventStates IntrinsicState() const;
   356   /**
   357    * Method to add state bits.  This should be called from subclass
   358    * constructors to set up our event state correctly at construction
   359    * time and other places where we don't want to notify a state
   360    * change.
   361    */
   362   void AddStatesSilently(EventStates aStates)
   363   {
   364     mState |= aStates;
   365   }
   367   /**
   368    * Method to remove state bits.  This should be called from subclass
   369    * constructors to set up our event state correctly at construction
   370    * time and other places where we don't want to notify a state
   371    * change.
   372    */
   373   void RemoveStatesSilently(EventStates aStates)
   374   {
   375     mState &= ~aStates;
   376   }
   378 private:
   379   // Need to allow the ESM, nsGlobalWindow, and the focus manager to
   380   // set our state
   381   friend class mozilla::EventStateManager;
   382   friend class ::nsGlobalWindow;
   383   friend class ::nsFocusManager;
   385   // Also need to allow Link to call UpdateLinkState.
   386   friend class Link;
   388   void NotifyStateChange(EventStates aStates);
   390   void NotifyStyleStateChange(EventStates aStates);
   392   // Style state computed from element's state and style locks.
   393   EventStates StyleStateFromLocks() const;
   395 protected:
   396   // Methods for the ESM to manage state bits.  These will handle
   397   // setting up script blockers when they notify, so no need to do it
   398   // in the callers unless desired.
   399   virtual void AddStates(EventStates aStates)
   400   {
   401     NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
   402                     "Should only be adding ESM-managed states here");
   403     AddStatesSilently(aStates);
   404     NotifyStateChange(aStates);
   405   }
   406   virtual void RemoveStates(EventStates aStates)
   407   {
   408     NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
   409                     "Should only be removing ESM-managed states here");
   410     RemoveStatesSilently(aStates);
   411     NotifyStateChange(aStates);
   412   }
   413 public:
   414   virtual void UpdateEditableState(bool aNotify) MOZ_OVERRIDE;
   416   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
   417                               nsIContent* aBindingParent,
   418                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   419   virtual void UnbindFromTree(bool aDeep = true,
   420                               bool aNullParent = true) MOZ_OVERRIDE;
   422   /**
   423    * Normalizes an attribute name and returns it as a nodeinfo if an attribute
   424    * with that name exists. This method is intended for character case
   425    * conversion if the content object is case insensitive (e.g. HTML). Returns
   426    * the nodeinfo of the attribute with the specified name if one exists or
   427    * null otherwise.
   428    *
   429    * @param aStr the unparsed attribute string
   430    * @return the node info. May be nullptr.
   431    */
   432   already_AddRefed<nsINodeInfo>
   433   GetExistingAttrNameFromQName(const nsAString& aStr) const;
   435   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
   436                    const nsAString& aValue, bool aNotify)
   437   {
   438     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   439   }
   441   /**
   442    * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify
   443    * is true or there are mutation listeners that must be triggered, the
   444    * attribute is currently set, and the new value that is about to be set is
   445    * different to the current value. As a perf optimization the new and old
   446    * values will not actually be compared if we aren't notifying and we don't
   447    * have mutation listeners (in which case it's cheap to just return false
   448    * and let the caller go ahead and set the value).
   449    * @param aOldValue Set to the old value of the attribute, but only if there
   450    *   are event listeners. If set, the type of aOldValue will be either
   451    *   nsAttrValue::eString or nsAttrValue::eAtom.
   452    * @param aModType Set to nsIDOMMutationEvent::MODIFICATION or to
   453    *   nsIDOMMutationEvent::ADDITION, but only if this helper returns true
   454    * @param aHasListeners Set to true if there are mutation event listeners
   455    *   listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
   456    */
   457   bool MaybeCheckSameAttrVal(int32_t aNamespaceID, nsIAtom* aName,
   458                              nsIAtom* aPrefix,
   459                              const nsAttrValueOrString& aValue,
   460                              bool aNotify, nsAttrValue& aOldValue,
   461                              uint8_t* aModType, bool* aHasListeners);
   463   bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
   464                               nsIAtom* aPrefix,
   465                               const nsAttrValueOrString& aValue,
   466                               bool aNotify, nsAttrValue& aOldValue,
   467                               uint8_t* aModType, bool* aHasListeners);
   469   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
   470                            const nsAString& aValue, bool aNotify) MOZ_OVERRIDE;
   471   nsresult SetParsedAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
   472                          nsAttrValue& aParsedValue, bool aNotify);
   473   // GetAttr is not inlined on purpose, to keep down codesize from all
   474   // the inlined nsAttrValue bits for C++ callers.
   475   bool GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
   476                nsAString& aResult) const;
   477   inline bool HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const;
   478   // aCaseSensitive == eIgnoreCaase means ASCII case-insensitive matching.
   479   inline bool AttrValueIs(int32_t aNameSpaceID, nsIAtom* aName,
   480                           const nsAString& aValue,
   481                           nsCaseTreatment aCaseSensitive) const;
   482   inline bool AttrValueIs(int32_t aNameSpaceID, nsIAtom* aName,
   483                           nsIAtom* aValue,
   484                           nsCaseTreatment aCaseSensitive) const;
   485   virtual int32_t FindAttrValueIn(int32_t aNameSpaceID,
   486                                   nsIAtom* aName,
   487                                   AttrValuesArray* aValues,
   488                                   nsCaseTreatment aCaseSensitive) const MOZ_OVERRIDE;
   489   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
   490                              bool aNotify) MOZ_OVERRIDE;
   491   virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const MOZ_OVERRIDE;
   492   virtual uint32_t GetAttrCount() const MOZ_OVERRIDE;
   493   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
   495 #ifdef DEBUG
   496   virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE
   497   {
   498     List(out, aIndent, EmptyCString());
   499   }
   500   virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const MOZ_OVERRIDE;
   501   void List(FILE* out, int32_t aIndent, const nsCString& aPrefix) const;
   502   void ListAttributes(FILE* out) const;
   503 #endif
   505   void Describe(nsAString& aOutDescription) const MOZ_OVERRIDE;
   507   /*
   508    * Attribute Mapping Helpers
   509    */
   510   struct MappedAttributeEntry {
   511     nsIAtom** attribute;
   512   };
   514   /**
   515    * A common method where you can just pass in a list of maps to check
   516    * for attribute dependence. Most implementations of
   517    * IsAttributeMapped should use this function as a default
   518    * handler.
   519    */
   520   template<size_t N>
   521   static bool
   522   FindAttributeDependence(const nsIAtom* aAttribute,
   523                           const MappedAttributeEntry* const (&aMaps)[N])
   524   {
   525     return FindAttributeDependence(aAttribute, aMaps, N);
   526   }
   528 private:
   529   void DescribeAttribute(uint32_t index, nsAString& aOutDescription) const;
   531   static bool
   532   FindAttributeDependence(const nsIAtom* aAttribute,
   533                           const MappedAttributeEntry* const aMaps[],
   534                           uint32_t aMapCount);
   536 protected:
   537   inline bool GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
   538                       DOMString& aResult) const
   539   {
   540     NS_ASSERTION(nullptr != aName, "must have attribute name");
   541     NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
   542                  "must have a real namespace ID!");
   543     MOZ_ASSERT(aResult.HasStringBuffer() && aResult.StringBufferLength() == 0,
   544                "Should have empty string coming in");
   545     const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
   546     if (val) {
   547       val->ToString(aResult);
   548       return true;
   549     }
   550     // else DOMString comes pre-emptied.
   551     return false;
   552   }
   554 public:
   555   bool HasAttrs() const { return mAttrsAndChildren.HasAttrs(); }
   557   inline bool GetAttr(const nsAString& aName, DOMString& aResult) const
   558   {
   559     MOZ_ASSERT(aResult.HasStringBuffer() && aResult.StringBufferLength() == 0,
   560                "Should have empty string coming in");
   561     const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName);
   562     if (val) {
   563       val->ToString(aResult);
   564       return true;
   565     }
   566     // else DOMString comes pre-emptied.
   567     return false;
   568   }
   570   void GetTagName(nsAString& aTagName) const
   571   {
   572     aTagName = NodeName();
   573   }
   574   void GetId(nsAString& aId) const
   575   {
   576     GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
   577   }
   578   void GetId(DOMString& aId) const
   579   {
   580     GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
   581   }
   582   void SetId(const nsAString& aId)
   583   {
   584     SetAttr(kNameSpaceID_None, nsGkAtoms::id, aId, true);
   585   }
   587   nsDOMTokenList* GetClassList();
   588   nsDOMAttributeMap* Attributes()
   589   {
   590     nsDOMSlots* slots = DOMSlots();
   591     if (!slots->mAttributeMap) {
   592       slots->mAttributeMap = new nsDOMAttributeMap(this);
   593     }
   595     return slots->mAttributeMap;
   596   }
   597   void GetAttribute(const nsAString& aName, nsString& aReturn)
   598   {
   599     DOMString str;
   600     GetAttribute(aName, str);
   601     str.ToString(aReturn);
   602   }
   604   void GetAttribute(const nsAString& aName, DOMString& aReturn);
   605   void GetAttributeNS(const nsAString& aNamespaceURI,
   606                       const nsAString& aLocalName,
   607                       nsAString& aReturn);
   608   void SetAttribute(const nsAString& aName, const nsAString& aValue,
   609                     ErrorResult& aError);
   610   void SetAttributeNS(const nsAString& aNamespaceURI,
   611                       const nsAString& aLocalName,
   612                       const nsAString& aValue,
   613                       ErrorResult& aError);
   614   void RemoveAttribute(const nsAString& aName,
   615                        ErrorResult& aError);
   616   void RemoveAttributeNS(const nsAString& aNamespaceURI,
   617                          const nsAString& aLocalName,
   618                          ErrorResult& aError);
   619   bool HasAttribute(const nsAString& aName) const
   620   {
   621     return InternalGetExistingAttrNameFromQName(aName) != nullptr;
   622   }
   623   bool HasAttributeNS(const nsAString& aNamespaceURI,
   624                       const nsAString& aLocalName) const;
   625   already_AddRefed<nsIHTMLCollection>
   626     GetElementsByTagName(const nsAString& aQualifiedName);
   627   already_AddRefed<nsIHTMLCollection>
   628     GetElementsByTagNameNS(const nsAString& aNamespaceURI,
   629                            const nsAString& aLocalName,
   630                            ErrorResult& aError);
   631   already_AddRefed<nsIHTMLCollection>
   632     GetElementsByClassName(const nsAString& aClassNames);
   633   bool MozMatchesSelector(const nsAString& aSelector,
   634                           ErrorResult& aError);
   635   void SetPointerCapture(int32_t aPointerId, ErrorResult& aError)
   636   {
   637     bool activeState = false;
   638     if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
   639       aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
   640       return;
   641     }
   642     if (!activeState) {
   643       return;
   644     }
   645     nsIPresShell::SetPointerCapturingContent(aPointerId, this);
   646   }
   647   void ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError)
   648   {
   649     bool activeState = false;
   650     if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
   651       aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
   652       return;
   653     }
   655     // Ignoring ReleasePointerCapture call on incorrect element (on element
   656     // that didn't have capture before).
   657     if (nsIPresShell::GetPointerCapturingContent(aPointerId) == this) {
   658       nsIPresShell::ReleasePointerCapturingContent(aPointerId, this);
   659     }
   660   }
   661   void SetCapture(bool aRetargetToElement)
   662   {
   663     // If there is already an active capture, ignore this request. This would
   664     // occur if a splitter, frame resizer, etc had already captured and we don't
   665     // want to override those.
   666     if (!nsIPresShell::GetCapturingContent()) {
   667       nsIPresShell::SetCapturingContent(this, CAPTURE_PREVENTDRAG |
   668         (aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
   669     }
   670   }
   671   void ReleaseCapture()
   672   {
   673     if (nsIPresShell::GetCapturingContent() == this) {
   674       nsIPresShell::SetCapturingContent(nullptr, 0);
   675     }
   676   }
   677   void MozRequestFullScreen();
   678   void MozRequestPointerLock();
   679   Attr* GetAttributeNode(const nsAString& aName);
   680   already_AddRefed<Attr> SetAttributeNode(Attr& aNewAttr,
   681                                           ErrorResult& aError);
   682   already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
   683                                              ErrorResult& aError);
   684   Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
   685                            const nsAString& aLocalName);
   686   already_AddRefed<Attr> SetAttributeNodeNS(Attr& aNewAttr,
   687                                             ErrorResult& aError);
   689   already_AddRefed<DOMRectList> GetClientRects();
   690   already_AddRefed<DOMRect> GetBoundingClientRect();
   692   already_AddRefed<ShadowRoot> CreateShadowRoot(ErrorResult& aError);
   694   void ScrollIntoView()
   695   {
   696     ScrollIntoView(true);
   697   }
   698   void ScrollIntoView(bool aTop);
   699   int32_t ScrollTop()
   700   {
   701     nsIScrollableFrame* sf = GetScrollFrame();
   702     return sf ? sf->GetScrollPositionCSSPixels().y : 0;
   703   }
   704   void SetScrollTop(int32_t aScrollTop)
   705   {
   706     nsIScrollableFrame* sf = GetScrollFrame();
   707     if (sf) {
   708       sf->ScrollToCSSPixels(CSSIntPoint(sf->GetScrollPositionCSSPixels().x,
   709                                         aScrollTop));
   710     }
   711   }
   712   int32_t ScrollLeft()
   713   {
   714     nsIScrollableFrame* sf = GetScrollFrame();
   715     return sf ? sf->GetScrollPositionCSSPixels().x : 0;
   716   }
   717   void SetScrollLeft(int32_t aScrollLeft)
   718   {
   719     nsIScrollableFrame* sf = GetScrollFrame();
   720     if (sf) {
   721       sf->ScrollToCSSPixels(CSSIntPoint(aScrollLeft,
   722                                         sf->GetScrollPositionCSSPixels().y));
   723     }
   724   }
   725   /* Scrolls without flushing the layout.
   726    * aDx is the x offset, aDy the y offset in CSS pixels.
   727    * Returns true if we actually scrolled.
   728    */
   729   bool ScrollByNoFlush(int32_t aDx, int32_t aDy);
   730   int32_t ScrollWidth();
   731   int32_t ScrollHeight();
   732   int32_t ClientTop()
   733   {
   734     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y);
   735   }
   736   int32_t ClientLeft()
   737   {
   738     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().x);
   739   }
   740   int32_t ClientWidth()
   741   {
   742     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().width);
   743   }
   744   int32_t ClientHeight()
   745   {
   746     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().height);
   747   }
   748   int32_t ScrollTopMax()
   749   {
   750     nsIScrollableFrame* sf = GetScrollFrame();
   751     return sf ?
   752            nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().YMost()) :
   753            0;
   754   }
   755   int32_t ScrollLeftMax()
   756   {
   757     nsIScrollableFrame* sf = GetScrollFrame();
   758     return sf ?
   759            nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().XMost()) :
   760            0;
   761   }
   763   virtual already_AddRefed<UndoManager> GetUndoManager()
   764   {
   765     return nullptr;
   766   }
   768   virtual bool UndoScope()
   769   {
   770     return false;
   771   }
   773   virtual void SetUndoScope(bool aUndoScope, ErrorResult& aError)
   774   {
   775   }
   777   NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
   778   virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
   779   void GetOuterHTML(nsAString& aOuterHTML);
   780   void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
   781   void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
   782                           ErrorResult& aError);
   784   //----------------------------------------
   786   /**
   787    * Add a script event listener with the given event handler name
   788    * (like onclick) and with the value as JS
   789    * @param aEventName the event listener name
   790    * @param aValue the JS to attach
   791    * @param aDefer indicates if deferred execution is allowed
   792    */
   793   nsresult SetEventHandler(nsIAtom* aEventName,
   794                            const nsAString& aValue,
   795                            bool aDefer = true);
   797   /**
   798    * Do whatever needs to be done when the mouse leaves a link
   799    */
   800   nsresult LeaveLink(nsPresContext* aPresContext);
   802   static bool ShouldBlur(nsIContent *aContent);
   804   /**
   805    * Method to create and dispatch a left-click event loosely based on
   806    * aSourceEvent. If aFullDispatch is true, the event will be dispatched
   807    * through the full dispatching of the presshell of the aPresContext; if it's
   808    * false the event will be dispatched only as a DOM event.
   809    * If aPresContext is nullptr, this does nothing.
   810    *
   811    * @param aFlags      Extra flags for the dispatching event.  The true flags
   812    *                    will be respected.
   813    */
   814   static nsresult DispatchClickEvent(nsPresContext* aPresContext,
   815                                      WidgetInputEvent* aSourceEvent,
   816                                      nsIContent* aTarget,
   817                                      bool aFullDispatch,
   818                                      const EventFlags* aFlags,
   819                                      nsEventStatus* aStatus);
   821   /**
   822    * Method to dispatch aEvent to aTarget. If aFullDispatch is true, the event
   823    * will be dispatched through the full dispatching of the presshell of the
   824    * aPresContext; if it's false the event will be dispatched only as a DOM
   825    * event.
   826    * If aPresContext is nullptr, this does nothing.
   827    */
   828   using nsIContent::DispatchEvent;
   829   static nsresult DispatchEvent(nsPresContext* aPresContext,
   830                                 WidgetEvent* aEvent,
   831                                 nsIContent* aTarget,
   832                                 bool aFullDispatch,
   833                                 nsEventStatus* aStatus);
   835   /**
   836    * Get the primary frame for this content with flushing
   837    *
   838    * @param aType the kind of flush to do, typically Flush_Frames or
   839    *              Flush_Layout
   840    * @return the primary frame
   841    */
   842   nsIFrame* GetPrimaryFrame(mozFlushType aType);
   843   // Work around silly C++ name hiding stuff
   844   nsIFrame* GetPrimaryFrame() const { return nsIContent::GetPrimaryFrame(); }
   846   /**
   847    * Struct that stores info on an attribute.  The name and value must
   848    * either both be null or both be non-null.
   849    */
   850   struct nsAttrInfo {
   851     nsAttrInfo(const nsAttrName* aName, const nsAttrValue* aValue) :
   852       mName(aName), mValue(aValue) {}
   853     nsAttrInfo(const nsAttrInfo& aOther) :
   854       mName(aOther.mName), mValue(aOther.mValue) {}
   856     const nsAttrName* mName;
   857     const nsAttrValue* mValue;
   858   };
   860   // Be careful when using this method. This does *NOT* handle
   861   // XUL prototypes. You may want to use GetAttrInfo.
   862   const nsAttrValue* GetParsedAttr(nsIAtom* aAttr) const
   863   {
   864     return mAttrsAndChildren.GetAttr(aAttr);
   865   }
   867   /**
   868    * Returns the attribute map, if there is one.
   869    *
   870    * @return existing attribute map or nullptr.
   871    */
   872   nsDOMAttributeMap *GetAttributeMap()
   873   {
   874     nsDOMSlots *slots = GetExistingDOMSlots();
   876     return slots ? slots->mAttributeMap.get() : nullptr;
   877   }
   879   virtual void RecompileScriptEventListeners()
   880   {
   881   }
   883   /**
   884    * Get the attr info for the given namespace ID and attribute name.  The
   885    * namespace ID must not be kNameSpaceID_Unknown and the name must not be
   886    * null.  Note that this can only return info on attributes that actually
   887    * live on this element (and is only virtual to handle XUL prototypes).  That
   888    * is, this should only be called from methods that only care about attrs
   889    * that effectively live in mAttrsAndChildren.
   890    */
   891   virtual nsAttrInfo GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const;
   893   virtual void NodeInfoChanged(nsINodeInfo* aOldNodeInfo)
   894   {
   895   }
   897   /**
   898    * Parse a string into an nsAttrValue for a CORS attribute.  This
   899    * never fails.  The resulting value is an enumerated value whose
   900    * GetEnumValue() returns one of the above constants.
   901    */
   902   static void ParseCORSValue(const nsAString& aValue, nsAttrValue& aResult);
   904   /**
   905    * Return the CORS mode for a given string
   906    */
   907   static CORSMode StringToCORSMode(const nsAString& aValue);
   909   /**
   910    * Return the CORS mode for a given nsAttrValue (which may be null,
   911    * but if not should have been parsed via ParseCORSValue).
   912    */
   913   static CORSMode AttrValueToCORSMode(const nsAttrValue* aValue);
   915   // These are just used to implement nsIDOMElement using
   916   // NS_FORWARD_NSIDOMELEMENT_TO_GENERIC and for quickstubs.
   917   void
   918     GetElementsByTagName(const nsAString& aQualifiedName,
   919                          nsIDOMHTMLCollection** aResult);
   920   nsresult
   921     GetElementsByTagNameNS(const nsAString& aNamespaceURI,
   922                            const nsAString& aLocalName,
   923                            nsIDOMHTMLCollection** aResult);
   924   nsresult
   925     GetElementsByClassName(const nsAString& aClassNames,
   926                            nsIDOMHTMLCollection** aResult);
   927   void GetClassList(nsISupports** aClassList);
   929   virtual JSObject* WrapObject(JSContext *aCx) MOZ_FINAL MOZ_OVERRIDE;
   931   /**
   932    * Locate an nsIEditor rooted at this content node, if there is one.
   933    */
   934   nsIEditor* GetEditorInternal();
   936   /**
   937    * Helper method for NS_IMPL_BOOL_ATTR macro.
   938    * Gets value of boolean attribute. Only works for attributes in null
   939    * namespace.
   940    *
   941    * @param aAttr    name of attribute.
   942    * @param aValue   Boolean value of attribute.
   943    */
   944   NS_HIDDEN_(bool) GetBoolAttr(nsIAtom* aAttr) const
   945   {
   946     return HasAttr(kNameSpaceID_None, aAttr);
   947   }
   949   /**
   950    * Helper method for NS_IMPL_BOOL_ATTR macro.
   951    * Sets value of boolean attribute by removing attribute or setting it to
   952    * the empty string. Only works for attributes in null namespace.
   953    *
   954    * @param aAttr    name of attribute.
   955    * @param aValue   Boolean value of attribute.
   956    */
   957   NS_HIDDEN_(nsresult) SetBoolAttr(nsIAtom* aAttr, bool aValue);
   959   /**
   960    * Retrieve the ratio of font-size-inflated text font size to computed font
   961    * size for this element. This will query the element for its primary frame,
   962    * and then use this to get font size inflation information about the frame.
   963    *
   964    * @returns The font size inflation ratio (inflated font size to uninflated
   965    *          font size) for the primary frame of this element. Returns 1.0
   966    *          by default if font size inflation is not enabled. Returns -1
   967    *          if the element does not have a primary frame.
   968    *
   969    * @note The font size inflation ratio that is returned is actually the
   970    *       font size inflation data for the element's _primary frame_, not the
   971    *       element itself, but for most purposes, this should be sufficient.
   972    */
   973   float FontSizeInflation();
   975 protected:
   976   /*
   977    * Named-bools for use with SetAttrAndNotify to make call sites easier to
   978    * read.
   979    */
   980   static const bool kFireMutationEvent           = true;
   981   static const bool kDontFireMutationEvent       = false;
   982   static const bool kNotifyDocumentObservers     = true;
   983   static const bool kDontNotifyDocumentObservers = false;
   984   static const bool kCallAfterSetAttr            = true;
   985   static const bool kDontCallAfterSetAttr        = false;
   987   /**
   988    * Set attribute and (if needed) notify documentobservers and fire off
   989    * mutation events.  This will send the AttributeChanged notification.
   990    * Callers of this method are responsible for calling AttributeWillChange,
   991    * since that needs to happen before the new attr value has been set, and
   992    * in particular before it has been parsed.
   993    *
   994    * For the boolean parameters, consider using the named bools above to aid
   995    * code readability.
   996    *
   997    * @param aNamespaceID  namespace of attribute
   998    * @param aAttribute    local-name of attribute
   999    * @param aPrefix       aPrefix of attribute
  1000    * @param aOldValue     previous value of attribute. Only needed if
  1001    *                      aFireMutation is true or if the element is a
  1002    *                      custom element (in web components).
  1003    * @param aParsedValue  parsed new value of attribute
  1004    * @param aModType      nsIDOMMutationEvent::MODIFICATION or ADDITION.  Only
  1005    *                      needed if aFireMutation or aNotify is true.
  1006    * @param aFireMutation should mutation-events be fired?
  1007    * @param aNotify       should we notify document-observers?
  1008    * @param aCallAfterSetAttr should we call AfterSetAttr?
  1009    */
  1010   nsresult SetAttrAndNotify(int32_t aNamespaceID,
  1011                             nsIAtom* aName,
  1012                             nsIAtom* aPrefix,
  1013                             const nsAttrValue& aOldValue,
  1014                             nsAttrValue& aParsedValue,
  1015                             uint8_t aModType,
  1016                             bool aFireMutation,
  1017                             bool aNotify,
  1018                             bool aCallAfterSetAttr);
  1020   /**
  1021    * Convert an attribute string value to attribute type based on the type of
  1022    * attribute.  Called by SetAttr().  Note that at the moment we only do this
  1023    * for attributes in the null namespace (kNameSpaceID_None).
  1025    * @param aNamespaceID the namespace of the attribute to convert
  1026    * @param aAttribute the attribute to convert
  1027    * @param aValue the string value to convert
  1028    * @param aResult the nsAttrValue [OUT]
  1029    * @return true if the parsing was successful, false otherwise
  1030    */
  1031   virtual bool ParseAttribute(int32_t aNamespaceID,
  1032                                 nsIAtom* aAttribute,
  1033                                 const nsAString& aValue,
  1034                                 nsAttrValue& aResult);
  1036   /**
  1037    * Try to set the attribute as a mapped attribute, if applicable.  This will
  1038    * only be called for attributes that are in the null namespace and only on
  1039    * attributes that returned true when passed to IsAttributeMapped.  The
  1040    * caller will not try to set the attr in any other way if this method
  1041    * returns true (the value of aRetval does not matter for that purpose).
  1043    * @param aDocument the current document of this node (an optimization)
  1044    * @param aName the name of the attribute
  1045    * @param aValue the nsAttrValue to set
  1046    * @param [out] aRetval the nsresult status of the operation, if any.
  1047    * @return true if the setting was attempted, false otherwise.
  1048    */
  1049   virtual bool SetMappedAttribute(nsIDocument* aDocument,
  1050                                     nsIAtom* aName,
  1051                                     nsAttrValue& aValue,
  1052                                     nsresult* aRetval);
  1054   /**
  1055    * Hook that is called by Element::SetAttr to allow subclasses to
  1056    * deal with attribute sets.  This will only be called after we verify that
  1057    * we're actually doing an attr set and will be called before
  1058    * AttributeWillChange and before ParseAttribute and hence before we've set
  1059    * the new value.
  1061    * @param aNamespaceID the namespace of the attr being set
  1062    * @param aName the localname of the attribute being set
  1063    * @param aValue the value it's being set to represented as either a string or
  1064    *        a parsed nsAttrValue. Alternatively, if the attr is being removed it
  1065    *        will be null.
  1066    * @param aNotify Whether we plan to notify document observers.
  1067    */
  1068   // Note that this is inlined so that when subclasses call it it gets
  1069   // inlined.  Those calls don't go through a vtable.
  1070   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
  1071                                  const nsAttrValueOrString* aValue,
  1072                                  bool aNotify)
  1074     return NS_OK;
  1077   /**
  1078    * Hook that is called by Element::SetAttr to allow subclasses to
  1079    * deal with attribute sets.  This will only be called after we have called
  1080    * SetAndTakeAttr and AttributeChanged (that is, after we have actually set
  1081    * the attr).  It will always be called under a scriptblocker.
  1083    * @param aNamespaceID the namespace of the attr being set
  1084    * @param aName the localname of the attribute being set
  1085    * @param aValue the value it's being set to.  If null, the attr is being
  1086    *        removed.
  1087    * @param aNotify Whether we plan to notify document observers.
  1088    */
  1089   // Note that this is inlined so that when subclasses call it it gets
  1090   // inlined.  Those calls don't go through a vtable.
  1091   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
  1092                                 const nsAttrValue* aValue, bool aNotify)
  1094     return NS_OK;
  1097   /**
  1098    * Hook to allow subclasses to produce a different EventListenerManager if
  1099    * needed for attachment of attribute-defined handlers
  1100    */
  1101   virtual EventListenerManager*
  1102     GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer);
  1104   /**
  1105    * Internal hook for converting an attribute name-string to an atomized name
  1106    */
  1107   virtual const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
  1109   nsIFrame* GetStyledFrame();
  1111   virtual Element* GetNameSpaceElement()
  1113     return this;
  1116   Attr* GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
  1117                                    const nsAString& aLocalName);
  1119   inline void RegisterFreezableElement();
  1120   inline void UnregisterFreezableElement();
  1122   /**
  1123    * Add/remove this element to the documents id cache
  1124    */
  1125   void AddToIdTable(nsIAtom* aId);
  1126   void RemoveFromIdTable(); // checks HasID() and uses DoGetID()
  1127   void RemoveFromIdTable(nsIAtom* aId);
  1129   /**
  1130    * Functions to carry out event default actions for links of all types
  1131    * (HTML links, XLinks, SVG "XLinks", etc.)
  1132    */
  1134   /**
  1135    * Check that we meet the conditions to handle a link event
  1136    * and that we are actually on a link.
  1138    * @param aVisitor event visitor
  1139    * @param aURI the uri of the link, set only if the return value is true [OUT]
  1140    * @return true if we can handle the link event, false otherwise
  1141    */
  1142   bool CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor,
  1143                                             nsIURI** aURI) const;
  1145   /**
  1146    * Handle status bar updates before they can be cancelled.
  1147    */
  1148   nsresult PreHandleEventForLinks(EventChainPreVisitor& aVisitor);
  1150   /**
  1151    * Handle default actions for link event if the event isn't consumed yet.
  1152    */
  1153   nsresult PostHandleEventForLinks(EventChainPostVisitor& aVisitor);
  1155   /**
  1156    * Get the target of this link element. Consumers should established that
  1157    * this element is a link (probably using IsLink) before calling this
  1158    * function (or else why call it?)
  1160    * Note: for HTML this gets the value of the 'target' attribute; for XLink
  1161    * this gets the value of the xlink:_moz_target attribute, or failing that,
  1162    * the value of xlink:show, converted to a suitably equivalent named target
  1163    * (e.g. _blank).
  1164    */
  1165   virtual void GetLinkTarget(nsAString& aTarget);
  1167 private:
  1168   /**
  1169    * Get this element's client area rect in app units.
  1170    * @return the frame's client area
  1171    */
  1172   nsRect GetClientAreaRect();
  1174   nsIScrollableFrame* GetScrollFrame(nsIFrame **aStyledFrame = nullptr,
  1175                                      bool aFlushLayout = true);
  1177   // Data members
  1178   EventStates mState;
  1179 };
  1181 NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
  1183 inline bool
  1184 Element::HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const
  1186   NS_ASSERTION(nullptr != aName, "must have attribute name");
  1187   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
  1188                "must have a real namespace ID!");
  1190   return mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID) >= 0;
  1193 inline bool
  1194 Element::AttrValueIs(int32_t aNameSpaceID,
  1195                      nsIAtom* aName,
  1196                      const nsAString& aValue,
  1197                      nsCaseTreatment aCaseSensitive) const
  1199   NS_ASSERTION(aName, "Must have attr name");
  1200   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
  1202   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
  1203   return val && val->Equals(aValue, aCaseSensitive);
  1206 inline bool
  1207 Element::AttrValueIs(int32_t aNameSpaceID,
  1208                      nsIAtom* aName,
  1209                      nsIAtom* aValue,
  1210                      nsCaseTreatment aCaseSensitive) const
  1212   NS_ASSERTION(aName, "Must have attr name");
  1213   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
  1214   NS_ASSERTION(aValue, "Null value atom");
  1216   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
  1217   return val && val->Equals(aValue, aCaseSensitive);
  1220 } // namespace dom
  1221 } // namespace mozilla
  1223 inline mozilla::dom::Element* nsINode::AsElement()
  1225   MOZ_ASSERT(IsElement());
  1226   return static_cast<mozilla::dom::Element*>(this);
  1229 inline const mozilla::dom::Element* nsINode::AsElement() const
  1231   MOZ_ASSERT(IsElement());
  1232   return static_cast<const mozilla::dom::Element*>(this);
  1235 inline bool nsINode::HasAttributes() const
  1237   return IsElement() && AsElement()->HasAttrs();
  1240 /**
  1241  * Macros to implement Clone(). _elementName is the class for which to implement
  1242  * Clone.
  1243  */
  1244 #define NS_IMPL_ELEMENT_CLONE(_elementName)                                 \
  1245 nsresult                                                                    \
  1246 _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const        \
  1247 {                                                                           \
  1248   *aResult = nullptr;                                                       \
  1249   already_AddRefed<nsINodeInfo> ni =                                        \
  1250     nsCOMPtr<nsINodeInfo>(aNodeInfo).forget();                              \
  1251   _elementName *it = new _elementName(ni);                                  \
  1252   if (!it) {                                                                \
  1253     return NS_ERROR_OUT_OF_MEMORY;                                          \
  1254   }                                                                         \
  1256   nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
  1257   nsresult rv = const_cast<_elementName*>(this)->CopyInnerTo(it);           \
  1258   if (NS_SUCCEEDED(rv)) {                                                   \
  1259     kungFuDeathGrip.swap(*aResult);                                         \
  1260   }                                                                         \
  1262   return rv;                                                                \
  1265 #define NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName)                       \
  1266 nsresult                                                                    \
  1267 _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const        \
  1268 {                                                                           \
  1269   *aResult = nullptr;                                                       \
  1270   already_AddRefed<nsINodeInfo> ni =                                        \
  1271     nsCOMPtr<nsINodeInfo>(aNodeInfo).forget();                              \
  1272   _elementName *it = new _elementName(ni);                                  \
  1273   if (!it) {                                                                \
  1274     return NS_ERROR_OUT_OF_MEMORY;                                          \
  1275   }                                                                         \
  1277   nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
  1278   nsresult rv = it->Init();                                                 \
  1279   nsresult rv2 = const_cast<_elementName*>(this)->CopyInnerTo(it);          \
  1280   if (NS_FAILED(rv2)) {                                                     \
  1281     rv = rv2;                                                               \
  1282   }                                                                         \
  1283   if (NS_SUCCEEDED(rv)) {                                                   \
  1284     kungFuDeathGrip.swap(*aResult);                                         \
  1285   }                                                                         \
  1287   return rv;                                                                \
  1290 /**
  1291  * A macro to implement the getter and setter for a given string
  1292  * valued content property. The method uses the generic GetAttr and
  1293  * SetAttr methods.  We use the 5-argument form of SetAttr, because
  1294  * some consumers only implement that one, hiding superclass
  1295  * 4-argument forms.
  1296  */
  1297 #define NS_IMPL_STRING_ATTR(_class, _method, _atom)                     \
  1298   NS_IMETHODIMP                                                         \
  1299   _class::Get##_method(nsAString& aValue)                               \
  1300   {                                                                     \
  1301     GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue);               \
  1302     return NS_OK;                                                       \
  1303   }                                                                     \
  1304   NS_IMETHODIMP                                                         \
  1305   _class::Set##_method(const nsAString& aValue)                         \
  1306   {                                                                     \
  1307     return SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, nullptr, aValue, true); \
  1310 /**
  1311  * A macro to implement the getter and setter for a given boolean
  1312  * valued content property. The method uses the GetBoolAttr and
  1313  * SetBoolAttr methods.
  1314  */
  1315 #define NS_IMPL_BOOL_ATTR(_class, _method, _atom)                     \
  1316   NS_IMETHODIMP                                                       \
  1317   _class::Get##_method(bool* aValue)                                  \
  1318   {                                                                   \
  1319     *aValue = GetBoolAttr(nsGkAtoms::_atom);                          \
  1320     return NS_OK;                                                     \
  1321   }                                                                   \
  1322   NS_IMETHODIMP                                                       \
  1323   _class::Set##_method(bool aValue)                                   \
  1324   {                                                                   \
  1325     return SetBoolAttr(nsGkAtoms::_atom, aValue);                     \
  1328 #define NS_FORWARD_NSIDOMELEMENT_TO_GENERIC                                   \
  1329 typedef mozilla::dom::Element Element;                                        \
  1330 NS_IMETHOD GetTagName(nsAString& aTagName) MOZ_FINAL                          \
  1331 {                                                                             \
  1332   Element::GetTagName(aTagName);                                              \
  1333   return NS_OK;                                                               \
  1334 }                                                                             \
  1335 NS_IMETHOD GetClassList(nsISupports** aClassList) MOZ_FINAL                   \
  1336 {                                                                             \
  1337   Element::GetClassList(aClassList);                                          \
  1338   return NS_OK;                                                               \
  1339 }                                                                             \
  1340 NS_IMETHOD GetAttributes(nsIDOMMozNamedAttrMap** aAttributes) MOZ_FINAL       \
  1341 {                                                                             \
  1342   NS_ADDREF(*aAttributes = Attributes());                                     \
  1343   return NS_OK;                                                               \
  1344 }                                                                             \
  1345 using Element::GetAttribute;                                                  \
  1346 NS_IMETHOD GetAttribute(const nsAString& name, nsAString& _retval) MOZ_FINAL  \
  1347 {                                                                             \
  1348   nsString attr;                                                              \
  1349   GetAttribute(name, attr);                                                   \
  1350   _retval = attr;                                                             \
  1351   return NS_OK;                                                               \
  1352 }                                                                             \
  1353 NS_IMETHOD GetAttributeNS(const nsAString& namespaceURI,                      \
  1354                           const nsAString& localName,                         \
  1355                           nsAString& _retval) MOZ_FINAL                       \
  1356 {                                                                             \
  1357   Element::GetAttributeNS(namespaceURI, localName, _retval);                  \
  1358   return NS_OK;                                                               \
  1359 }                                                                             \
  1360 NS_IMETHOD SetAttribute(const nsAString& name,                                \
  1361                         const nsAString& value)                               \
  1362 {                                                                             \
  1363   mozilla::ErrorResult rv;                                                    \
  1364   Element::SetAttribute(name, value, rv);                                     \
  1365   return rv.ErrorCode();                                                      \
  1366 }                                                                             \
  1367 NS_IMETHOD SetAttributeNS(const nsAString& namespaceURI,                      \
  1368                           const nsAString& qualifiedName,                     \
  1369                           const nsAString& value) MOZ_FINAL                   \
  1370 {                                                                             \
  1371   mozilla::ErrorResult rv;                                                    \
  1372   Element::SetAttributeNS(namespaceURI, qualifiedName, value, rv);            \
  1373   return rv.ErrorCode();                                                      \
  1374 }                                                                             \
  1375 using Element::RemoveAttribute;                                               \
  1376 NS_IMETHOD RemoveAttribute(const nsAString& name) MOZ_FINAL                   \
  1377 {                                                                             \
  1378   mozilla::ErrorResult rv;                                                    \
  1379   RemoveAttribute(name, rv);                                                  \
  1380   return rv.ErrorCode();                                                      \
  1381 }                                                                             \
  1382 NS_IMETHOD RemoveAttributeNS(const nsAString& namespaceURI,                   \
  1383                              const nsAString& localName) MOZ_FINAL            \
  1384 {                                                                             \
  1385   mozilla::ErrorResult rv;                                                    \
  1386   Element::RemoveAttributeNS(namespaceURI, localName, rv);                    \
  1387   return rv.ErrorCode();                                                      \
  1388 }                                                                             \
  1389 using Element::HasAttribute;                                                  \
  1390 NS_IMETHOD HasAttribute(const nsAString& name,                                \
  1391                            bool* _retval) MOZ_FINAL                           \
  1392 {                                                                             \
  1393   *_retval = HasAttribute(name);                                              \
  1394   return NS_OK;                                                               \
  1395 }                                                                             \
  1396 NS_IMETHOD HasAttributeNS(const nsAString& namespaceURI,                      \
  1397                           const nsAString& localName,                         \
  1398                           bool* _retval) MOZ_FINAL                            \
  1399 {                                                                             \
  1400   *_retval = Element::HasAttributeNS(namespaceURI, localName);                \
  1401   return NS_OK;                                                               \
  1402 }                                                                             \
  1403 NS_IMETHOD GetAttributeNode(const nsAString& name,                            \
  1404                             nsIDOMAttr** _retval) MOZ_FINAL                   \
  1405 {                                                                             \
  1406   NS_IF_ADDREF(*_retval = Element::GetAttributeNode(name));                   \
  1407   return NS_OK;                                                               \
  1408 }                                                                             \
  1409 NS_IMETHOD SetAttributeNode(nsIDOMAttr* newAttr,                              \
  1410                             nsIDOMAttr** _retval) MOZ_FINAL                   \
  1411 {                                                                             \
  1412   if (!newAttr) {                                                             \
  1413     return NS_ERROR_INVALID_POINTER;                                          \
  1414   }                                                                           \
  1415   mozilla::ErrorResult rv;                                                    \
  1416   mozilla::dom::Attr* attr = static_cast<mozilla::dom::Attr*>(newAttr);       \
  1417   *_retval = Element::SetAttributeNode(*attr, rv).take();                     \
  1418   return rv.ErrorCode();                                                      \
  1419 }                                                                             \
  1420 NS_IMETHOD RemoveAttributeNode(nsIDOMAttr* oldAttr,                           \
  1421                                nsIDOMAttr** _retval) MOZ_FINAL                \
  1422 {                                                                             \
  1423   if (!oldAttr) {                                                             \
  1424     return NS_ERROR_INVALID_POINTER;                                          \
  1425   }                                                                           \
  1426   mozilla::ErrorResult rv;                                                    \
  1427   mozilla::dom::Attr* attr = static_cast<mozilla::dom::Attr*>(oldAttr);       \
  1428   *_retval = Element::RemoveAttributeNode(*attr, rv).take();                  \
  1429   return rv.ErrorCode();                                                      \
  1430 }                                                                             \
  1431 NS_IMETHOD GetAttributeNodeNS(const nsAString& namespaceURI,                  \
  1432                               const nsAString& localName,                     \
  1433                               nsIDOMAttr** _retval) MOZ_FINAL                 \
  1434 {                                                                             \
  1435   NS_IF_ADDREF(*_retval = Element::GetAttributeNodeNS(namespaceURI,           \
  1436                                                       localName));            \
  1437   return NS_OK;                                                               \
  1438 }                                                                             \
  1439 NS_IMETHOD SetAttributeNodeNS(nsIDOMAttr* newAttr,                            \
  1440                               nsIDOMAttr** _retval) MOZ_FINAL                 \
  1441 {                                                                             \
  1442   mozilla::ErrorResult rv;                                                    \
  1443   mozilla::dom::Attr* attr = static_cast<mozilla::dom::Attr*>(newAttr);       \
  1444   *_retval = Element::SetAttributeNodeNS(*attr, rv).take();                   \
  1445   return rv.ErrorCode();                                                      \
  1446 }                                                                             \
  1447 NS_IMETHOD GetElementsByTagName(const nsAString& name,                        \
  1448                                 nsIDOMHTMLCollection** _retval) MOZ_FINAL     \
  1449 {                                                                             \
  1450   Element::GetElementsByTagName(name, _retval);                               \
  1451   return NS_OK;                                                               \
  1452 }                                                                             \
  1453 NS_IMETHOD GetElementsByTagNameNS(const nsAString& namespaceURI,              \
  1454                                   const nsAString& localName,                 \
  1455                                   nsIDOMHTMLCollection** _retval) MOZ_FINAL   \
  1456 {                                                                             \
  1457   return Element::GetElementsByTagNameNS(namespaceURI, localName,             \
  1458                                          _retval);                            \
  1459 }                                                                             \
  1460 NS_IMETHOD GetElementsByClassName(const nsAString& classes,                   \
  1461                                   nsIDOMHTMLCollection** _retval) MOZ_FINAL   \
  1462 {                                                                             \
  1463   return Element::GetElementsByClassName(classes, _retval);                   \
  1464 }                                                                             \
  1465 NS_IMETHOD GetChildElements(nsIDOMNodeList** aChildElements) MOZ_FINAL        \
  1466 {                                                                             \
  1467   nsIHTMLCollection* list = FragmentOrElement::Children();                    \
  1468   return CallQueryInterface(list, aChildElements);                            \
  1469 }                                                                             \
  1470 NS_IMETHOD GetFirstElementChild(nsIDOMElement** aFirstElementChild) MOZ_FINAL \
  1471 {                                                                             \
  1472   Element* element = Element::GetFirstElementChild();                         \
  1473   if (!element) {                                                             \
  1474     *aFirstElementChild = nullptr;                                            \
  1475     return NS_OK;                                                             \
  1476   }                                                                           \
  1477   return CallQueryInterface(element, aFirstElementChild);                     \
  1478 }                                                                             \
  1479 NS_IMETHOD GetLastElementChild(nsIDOMElement** aLastElementChild) MOZ_FINAL   \
  1480 {                                                                             \
  1481   Element* element = Element::GetLastElementChild();                          \
  1482   if (!element) {                                                             \
  1483     *aLastElementChild = nullptr;                                             \
  1484     return NS_OK;                                                             \
  1485   }                                                                           \
  1486   return CallQueryInterface(element, aLastElementChild);                      \
  1487 }                                                                             \
  1488 NS_IMETHOD GetPreviousElementSibling(nsIDOMElement** aPreviousElementSibling) \
  1489   MOZ_FINAL                                                                   \
  1490 {                                                                             \
  1491   Element* element = Element::GetPreviousElementSibling();                    \
  1492   if (!element) {                                                             \
  1493     *aPreviousElementSibling = nullptr;                                       \
  1494     return NS_OK;                                                             \
  1495   }                                                                           \
  1496   return CallQueryInterface(element, aPreviousElementSibling);                \
  1497 }                                                                             \
  1498 NS_IMETHOD GetNextElementSibling(nsIDOMElement** aNextElementSibling)         \
  1499   MOZ_FINAL                                                                   \
  1500 {                                                                             \
  1501   Element* element = Element::GetNextElementSibling();                        \
  1502   if (!element) {                                                             \
  1503     *aNextElementSibling = nullptr;                                           \
  1504     return NS_OK;                                                             \
  1505   }                                                                           \
  1506   return CallQueryInterface(element, aNextElementSibling);                    \
  1507 }                                                                             \
  1508 NS_IMETHOD GetChildElementCount(uint32_t* aChildElementCount) MOZ_FINAL       \
  1509 {                                                                             \
  1510   *aChildElementCount = Element::ChildElementCount();                         \
  1511   return NS_OK;                                                               \
  1512 }                                                                             \
  1513 NS_IMETHOD MozRemove() MOZ_FINAL                                              \
  1514 {                                                                             \
  1515   nsINode::Remove();                                                          \
  1516   return NS_OK;                                                               \
  1517 }                                                                             \
  1518 NS_IMETHOD GetClientRects(nsIDOMClientRectList** _retval) MOZ_FINAL           \
  1519 {                                                                             \
  1520   *_retval = Element::GetClientRects().take();                                \
  1521   return NS_OK;                                                               \
  1522 }                                                                             \
  1523 NS_IMETHOD GetBoundingClientRect(nsIDOMClientRect** _retval) MOZ_FINAL        \
  1524 {                                                                             \
  1525   *_retval = Element::GetBoundingClientRect().take();                         \
  1526   return NS_OK;                                                               \
  1527 }                                                                             \
  1528 NS_IMETHOD GetScrollTop(int32_t* aScrollTop) MOZ_FINAL                        \
  1529 {                                                                             \
  1530   *aScrollTop = Element::ScrollTop();                                         \
  1531   return NS_OK;                                                               \
  1532 }                                                                             \
  1533 NS_IMETHOD SetScrollTop(int32_t aScrollTop) MOZ_FINAL                         \
  1534 {                                                                             \
  1535   Element::SetScrollTop(aScrollTop);                                          \
  1536   return NS_OK;                                                               \
  1537 }                                                                             \
  1538 NS_IMETHOD GetScrollLeft(int32_t* aScrollLeft) MOZ_FINAL                      \
  1539 {                                                                             \
  1540   *aScrollLeft = Element::ScrollLeft();                                       \
  1541   return NS_OK;                                                               \
  1542 }                                                                             \
  1543 NS_IMETHOD SetScrollLeft(int32_t aScrollLeft) MOZ_FINAL                       \
  1544 {                                                                             \
  1545   Element::SetScrollLeft(aScrollLeft);                                        \
  1546   return NS_OK;                                                               \
  1547 }                                                                             \
  1548 NS_IMETHOD GetScrollWidth(int32_t* aScrollWidth) MOZ_FINAL                    \
  1549 {                                                                             \
  1550   *aScrollWidth = Element::ScrollWidth();                                     \
  1551   return NS_OK;                                                               \
  1552 }                                                                             \
  1553 NS_IMETHOD GetScrollHeight(int32_t* aScrollHeight) MOZ_FINAL                  \
  1554 {                                                                             \
  1555   *aScrollHeight = Element::ScrollHeight();                                   \
  1556   return NS_OK;                                                               \
  1557 }                                                                             \
  1558 NS_IMETHOD GetClientTop(int32_t* aClientTop) MOZ_FINAL                        \
  1559 {                                                                             \
  1560   *aClientTop = Element::ClientTop();                                         \
  1561   return NS_OK;                                                               \
  1562 }                                                                             \
  1563 NS_IMETHOD GetClientLeft(int32_t* aClientLeft) MOZ_FINAL                      \
  1564 {                                                                             \
  1565   *aClientLeft = Element::ClientLeft();                                       \
  1566   return NS_OK;                                                               \
  1567 }                                                                             \
  1568 NS_IMETHOD GetClientWidth(int32_t* aClientWidth) MOZ_FINAL                    \
  1569 {                                                                             \
  1570   *aClientWidth = Element::ClientWidth();                                     \
  1571   return NS_OK;                                                               \
  1572 }                                                                             \
  1573 NS_IMETHOD GetClientHeight(int32_t* aClientHeight) MOZ_FINAL                  \
  1574 {                                                                             \
  1575   *aClientHeight = Element::ClientHeight();                                   \
  1576   return NS_OK;                                                               \
  1577 }                                                                             \
  1578 NS_IMETHOD GetScrollLeftMax(int32_t* aScrollLeftMax) MOZ_FINAL                \
  1579 {                                                                             \
  1580   *aScrollLeftMax = Element::ScrollLeftMax();                                 \
  1581   return NS_OK;                                                               \
  1582 }                                                                             \
  1583 NS_IMETHOD GetScrollTopMax(int32_t* aScrollTopMax) MOZ_FINAL                  \
  1584 {                                                                             \
  1585   *aScrollTopMax = Element::ScrollTopMax();                                   \
  1586   return NS_OK;                                                               \
  1587 }                                                                             \
  1588 NS_IMETHOD MozMatchesSelector(const nsAString& selector,                      \
  1589                               bool* _retval) MOZ_FINAL                        \
  1590 {                                                                             \
  1591   mozilla::ErrorResult rv;                                                    \
  1592   *_retval = Element::MozMatchesSelector(selector, rv);                       \
  1593   return rv.ErrorCode();                                                      \
  1594 }                                                                             \
  1595 NS_IMETHOD SetCapture(bool retargetToElement) MOZ_FINAL                       \
  1596 {                                                                             \
  1597   Element::SetCapture(retargetToElement);                                     \
  1598   return NS_OK;                                                               \
  1599 }                                                                             \
  1600 NS_IMETHOD ReleaseCapture(void) MOZ_FINAL                                     \
  1601 {                                                                             \
  1602   Element::ReleaseCapture();                                                  \
  1603   return NS_OK;                                                               \
  1604 }                                                                             \
  1605 NS_IMETHOD MozRequestFullScreen(void) MOZ_FINAL                               \
  1606 {                                                                             \
  1607   Element::MozRequestFullScreen();                                            \
  1608   return NS_OK;                                                               \
  1609 }                                                                             \
  1610 NS_IMETHOD MozRequestPointerLock(void) MOZ_FINAL                              \
  1611 {                                                                             \
  1612   Element::MozRequestPointerLock();                                           \
  1613   return NS_OK;                                                               \
  1614 }                                                                             \
  1615 using nsINode::QuerySelector;                                                 \
  1616 NS_IMETHOD QuerySelector(const nsAString& aSelector,                          \
  1617                          nsIDOMElement **aReturn) MOZ_FINAL                   \
  1618 {                                                                             \
  1619   return nsINode::QuerySelector(aSelector, aReturn);                          \
  1620 }                                                                             \
  1621 using nsINode::QuerySelectorAll;                                              \
  1622 NS_IMETHOD QuerySelectorAll(const nsAString& aSelector,                       \
  1623                             nsIDOMNodeList **aReturn) MOZ_FINAL               \
  1624 {                                                                             \
  1625   return nsINode::QuerySelectorAll(aSelector, aReturn);                       \
  1628 #endif // mozilla_dom_Element_h__

mercurial