Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/Element.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/*
8
 * Base class for all element classes; this provides an implementation
9
 * of DOM Core's Element, implements nsIContent, provides
10
 * utility methods for subclasses, and so forth.
11
 */
12
13
#ifndef mozilla_dom_Element_h__
14
#define mozilla_dom_Element_h__
15
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/ServoTypes.h"
20
#include "mozilla/dom/DirectionalityUtils.h"
21
#include "nsILinkHandler.h"
22
#include "nsINodeList.h"
23
#include "nsNodeUtils.h"
24
#include "AttrArray.h"
25
#include "mozilla/FlushType.h"
26
#include "nsDOMAttributeMap.h"
27
#include "nsPresContext.h"
28
#include "mozilla/CORSMode.h"
29
#include "mozilla/Attributes.h"
30
#include "nsIScrollableFrame.h"
31
#include "mozilla/dom/Attr.h"
32
#include "nsISMILAttr.h"
33
#include "mozilla/dom/DOMRect.h"
34
#include "nsAttrValue.h"
35
#include "nsAttrValueInlines.h"
36
#include "mozilla/EventForwards.h"
37
#include "mozilla/dom/BindingDeclarations.h"
38
#include "mozilla/dom/DOMTokenListSupportedTokens.h"
39
#include "mozilla/dom/WindowBinding.h"
40
#include "mozilla/dom/ElementBinding.h"
41
#include "mozilla/dom/Nullable.h"
42
#include "mozilla/dom/PointerEventHandler.h"
43
#include "mozilla/UniquePtr.h"
44
#include "Units.h"
45
#include "DOMIntersectionObserver.h"
46
47
class mozAutoDocUpdate;
48
class nsIFrame;
49
class nsIMozBrowserFrame;
50
class nsIURI;
51
class nsIScrollableFrame;
52
class nsAttrValueOrString;
53
class nsContentList;
54
class nsDOMTokenList;
55
struct nsRect;
56
class nsFocusManager;
57
class nsGlobalWindowInner;
58
class nsGlobalWindowOuter;
59
class nsDOMCSSAttributeDeclaration;
60
class nsISMILAttr;
61
class nsDocument;
62
class nsDOMStringMap;
63
64
namespace mozilla {
65
class DeclarationBlock;
66
struct MutationClosureData;
67
class TextEditor;
68
namespace css {
69
  struct URLValue;
70
} // namespace css
71
namespace dom {
72
  struct AnimationFilter;
73
  struct ScrollIntoViewOptions;
74
  struct ScrollToOptions;
75
  class DOMIntersectionObserver;
76
  class DOMMatrixReadOnly;
77
  class Element;
78
  class ElementOrCSSPseudoElement;
79
  class UnrestrictedDoubleOrKeyframeAnimationOptions;
80
  enum class CallerType : uint32_t;
81
  typedef nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
82
    IntersectionObserverList;
83
} // namespace dom
84
} // namespace mozilla
85
86
// Declared here because of include hell.
87
extern "C" bool Servo_Element_IsDisplayContents(const mozilla::dom::Element*);
88
89
already_AddRefed<nsContentList>
90
NS_GetContentList(nsINode* aRootNode,
91
                  int32_t  aMatchNameSpaceId,
92
                  const nsAString& aTagname);
93
94
#define ELEMENT_FLAG_BIT(n_) NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
95
96
// Element-specific flags
97
enum {
98
  // Whether this node has dirty descendants for Servo's style system.
99
  ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO = ELEMENT_FLAG_BIT(0),
100
  // Whether this node has dirty descendants for animation-only restyle for
101
  // Servo's style system.
102
  ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO = ELEMENT_FLAG_BIT(1),
103
104
  // Whether the element has been snapshotted due to attribute or state changes
105
  // by the Servo restyle manager.
106
  ELEMENT_HAS_SNAPSHOT = ELEMENT_FLAG_BIT(2),
107
108
  // Whether the element has already handled its relevant snapshot.
109
  //
110
  // Used by the servo restyle process in order to accurately track whether the
111
  // style of an element is up-to-date, even during the same restyle process.
112
  ELEMENT_HANDLED_SNAPSHOT = ELEMENT_FLAG_BIT(3),
113
114
  // Remaining bits are for subclasses
115
  ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 4
116
};
117
118
#undef ELEMENT_FLAG_BIT
119
120
// Make sure we have space for our bits
121
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
122
123
namespace mozilla {
124
enum class CSSPseudoElementType : uint8_t;
125
class EventChainPostVisitor;
126
class EventChainPreVisitor;
127
class EventChainVisitor;
128
class EventListenerManager;
129
class EventStateManager;
130
131
namespace dom {
132
133
struct CustomElementDefinition;
134
class Animation;
135
class CustomElementRegistry;
136
class Link;
137
class DOMRect;
138
class DOMRectList;
139
class Flex;
140
class Grid;
141
142
// IID for the dom::Element interface
143
#define NS_ELEMENT_IID \
144
{ 0xc67ed254, 0xfd3b, 0x4b10, \
145
  { 0x96, 0xa2, 0xc5, 0x8b, 0x7b, 0x64, 0x97, 0xd1 } }
146
147
class Element : public FragmentOrElement
148
{
149
public:
150
#ifdef MOZILLA_INTERNAL_API
151
  explicit Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) :
152
    FragmentOrElement(std::move(aNodeInfo)),
153
    mState(NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_DEFINED)
154
  {
155
    MOZ_ASSERT(mNodeInfo->NodeType() == ELEMENT_NODE,
156
               "Bad NodeType in aNodeInfo");
157
    SetIsElement();
158
  }
159
160
  ~Element()
161
  {
162
    NS_ASSERTION(!HasServoData(), "expected ServoData to be cleared earlier");
163
  }
164
165
#endif // MOZILLA_INTERNAL_API
166
167
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
168
169
  NS_DECL_ADDSIZEOFEXCLUDINGTHIS
170
171
  NS_IMPL_FROMNODE_HELPER(Element, IsElement())
172
173
  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
174
175
  /**
176
   * Method to get the full state of this element.  See mozilla/EventStates.h
177
   * for the possible bits that could be set here.
178
   */
179
  EventStates State() const
180
  {
181
    // mState is maintained by having whoever might have changed it
182
    // call UpdateState() or one of the other mState mutators.
183
    return mState;
184
  }
185
186
  /**
187
   * Ask this element to update its state.  If aNotify is false, then
188
   * state change notifications will not be dispatched; in that
189
   * situation it is the caller's responsibility to dispatch them.
190
   *
191
   * In general, aNotify should only be false if we're guaranteed that
192
   * the element can't have a frame no matter what its style is
193
   * (e.g. if we're in the middle of adding it to the document or
194
   * removing it from the document).
195
   */
196
  void UpdateState(bool aNotify);
197
198
  /**
199
   * Method to update mState with link state information.  This does not notify.
200
   */
201
  void UpdateLinkState(EventStates aState);
202
203
  virtual int32_t TabIndexDefault()
204
  {
205
    return -1;
206
  }
207
208
  /**
209
   * Get tabIndex of this element. If not found, return TabIndexDefault.
210
   */
211
  int32_t TabIndex();
212
213
  /**
214
   * Set tabIndex value to this element.
215
   */
216
  void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
217
218
  /**
219
   * Sets or unsets an XBL binding for this element. Setting a
220
   * binding on an element that already has a binding will remove the
221
   * old binding.
222
   *
223
   * @param aBinding The binding to bind to this content. If nullptr is
224
   *        provided as the argument, then existing binding will be
225
   *        removed.
226
   *
227
   * @param aOldBindingManager The old binding manager that contains
228
   *                           this content if this content was adopted
229
   *                           to another document.
230
   */
231
  void SetXBLBinding(nsXBLBinding* aBinding,
232
                     nsBindingManager* aOldBindingManager = nullptr);
233
234
  /**
235
   * Sets the ShadowRoot binding for this element. The contents of the
236
   * binding is rendered in place of this node's children.
237
   *
238
   * @param aShadowRoot The ShadowRoot to be bound to this element.
239
   */
240
  void SetShadowRoot(ShadowRoot* aShadowRoot);
241
242
  /**
243
   * Make focus on this element.
244
   */
245
  virtual void Focus(mozilla::ErrorResult& aError);
246
247
  /**
248
   * Show blur and clear focus.
249
   */
250
  virtual void Blur(mozilla::ErrorResult& aError);
251
252
  /**
253
   * The style state of this element. This is the real state of the element
254
   * with any style locks applied for pseudo-class inspecting.
255
   */
256
  EventStates StyleState() const
257
  {
258
    if (!HasLockedStyleStates()) {
259
      return mState;
260
    }
261
    return StyleStateFromLocks();
262
  }
263
264
  /**
265
   * StyleStateLocks is used to specify which event states should be locked,
266
   * and whether they should be locked to on or off.
267
   */
268
  struct StyleStateLocks {
269
    // mLocks tracks which event states should be locked.
270
    EventStates mLocks;
271
    // mValues tracks if the locked state should be on or off.
272
    EventStates mValues;
273
  };
274
275
  /**
276
   * The style state locks applied to this element.
277
   */
278
  StyleStateLocks LockedStyleStates() const;
279
280
  /**
281
   * Add a style state lock on this element.
282
   * aEnabled is the value to lock the given state bits to.
283
   */
284
  void LockStyleStates(EventStates aStates, bool aEnabled);
285
286
  /**
287
   * Remove a style state lock on this element.
288
   */
289
  void UnlockStyleStates(EventStates aStates);
290
291
  /**
292
   * Clear all style state locks on this element.
293
   */
294
  void ClearStyleStateLocks();
295
296
  /**
297
   * Accessors for the state of our dir attribute.
298
   */
299
  bool HasDirAuto() const
300
  {
301
    return State().HasState(NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO);
302
  }
303
304
  /**
305
   * Elements with dir="rtl" or dir="ltr".
306
   */
307
  bool HasFixedDir() const
308
  {
309
    return State().HasAtLeastOneOfStates(NS_EVENT_STATE_DIR_ATTR_LTR |
310
                                         NS_EVENT_STATE_DIR_ATTR_RTL);
311
  }
312
313
  /**
314
   * Get the inline style declaration, if any, for this element.
315
   */
316
  DeclarationBlock* GetInlineStyleDeclaration() const;
317
318
  /**
319
   * Get the mapped attributes, if any, for this element.
320
   */
321
  const nsMappedAttributes* GetMappedAttributes() const;
322
323
  void ClearMappedServoStyle()
324
  {
325
    mAttrs.ClearMappedServoStyle();
326
  }
327
328
  /**
329
   * InlineStyleDeclarationWillChange is called before SetInlineStyleDeclaration
330
   * so that the element implementation can access the old style attribute
331
   * value.
332
   */
333
  virtual void InlineStyleDeclarationWillChange(MutationClosureData& aData);
334
335
  /**
336
   * Set the inline style declaration for this element.
337
   */
338
  virtual nsresult SetInlineStyleDeclaration(DeclarationBlock& aDeclaration,
339
                                             MutationClosureData& aData);
340
341
  /**
342
   * Get the SMIL override style declaration for this element. If the
343
   * rule hasn't been created, this method simply returns null.
344
   */
345
  DeclarationBlock* GetSMILOverrideStyleDeclaration();
346
347
  /**
348
   * Set the SMIL override style declaration for this element. If
349
   * aNotify is true, this method will notify the document's pres
350
   * context, so that the style changes will be noticed.
351
   */
352
  nsresult SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration,
353
                                           bool aNotify);
354
355
  /**
356
   * Returns a new nsISMILAttr that allows the caller to animate the given
357
   * attribute on this element.
358
   */
359
  virtual UniquePtr<nsISMILAttr> GetAnimatedAttr(int32_t aNamespaceID,
360
                                                 nsAtom* aName)
361
  {
362
    return nullptr;
363
  }
364
365
  /**
366
   * Get the SMIL override style for this element. This is a style declaration
367
   * that is applied *after* the inline style, and it can be used e.g. to store
368
   * animated style values.
369
   *
370
   * Note: This method is analogous to the 'GetStyle' method in
371
   * nsGenericHTMLElement and nsStyledElement.
372
   */
373
  nsDOMCSSAttributeDeclaration* SMILOverrideStyle();
374
375
  /**
376
   * Returns if the element is labelable as per HTML specification.
377
   */
378
  virtual bool IsLabelable() const;
379
380
  /**
381
   * Returns if the element is interactive content as per HTML specification.
382
   */
383
  virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const;
384
385
  /**
386
   * Returns |this| as an nsIMozBrowserFrame* if the element is a frame or
387
   * iframe element.
388
   *
389
   * We have this method, rather than using QI, so that we can use it during
390
   * the servo traversal, where we can't QI DOM nodes because of non-thread-safe
391
   * refcounts.
392
   */
393
  virtual nsIMozBrowserFrame* GetAsMozBrowserFrame() { return nullptr; }
394
395
  /**
396
   * Is the attribute named stored in the mapped attributes?
397
   *
398
   * // XXXbz we use this method in HasAttributeDependentStyle, so svg
399
   *    returns true here even though it stores nothing in the mapped
400
   *    attributes.
401
   */
402
  NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const;
403
404
  /**
405
   * Get a hint that tells the style system what to do when
406
   * an attribute on this node changes, if something needs to happen
407
   * in response to the change *other* than the result of what is
408
   * mapped into style data via any type of style rule.
409
   */
410
  virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
411
                                              int32_t aModType) const;
