nsHtml5TreeOpExecutor.h (9132B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef nsHtml5TreeOpExecutor_h 6 #define nsHtml5TreeOpExecutor_h 7 8 #include "nsAtom.h" 9 #include "nsTraceRefcnt.h" 10 #include "nsHtml5TreeOperation.h" 11 #include "nsHtml5SpeculativeLoad.h" 12 #include "nsTArray.h" 13 #include "nsContentSink.h" 14 #include "nsNodeInfoManager.h" 15 #include "nsHtml5DocumentMode.h" 16 #include "nsIScriptElement.h" 17 #include "nsIParser.h" 18 #include "nsAHtml5TreeOpSink.h" 19 #include "nsHtml5TreeOpStage.h" 20 #include "nsIURI.h" 21 #include "nsTHashSet.h" 22 #include "nsHashKeys.h" 23 #include "mozilla/LinkedList.h" 24 #include "nsHtml5DocumentBuilder.h" 25 #include "nsCharsetSource.h" 26 27 class nsHtml5Parser; 28 class nsHtml5StreamParser; 29 class nsIContent; 30 namespace mozilla { 31 namespace dom { 32 class Document; 33 } 34 } // namespace mozilla 35 36 class nsHtml5TreeOpExecutor final 37 : public nsHtml5DocumentBuilder, 38 public nsIContentSink, 39 public nsAHtml5TreeOpSink, 40 public mozilla::LinkedListElement<nsHtml5TreeOpExecutor> { 41 friend class nsHtml5FlushLoopGuard; 42 typedef mozilla::dom::ReferrerPolicy ReferrerPolicy; 43 using Encoding = mozilla::Encoding; 44 template <typename T> 45 using NotNull = mozilla::NotNull<T>; 46 47 public: 48 NS_DECL_ISUPPORTS_INHERITED 49 50 private: 51 #ifdef DEBUG 52 static uint32_t sAppendBatchMaxSize; 53 static uint32_t sAppendBatchSlotsExamined; 54 static uint32_t sAppendBatchExaminations; 55 static uint32_t sLongestTimeOffTheEventLoop; 56 static uint32_t sTimesFlushLoopInterrupted; 57 #endif 58 59 /** 60 * Whether EOF needs to be suppressed 61 */ 62 bool mSuppressEOF; 63 64 bool mReadingFromStage; 65 nsTArray<nsHtml5TreeOperation> mOpQueue; 66 nsHtml5StreamParser* mStreamParser; 67 68 /** 69 * URLs already preloaded/preloading. 70 */ 71 nsTHashSet<nsCString> mPreloadedURLs; 72 73 nsCOMPtr<nsIURI> mSpeculationBaseURI; 74 75 nsCOMPtr<nsIURI> mViewSourceBaseURI; 76 77 /** 78 * Whether the parser has started 79 */ 80 bool mStarted; 81 82 nsHtml5TreeOpStage mStage; 83 84 bool mRunFlushLoopOnStack; 85 86 bool mCallContinueInterruptedParsingIfEnabled; 87 88 /** 89 * Whether this executor has already complained about matters related 90 * to character encoding declarations. 91 */ 92 bool mAlreadyComplainedAboutCharset; 93 94 /** 95 * Whether this executor has already complained about the tree being too 96 * deep. 97 */ 98 bool mAlreadyComplainedAboutDeepTree; 99 100 public: 101 nsHtml5TreeOpExecutor(); 102 103 protected: 104 virtual ~nsHtml5TreeOpExecutor(); 105 106 public: 107 // nsIContentSink 108 109 /** 110 * Unimplemented. For interface compat only. 111 */ 112 NS_IMETHOD WillParse() override; 113 114 NS_IMETHOD WillBuildModel() override; 115 116 /** 117 * Emits EOF. 118 */ 119 NS_IMETHOD DidBuildModel(bool aTerminated) override; 120 121 /** 122 * Forwards to nsContentSink 123 */ 124 NS_IMETHOD WillInterrupt() override; 125 126 /** 127 * Unimplemented. For interface compat only. 128 */ 129 void WillResume() override; 130 131 virtual nsIContentSink* AsExecutor() override { return this; } 132 133 virtual void InitialTranslationCompleted() override; 134 135 /** 136 * Sets the parser. 137 */ 138 NS_IMETHOD SetParser(nsParserBase* aParser) override; 139 140 /** 141 * No-op for backwards compat. 142 */ 143 virtual void FlushPendingNotifications(mozilla::FlushType aType) override; 144 145 /** 146 * Don't call. For interface compat only. 147 */ 148 virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override { 149 MOZ_ASSERT_UNREACHABLE("No one should call this."); 150 } 151 152 /** 153 * Returns the document. 154 */ 155 virtual nsISupports* GetTarget() override; 156 157 virtual void ContinueInterruptedParsingAsync() override; 158 159 bool IsScriptExecuting() override { return IsScriptExecutingImpl(); } 160 161 void ContinueParsingDocumentAfterCurrentScript() override { 162 ContinueParsingDocumentAfterCurrentScriptImpl(); 163 } 164 165 // Not from interface 166 167 void SetStreamParser(nsHtml5StreamParser* aStreamParser) { 168 mStreamParser = aStreamParser; 169 } 170 171 void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, 172 int32_t aLine); 173 174 bool IsScriptEnabled(); 175 176 virtual nsresult MarkAsBroken(nsresult aReason) override; 177 178 void StartLayout(bool* aInterrupted); 179 180 void PauseDocUpdate(bool* aInterrupted); 181 182 void FlushSpeculativeLoads(); 183 184 void RunFlushLoop(); 185 186 nsresult FlushDocumentWrite(); 187 188 void CommitToInternalEncoding(); 189 190 [[nodiscard]] bool TakeOpsFromStage(); 191 192 void MaybeSuspend(); 193 194 void Start(); 195 196 void SetDocumentCharsetAndSource(NotNull<const Encoding*> aEncoding, 197 nsCharsetSource aCharsetSource); 198 199 void UpdateCharsetSource(nsCharsetSource aCharsetSource); 200 201 void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding, int32_t aSource, 202 uint32_t aLineNumber); 203 204 void MaybeComplainAboutCharset(const char* aMsgId, bool aError, 205 uint32_t aLineNumber); 206 207 void ComplainAboutBogusProtocolCharset(mozilla::dom::Document* aDoc, 208 bool aUnrecognized); 209 210 void MaybeComplainAboutDeepTree(uint32_t aLineNumber); 211 212 bool HasStarted() { return mStarted; } 213 214 bool IsFlushing() { return mFlushState >= eInFlush; } 215 216 #ifdef DEBUG 217 bool IsInFlushLoop() { return mRunFlushLoopOnStack; } 218 #endif 219 220 void RunScript(nsIContent* aScriptElement, bool aMayDocumentWriteOrBlock); 221 222 /** 223 * Flush the operations from the tree operations from the argument 224 * queue unconditionally. (This is for the main thread case.) 225 */ 226 [[nodiscard]] virtual bool MoveOpsFrom( 227 nsTArray<nsHtml5TreeOperation>& aOpQueue) override; 228 229 void ClearOpQueue(); 230 231 void RemoveFromStartOfOpQueue(size_t aNumberOfOpsToRemove); 232 233 inline size_t OpQueueLength() { return mOpQueue.Length(); } 234 235 nsHtml5TreeOpStage* GetStage() { return &mStage; } 236 237 void StartReadingFromStage() { mReadingFromStage = true; } 238 239 void StreamEnded(); 240 241 #ifdef DEBUG 242 void AssertStageEmpty() { mStage.AssertEmpty(); } 243 #endif 244 245 nsIURI* GetViewSourceBaseURI(); 246 247 void PreloadScript(const nsAString& aURL, const nsAString& aCharset, 248 const nsAString& aType, const nsAString& aCrossOrigin, 249 const nsAString& aMedia, const nsAString& aNonce, 250 const nsAString& aFetchPriority, 251 const nsAString& aIntegrity, 252 ReferrerPolicy aReferrerPolicy, bool aScriptFromHead, 253 bool aAsync, bool aDefer, bool aLinkPreload); 254 255 void PreloadStyle(const nsAString& aURL, const nsAString& aCharset, 256 const nsAString& aCrossOrigin, const nsAString& aMedia, 257 const nsAString& aReferrerPolicy, const nsAString& aNonce, 258 const nsAString& aIntegrity, bool aLinkPreload, 259 const nsAString& aFetchPriority); 260 261 void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin, 262 const nsAString& aMedia, const nsAString& aSrcset, 263 const nsAString& aSizes, 264 const nsAString& aImageReferrerPolicy, bool aLinkPreload, 265 const nsAString& aFetchPriority, const nsAString& aType); 266 267 void PreloadOpenPicture(); 268 269 void PreloadEndPicture(); 270 271 void PreloadPictureSource(const nsAString& aSrcset, const nsAString& aSizes, 272 const nsAString& aType, const nsAString& aMedia); 273 274 void PreloadFont(const nsAString& aURL, const nsAString& aCrossOrigin, 275 const nsAString& aMedia, const nsAString& aReferrerPolicy, 276 const nsAString& aFetchPriority); 277 278 void PreloadFetch(const nsAString& aURL, const nsAString& aCrossOrigin, 279 const nsAString& aMedia, const nsAString& aReferrerPolicy, 280 const nsAString& aFetchPriority); 281 282 void SetSpeculationBase(const nsAString& aURL); 283 284 void UpdateReferrerInfoFromMeta(const nsAString& aMetaReferrer); 285 286 void AddSpeculationCSP(const nsAString& aCSP); 287 288 void AddBase(const nsAString& aURL); 289 290 private: 291 nsHtml5Parser* GetParser(); 292 293 bool IsExternalViewSource(); 294 295 /** 296 * Get a nsIURI for an nsString if the URL hasn't been preloaded yet. 297 */ 298 already_AddRefed<nsIURI> ConvertIfNotPreloadedYet(const nsAString& aURL); 299 300 /** 301 * The above, plus also checks that the media attribute applies. 302 */ 303 already_AddRefed<nsIURI> ConvertIfNotPreloadedYetAndMediaApplies( 304 const nsAString& aURL, const nsAString& aMedia); 305 306 /** Returns whether the given media attribute applies to mDocument */ 307 bool MediaApplies(const nsAString& aMedia); 308 309 /** 310 * The base URI we would use for current preload operations 311 */ 312 nsIURI* BaseURIForPreload(); 313 314 /** 315 * Returns true if we haven't preloaded this URI yet, and adds it to the 316 * list of preloaded URIs 317 */ 318 bool ShouldPreloadURI(nsIURI* aURI); 319 320 /** 321 * Returns true if the image type is supported. 322 */ 323 bool ImageTypeSupports(const nsAString& aType); 324 325 ReferrerPolicy GetPreloadReferrerPolicy(const nsAString& aReferrerPolicy); 326 327 ReferrerPolicy GetPreloadReferrerPolicy(ReferrerPolicy aReferrerPolicy); 328 }; 329 330 #endif // nsHtml5TreeOpExecutor_h