Highlight.h (6459B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 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_Highlight_h 8 #define mozilla_dom_Highlight_h 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/dom/BindingDeclarations.h" 12 #include "mozilla/dom/HighlightBinding.h" 13 #include "nsAtomHashKeys.h" 14 #include "nsCycleCollectionParticipant.h" 15 #include "nsTArray.h" 16 #include "nsTHashSet.h" 17 #include "nsWrapperCache.h" 18 19 class nsFrameSelection; 20 class nsPIDOMWindowInner; 21 namespace mozilla { 22 class ErrorResult; 23 } 24 25 namespace mozilla::dom { 26 class AbstractRange; 27 class Document; 28 class HighlightRegistry; 29 class Selection; 30 31 /** 32 * @brief Collection of all data of a highlight instance. 33 * 34 * This struct is intended to be allocated on the stack and passed on 35 * to the `nsFrameSelection` and layout code. 36 */ 37 struct HighlightSelectionData { 38 RefPtr<nsAtom> mHighlightName; 39 RefPtr<Highlight> mHighlight; 40 }; 41 42 /** 43 * @brief Representation of a custom `Highlight`. 44 * 45 * A `Highlight` is defined in JS as a collection of `AbstractRange`s. 46 * Furthermore, a custom highlight contains the highlight type and priority. 47 * 48 * A highlight is added to a document using the `HighlightRegistry` interface. 49 * A highlight can be added to a document using different names as well as to 50 * multiple `HighlightRegistries`. 51 * To propagate runtime changes of the highlight to its registries, an 52 * observer pattern is implemented. 53 * 54 * The spec defines this class as a `setlike`. To allow access and iteration 55 * of the setlike contents from C++, the insertion and deletion operations are 56 * overridden and the Ranges are also stored internally in an Array. 57 * 58 * @see https://drafts.csswg.org/css-highlight-api-1/#creation 59 */ 60 class Highlight final : public nsISupports, public nsWrapperCache { 61 public: 62 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 63 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Highlight) 64 65 protected: 66 MOZ_CAN_RUN_SCRIPT Highlight( 67 const Sequence<OwningNonNull<AbstractRange>>& aInitialRanges, 68 nsPIDOMWindowInner* aWindow, ErrorResult& aRv); 69 ~Highlight() = default; 70 71 public: 72 /** 73 * @brief Adds `this` to `aHighlightRegistry`. 74 * 75 * Highlights must know of all registry objects which contain them, so that 76 * the registries can be notified when a property of the Highlight changes. 77 * 78 * Since a Highlight can be part of a registry using different names, 79 * the name has to be provided as well. 80 */ 81 void AddToHighlightRegistry(HighlightRegistry& aHighlightRegistry, 82 nsAtom& aHighlightName); 83 84 /** 85 * @brief Removes `this` from `aHighlightRegistry`. 86 */ 87 void RemoveFromHighlightRegistry(HighlightRegistry& aHighlightRegistry, 88 nsAtom& aHighlightName); 89 90 /** 91 * @brief Creates a Highlight Selection using the given ranges. 92 */ 93 MOZ_CAN_RUN_SCRIPT already_AddRefed<Selection> CreateHighlightSelection( 94 nsAtom* aHighlightName, nsFrameSelection* aFrameSelection); 95 96 // WebIDL interface 97 nsPIDOMWindowInner* GetParentObject() const { return mWindow; } 98 99 JSObject* WrapObject(JSContext* aCx, 100 JS::Handle<JSObject*> aGivenProto) override; 101 102 static MOZ_CAN_RUN_SCRIPT_BOUNDARY already_AddRefed<Highlight> Constructor( 103 const GlobalObject& aGlobal, 104 const Sequence<OwningNonNull<AbstractRange>>& aInitialRanges, 105 ErrorResult& aRv); 106 107 /** 108 * @brief Priority of this highlight. 109 * 110 * Priority is used to stack overlapping highlights. 111 */ 112 int32_t Priority() const { return mPriority; } 113 114 /** 115 * @brief Set the priority of this Highlight. 116 * 117 * Priority is used to stack overlapping highlights. 118 */ 119 void SetPriority(int32_t aPriority); 120 121 /** 122 * @brief The HighlightType of this Highlight (Highlight, Spelling Error, 123 * Grammar Error) 124 */ 125 HighlightType Type() const { return mHighlightType; } 126 127 /** 128 * @brief Sets the HighlightType (Highlight, Spelling Error, Grammar Error) 129 */ 130 void SetType(HighlightType aHighlightType); 131 132 /** 133 * @brief This mirrors the `size` property in JS world (_not_ exposed via 134 * webIDL) 135 */ 136 uint32_t Size() const { return mRanges.Length(); } 137 138 /** 139 * @brief Adds a `Range` to this highlight. 140 * 141 * This adds `aRange` both to the setlike data storage and the internal one 142 * needed for iteration, if it is not yet present. 143 * 144 * Also notifies all `HighlightRegistry` instances. 145 */ 146 MOZ_CAN_RUN_SCRIPT Highlight* Add(AbstractRange& aRange, ErrorResult& aRv); 147 148 /** 149 * @brief Removes all ranges from this highlight. 150 * 151 * This removes all highlights from the setlike data structure as well as from 152 * the internal one. 153 * 154 * Also notifies all `HighlightRegistry` instances. 155 */ 156 MOZ_CAN_RUN_SCRIPT void Clear(ErrorResult& aRv); 157 158 /** 159 * @brief Removes `aRange` from this highlight. 160 * 161 * This removes `aRange` from the setlike data structure as well as from the 162 * internal one. 163 * 164 * Also notifies all `HighlightRegistry` instances. 165 * 166 * @return As per spec, returns true if the range was deleted. 167 */ 168 MOZ_CAN_RUN_SCRIPT bool Delete(AbstractRange& aRange, ErrorResult& aRv); 169 170 private: 171 void Repaint(); 172 173 RefPtr<nsPIDOMWindowInner> mWindow; 174 175 /** 176 * All Range objects contained in this highlight. 177 */ 178 nsTArray<RefPtr<AbstractRange>> mRanges; 179 180 /** 181 * Type of this highlight. 182 * @see HighlightType 183 */ 184 HighlightType mHighlightType{HighlightType::Highlight}; 185 186 /** 187 * Priority of this highlight. 188 * 189 * If highlights are overlapping, the priority can 190 * be used to prioritize. If the priorities of all 191 * Highlights involved are equal, the highlights are 192 * stacked in order of ther insertion into the 193 * `HighlightRegistry`. 194 */ 195 int32_t mPriority{0}; 196 197 /** 198 * All highlight registries that contain this Highlight. 199 * 200 * A highlight can be included in several registries 201 * using several names. 202 * 203 * Note: Storing `HighlightRegistry` as raw pointer is safe here 204 * because it unregisters itself from `this` when it is destroyed/CC'd 205 */ 206 nsTHashMap<nsPtrHashKey<HighlightRegistry>, nsTHashSet<RefPtr<nsAtom>>> 207 mHighlightRegistries; 208 }; 209 210 } // namespace mozilla::dom 211 212 #endif // mozilla_dom_Highlight_h