412
413
414
  inline Directionality GetDirectionality() const {
415
    if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
416
      return eDir_RTL;
417
    }
418
419
    if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
420
      return eDir_LTR;
421
    }
422
423
    return eDir_NotSet;
424
  }
425
426
  inline void SetDirectionality(Directionality aDir, bool aNotify) {
427
    UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
428
    if (!aNotify) {
429
      RemoveStatesSilently(DIRECTION_STATES);
430
    }
431
432
    switch (aDir) {
433
      case (eDir_RTL):
434
        SetFlags(NODE_HAS_DIRECTION_RTL);
435
        if (!aNotify) {
436
          AddStatesSilently(NS_EVENT_STATE_RTL);
437
        }
438
        break;
439
440
      case(eDir_LTR):
441
        SetFlags(NODE_HAS_DIRECTION_LTR);
442
        if (!aNotify) {
443
          AddStatesSilently(NS_EVENT_STATE_LTR);
444
        }
445
        break;
446
447
      default:
448
        break;
449
    }
450
451
    /*
452
     * Only call UpdateState if we need to notify, because we call
453
     * SetDirectionality for every element, and UpdateState is very very slow
454
     * for some elements.
455
     */
456
    if (aNotify) {
457
      UpdateState(true);
458
    }
459
  }
460
461
  bool GetBindingURL(nsIDocument* aDocument, css::URLValue **aResult);
462
463
  Directionality GetComputedDirectionality() const;
464
465
  static const uint32_t kAllServoDescendantBits =
466
    ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO |
467
    ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO |
468
    NODE_DESCENDANTS_NEED_FRAMES;
469
470
  /**
471
   * Notes that something in the given subtree of this element needs dirtying,
472
   * and that all the relevant dirty bits have already been propagated up to the
473
   * element.
474
   *
475
   * This is important because `NoteDirtyForServo` uses the dirty bits to reason
476
   * about the shape of the tree, so we can't just call into there.
477
   */
478
  void NoteDirtySubtreeForServo();
479
480
  void NoteDirtyForServo();
481
  void NoteAnimationOnlyDirtyForServo();
482
  void NoteDescendantsNeedFramesForServo();
483
484
  bool HasDirtyDescendantsForServo() const
485
  {
486
    return HasFlag(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
487
  }
488
489
  void SetHasDirtyDescendantsForServo() {
490
    SetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
491
  }
492
493
  void UnsetHasDirtyDescendantsForServo() {
494
    UnsetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
495
  }
496
497
  bool HasAnimationOnlyDirtyDescendantsForServo() const {
498
    return HasFlag(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
499
  }
500
501
  void SetHasAnimationOnlyDirtyDescendantsForServo() {
502
    SetFlags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
503
  }
504
505
  void UnsetHasAnimationOnlyDirtyDescendantsForServo() {
506
    UnsetFlags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
507
  }
508
509
  bool HasServoData() const {
510
    return !!mServoData.Get();
511
  }
512
513
  void ClearServoData() { ClearServoData(GetComposedDoc()); }
514
  void ClearServoData(nsIDocument* aDocument);
515
516
  /**
517
   * Gets the custom element data used by web components custom element.
518
   * Custom element data is created at the first attempt to enqueue a callback.
519
   *
520
   * @return The custom element data or null if none.
521
   */
522
  inline CustomElementData* GetCustomElementData() const
523
  {
524
    if (!HasCustomElementData()) {
525
      return nullptr;
526
    }
527
528
    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
529
    return slots ? slots->mCustomElementData.get() : nullptr;
530
  }
531
532
533
  /**
534
   * Sets the custom element data, ownership of the
535
   * callback data is taken by this element.
536
   *
537
   * @param aData The custom element data.
538
   */
539
  void SetCustomElementData(CustomElementData* aData);
540
541
  /**
542
   * Gets the custom element definition used by web components custom element.
543
   *
544
   * @return The custom element definition or null if element is not a custom
545
   *         element or custom element is not defined yet.
546
   */
547
  CustomElementDefinition* GetCustomElementDefinition() const;
548
549
  /**
550
   * Sets the custom element definition, called when custom element is created
551
   * or upgraded.
552
   *
553
   * @param aDefinition The custom element definition.
554
   */
555
  void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
556
557
  void SetDefined(bool aSet)
558
  {
559
    if (aSet) {
560
      AddStates(NS_EVENT_STATE_DEFINED);
561
    } else {
562
      RemoveStates(NS_EVENT_STATE_DEFINED);
563
    }
564
  }
565
protected:
566
  /**
567
   * Method to get the _intrinsic_ content state of this element.  This is the
568
   * state that is independent of the element's presentation.  To get the full
569
   * content state, use State().  See mozilla/EventStates.h for
570
   * the possible bits that could be set here.
571
   */
572
  virtual EventStates IntrinsicState() const;
573
574
  /**
575
   * Method to add state bits.  This should be called from subclass
576
   * constructors to set up our event state correctly at construction
577
   * time and other places where we don't want to notify a state
578
   * change.
579
   */
580
  void AddStatesSilently(EventStates aStates)
581
  {
582
    mState |= aStates;
583
  }
584
585
  /**
586
   * Method to remove state bits.  This should be called from subclass
587
   * constructors to set up our event state correctly at construction
588
   * time and other places where we don't want to notify a state
589
   * change.
590
   */
591
  void RemoveStatesSilently(EventStates aStates)
592
  {
593
    mState &= ~aStates;
594
  }
595
596
  already_AddRefed<ShadowRoot> AttachShadowInternal(
597
    ShadowRootMode, ErrorResult& aError);
598
599
  MOZ_CAN_RUN_SCRIPT
600
  nsIScrollableFrame* GetScrollFrame(nsIFrame **aStyledFrame = nullptr,
601
                                     FlushType aFlushType = FlushType::Layout);
602
603
private:
604
  // Need to allow the ESM, nsGlobalWindow, and the focus manager to
605
  // set our state
606
  friend class mozilla::EventStateManager;
607
  friend class ::nsGlobalWindowInner;
608
  friend class ::nsGlobalWindowOuter;
609
  friend class ::nsFocusManager;
610
611
  // Allow CusomtElementRegistry to call AddStates.
612
  friend class CustomElementRegistry;
613
614
  // Also need to allow Link to call UpdateLinkState.
615
  friend class Link;
616
617
  void NotifyStateChange(EventStates aStates);
618
619
  void NotifyStyleStateChange(EventStates aStates);
620
621
  // Style state computed from element's state and style locks.
622
  EventStates StyleStateFromLocks() const;
623
624
protected:
625
  // Methods for the ESM, nsGlobalWindow and focus manager to manage state bits.
626
  // These will handle setting up script blockers when they notify, so no need
627
  // to do it in the callers unless desired.  States passed here must only be
628
  // those in EXTERNALLY_MANAGED_STATES.
629
  virtual void AddStates(EventStates aStates)
630
  {
631
    MOZ_ASSERT(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
632
               "Should only be adding externally-managed states here");
633
    AddStatesSilently(aStates);
634
    NotifyStateChange(aStates);
635
  }
636
  virtual void RemoveStates(EventStates aStates)
637
  {
638
    MOZ_ASSERT(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
639
               "Should only be removing externally-managed states here");
640
    RemoveStatesSilently(aStates);
641
    NotifyStateChange(aStates);
642
  }
643
  virtual void ToggleStates(EventStates aStates, bool aNotify)
644
  {
645
    MOZ_ASSERT(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
646
               "Should only be removing externally-managed states here");
647
    mState ^= aStates;
648
    if (aNotify) {
649
      NotifyStateChange(aStates);
650
    }
651
  }
652
653
public:
654
  // Public methods to manage state bits in MANUALLY_MANAGED_STATES.
655
  void AddManuallyManagedStates(EventStates aStates)
656
  {
657
    MOZ_ASSERT(MANUALLY_MANAGED_STATES.HasAllStates(aStates),
658
               "Should only be adding manually-managed states here");
659
    AddStates(aStates);
660
  }
661
  void RemoveManuallyManagedStates(EventStates aStates)
662
  {
663
    MOZ_ASSERT(MANUALLY_MANAGED_STATES.HasAllStates(aStates),
664
               "Should only be removing manually-managed states here");
665
    RemoveStates(aStates);
666
  }
667
668
  void UpdateEditableState(bool aNotify) override;
669
670
  nsresult BindToTree(nsIDocument* aDocument,
671
                      nsIContent* aParent,
672
                      nsIContent* aBindingParent) override;
673
674
  void UnbindFromTree(bool aDeep = true,
675
                      bool aNullParent = true) override;
676
677
  /**
678
   * Normalizes an attribute name and returns it as a nodeinfo if an attribute
679
   * with that name exists. This method is intended for character case
680
   * conversion if the content object is case insensitive (e.g. HTML). Returns
681
   * the nodeinfo of the attribute with the specified name if one exists or
682
   * null otherwise.
683
   *
684
   * @param aStr the unparsed attribute string
685
   * @return the node info. May be nullptr.
686
   */
687
  already_AddRefed<mozilla::dom::NodeInfo>
688
  GetExistingAttrNameFromQName(const nsAString& aStr) const;
689
690
  /**
691
   * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify
692
   * is true or there are mutation listeners that must be triggered, the
693
   * attribute is currently set, and the new value that is about to be set is
694
   * different to the current value. As a perf optimization the new and old
695
   * values will not actually be compared if we aren't notifying and we don't
696
   * have mutation listeners (in which case it's cheap to just return false
697
   * and let the caller go ahead and set the value).
698
   * @param aOldValue [out] Set to the old value of the attribute, but only if
699
   *   there are event listeners. If set, the type of aOldValue will be either
700
   *   nsAttrValue::eString or nsAttrValue::eAtom.
701
   * @param aModType [out] Set to MutationEvent_Binding::MODIFICATION or to
702
   *   MutationEvent_Binding::ADDITION, but only if this helper returns true
703
   * @param aHasListeners [out] Set to true if there are mutation event
704
   *   listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
705
   * @param aOldValueSet [out] Indicates whether an old attribute value has been
706
   *   stored in aOldValue. The bool will be set to true if a value was stored.
707
   */
708
  bool MaybeCheckSameAttrVal(int32_t aNamespaceID, nsAtom* aName,
709
                             nsAtom* aPrefix,
710
                             const nsAttrValueOrString& aValue,
711
                             bool aNotify, nsAttrValue& aOldValue,
712
                             uint8_t* aModType, bool* aHasListeners,
713
                             bool* aOldValueSet);
714
715
  /**
716
   * Notifies mutation listeners if aNotify is true, there are mutation
717
   * listeners, and the attribute value is changing.
718
   *
719
   * @param aNamespaceID The namespace of the attribute
720
   * @param aName The local name of the attribute
721
   * @param aPrefix The prefix of the attribute
722
   * @param aValue The value that the attribute is being changed to
723
   * @param aNotify If true, mutation listeners will be notified if they exist
724
   *   and the attribute value is changing
725
   * @param aOldValue [out] Set to the old value of the attribute, but only if
726
   *   there are event listeners. If set, the type of aOldValue will be either
727
   *   nsAttrValue::eString or nsAttrValue::eAtom.
728
   * @param aModType [out] Set to MutationEvent_Binding::MODIFICATION or to
729
   *   MutationEvent_Binding::ADDITION, but only if this helper returns true
730
   * @param aHasListeners [out] Set to true if there are mutation event
731
   *   listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
732
   * @param aOldValueSet [out] Indicates whether an old attribute value has been
733
   *   stored in aOldValue. The bool will be set to true if a value was stored.
734
   */
735
  bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsAtom* aName,
736
                              nsAtom* aPrefix,
737
                              const nsAttrValueOrString& aValue,
738
                              bool aNotify, nsAttrValue& aOldValue,
739
                              uint8_t* aModType, bool* aHasListeners,
740
                              bool* aOldValueSet);
741
742
  /**
743
   * Sets the class attribute to a value that contains no whitespace.
744
   * Assumes that we are not notifying and that the attribute hasn't been
745
   * set previously.
746
   */
747
  nsresult SetSingleClassFromParser(nsAtom* aSingleClassName);
748
749
  // aParsedValue receives the old value of the attribute. That's useful if
750
  // either the input or output value of aParsedValue is StoresOwnData.
751
  nsresult SetParsedAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
752
                         nsAttrValue& aParsedValue, bool aNotify);
