tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ShadowRoot.h (11849B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_shadowroot_h__
      8 #define mozilla_dom_shadowroot_h__
      9 
     10 #include "mozilla/BindgenUniquePtr.h"
     11 #include "mozilla/DOMEventTargetHelper.h"
     12 #include "mozilla/ServoBindingTypes.h"
     13 #include "mozilla/dom/DocumentBinding.h"
     14 #include "mozilla/dom/DocumentFragment.h"
     15 #include "mozilla/dom/DocumentOrShadowRoot.h"
     16 #include "mozilla/dom/NameSpaceConstants.h"
     17 #include "mozilla/dom/ShadowRootBinding.h"
     18 #include "nsCOMPtr.h"
     19 #include "nsCycleCollectionParticipant.h"
     20 #include "nsStubMutationObserver.h"
     21 #include "nsTHashtable.h"
     22 
     23 class nsAtom;
     24 class nsIContent;
     25 class nsIPrincipal;
     26 
     27 namespace mozilla {
     28 
     29 struct StyleAuthorStyles;
     30 struct StyleRuleChange;
     31 
     32 class EventChainPreVisitor;
     33 class ServoStyleRuleMap;
     34 
     35 enum class StyleRuleChangeKind : uint32_t;
     36 enum class BuiltInStyleSheet : uint8_t;
     37 
     38 namespace css {
     39 class Rule;
     40 }
     41 
     42 namespace dom {
     43 
     44 class CSSImportRule;
     45 class Element;
     46 class HTMLInputElement;
     47 class OwningTrustedHTMLOrNullIsEmptyString;
     48 class TrustedHTMLOrString;
     49 class TrustedHTMLOrNullIsEmptyString;
     50 
     51 class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
     52  friend class DocumentOrShadowRoot;
     53 
     54  using Declarative = Element::ShadowRootDeclarative;
     55  using IsClonable = Element::ShadowRootClonable;
     56  using IsSerializable = Element::ShadowRootSerializable;
     57 
     58 public:
     59  NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
     60 
     61  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment)
     62  NS_DECL_ISUPPORTS_INHERITED
     63 
     64  ShadowRoot(Element* aElement, ShadowRootMode aMode,
     65             Element::DelegatesFocus aDelegatesFocus,
     66             SlotAssignmentMode aSlotAssignment, IsClonable aClonable,
     67             IsSerializable aIsSerializable, Declarative aDeclarative,
     68             already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
     69 
     70  void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final;
     71 
     72  // Try to reassign an element or text to a slot.
     73  void MaybeReassignContent(nsIContent& aElementOrText);
     74  // Called when an element is inserted as a direct child of our host. Tries to
     75  // slot the child in one of our slots.
     76  void MaybeSlotHostChild(nsIContent&);
     77  // Called when a direct child of our host is removed. Tries to un-slot the
     78  // child from the currently-assigned slot, if any.
     79  void MaybeUnslotHostChild(nsIContent&);
     80 
     81  // Shadow DOM v1
     82  Element* Host() const {
     83    MOZ_ASSERT(GetHost(),
     84               "ShadowRoot always has a host, how did we create "
     85               "this ShadowRoot?");
     86    return GetHost();
     87  }
     88 
     89  ShadowRootMode Mode() const { return mMode; }
     90  bool DelegatesFocus() const {
     91    return mDelegatesFocus == Element::DelegatesFocus::Yes;
     92  }
     93  SlotAssignmentMode SlotAssignment() const { return mSlotAssignment; }
     94  bool Clonable() const { return mIsClonable == IsClonable::Yes; }
     95  bool IsClosed() const { return mMode == ShadowRootMode::Closed; }
     96  bool Serializable() const { return mIsSerializable == IsSerializable::Yes; }
     97 
     98  void RemoveSheetFromStyles(StyleSheet&);
     99  void RuleAdded(StyleSheet&, css::Rule&);
    100  void RuleRemoved(StyleSheet&, css::Rule&);
    101  void RuleChanged(StyleSheet&, css::Rule*, const StyleRuleChange&);
    102  void ImportRuleLoaded(StyleSheet&);
    103  void SheetCloned(StyleSheet&);
    104  void StyleSheetApplicableStateChanged(StyleSheet&);
    105 
    106  // Adds a built-in author style-sheet to the shadow tree.
    107  void AppendBuiltInStyleSheet(BuiltInStyleSheet);
    108 
    109  /**
    110   * Clones internal state, for example stylesheets, of aOther to 'this'.
    111   */
    112  void CloneInternalDataFrom(ShadowRoot* aOther);
    113  void InsertSheetAt(size_t aIndex, StyleSheet&);
    114 
    115  // Calls UnbindFromTree for each of our kids, and also flags us as no longer
    116  // being connected.
    117  void Unbind();
    118 
    119  // Only intended for UA widgets / special shadow roots, or for handling
    120  // failure cases when adopting (see BlastSubtreeToPieces).
    121  //
    122  // Forgets our shadow host and unbinds all our kids.
    123  void Unattach();
    124 
    125  // Calls BindToTree on each of our kids, and also maybe flags us as being
    126  // connected.
    127  nsresult Bind();
    128 
    129  /**
    130   * Explicitly invalidates the style and layout of the flattened-tree subtree
    131   * rooted at the element.
    132   *
    133   * You need to use this whenever the flat tree is going to be shuffled in a
    134   * way that layout doesn't understand via the usual ContentInserted /
    135   * ContentAppended / ContentRemoved notifications. For example, if removing an
    136   * element will cause a change in the flat tree such that other element will
    137   * start showing up (like fallback content), this method needs to be called on
    138   * an ancestor of that element.
    139   *
    140   * It is important that this runs _before_ actually shuffling the flat tree
    141   * around, so that layout knows the actual tree that it needs to invalidate.
    142   */
    143  void InvalidateStyleAndLayoutOnSubtree(Element*);
    144 
    145 private:
    146  void InsertSheetIntoAuthorData(size_t aIndex, StyleSheet&,
    147                                 const nsTArray<RefPtr<StyleSheet>>&);
    148 
    149  void AppendStyleSheet(StyleSheet& aSheet) {
    150    InsertSheetAt(SheetCount(), aSheet);
    151  }
    152 
    153  /**
    154   * Represents the insertion point in a slot for a given node.
    155   */
    156  struct SlotInsertionPoint {
    157    HTMLSlotElement* mSlot = nullptr;
    158    Maybe<uint32_t> mIndex;
    159 
    160    SlotInsertionPoint() = default;
    161    SlotInsertionPoint(HTMLSlotElement* aSlot, const Maybe<uint32_t>& aIndex)
    162        : mSlot(aSlot), mIndex(aIndex) {}
    163  };
    164 
    165  /**
    166   * Return the assignment corresponding to the content node at this particular
    167   * point in time.
    168   *
    169   * It's the caller's responsibility to actually call InsertAssignedNode /
    170   * AppendAssignedNode in the slot as needed.
    171   */
    172  SlotInsertionPoint SlotInsertionPointFor(nsIContent&);
    173 
    174  /**
    175   * Returns the effective slot name for a given slottable. In most cases, this
    176   * is just the value of the slot attribute, if any, or the empty string, but
    177   * this also deals with the <details> shadow tree specially.
    178   */
    179  void GetSlotNameFor(const nsIContent&, nsAString&) const;
    180 
    181  /**
    182   * Re-assign the current main summary if it has changed.
    183   *
    184   * Must be called only if mIsDetailsShadowTree is true.
    185   */
    186  enum class SummaryChangeReason { Deletion, Insertion };
    187  void MaybeReassignMainSummary(SummaryChangeReason);
    188 
    189 public:
    190  void AddSlot(HTMLSlotElement* aSlot);
    191  void RemoveSlot(HTMLSlotElement* aSlot);
    192  bool HasSlots() const { return !mSlotMap.IsEmpty(); };
    193  HTMLSlotElement* GetDefaultSlot() const {
    194    SlotArray* list = mSlotMap.Get(u""_ns);
    195    return list ? (*list).AsSpan()[0] : nullptr;
    196  }
    197 
    198  void PartAdded(const Element&);
    199  void PartRemoved(const Element&);
    200 
    201  IMPL_EVENT_HANDLER(slotchange);
    202 
    203  const nsTArray<const Element*>& Parts() const { return mParts; }
    204 
    205  const StyleAuthorStyles* GetServoStyles() const { return mServoStyles.get(); }
    206 
    207  StyleAuthorStyles* GetServoStyles() { return mServoStyles.get(); }
    208 
    209  mozilla::ServoStyleRuleMap& ServoStyleRuleMap();
    210 
    211  JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) final;
    212 
    213  void NodeInfoChanged(Document* aOldDoc) override;
    214 
    215  void AddToIdTable(Element* aElement, nsAtom* aId);
    216  void RemoveFromIdTable(Element* aElement, nsAtom* aId);
    217 
    218  // WebIDL methods.
    219  using mozilla::dom::DocumentOrShadowRoot::GetElementById;
    220 
    221  Element* GetActiveElement();
    222 
    223  /**
    224   * These methods allow UA Widget to insert DOM elements into the Shadow ROM
    225   * without putting their DOM reflectors to content scope first.
    226   * The inserted DOM will have their reflectors in the UA Widget scope.
    227   */
    228  nsINode* ImportNodeAndAppendChildAt(nsINode& aParentNode, nsINode& aNode,
    229                                      bool aDeep, mozilla::ErrorResult& rv);
    230 
    231  nsINode* CreateElementAndAppendChildAt(nsINode& aParentNode,
    232                                         const nsAString& aTagName,
    233                                         mozilla::ErrorResult& rv);
    234 
    235  bool IsUAWidget() const { return HasBeenInUAWidget(); }
    236 
    237  void SetIsUAWidget() {
    238    MOZ_ASSERT(!HasChildren());
    239    SetIsNativeAnonymousRoot();
    240    SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
    241  }
    242 
    243  bool IsAvailableToElementInternals() const {
    244    return mIsAvailableToElementInternals;
    245  }
    246 
    247  void SetAvailableToElementInternals() {
    248    mIsAvailableToElementInternals = true;
    249  }
    250 
    251  void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
    252 
    253  bool IsDeclarative() const { return mIsDeclarative == Declarative::Yes; }
    254  void SetIsDeclarative(Declarative aIsDeclarative) {
    255    mIsDeclarative = aIsDeclarative;
    256  }
    257  void SetIsDeclarative(bool aIsDeclarative) {
    258    mIsDeclarative = aIsDeclarative ? Declarative::Yes : Declarative::No;
    259  }
    260 
    261  void SetHTML(const nsAString& aInnerHTML, const SetHTMLOptions& aOptions,
    262               ErrorResult& aError);
    263 
    264  MOZ_CAN_RUN_SCRIPT
    265  void SetHTMLUnsafe(const TrustedHTMLOrString& aHTML,
    266                     const SetHTMLUnsafeOptions& aOptions,
    267                     nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
    268 
    269  // @param aInnerHTML will always be of type `NullIsEmptyString`.
    270  void GetInnerHTML(OwningTrustedHTMLOrNullIsEmptyString& aInnerHTML);
    271 
    272  MOZ_CAN_RUN_SCRIPT void SetInnerHTML(
    273      const TrustedHTMLOrNullIsEmptyString& aInnerHTML,
    274      nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
    275 
    276  void GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult);
    277 
    278  void GetReferenceTarget(nsAString& aResult) const {
    279    mReferenceTarget->ToString(aResult);
    280  }
    281  nsAtom* ReferenceTarget() const { return mReferenceTarget; }
    282  void SetReferenceTarget(const nsAString& aValue) {
    283    SetReferenceTarget(NS_Atomize(aValue));
    284  }
    285  void SetReferenceTarget(RefPtr<nsAtom> aTarget);
    286  Element* GetReferenceTargetElement() const {
    287    return mReferenceTarget->IsEmpty() ? nullptr
    288                                       : GetElementById(mReferenceTarget);
    289  }
    290 
    291 protected:
    292  // FIXME(emilio): This will need to become more fine-grained.
    293  void ApplicableRulesChanged();
    294 
    295  virtual ~ShadowRoot();
    296 
    297  // Make sure that the first field is pointer-aligned so it doesn't get packed
    298  // in the base class' padding, since otherwise rust-bindgen can't generate
    299  // correct bindings for it, see
    300  // https://github.com/rust-lang/rust-bindgen/issues/380
    301 
    302  // The computed data from the style sheets.
    303  BindgenUniquePtr<StyleAuthorStyles> mServoStyles;
    304  UniquePtr<mozilla::ServoStyleRuleMap> mStyleRuleMap;
    305 
    306  using SlotArray = TreeOrderedArray<HTMLSlotElement*>;
    307  // Map from name of slot to an array of all slots in the shadow DOM with with
    308  // the given name. The slots are stored as a weak pointer because the elements
    309  // are in the shadow tree and should be kept alive by its parent.
    310  nsClassHashtable<nsStringHashKey, SlotArray> mSlotMap;
    311 
    312  // Unordered array of all elements that have a part attribute in this shadow
    313  // tree.
    314  nsTArray<const Element*> mParts;
    315 
    316  const ShadowRootMode mMode;
    317 
    318  Element::DelegatesFocus mDelegatesFocus;
    319 
    320  const SlotAssignmentMode mSlotAssignment;
    321 
    322  // Whether this is the <details> internal shadow tree.
    323  bool mIsDetailsShadowTree : 1;
    324 
    325  // https://dom.spec.whatwg.org/#shadowroot-available-to-element-internals
    326  bool mIsAvailableToElementInternals : 1;
    327 
    328  // https://dom.spec.whatwg.org/#shadowroot-declarative
    329  Declarative mIsDeclarative;
    330 
    331  // https://dom.spec.whatwg.org/#shadowroot-clonable
    332  const IsClonable mIsClonable;
    333 
    334  // https://dom.spec.whatwg.org/#shadowroot-serializable
    335  const IsSerializable mIsSerializable;
    336 
    337  RefPtr<nsAtom> mReferenceTarget;
    338 
    339  nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
    340 };
    341 
    342 }  // namespace dom
    343 }  // namespace mozilla
    344 
    345 #endif  // mozilla_dom_shadowroot_h__