DocumentOrShadowRoot.h (10088B)
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_DocumentOrShadowRoot_h__ 8 #define mozilla_dom_DocumentOrShadowRoot_h__ 9 10 #include "mozilla/IdentifierMapEntry.h" 11 #include "mozilla/RelativeTo.h" 12 #include "mozilla/ReverseIterator.h" 13 #include "mozilla/dom/NameSpaceConstants.h" 14 #include "nsClassHashtable.h" 15 #include "nsContentListDeclarations.h" 16 #include "nsTArray.h" 17 #include "nsTHashSet.h" 18 19 class nsContentList; 20 class nsCycleCollectionTraversalCallback; 21 class nsINode; 22 class nsINodeList; 23 class nsWindowSizes; 24 25 namespace mozilla { 26 class ErrorResult; 27 class StyleSheet; 28 class ErrorResult; 29 30 namespace dom { 31 32 class Animation; 33 class Element; 34 class Document; 35 class DocumentOrShadowRoot; 36 class HTMLInputElement; 37 class StyleSheetList; 38 class ShadowRoot; 39 template <typename T> 40 class Sequence; 41 42 /** 43 * A class meant to be shared by ShadowRoot and Document, that holds a list of 44 * stylesheets. 45 * 46 * TODO(emilio, bug 1418159): In the future this should hold most of the 47 * relevant style state, this should allow us to fix bug 548397. 48 */ 49 class DocumentOrShadowRoot { 50 enum class Kind { 51 Document, 52 ShadowRoot, 53 }; 54 55 public: 56 // These should always be non-null, but can't use a reference because 57 // dereferencing `this` on initializer lists is UB, apparently, see 58 // bug 1596499. 59 explicit DocumentOrShadowRoot(Document*); 60 explicit DocumentOrShadowRoot(ShadowRoot*); 61 62 // Unusual argument naming is because of cycle collection macros. 63 static void Traverse(DocumentOrShadowRoot* tmp, 64 nsCycleCollectionTraversalCallback& cb); 65 static void Unlink(DocumentOrShadowRoot* tmp); 66 67 nsINode& AsNode() { return *mAsNode; } 68 69 const nsINode& AsNode() const { return *mAsNode; } 70 71 StyleSheet* SheetAt(size_t aIndex) const { 72 return mStyleSheets.SafeElementAt(aIndex); 73 } 74 75 size_t SheetCount() const { return mStyleSheets.Length(); } 76 77 const nsTArray<RefPtr<StyleSheet>>& AdoptedStyleSheets() const { 78 return mAdoptedStyleSheets; 79 } 80 81 size_t FindSheetInsertionPointInTree(const StyleSheet&) const; 82 83 /** 84 * Returns an index for the sheet in relative style order. 85 * If there are non-applicable sheets, then this index may 86 * not match 1:1 with the sheet's actual index in the style set. 87 * 88 * Handles sheets from both mStyleSheets and mAdoptedStyleSheets 89 */ 90 size_t StyleOrderIndexOfSheet(const StyleSheet& aSheet) const; 91 92 StyleSheetList* StyleSheets(); 93 94 void RemoveStyleSheet(StyleSheet&); 95 96 Element* GetElementById(const nsAString& aElementId) const; 97 Element* GetElementById(nsAtom* aElementId) const; 98 99 /** 100 * This method returns _all_ the elements in this scope which have id 101 * aElementId, if there are any. Otherwise it returns null. 102 * 103 * This is useful for stuff like QuerySelector optimization and such. 104 */ 105 Span<Element* const> GetAllElementsForId( 106 const IdentifierMapEntry::DependentAtomOrString& aElementId) const { 107 if (IdentifierMapEntry* entry = mIdentifierMap.GetEntry(aElementId)) { 108 return entry->GetIdElements(); 109 } 110 return {}; 111 } 112 113 already_AddRefed<nsContentList> GetElementsByTagName( 114 const nsAString& aTagName) { 115 return NS_GetContentList(&AsNode(), kNameSpaceID_Unknown, aTagName); 116 } 117 118 already_AddRefed<nsContentList> GetElementsByTagNameNS( 119 const nsAString& aNamespaceURI, const nsAString& aLocalName); 120 121 already_AddRefed<nsContentList> GetElementsByTagNameNS( 122 const nsAString& aNamespaceURI, const nsAString& aLocalName, 123 mozilla::ErrorResult&); 124 125 already_AddRefed<nsContentList> GetElementsByClassName( 126 const nsAString& aClasses); 127 128 ~DocumentOrShadowRoot(); 129 130 Element* GetPointerLockElement(); 131 Element* GetFullscreenElement() const; 132 133 Element* ElementFromPoint(float aX, float aY); 134 nsINode* NodeFromPoint(float aX, float aY); 135 136 void ElementsFromPoint(float aX, float aY, nsTArray<RefPtr<Element>>&); 137 void NodesFromPoint(float aX, float aY, nsTArray<RefPtr<nsINode>>&); 138 139 /** 140 * Helper for elementFromPoint implementation that allows 141 * ignoring the scroll frame and/or avoiding layout flushes. 142 * 143 * @see nsIDOMWindowUtils::elementFromPoint 144 */ 145 Element* ElementFromPointHelper(float aX, float aY, 146 bool aIgnoreRootScrollFrame, 147 bool aFlushLayout, ViewportType aViewportType, 148 bool aPerformRetargeting = true); 149 150 void NodesFromRect(float aX, float aY, float aTopSize, float aRightSize, 151 float aBottomSize, float aLeftSize, 152 bool aIgnoreRootScrollFrame, bool aFlushLayout, 153 bool aOnlyVisible, float aVisibleThreshold, 154 nsTArray<RefPtr<nsINode>>&); 155 156 /** 157 * This gets fired when the element that an id refers to changes. 158 * This fires at difficult times. It is generally not safe to do anything 159 * which could modify the DOM in any way. Use 160 * nsContentUtils::AddScriptRunner. 161 * @return true to keep the callback in the callback set, false 162 * to remove it. 163 */ 164 typedef bool (*IDTargetObserver)(Element* aOldElement, Element* aNewelement, 165 void* aData); 166 167 /** 168 * Add an IDTargetObserver for a specific ID. The IDTargetObserver 169 * will be fired whenever the content associated with the ID changes 170 * in the future. If aForImage is true, mozSetImageElement can override 171 * what content is associated with the ID. In that case the IDTargetObserver 172 * will be notified at those times when the result of LookupImageElement 173 * changes. 174 * At most one (aObserver, aData, aForImage) triple can be 175 * registered for each ID. 176 * @return the content currently associated with the ID. 177 */ 178 Element* AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver, 179 void* aData, bool aForImage); 180 181 /** 182 * Remove the (aObserver, aData, aForImage) triple for a specific ID, if 183 * registered. 184 */ 185 void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver, 186 void* aData, bool aForImage); 187 188 /** 189 * Lookup an image element using its associated ID, which is usually provided 190 * by |-moz-element()|. Similar to GetElementById, with the difference that 191 * elements set using mozSetImageElement have higher priority. 192 * @param aId the ID associated the element we want to lookup 193 * @return the element associated with |aId| 194 */ 195 Element* LookupImageElement(nsAtom* aId); 196 197 /** 198 * Check that aId is not empty and log a message to the console 199 * service if it is. 200 * @returns true if aId looks correct, false otherwise. 201 */ 202 inline bool CheckGetElementByIdArg(const nsAString& aId) { 203 if (aId.IsEmpty()) { 204 ReportEmptyGetElementByIdArg(); 205 return false; 206 } 207 return true; 208 } 209 210 void ReportEmptyGetElementByIdArg() const; 211 212 // Web Animations 213 MOZ_CAN_RUN_SCRIPT 214 void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations); 215 216 nsINode* Retarget(nsINode*) const; 217 218 void OnSetAdoptedStyleSheets(StyleSheet&, uint32_t aIndex, ErrorResult&); 219 void OnDeleteAdoptedStyleSheets(StyleSheet&, uint32_t aIndex, ErrorResult&); 220 221 // This is needed because ServoStyleSet / ServoAuthorData don't deal with 222 // duplicate stylesheets (and it's unclear we'd want to support that as it'd 223 // be a bunch of duplicate work), while adopted stylesheets do need to deal 224 // with them. 225 template <typename Callback> 226 void EnumerateUniqueAdoptedStyleSheetsBackToFront(Callback aCallback) { 227 StyleSheetSet set(mAdoptedStyleSheets.Length()); 228 for (StyleSheet* sheet : Reversed(mAdoptedStyleSheets)) { 229 if (MOZ_UNLIKELY(!set.EnsureInserted(sheet))) { 230 continue; 231 } 232 aCallback(*sheet); 233 } 234 } 235 236 protected: 237 // Cycle collection helper functions 238 void TraverseSheetRefInStylesIfApplicable( 239 StyleSheet&, nsCycleCollectionTraversalCallback&); 240 void TraverseStyleSheets(nsTArray<RefPtr<StyleSheet>>&, const char*, 241 nsCycleCollectionTraversalCallback&); 242 void UnlinkStyleSheets(nsTArray<RefPtr<StyleSheet>>&); 243 244 using StyleSheetSet = nsTHashSet<const StyleSheet*>; 245 void RemoveSheetFromStylesIfApplicable(StyleSheet&); 246 void ClearAdoptedStyleSheets(); 247 248 /** 249 * Clone's the argument's adopted style sheets into this. 250 * This should only be used when cloning a static document for printing. 251 */ 252 void CloneAdoptedSheetsFrom(const DocumentOrShadowRoot&); 253 254 void InsertSheetAt(size_t aIndex, StyleSheet& aSheet); 255 256 void AddSizeOfExcludingThis(nsWindowSizes&) const; 257 void AddSizeOfOwnedSheetArrayExcludingThis( 258 nsWindowSizes&, const nsTArray<RefPtr<StyleSheet>>&) const; 259 260 /** 261 * If focused element's subtree root is this document or shadow root, return 262 * focused element, otherwise, get the shadow host recursively until the 263 * shadow host's subtree root is this document or shadow root. 264 */ 265 Element* GetRetargetedFocusedElement(); 266 267 nsTArray<RefPtr<StyleSheet>> mStyleSheets; 268 RefPtr<StyleSheetList> mDOMStyleSheets; 269 270 /** 271 * Style sheets that are adopted by assinging to the `adoptedStyleSheets` 272 * WebIDL atribute. These can only be constructed stylesheets. 273 */ 274 nsTArray<RefPtr<StyleSheet>> mAdoptedStyleSheets; 275 276 /* 277 * mIdentifierMap works as follows for IDs: 278 * 1) Attribute changes affect the table immediately (removing and adding 279 * entries as needed). 280 * 2) Removals from the DOM affect the table immediately 281 * 3) Additions to the DOM always update existing entries for names, and add 282 * new ones for IDs. 283 */ 284 nsTHashtable<IdentifierMapEntry> mIdentifierMap; 285 286 // Always non-null, see comment in the constructor as to why a pointer instead 287 // of a reference. 288 nsINode* mAsNode; 289 const Kind mKind; 290 }; 291 292 } // namespace dom 293 294 } // namespace mozilla 295 296 #endif