753
  /**
754
   * Get the current value of the attribute. This returns a form that is
755
   * suitable for passing back into SetAttr.
756
   *
757
   * @param aNameSpaceID the namespace of the attr (defaults to
758
                         kNameSpaceID_None in the overload that omits this arg)
759
   * @param aName the name of the attr
760
   * @param aResult the value (may legitimately be the empty string) [OUT]
761
   * @returns true if the attribute was set (even when set to empty string)
762
   *          false when not set.
763
   * GetAttr is not inlined on purpose, to keep down codesize from all the
764
   * inlined nsAttrValue bits for C++ callers.
765
   */
766
  bool GetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAString& aResult) const;
767
768
  bool GetAttr(nsAtom* aName, nsAString& aResult) const
769
  {
770
    return GetAttr(kNameSpaceID_None, aName, aResult);
771
  }
772
773
  /**
774
   * Determine if an attribute has been set (empty string or otherwise).
775
   *
776
   * @param aNameSpaceId the namespace id of the attribute (defaults to
777
                         kNameSpaceID_None in the overload that omits this arg)
778
   * @param aAttr the attribute name
779
   * @return whether an attribute exists
780
   */
781
  inline bool HasAttr(int32_t aNameSpaceID, nsAtom* aName) const;
782
783
  bool HasAttr(nsAtom* aAttr) const
784
  {
785
    return HasAttr(kNameSpaceID_None, aAttr);
786
  }
787
788
  /**
789
   * Test whether this Element's given attribute has the given value.  If the
790
   * attribute is not set at all, this will return false.
791
   *
792
   * @param aNameSpaceID The namespace ID of the attribute.  Must not
793
   *                     be kNameSpaceID_Unknown.
794
   * @param aName The name atom of the attribute.  Must not be null.
795
   * @param aValue The value to compare to.
796
   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
797
   */
798
  inline bool AttrValueIs(int32_t aNameSpaceID, nsAtom* aName,
799
                          const nsAString& aValue,
800
                          nsCaseTreatment aCaseSensitive) const;
801
802
  /**
803
   * Test whether this Element's given attribute has the given value.  If the
804
   * attribute is not set at all, this will return false.
805
   *
806
   * @param aNameSpaceID The namespace ID of the attribute.  Must not
807
   *                     be kNameSpaceID_Unknown.
808
   * @param aName The name atom of the attribute.  Must not be null.
809
   * @param aValue The value to compare to.  Must not be null.
810
   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
811
   */
812
  bool AttrValueIs(int32_t aNameSpaceID,
813
                   nsAtom* aName,
814
                   nsAtom* aValue,
815
                   nsCaseTreatment aCaseSensitive) const;
816
817
  enum {
818
    ATTR_MISSING = -1,
819
    ATTR_VALUE_NO_MATCH = -2
820
  };
821
  /**
822
   * Check whether this Element's given attribute has one of a given list of
823
   * values. If there is a match, we return the index in the list of the first
824
   * matching value. If there was no attribute at all, then we return
825
   * ATTR_MISSING. If there was an attribute but it didn't match, we return
826
   * ATTR_VALUE_NO_MATCH. A non-negative result always indicates a match.
827
   *
828
   * @param aNameSpaceID The namespace ID of the attribute.  Must not
829
   *                     be kNameSpaceID_Unknown.
830
   * @param aName The name atom of the attribute.  Must not be null.
831
   * @param aValues a nullptr-terminated array of pointers to atom values to test
832
   *                against.
833
   * @param aCaseSensitive Whether to do a case-sensitive compare on the values.
834
   * @return ATTR_MISSING, ATTR_VALUE_NO_MATCH or the non-negative index
835
   * indicating the first value of aValues that matched
836
   */
837
  typedef nsStaticAtom* const* const AttrValuesArray;
838
  int32_t FindAttrValueIn(int32_t aNameSpaceID,
839
                                  nsAtom* aName,
840
                                  AttrValuesArray* aValues,
841
                                  nsCaseTreatment aCaseSensitive) const;
842
843
  /**
844
   * Set attribute values. All attribute values are assumed to have a
845
   * canonical string representation that can be used for these
846
   * methods. The SetAttr method is assumed to perform a translation
847
   * of the canonical form into the underlying content specific
848
   * form.
849
   *
850
   * @param aNameSpaceID the namespace of the attribute
851
   * @param aName the name of the attribute
852
   * @param aValue the value to set
853
   * @param aNotify specifies how whether or not the document should be
854
   *        notified of the attribute change.
855
   */
856
  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
857
                   const nsAString& aValue, bool aNotify)
858
  {
859
    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
860
  }
861
  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
862
                   const nsAString& aValue, bool aNotify)
863
  {
864
    return SetAttr(aNameSpaceID, aName, aPrefix, aValue, nullptr, aNotify);
865
  }
866
  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAString& aValue,
867
                   nsIPrincipal* aTriggeringPrincipal, bool aNotify)
868
  {
869
    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aTriggeringPrincipal, aNotify);
870
  }
871
872
  /**
873
   * Set attribute values. All attribute values are assumed to have a
874
   * canonical String representation that can be used for these
875
   * methods. The SetAttr method is assumed to perform a translation
876
   * of the canonical form into the underlying content specific
877
   * form.
878
   *
879
   * @param aNameSpaceID the namespace of the attribute
880
   * @param aName the name of the attribute
881
   * @param aPrefix the prefix of the attribute
882
   * @param aValue the value to set
883
   * @param aMaybeScriptedPrincipal the principal of the scripted caller responsible
884
   *        for setting the attribute, or null if no scripted caller can be
885
   *        determined. A null value here does not guarantee that there is no
886
   *        scripted caller, but a non-null value does guarantee that a scripted
887
   *        caller with the given principal is directly responsible for the
888
   *        attribute change.
889
   * @param aNotify specifies how whether or not the document should be
890
   *        notified of the attribute change.
891
   */
892
  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
893
                   nsAtom* aPrefix, const nsAString& aValue,
894
                   nsIPrincipal* aMaybeScriptedPrincipal,
895
                   bool aNotify);
896
897
  /**
898
   * Remove an attribute so that it is no longer explicitly specified.
899
   *
900
   * @param aNameSpaceID the namespace id of the attribute
901
   * @param aAttr the name of the attribute to unset
902
   * @param aNotify specifies whether or not the document should be
903
   * notified of the attribute change
904
   */
905
  nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute, bool aNotify);
906
907
  /**
908
   * Get the namespace / name / prefix of a given attribute.
909
   *
910
   * @param   aIndex the index of the attribute name
911
   * @returns The name at the given index, or null if the index is
912
   *          out-of-bounds.
913
   * @note    The document returned by NodeInfo()->GetDocument() (if one is
914
   *          present) is *not* necessarily the owner document of the element.
915
   * @note    The pointer returned by this function is only valid until the
916
   *          next call of either GetAttrNameAt or SetAttr on the element.
917
   */
918
  const nsAttrName* GetAttrNameAt(uint32_t aIndex) const
919
  {
920
    return mAttrs.GetSafeAttrNameAt(aIndex);
921
  }
922
923
  /**
924
   * Gets the attribute info (name and value) for this element at a given index.
925
   */
926
  BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const
927
  {
928
    if (aIndex >= mAttrs.AttrCount()) {
929
      return BorrowedAttrInfo(nullptr, nullptr);
930
    }
931
932
    return mAttrs.AttrInfoAt(aIndex);
933
  }
934
935
  /**
936
   * Get the number of all specified attributes.
937
   *
938
   * @return the number of attributes
939
   */
940
  uint32_t GetAttrCount() const
941
  {
942
    return mAttrs.AttrCount();
943
  }
944
945
  virtual bool IsNodeOfType(uint32_t aFlags) const override;
946
947
  /**
948
   * Get the class list of this element (this corresponds to the value of the
949
   * class attribute).  This may be null if there are no classes, but that's not
950
   * guaranteed (e.g. we could have class="").
951
   */
952
  const nsAttrValue* GetClasses() const
953
  {
954
    if (!MayHaveClass()) {
955
      return nullptr;
956
    }
957
958
    if (IsSVGElement()) {
959
      if (const nsAttrValue* value = GetSVGAnimatedClass()) {
960
        return value;
961
      }
962
    }
963
964
    return GetParsedAttr(nsGkAtoms::_class);
965
  }
966
967
#ifdef DEBUG
968
  virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override
969
  {
970
    List(out, aIndent, EmptyCString());
971
  }
972
  virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override;
973
  void List(FILE* out, int32_t aIndent, const nsCString& aPrefix) const;
974
  void ListAttributes(FILE* out) const;
975
#endif
976
977
  /**
978
   * Append to aOutDescription a short (preferably one line) string
979
   * describing the element.
980
   */
981
  void Describe(nsAString& aOutDescription) const;
982
983
  /*
984
   * Attribute Mapping Helpers
985
   */
986
  struct MappedAttributeEntry {
987
    nsStaticAtom** attribute;
988
  };
989
990
  /**
991
   * A common method where you can just pass in a list of maps to check
992
   * for attribute dependence. Most implementations of
993
   * IsAttributeMapped should use this function as a default
994
   * handler.
995
   */
996
  template<size_t N>
997
  static bool
998
  FindAttributeDependence(const nsAtom* aAttribute,
999
                          const MappedAttributeEntry* const (&aMaps)[N])
1000
  {
1001
    return FindAttributeDependence(aAttribute, aMaps, N);
1002
  }
1003
1004
  static nsStaticAtom*** HTMLSVGPropertiesToTraverseAndUnlink();
1005
1006
private:
1007
  void DescribeAttribute(uint32_t index, nsAString& aOutDescription) const;
1008
1009
  static bool
1010
  FindAttributeDependence(const nsAtom* aAttribute,
1011
                          const MappedAttributeEntry* const aMaps[],
1012
                          uint32_t aMapCount);
1013
1014
protected:
1015
  inline bool GetAttr(int32_t aNameSpaceID, nsAtom* aName,
1016
                      DOMString& aResult) const
1017
  {
1018
    NS_ASSERTION(nullptr != aName, "must have attribute name");
1019
    NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
1020
                 "must have a real namespace ID!");
1021
    MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in");
1022
    const nsAttrValue* val = mAttrs.GetAttr(aName, aNameSpaceID);
1023
    if (val) {
1024
      val->ToString(aResult);
1025
      return true;
1026
    }
1027
    // else DOMString comes pre-emptied.
1028
    return false;
1029
  }
1030
1031
public:
1032
  bool HasAttrs() const { return mAttrs.HasAttrs(); }
1033
1034
  inline bool GetAttr(const nsAString& aName, DOMString& aResult) const
1035
  {
1036
    MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in");
1037
    const nsAttrValue* val = mAttrs.GetAttr(aName);
1038
    if (val) {
1039
      val->ToString(aResult);
1040
      return true;
1041
    }
1042
    // else DOMString comes pre-emptied.
1043
    return false;
1044
  }
1045
1046
  void GetTagName(nsAString& aTagName) const
1047
  {
1048
    aTagName = NodeName();
1049
  }
1050
  void GetId(nsAString& aId) const
1051
0
  {
1052
0
    GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
1053
0
  }
1054
  void GetId(DOMString& aId) const
1055
  {
1056
    GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
1057
  }
1058
  void SetId(const nsAString& aId)
1059
  {
1060
    SetAttr(kNameSpaceID_None, nsGkAtoms::id, aId, true);
1061
  }
1062
  void GetClassName(nsAString& aClassName)
1063
  {
1064
    GetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName);
1065
  }
1066
  void GetClassName(DOMString& aClassName)
1067
  {
1068
    GetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName);
1069
  }
1070
  void SetClassName(const nsAString& aClassName)
1071
  {
1072
    SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName, true);
1073
  }
1074
1075
  nsDOMTokenList* ClassList();
1076
  nsDOMAttributeMap* Attributes()
1077
  {
1078
    nsDOMSlots* slots = DOMSlots();
1079
    if (!slots->mAttributeMap) {
1080
      slots->mAttributeMap = new nsDOMAttributeMap(this);
1081
    }
1082
1083
    return slots->mAttributeMap;
1084
  }
1085
1086
  void GetAttributeNames(nsTArray<nsString>& aResult);
1087
1088
  void GetAttribute(const nsAString& aName, nsAString& aReturn)
1089
  {
1090
    DOMString str;
1091
    GetAttribute(aName, str);
1092
    str.ToString(aReturn);
1093
  }
1094
1095
  void GetAttribute(const nsAString& aName, DOMString& aReturn);
1096
  void GetAttributeNS(const nsAString& aNamespaceURI,
1097
                      const nsAString& aLocalName,
1098
                      nsAString& aReturn);
1099
  bool ToggleAttribute(const nsAString& aName, const Optional<bool>& aForce,
1100
                       nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
1101
  void SetAttribute(const nsAString& aName, const nsAString& aValue,
1102
                    nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
1103
  void SetAttributeNS(const nsAString& aNamespaceURI,
1104
                      const nsAString& aLocalName,
1105
                      const nsAString& aValue,
1106
                      nsIPrincipal* aTriggeringPrincipal,
1107
                      ErrorResult& aError);
1108
  void SetAttribute(const nsAString& aName, const nsAString& aValue,
1109
                    ErrorResult& aError)
1110
  {
1111
    SetAttribute(aName, aValue, nullptr, aError);
1112
  }
1113
1114
  void RemoveAttribute(const nsAString& aName,
1115
                       ErrorResult& aError);
1116
  void RemoveAttributeNS(const nsAString& aNamespaceURI,
1117
                         const nsAString& aLocalName,
1118
                         ErrorResult& aError);
1119
  bool HasAttribute(const nsAString& aName) const
1120
  {
1121
    return InternalGetAttrNameFromQName(aName) != nullptr;
1122
  }
1123
  bool HasAttributeNS(const nsAString& aNamespaceURI,
1124
                      const nsAString& aLocalName) const;
1125
  bool HasAttributes() const
1126
  {
1127
    return HasAttrs();
1128
  }
1129
  Element* Closest(const nsAString& aSelector,
1130
                   ErrorResult& aResult);
1131
  bool Matches(const nsAString& aSelector,
1132
               ErrorResult& aError);
1133
  already_AddRefed<nsIHTMLCollection>
1134
    GetElementsByTagName(const nsAString& aQualifiedName);
1135
  already_AddRefed<nsIHTMLCollection>
1136
    GetElementsByTagNameNS(const nsAString& aNamespaceURI,
1137
                           const nsAString& aLocalName,
1138
                           ErrorResult& aError);
1139
  already_AddRefed<nsIHTMLCollection>
1140
    GetElementsByClassName(const nsAString& aClassNames);
1141
1142
  CSSPseudoElementType GetPseudoElementType() const {
1143
    nsresult rv = NS_OK;
1144
    auto raw = GetProperty(nsGkAtoms::pseudoProperty, &rv);
1145
    if (rv == NS_PROPTABLE_PROP_NOT_THERE) {
1146
      return CSSPseudoElementType::NotPseudo;
1147
    }
1148
    return CSSPseudoElementType(reinterpret_cast<uintptr_t>(raw));
1149
  }
1150
1151
  void SetPseudoElementType(CSSPseudoElementType aPseudo) {
1152
    static_assert(sizeof(CSSPseudoElementType) <= sizeof(uintptr_t),
1153
                  "Need to be able to store this in a void*");
1154
    MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo);
1155
    SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
1156
  }
1157
1158
  /**
1159
   * Return an array of all elements in the subtree rooted at this
1160
   * element that have grid container frames. This does not include
1161
   * pseudo-elements.
1162
   */
1163
  void GetElementsWithGrid(nsTArray<RefPtr<Element>>& aElements);
1164
1165
private:
1166
  /**
1167
   * Implement the algorithm specified at
1168
   * https://dom.spec.whatwg.org/#insert-adjacent for both
1169
   * |insertAdjacentElement()| and |insertAdjacentText()| APIs.
1170
   */
1171
  nsINode* InsertAdjacent(const nsAString& aWhere,
1172
                          nsINode* aNode,
1173
                          ErrorResult& aError);
1174
1175
public:
1176
  Element* InsertAdjacentElement(const nsAString& aWhere,
1177
                                 Element& aElement,
1178
                                 ErrorResult& aError);
1179
1180
  void InsertAdjacentText(const nsAString& aWhere,
1181
                          const nsAString& aData,
1182
                          ErrorResult& aError);
1183
1184
  void SetPointerCapture(int32_t aPointerId, ErrorResult& aError)
1185
  {
1186
    bool activeState = false;
1187
    if (!PointerEventHandler::GetPointerInfo(aPointerId, activeState)) {
1188
      aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
1189
      return;
1190
    }
1191
    if (!IsInUncomposedDoc()) {
1192
      aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1193
      return;
1194
    }
1195
    if (OwnerDoc()->GetPointerLockElement()) {
1196
      // Throw an exception 'InvalidStateError' while the page has a locked
1197
      // element.
1198
      aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1199
      return;
1200
    }
1201
    if (!activeState) {
1202
      return;
1203
    }
1204
    PointerEventHandler::SetPointerCaptureById(aPointerId, this);
1205
  }
1206
  void ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError)
1207
  {
1208
    bool activeState = false;
1209
    if (!PointerEventHandler::GetPointerInfo(aPointerId, activeState)) {
1210
      aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
1211
      return;
1212
    }
1213
    if (HasPointerCapture(aPointerId)) {
1214
      PointerEventHandler::ReleasePointerCaptureById(aPointerId);
1215
    }
1216
  }
1217
  bool HasPointerCapture(long aPointerId)
1218
  {
1219
    PointerCaptureInfo* pointerCaptureInfo =
1220
      PointerEventHandler::GetPointerCaptureInfo(aPointerId);
1221
    if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
1222
      return true;
1223
    }
1224
    return false;
1225
  }
1226
  void SetCapture(bool aRetargetToElement)
1227
  {
1228
    // If there is already an active capture, ignore this request. This would
1229
    // occur if a splitter, frame resizer, etc had already captured and we don't
1230
    // want to override those.
1231
    if (!nsIPresShell::GetCapturingContent()) {
1232
      nsIPresShell::SetCapturingContent(this, CAPTURE_PREVENTDRAG |
1233
        (aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
1234
    }
1235
  }
1236
1237
  void SetCaptureAlways(bool aRetargetToElement)
1238
  {
1239
    nsIPresShell::SetCapturingContent(this,
1240
        CAPTURE_PREVENTDRAG | CAPTURE_IGNOREALLOWED |
1241
        (aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
1242
  }
1243
1244
  void ReleaseCapture()
1245
  {
1246
    if (nsIPresShell::GetCapturingContent() == this) {
1247
      nsIPresShell::SetCapturingContent(nullptr, 0);
1248
    }
1249
  }
1250
1251
  already_AddRefed<Promise> RequestFullscreen(CallerType, ErrorResult&);
1252
  void RequestPointerLock(CallerType aCallerType);
1253
  Attr* GetAttributeNode(const nsAString& aName);
1254
  already_AddRefed<Attr> SetAttributeNode(Attr& aNewAttr,
1255
                                          ErrorResult& aError);
1256
  already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
1257
                                             ErrorResult& aError);
1258
  Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
1259
                           const nsAString& aLocalName);
1260
  already_AddRefed<Attr> SetAttributeNodeNS(Attr& aNewAttr,
1261
                                            ErrorResult& aError);
1262
1263
  MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRectList> GetClientRects();
1264
  MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRect> GetBoundingClientRect();
1265
1266
  // Shadow DOM v1
1267
  already_AddRefed<ShadowRoot> AttachShadow(const ShadowRootInit& aInit,
1268
                                            ErrorResult& aError);
1269
1270
  already_AddRefed<ShadowRoot> AttachShadowWithoutNameChecks(ShadowRootMode aMode);
1271
  void UnattachShadow();
1272
1273
  ShadowRoot* GetShadowRootByMode() const;
1274
  void SetSlot(const nsAString& aName, ErrorResult& aError);
1275
  void GetSlot(nsAString& aName);
1276
1277
  ShadowRoot* GetShadowRoot() const
1278
  {
1279
    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
1280
    return slots ? slots->mShadowRoot.get() : nullptr;
1281
  }
1282
1283
private:
1284
  void ScrollIntoView(const ScrollIntoViewOptions &aOptions);
1285
public:
1286
  void ScrollIntoView(const BooleanOrScrollIntoViewOptions& aObject);
1287
  MOZ_CAN_RUN_SCRIPT void Scroll(double aXScroll, double aYScroll);
1288
  MOZ_CAN_RUN_SCRIPT void Scroll(const ScrollToOptions& aOptions);
1289
  MOZ_CAN_RUN_SCRIPT void ScrollTo(double aXScroll, double aYScroll);
1290
  MOZ_CAN_RUN_SCRIPT void ScrollTo(const ScrollToOptions& aOptions);
1291
  MOZ_CAN_RUN_SCRIPT void ScrollBy(double aXScrollDif, double aYScrollDif);
1292
  MOZ_CAN_RUN_SCRIPT void ScrollBy(const ScrollToOptions& aOptions);
1293
  /* Scrolls without flushing the layout.
1294
   * aDx is the x offset, aDy the y offset in CSS pixels.
1295
   * Returns true if we actually scrolled.
1296
   */
1297
  MOZ_CAN_RUN_SCRIPT bool ScrollByNoFlush(int32_t aDx, int32_t aDy);
1298
  MOZ_CAN_RUN_SCRIPT int32_t ScrollTop();
1299
  MOZ_CAN_RUN_SCRIPT void SetScrollTop(int32_t aScrollTop);
1300
  MOZ_CAN_RUN_SCRIPT int32_t ScrollLeft();
1301
  MOZ_CAN_RUN_SCRIPT void SetScrollLeft(int32_t aScrollLeft);
1302
  MOZ_CAN_RUN_SCRIPT int32_t ScrollWidth();
1303
  MOZ_CAN_RUN_SCRIPT int32_t ScrollHeight();
1304
  MOZ_CAN_RUN_SCRIPT void MozScrollSnap();
1305
  MOZ_CAN_RUN_SCRIPT int32_t ClientTop()
1306
  {
1307
    return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y);
1308
  }
1309
  MOZ_CAN_RUN_SCRIPT int32_t ClientLeft()
1310
  {
1311
    return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().x);
1312
  }
1313
  MOZ_CAN_RUN_SCRIPT int32_t ClientWidth()
1314
  {
1315
    return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().Width());
1316
  }
1317
  MOZ_CAN_RUN_SCRIPT int32_t ClientHeight()
1318
  {
1319
    return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().Height());
1320
  }
1321
  MOZ_CAN_RUN_SCRIPT int32_t ScrollTopMin()
1322
  {
1323
    nsIScrollableFrame* sf = GetScrollFrame();
1324
    return sf ?
1325
           nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().y) : 0;
1326
  }
1327
  MOZ_CAN_RUN_SCRIPT int32_t ScrollTopMax()
1328
  {
1329
    nsIScrollableFrame* sf = GetScrollFrame();
1330
    return sf ?
1331
           nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().YMost()) :
1332
           0;
1333
  }
1334
  MOZ_CAN_RUN_SCRIPT int32_t ScrollLeftMin()
1335
  {
1336
    nsIScrollableFrame* sf = GetScrollFrame();
1337
    return sf ?
1338
           nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().x) : 0;
1339
  }
1340
  MOZ_CAN_RUN_SCRIPT int32_t ScrollLeftMax()
1341
  {
1342
    nsIScrollableFrame* sf = GetScrollFrame();
1343
    return sf ?
1344
           nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().XMost()) :
1345
           0;
1346
  }
1347
1348
  already_AddRefed<Flex> GetAsFlexContainer();
1349
  void GetGridFragments(nsTArray<RefPtr<Grid>>& aResult);
1350
1351
  already_AddRefed<DOMMatrixReadOnly> GetTransformToAncestor(Element& aAncestor);
1352
  already_AddRefed<DOMMatrixReadOnly> GetTransformToParent();
1353
  already_AddRefed<DOMMatrixReadOnly> GetTransformToViewport();
1354
1355
  already_AddRefed<Animation>
1356
  Animate(JSContext* aContext,
1357
          JS::Handle<JSObject*> aKeyframes,
1358
          const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
1359
          ErrorResult& aError);
1360
1361
  // A helper method that factors out the common functionality needed by
1362
  // Element::Animate and CSSPseudoElement::Animate
1363
  static already_AddRefed<Animation>
1364
  Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
1365
          JSContext* aContext,
1366
          JS::Handle<JSObject*> aKeyframes,
1367
          const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
1368
          ErrorResult& aError);
1369
1370
  // Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
1371
  // Callers must keep this element alive because flushing style may destroy
1372
  // this element.
1373
  void GetAnimations(const AnimationFilter& filter,
1374
                     nsTArray<RefPtr<Animation>>& aAnimations);
1375
  static void GetAnimationsUnsorted(Element* aElement,
1376
                                    CSSPseudoElementType aPseudoType,
1377
                                    nsTArray<RefPtr<Animation>>& aAnimations);
1378
1379
  virtual void GetInnerHTML(nsAString& aInnerHTML, OOMReporter& aError);
1380
  virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
1381
  void GetOuterHTML(nsAString& aOuterHTML);
1382
  void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
1383
  void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
1384
                          ErrorResult& aError);
1385
1386
  //----------------------------------------
1387
1388
  /**
1389
   * Add a script event listener with the given event handler name
1390
   * (like onclick) and with the value as JS
1391
   * @param aEventName the event listener name
1392
   * @param aValue the JS to attach
1393
   * @param aDefer indicates if deferred execution is allowed
1394
   */
1395
  nsresult SetEventHandler(nsAtom* aEventName,
1396
                           const nsAString& aValue,
1397
                           bool aDefer = true);
1398
1399
  /**
1400
   * Do whatever needs to be done when the mouse leaves a link
1401
   */
1402
  nsresult LeaveLink(nsPresContext* aPresContext);
1403
1404
  static bool ShouldBlur(nsIContent *aContent);
1405
1406
  /**
1407
   * Method to create and dispatch a left-click event loosely based on
1408
   * aSourceEvent. If aFullDispatch is true, the event will be dispatched
1409
   * through the full dispatching of the presshell of the aPresContext; if it's
1410
   * false the event will be dispatched only as a DOM event.
1411
   * If aPresContext is nullptr, this does nothing.
1412
   *
1413
   * @param aFlags      Extra flags for the dispatching event.  The true flags
1414
   *                    will be respected.
1415
   */
1416
  static nsresult DispatchClickEvent(nsPresContext* aPresContext,
1417
                                     WidgetInputEvent* aSourceEvent,
1418
                                     nsIContent* aTarget,
1419
                                     bool aFullDispatch,
1420
                                     const EventFlags* aFlags,
1421
                                     nsEventStatus* aStatus);
1422
1423
  /**
1424
   * Method to dispatch aEvent to aTarget. If aFullDispatch is true, the event
1425
   * will be dispatched through the full dispatching of the presshell of the
1426
   * aPresContext; if it's false the event will be dispatched only as a DOM
1427
   * event.
1428
   * If aPresContext is nullptr, this does nothing.
1429
   */
1430
  using nsIContent::DispatchEvent;
1431
  static nsresult DispatchEvent(nsPresContext* aPresContext,
1432
                                WidgetEvent* aEvent,
1433
                                nsIContent* aTarget,
1434
                                bool aFullDispatch,
1435
                                nsEventStatus* aStatus);
1436
1437
  /**
1438
   * Get the primary frame for this content with flushing
1439
   *
1440
   * @param aType the kind of flush to do, typically FlushType::Frames or
1441
   *              FlushType::Layout
1442
   * @return the primary frame
1443
   */
1444
  nsIFrame* GetPrimaryFrame(FlushType aType);
1445
  // Work around silly C++ name hiding stuff
1446
  nsIFrame* GetPrimaryFrame() const { return nsIContent::GetPrimaryFrame(); }
1447
1448
  bool IsDisplayContents() const
1449
  {
1450
    return HasServoData() && Servo_Element_IsDisplayContents(this);
1451
  }
1452
1453
  const nsAttrValue* GetParsedAttr(nsAtom* aAttr) const
1454
  {
1455
    return mAttrs.GetAttr(aAttr);
1456
  }
1457
1458
  const nsAttrValue* GetParsedAttr(nsAtom* aAttr, int32_t aNameSpaceID) const
1459
  {
1460
    return mAttrs.GetAttr(aAttr, aNameSpaceID);
1461
  }
1462
1463
  /**
1464
   * Returns the attribute map, if there is one.
1465
   *
1466
   * @return existing attribute map or nullptr.
1467
   */
1468
  nsDOMAttributeMap* GetAttributeMap()
1469
  {
1470
    nsDOMSlots* slots = GetExistingDOMSlots();
1471
1472
    return slots ? slots->mAttributeMap.get() : nullptr;
1473
  }
1474
1475
  virtual void RecompileScriptEventListeners()
1476
  {
1477
  }
1478
1479
  /**
1480
   * Get the attr info for the given namespace ID and attribute name.  The
1481
   * namespace ID must not be kNameSpaceID_Unknown and the name must not be
1482
   * null.  Note that this can only return info on attributes that actually
1483
   * live on this element (and is only virtual to handle XUL prototypes).  That
1484
   * is, this should only be called from methods that only care about attrs
1485
   * that effectively live in mAttrs.
1486
   */
1487
  BorrowedAttrInfo GetAttrInfo(int32_t aNamespaceID, nsAtom* aName) const
1488
  {
1489
    NS_ASSERTION(aName, "must have attribute name");
1490
    NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
1491
                 "must have a real namespace ID!");
1492
1493
    int32_t index = mAttrs.IndexOfAttr(aName, aNamespaceID);
1494
    if (index < 0) {
1495
      return BorrowedAttrInfo(nullptr, nullptr);
1496
    }
1497
1498
    return mAttrs.AttrInfoAt(index);
1499
  }
1500
1501
  /**
1502
   * Called when we have been adopted, and the information of the
1503
   * node has been changed.
1504
   *
1505
   * The new document can be reached via OwnerDoc().
1506
   *
1507
   * If you override this method,
1508
   * please call up to the parent NodeInfoChanged.
1509
   *
1510
   * If you change this, change also the similar method in Link.
1511
   */
1512
  virtual void NodeInfoChanged(nsIDocument* aOldDoc) {}
1513
1514
  /**
1515
   * Parse a string into an nsAttrValue for a CORS attribute.  This
1516
   * never fails.  The resulting value is an enumerated value whose
1517
   * GetEnumValue() returns one of the above constants.
1518
   */
1519
  static void ParseCORSValue(const nsAString& aValue, nsAttrValue& aResult);
1520
1521
  /**
1522
   * Return the CORS mode for a given string
1523
   */
1524
  static CORSMode StringToCORSMode(const nsAString& aValue);
1525
1526
  /**
1527
   * Return the CORS mode for a given nsAttrValue (which may be null,
1528
   * but if not should have been parsed via ParseCORSValue).
1529
   */
1530
  static CORSMode AttrValueToCORSMode(const nsAttrValue* aValue);
1531
1532
  JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) final;
1533
1534
  nsINode* GetScopeChainParent() const override;
1535
1536
  /**
1537
   * Locate a TextEditor rooted at this content node, if there is one.
1538
   */
1539
  mozilla::TextEditor* GetTextEditorInternal();
1540
1541
  /**
1542
   * Gets value of boolean attribute. Only works for attributes in null
1543
   * namespace.
1544
   *
1545
   * @param aAttr    name of attribute.
1546
   * @param aValue   Boolean value of attribute.
1547
   */
1548
  bool GetBoolAttr(nsAtom* aAttr) const
1549
  {
1550
    return HasAttr(kNameSpaceID_None, aAttr);
1551
  }
1552
1553
  /**
1554
   * Sets value of boolean attribute by removing attribute or setting it to
1555
   * the empty string. Only works for attributes in null namespace.
1556
   *
1557
   * @param aAttr    name of attribute.
1558
   * @param aValue   Boolean value of attribute.
1559
   */
1560
  nsresult SetBoolAttr(nsAtom* aAttr, bool aValue);
1561
1562
  /**
1563
   * Gets the enum value string of an attribute and using a default value if
1564
   * the attribute is missing or the string is an invalid enum value.
1565
   *
1566
   * @param aType     the name of the attribute.
1567
   * @param aDefault  the default value if the attribute is missing or invalid.
1568
   * @param aResult   string corresponding to the value [out].
1569
   */
1570
  void GetEnumAttr(nsAtom* aAttr,
1571
                   const char* aDefault,
1572
                   nsAString& aResult) const;
1573
1574
  /**
1575
   * Gets the enum value string of an attribute and using the default missing
1576
   * value if the attribute is missing or the default invalid value if the
1577
   * string is an invalid enum value.
1578
   *
1579
   * @param aType            the name of the attribute.
1580
   * @param aDefaultMissing  the default value if the attribute is missing.  If
1581
                             null and the attribute is missing, aResult will be
1582
                             set to the null DOMString; this only matters for
1583
                             cases in which we're reflecting a nullable string.
1584
   * @param aDefaultInvalid  the default value if the attribute is invalid.
1585
   * @param aResult          string corresponding to the value [out].
1586
   */
1587
  void GetEnumAttr(nsAtom* aAttr,
1588
                   const char* aDefaultMissing,
1589
                   const char* aDefaultInvalid,
1590
                   nsAString& aResult) const;
1591
1592
  /**
1593
   * Unset an attribute.
1594
   */
1595
  void UnsetAttr(nsAtom* aAttr, ErrorResult& aError)
1596
  {
1597
    aError = UnsetAttr(kNameSpaceID_None, aAttr, true);
1598
  }
1599
1600
  /**
1601
   * Set an attribute in the simplest way possible.
1602
   */
1603
  void SetAttr(nsAtom* aAttr, const nsAString& aValue, ErrorResult& aError)
1604
  {
1605
    aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
1606
  }
1607
1608
  void SetAttr(nsAtom* aAttr, const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError)
1609
  {
1610
    aError = SetAttr(kNameSpaceID_None, aAttr, aValue, aTriggeringPrincipal, true);
1611
  }
1612
1613
  /**
1614
   * Set a content attribute via a reflecting nullable string IDL
1615
   * attribute (e.g. a CORS attribute).  If DOMStringIsNull(aValue),
1616
   * this will actually remove the content attribute.
1617
   */
1618
  void SetOrRemoveNullableStringAttr(nsAtom* aName, const nsAString& aValue,
1619
                                     ErrorResult& aError);
1620
1621
  /**
1622
   * Retrieve the ratio of font-size-inflated text font size to computed font
1623
   * size for this element. This will query the element for its primary frame,
1624
   * and then use this to get font size inflation information about the frame.
1625
   *
1626
   * @returns The font size inflation ratio (inflated font size to uninflated
1627
   *          font size) for the primary frame of this element. Returns 1.0
1628
   *          by default if font size inflation is not enabled. Returns -1
1629
   *          if the element does not have a primary frame.
1630
   *
1631
   * @note The font size inflation ratio that is returned is actually the
1632
   *       font size inflation data for the element's _primary frame_, not the
1633
   *       element itself, but for most purposes, this should be sufficient.
1634
   */
1635
  float FontSizeInflation();
1636
1637
  net::ReferrerPolicy GetReferrerPolicyAsEnum();
1638
  net::ReferrerPolicy ReferrerPolicyFromAttr(const nsAttrValue* aValue);
1639
1640
  /*
1641
   * Helpers for .dataset.  This is implemented on Element, though only some
1642
   * sorts of elements expose it to JS as a .dataset property
1643
   */
1644
  // Getter, to be called from bindings.
1645
  already_AddRefed<nsDOMStringMap> Dataset();
1646
  // Callback for destructor of dataset to ensure to null out our weak pointer
1647
  // to it.
1648
  void ClearDataset();
1649
1650
  void RegisterIntersectionObserver(DOMIntersectionObserver* aObserver);
1651
  void UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver);
1652
  void UnlinkIntersectionObservers();
1653
  bool UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t threshold);
1654
1655
protected:
1656
  /*
1657
   * Named-bools for use with SetAttrAndNotify to make call sites easier to
1658
   * read.
1659
   */
1660
  static const bool kFireMutationEvent           = true;
1661
  static const bool kDontFireMutationEvent       = false;
1662
  static const bool kNotifyDocumentObservers     = true;
1663
  static const bool kDontNotifyDocumentObservers = false;
1664
  static const bool kCallAfterSetAttr            = true;
1665
  static const bool kDontCallAfterSetAttr        = false;
1666
1667
  /**
1668
   * Set attribute and (if needed) notify documentobservers and fire off
1669
   * mutation events.  This will send the AttributeChanged notification.
1670
   * Callers of this method are responsible for calling AttributeWillChange,
1671
   * since that needs to happen before the new attr value has been set, and
1672
   * in particular before it has been parsed.
1673
   *
1674
   * For the boolean parameters, consider using the named bools above to aid
1675
   * code readability.
1676
   *
1677
   * @param aNamespaceID  namespace of attribute
1678
   * @param aAttribute    local-name of attribute
1679
   * @param aPrefix       aPrefix of attribute
1680
   * @param aOldValue     The old value of the attribute to use as a fallback
1681
   *                      in the cases where the actual old value (i.e.
1682
   *                      its current value) is !StoresOwnData() --- in which
1683
   *                      case the current value is probably already useless.
1684
   *                      If the current value is StoresOwnData() (or absent),
1685
   *                      aOldValue will not be used. aOldValue will only be set
1686
   *                      in certain circumstances (there are mutation
1687
   *                      listeners, element is a custom element, attribute was
1688
   *                      not previously unset). Otherwise it will be null.
1689
   * @param aParsedValue  parsed new value of attribute. Replaced by the
1690
   *                      old value of the attribute. This old value is only
1691
   *                      useful if either it or the new value is StoresOwnData.
1692
   * @param aMaybeScriptedPrincipal
1693
   *                      the principal of the scripted caller responsible for
1694
   *                      setting the attribute, or null if no scripted caller
1695
   *                      can be determined. A null value here does not
1696
   *                      guarantee that there is no scripted caller, but a
1697
   *                      non-null value does guarantee that a scripted caller
1698
   *                      with the given principal is directly responsible for
1699
   *                      the attribute change.
1700
   * @param aModType      MutationEvent_Binding::MODIFICATION or ADDITION.  Only
1701
   *                      needed if aFireMutation or aNotify is true.
1702
   * @param aFireMutation should mutation-events be fired?
1703
   * @param aNotify       should we notify document-observers?
1704
   * @param aCallAfterSetAttr should we call AfterSetAttr?
1705
   * @param aComposedDocument The current composed document of the element.
1706
   */
1707
  nsresult SetAttrAndNotify(int32_t aNamespaceID,
1708
                            nsAtom* aName,
1709
                            nsAtom* aPrefix,
1710
                            const nsAttrValue* aOldValue,
1711
                            nsAttrValue& aParsedValue,
1712
                            nsIPrincipal* aMaybeScriptedPrincipal,
1713
                            uint8_t aModType,
1714
                            bool aFireMutation,
1715
                            bool aNotify,
1716
                            bool aCallAfterSetAttr,
1717
                            nsIDocument* aComposedDocument,
1718
                            const mozAutoDocUpdate& aGuard);
1719
1720
  /**
1721
   * Scroll to a new position using behavior evaluated from CSS and
1722
   * a CSSOM-View DOM method ScrollOptions dictionary.  The scrolling may
1723
   * be performed asynchronously or synchronously depending on the resolved
1724
   * scroll-behavior.
1725
   *
1726
   * @param aScroll       Destination of scroll, in CSS pixels
1727
   * @param aOptions      Dictionary of options to be evaluated
1728
   */
1729
  MOZ_CAN_RUN_SCRIPT
1730
  void Scroll(const CSSIntPoint& aScroll, const ScrollOptions& aOptions);
1731
1732
  /**
1733
   * Convert an attribute string value to attribute type based on the type of
1734
   * attribute.  Called by SetAttr().  Note that at the moment we only do this
1735
   * for attributes in the null namespace (kNameSpaceID_None).
1736
   *
1737
   * @param aNamespaceID the namespace of the attribute to convert
1738
   * @param aAttribute the attribute to convert
1739
   * @param aValue the string value to convert
1740
   * @param aMaybeScriptedPrincipal the principal of the script setting the
1741
   *        attribute, if one can be determined, or null otherwise. As in
1742
   *        AfterSetAttr, a null value does not guarantee that the attribute was
1743
   *        not set by a scripted caller, but a non-null value guarantees that
1744
   *        the attribute was set by a scripted caller with the given principal.
1745
   * @param aResult the nsAttrValue [OUT]
1746
   * @return true if the parsing was successful, false otherwise
1747
   */
1748
  virtual bool ParseAttribute(int32_t aNamespaceID,
1749
                                nsAtom* aAttribute,
1750
                                const nsAString& aValue,
1751
                                nsIPrincipal* aMaybeScriptedPrincipal,
1752
                                nsAttrValue& aResult);
1753
1754
  /**
1755
   * Try to set the attribute as a mapped attribute, if applicable.  This will
1756
   * only be called for attributes that are in the null namespace and only on
1757
   * attributes that returned true when passed to IsAttributeMapped.  The
1758
   * caller will not try to set the attr in any other way if this method
1759
   * returns true (the value of aRetval does not matter for that purpose).
1760
   *
1761
   * @param aName the name of the attribute
1762
   * @param aValue the nsAttrValue to set. Will be swapped with the existing
1763
   *               value of the attribute if the attribute already exists.
1764
   * @param [out] aValueWasSet If the attribute was not set previously,
1765
   *                           aValue will be swapped with an empty attribute
1766
   *                           and aValueWasSet will be set to false. Otherwise,
1767
   *                           aValueWasSet will be set to true and aValue will
1768
   *                           contain the previous value set.
1769
   * @param [out] aRetval the nsresult status of the operation, if any.
1770
   * @return true if the setting was attempted, false otherwise.
1771
   */
1772
  virtual bool SetAndSwapMappedAttribute(nsAtom* aName,
1773
                                         nsAttrValue& aValue,
1774
                                         bool* aValueWasSet,
1775
                                         nsresult* aRetval);
1776
1777
  /**
1778
   * Hook that is called by Element::SetAttr to allow subclasses to
1779
   * deal with attribute sets.  This will only be called after we verify that
1780
   * we're actually doing an attr set and will be called before
1781
   * AttributeWillChange and before ParseAttribute and hence before we've set
1782
   * the new value.
1783
   *
1784
   * @param aNamespaceID the namespace of the attr being set
1785
   * @param aName the localname of the attribute being set
1786
   * @param aValue the value it's being set to represented as either a string or
1787
   *        a parsed nsAttrValue. Alternatively, if the attr is being removed it
1788
   *        will be null.
1789
   * @param aNotify Whether we plan to notify document observers.
1790
   */
1791
  virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
1792
                                 const nsAttrValueOrString* aValue,
1793
                                 bool aNotify);
1794
1795
  /**
1796
   * Hook that is called by Element::SetAttr to allow subclasses to
1797
   * deal with attribute sets.  This will only be called after we have called
1798
   * SetAndSwapAttr (that is, after we have actually set the attr).  It will
1799
   * always be called under a scriptblocker.
1800
   *
1801
   * @param aNamespaceID the namespace of the attr being set
1802
   * @param aName the localname of the attribute being set
1803
   * @param aValue the value it's being set to.  If null, the attr is being
1804
   *        removed.
1805
   * @param aOldValue the value that the attribute had previously. If null,
1806
   *        the attr was not previously set. This argument may not have the
1807
   *        correct value for SVG elements, or other cases in which the
1808
   *        attribute value doesn't store its own data
1809
   * @param aMaybeScriptedPrincipal the principal of the scripted caller
1810
   *        responsible for setting the attribute, or null if no scripted caller
1811
   *        can be determined, or the attribute is being unset. A null value
1812
   *        here does not guarantee that there is no scripted caller, but a
1813
   *        non-null value does guarantee that a scripted caller with the given
1814
   *        principal is directly responsible for the attribute change.
1815
   * @param aNotify Whether we plan to notify document observers.
1816
   */
1817
  // Note that this is inlined so that when subclasses call it it gets
1818
  // inlined.  Those calls don't go through a vtable.
1819
  virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
1820
                                const nsAttrValue* aValue,
1821
                                const nsAttrValue* aOldValue,
1822
                                nsIPrincipal* aMaybeScriptedPrincipal,
1823
                                bool aNotify)
1824
  {
1825
    return NS_OK;
1826
  }
1827
1828
  /**
1829
   * This function shall be called just before the id attribute changes. It will
1830
   * be called after BeforeSetAttr. If the attribute being changed is not the id
1831
   * attribute, this function does nothing. Otherwise, it will remove the old id
1832
   * from the document's id cache.
1833
   *
1834
   * This must happen after BeforeSetAttr (rather than during) because the
1835
   * the subclasses' calls to BeforeSetAttr may notify on state changes. If they
1836
   * incorrectly determine whether the element had an id, the element may not be
1837
   * restyled properly.
1838
   *
1839
   * @param aNamespaceID the namespace of the attr being set
1840
   * @param aName the localname of the attribute being set
1841
   * @param aValue the new id value. Will be null if the id is being unset.
1842
   */
1843
  void PreIdMaybeChange(int32_t aNamespaceID, nsAtom* aName,
1844
                        const nsAttrValueOrString* aValue);
1845
1846
  /**
1847
   * This function shall be called just after the id attribute changes. It will
1848
   * be called before AfterSetAttr. If the attribute being changed is not the id
1849
   * attribute, this function does nothing. Otherwise, it will add the new id to
1850
   * the document's id cache and properly set the ElementHasID flag.
1851
   *
1852
   * This must happen before AfterSetAttr (rather than during) because the
1853
   * the subclasses' calls to AfterSetAttr may notify on state changes. If they
1854
   * incorrectly determine whether the element now has an id, the element may
1855
   * not be restyled properly.
1856
   *
1857
   * @param aNamespaceID the namespace of the attr being set
1858
   * @param aName the localname of the attribute being set
1859
   * @param aValue the new id value. Will be null if the id is being unset.
1860
   */
1861
  void PostIdMaybeChange(int32_t aNamespaceID, nsAtom* aName,
1862
                         const nsAttrValue* aValue);
1863
1864
  /**
1865
   * Usually, setting an attribute to the value that it already has results in
1866
   * no action. However, in some cases, setting an attribute to its current
1867
   * value should have the effect of, for example, forcing a reload of
1868
   * network data. To address that, this function will be called in this
1869
   * situation to allow the handling of such a case.
1870
   *
1871
   * @param aNamespaceID the namespace of the attr being set
1872
   * @param aName the localname of the attribute being set
1873
   * @param aValue the value it's being set to represented as either a string or
1874
   *        a parsed nsAttrValue.
1875
   * @param aNotify Whether we plan to notify document observers.
1876
   */
1877
  // Note that this is inlined so that when subclasses call it it gets
1878
  // inlined.  Those calls don't go through a vtable.
1879
  virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
1880
                                          const nsAttrValueOrString& aValue,
1881
                                          bool aNotify);
1882
1883
  /**
1884
   * Hook to allow subclasses to produce a different EventListenerManager if
1885
   * needed for attachment of attribute-defined handlers
1886
   */
1887
  virtual EventListenerManager*
1888
    GetEventListenerManagerForAttr(nsAtom* aAttrName, bool* aDefer);
1889
1890
  /**
1891
   * Internal hook for converting an attribute name-string to nsAttrName in
1892
   * case there is such existing attribute. aNameToUse can be passed to get
1893
   * name which was used for looking for the attribute (lowercase in HTML).
1894
   */
1895
  const nsAttrName*
1896
  InternalGetAttrNameFromQName(const nsAString& aStr,
1897
                               nsAutoString* aNameToUse = nullptr) const;
1898
1899
  virtual Element* GetNameSpaceElement() override
1900
  {
1901
    return this;
1902
  }
1903
1904
  Attr* GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
1905
                                   const nsAString& aLocalName);
1906
1907
  inline void RegisterActivityObserver();
1908
  inline void UnregisterActivityObserver();
1909
1910
  /**
1911
   * Add/remove this element to the documents id cache
1912
   */
1913
  void AddToIdTable(nsAtom* aId);
1914
  void RemoveFromIdTable();
1915
1916
  /**
1917
   * Functions to carry out event default actions for links of all types
1918
   * (HTML links, XLinks, SVG "XLinks", etc.)
1919
   */
1920
1921
  /**
1922
   * Check that we meet the conditions to handle a link event
1923
   * and that we are actually on a link.
1924
   *
1925
   * @param aVisitor event visitor
1926
   * @param aURI the uri of the link, set only if the return value is true [OUT]
1927
   * @return true if we can handle the link event, false otherwise
1928
   */
1929
  bool CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor,
1930
                                            nsIURI** aURI) const;
1931
1932
  /**
1933
   * Handle status bar updates before they can be cancelled.
1934
   */
1935
  void GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor);
1936
1937
  /**
1938
   * Handle default actions for link event if the event isn't consumed yet.
1939
   */
1940
  nsresult PostHandleEventForLinks(EventChainPostVisitor& aVisitor);
1941
1942
  /**
1943
   * Get the target of this link element. Consumers should established that
1944
   * this element is a link (probably using IsLink) before calling this
1945
   * function (or else why call it?)
1946
   *
1947
   * Note: for HTML this gets the value of the 'target' attribute; for XLink
1948
   * this gets the value of the xlink:_moz_target attribute, or failing that,
1949
   * the value of xlink:show, converted to a suitably equivalent named target
1950
   * (e.g. _blank).
1951
   */
1952
  virtual void GetLinkTarget(nsAString& aTarget);
1953
1954
  nsDOMTokenList* GetTokenList(nsAtom* aAtom,
1955
                               const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
1956
1957
private:
1958
  /**
1959
   * Slow path for GetClasses, this should only be called for SVG elements.
1960
   */
1961
  const nsAttrValue* GetSVGAnimatedClass() const;
1962
1963
  /**
1964
   * Get this element's client area rect in app units.
1965
   * @return the frame's client area
1966
   */
1967
  MOZ_CAN_RUN_SCRIPT nsRect GetClientAreaRect();
1968
1969
  /**
1970
   * GetCustomInterface is somewhat like a GetInterface, but it is expected
1971
   * that the implementation is provided by a custom element or via the
1972
   * the XBL implements keyword. To use this, create a public method that
1973
   * wraps a call to GetCustomInterface.
1974
   */
1975
  template<class T> void GetCustomInterface(nsGetterAddRefs<T> aResult);
1976
1977
  // Prevent people from doing pointless checks/casts on Element instances.
1978
  void IsElement() = delete;
1979
  void AsElement() = delete;
1980
1981
  // Data members
1982
  EventStates mState;
1983
  // Per-node data managed by Servo.
1984
  //
1985
  // There should not be data on nodes that are in the flattened tree, or
1986
  // descendants of display: none elements.
1987
  mozilla::ServoCell<ServoNodeData*> mServoData;
1988
};
1989
1990
class RemoveFromBindingManagerRunnable : public mozilla::Runnable
1991
{
1992
public:
1993
  RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
1994
                                   nsIContent* aContent,
1995
                                   nsIDocument* aDoc);
1996
1997
  NS_IMETHOD Run() override;
1998
private:
1999
  virtual ~RemoveFromBindingManagerRunnable();
2000
  RefPtr<nsBindingManager> mManager;
2001
  RefPtr<nsIContent> mContent;
2002
  nsCOMPtr<nsIDocument> mDoc;
2003
};
2004
2005
NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
2006
2007
inline bool
2008
Element::HasAttr(int32_t aNameSpaceID, nsAtom* aName) const
2009
{
2010
  NS_ASSERTION(nullptr != aName, "must have attribute name");
2011
  NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
2012
               "must have a real namespace ID!");
2013
2014
  return mAttrs.IndexOfAttr(aName, aNameSpaceID) >= 0;
2015
}
2016
2017
inline bool
2018
Element::AttrValueIs(int32_t aNameSpaceID,
2019
                     nsAtom* aName,
2020
                     const nsAString& aValue,
2021
                     nsCaseTreatment aCaseSensitive) const
2022
{
2023
  NS_ASSERTION(aName, "Must have attr name");
2024
  NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
2025
2026
  const nsAttrValue* val = mAttrs.GetAttr(aName, aNameSpaceID);
2027
  return val && val->Equals(aValue, aCaseSensitive);
2028
}
2029
2030
inline bool
2031
Element::AttrValueIs(int32_t aNameSpaceID,
2032
                     nsAtom* aName,
2033
                     nsAtom* aValue,
2034
                     nsCaseTreatment aCaseSensitive) const
2035
{
2036
  NS_ASSERTION(aName, "Must have attr name");
2037
  NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
2038
  NS_ASSERTION(aValue, "Null value atom");
2039
2040
  const nsAttrValue* val = mAttrs.GetAttr(aName, aNameSpaceID);
2041
  return val && val->Equals(aValue, aCaseSensitive);
2042
}
2043
2044
} // namespace dom
2045
} // namespace mozilla
2046
2047
inline mozilla::dom::Element*
2048
nsINode::AsElement()
2049
{
2050
  MOZ_ASSERT(IsElement());
2051
  return static_cast<mozilla::dom::Element*>(this);
2052
}
2053
2054
inline const mozilla::dom::Element*
2055
nsINode::AsElement() const
2056
{
2057
  MOZ_ASSERT(IsElement());
2058
  return static_cast<const mozilla::dom::Element*>(this);
2059
}
2060
2061
inline mozilla::dom::Element*
2062
nsINode::GetParentElement() const
2063
{
2064
  return mozilla::dom::Element::FromNodeOrNull(mParent);
2065
}
2066
2067
inline mozilla::dom::Element*
2068
nsINode::GetPreviousElementSibling() const
2069
0
{
2070
0
  nsIContent* previousSibling = GetPreviousSibling();
2071
0
  while (previousSibling) {
2072
0
    if (previousSibling->IsElement()) {
2073
0
      return previousSibling->AsElement();
2074
0
    }
2075
0
    previousSibling = previousSibling->GetPreviousSibling();
2076
0
  }
2077
0
2078
0
  return nullptr;
2079
0
}
2080
2081
inline mozilla::dom::Element*
2082
nsINode::GetNextElementSibling() const
2083
{
2084
  nsIContent* nextSibling = GetNextSibling();
2085
  while (nextSibling) {
2086
    if (nextSibling->IsElement()) {
2087
      return nextSibling->AsElement();
2088
    }
2089
    nextSibling = nextSibling->GetNextSibling();
2090
  }
2091
2092
  return nullptr;
2093
}
2094
2095
/**
2096
 * Macros to implement Clone(). _elementName is the class for which to implement
2097
 * Clone.
2098
 */
2099
#define NS_IMPL_ELEMENT_CLONE(_elementName)                                 \
2100
nsresult                                                                    \
2101
_elementName::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const \
2102
{                                                                           \
2103
  *aResult = nullptr;                                                       \
2104
  RefPtr<mozilla::dom::NodeInfo> ni(aNodeInfo);                             \
2105
  _elementName *it = new _elementName(ni.forget());                         \
2106
  if (!it) {                                                                \
2107
    return NS_ERROR_OUT_OF_MEMORY;                                          \
2108
  }                                                                         \
2109
                                                                            \
2110
  nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
2111
  nsresult rv = const_cast<_elementName*>(this)->CopyInnerTo(it);           \
2112
  if (NS_SUCCEEDED(rv)) {                                                   \
2113
    kungFuDeathGrip.swap(*aResult);                                         \
2114
  }                                                                         \
2115
                                                                            \
2116
  return rv;                                                                \
2117
}
2118
2119
#define EXPAND(...) __VA_ARGS__
2120
#define NS_IMPL_ELEMENT_CLONE_WITH_INIT_HELPER(_elementName, extra_args_)   \
2121
nsresult                                                                    \
2122
_elementName::Clone(mozilla::dom::NodeInfo* aNodeInfo,                      \
2123
                    nsINode** aResult) const                                \
2124
{                                                                           \
2125
  *aResult = nullptr;                                                       \
2126
  RefPtr<mozilla::dom::NodeInfo> ni(aNodeInfo);                             \
2127
  _elementName *it = new _elementName(ni.forget() EXPAND extra_args_);      \
2128
  if (!it) {                                                                \
2129
    return NS_ERROR_OUT_OF_MEMORY;                                          \
2130
  }                                                                         \
2131
                                                                            \
2132
  nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
2133
  nsresult rv = it->Init();                                                 \
2134
  nsresult rv2 = const_cast<_elementName*>(this)->CopyInnerTo(it);          \
2135
  if (NS_FAILED(rv2)) {                                                     \
2136
    rv = rv2;                                                               \
2137
  }                                                                         \
2138
  if (NS_SUCCEEDED(rv)) {                                                   \
2139
    kungFuDeathGrip.swap(*aResult);                                         \
2140
  }                                                                         \
2141
                                                                            \
2142
  return rv;                                                                \
2143
}
2144
2145
#define NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName) \
2146
  NS_IMPL_ELEMENT_CLONE_WITH_INIT_HELPER(_elementName, ())
2147
#define NS_IMPL_ELEMENT_CLONE_WITH_INIT_AND_PARSER(_elementName) \
2148
  NS_IMPL_ELEMENT_CLONE_WITH_INIT_HELPER(_elementName, (, NOT_FROM_PARSER))
2149
2150
#endif // mozilla_dom_Element_h__