Loader.h (26265B)
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 /* loading of CSS style sheets using the network APIs */ 8 9 #ifndef mozilla_css_Loader_h 10 #define mozilla_css_Loader_h 11 12 #include <tuple> 13 #include <utility> 14 15 #include "mozilla/Attributes.h" 16 #include "mozilla/CORSMode.h" 17 #include "mozilla/MemoryReporting.h" 18 #include "mozilla/SharedSubResourceCache.h" 19 #include "mozilla/css/StylePreloadKind.h" 20 #include "mozilla/dom/LinkStyle.h" 21 #include "nsCompatibility.h" 22 #include "nsCycleCollectionParticipant.h" 23 #include "nsRefPtrHashtable.h" 24 #include "nsStringFwd.h" 25 #include "nsTArray.h" 26 #include "nsTObserverArray.h" 27 #include "nsURIHashKey.h" 28 29 class nsICSSLoaderObserver; 30 class nsIConsoleReportCollector; 31 class nsIContent; 32 class nsIPrincipal; 33 34 namespace mozilla { 35 36 class PreloadHashKey; 37 class SharedStyleSheetCache; 38 class SheetLoadDataHashKey; 39 class StyleSheet; 40 41 namespace dom { 42 class DocGroup; 43 class Element; 44 enum class FetchPriority : uint8_t; 45 } // namespace dom 46 47 // The load data for a <link> or @import style-sheet. 48 // 49 // This must contain all the state that affects CSS parsing. 50 class SheetLoadDataHashKey : public PLDHashEntryHdr { 51 public: 52 using KeyType = const SheetLoadDataHashKey&; 53 using KeyTypePointer = const SheetLoadDataHashKey*; 54 55 explicit SheetLoadDataHashKey(const SheetLoadDataHashKey* aKey) 56 : mURI(aKey->mURI), 57 mLoaderPrincipal(aKey->mLoaderPrincipal), 58 mPartitionPrincipal(aKey->mPartitionPrincipal), 59 mEncodingGuess(aKey->mEncodingGuess), 60 mCORSMode(aKey->mCORSMode), 61 mParsingMode(aKey->mParsingMode), 62 mCompatMode(aKey->mCompatMode), 63 mSRIMetadata(aKey->mSRIMetadata), 64 mIsLinkRelPreloadOrEarlyHint(aKey->mIsLinkRelPreloadOrEarlyHint) { 65 MOZ_COUNT_CTOR(SheetLoadDataHashKey); 66 } 67 68 SheetLoadDataHashKey(nsIURI* aURI, nsIPrincipal* aLoaderPrincipal, 69 nsIPrincipal* aPartitionPrincipal, 70 NotNull<const Encoding*> aEncodingGuess, 71 CORSMode aCORSMode, css::SheetParsingMode aParsingMode, 72 nsCompatibility aCompatMode, 73 const dom::SRIMetadata& aSRIMetadata, 74 css::StylePreloadKind aPreloadKind) 75 : mURI(aURI), 76 mLoaderPrincipal(aLoaderPrincipal), 77 mPartitionPrincipal(aPartitionPrincipal), 78 mEncodingGuess(aEncodingGuess), 79 mCORSMode(aCORSMode), 80 mParsingMode(aParsingMode), 81 mCompatMode(aCompatMode), 82 mSRIMetadata(aSRIMetadata), 83 mIsLinkRelPreloadOrEarlyHint( 84 css::IsLinkRelPreloadOrEarlyHint(aPreloadKind)) { 85 MOZ_ASSERT(aURI); 86 MOZ_ASSERT(aLoaderPrincipal); 87 MOZ_COUNT_CTOR(SheetLoadDataHashKey); 88 } 89 90 SheetLoadDataHashKey(SheetLoadDataHashKey&& toMove) 91 : mURI(std::move(toMove.mURI)), 92 mLoaderPrincipal(std::move(toMove.mLoaderPrincipal)), 93 mPartitionPrincipal(std::move(toMove.mPartitionPrincipal)), 94 mEncodingGuess(std::move(toMove.mEncodingGuess)), 95 mCORSMode(std::move(toMove.mCORSMode)), 96 mParsingMode(std::move(toMove.mParsingMode)), 97 mCompatMode(std::move(toMove.mCompatMode)), 98 mSRIMetadata(std::move(toMove.mSRIMetadata)), 99 mIsLinkRelPreloadOrEarlyHint( 100 std::move(toMove.mIsLinkRelPreloadOrEarlyHint)) { 101 MOZ_COUNT_CTOR(SheetLoadDataHashKey); 102 } 103 104 explicit SheetLoadDataHashKey(const css::SheetLoadData&); 105 106 MOZ_COUNTED_DTOR(SheetLoadDataHashKey) 107 108 const SheetLoadDataHashKey& GetKey() const { return *this; } 109 const SheetLoadDataHashKey* GetKeyPointer() const { return this; } 110 111 bool KeyEquals(const SheetLoadDataHashKey* aKey) const { 112 return KeyEquals(*aKey); 113 } 114 115 bool KeyEquals(const SheetLoadDataHashKey&) const; 116 117 static const SheetLoadDataHashKey* KeyToPointer( 118 const SheetLoadDataHashKey& aKey) { 119 return &aKey; 120 } 121 static PLDHashNumber HashKey(const SheetLoadDataHashKey* aKey) { 122 return nsURIHashKey::HashKey(aKey->mURI); 123 } 124 125 nsIURI* URI() const { return mURI; } 126 127 nsIPrincipal* LoaderPrincipal() const { return mLoaderPrincipal; } 128 nsIPrincipal* PartitionPrincipal() const { return mPartitionPrincipal; } 129 130 css::SheetParsingMode ParsingMode() const { return mParsingMode; } 131 132 enum { ALLOW_MEMMOVE = true }; 133 134 protected: 135 const nsCOMPtr<nsIURI> mURI; 136 const nsCOMPtr<nsIPrincipal> mLoaderPrincipal; 137 const nsCOMPtr<nsIPrincipal> mPartitionPrincipal; 138 // The encoding guess is the encoding the sheet would get if the request 139 // didn't have any encoding information like @charset or a Content-Encoding 140 // header. 141 const NotNull<const Encoding*> mEncodingGuess; 142 const CORSMode mCORSMode; 143 const css::SheetParsingMode mParsingMode; 144 const nsCompatibility mCompatMode; 145 dom::SRIMetadata mSRIMetadata; 146 const bool mIsLinkRelPreloadOrEarlyHint; 147 }; 148 149 namespace css { 150 151 class SheetLoadData; 152 class ImportRule; 153 154 /********************* 155 * Style sheet reuse * 156 *********************/ 157 158 class MOZ_RAII LoaderReusableStyleSheets { 159 public: 160 LoaderReusableStyleSheets() = default; 161 162 /** 163 * Look for a reusable sheet (see AddReusableSheet) matching the 164 * given URL. If found, set aResult, remove the reused sheet from 165 * the internal list, and return true. If not found, return false; 166 * in this case, aResult is not modified. 167 * 168 * @param aURL the url to match 169 * @param aResult [out] the style sheet which can be reused 170 */ 171 bool FindReusableStyleSheet(nsIURI* aURL, RefPtr<StyleSheet>& aResult); 172 173 /** 174 * Indicate that a certain style sheet is available for reuse if its 175 * URI matches the URI of an @import. Sheets should be added in the 176 * opposite order in which they are intended to be reused. 177 * 178 * @param aSheet the sheet which can be reused 179 */ 180 void AddReusableSheet(StyleSheet* aSheet) { 181 mReusableSheets.AppendElement(aSheet); 182 } 183 184 private: 185 LoaderReusableStyleSheets(const LoaderReusableStyleSheets&) = delete; 186 LoaderReusableStyleSheets& operator=(const LoaderReusableStyleSheets&) = 187 delete; 188 189 // The sheets that can be reused. 190 nsTArray<RefPtr<StyleSheet>> mReusableSheets; 191 }; 192 193 class Loader final { 194 using ReferrerPolicy = dom::ReferrerPolicy; 195 196 public: 197 using Completed = dom::LinkStyle::Completed; 198 using HasAlternateRel = dom::LinkStyle::HasAlternateRel; 199 using IsAlternate = dom::LinkStyle::IsAlternate; 200 using IsInline = dom::LinkStyle::IsInline; 201 using IsExplicitlyEnabled = dom::LinkStyle::IsExplicitlyEnabled; 202 using MediaMatched = dom::LinkStyle::MediaMatched; 203 using LoadSheetResult = dom::LinkStyle::Update; 204 using SheetInfo = dom::LinkStyle::SheetInfo; 205 206 Loader(); 207 // aDocGroup is used for dispatching SheetLoadData in PostLoadEvent(). It 208 // can be null if you want to use this constructor, and there's no 209 // document when the Loader is constructed. 210 explicit Loader(dom::DocGroup*); 211 explicit Loader(dom::Document*); 212 213 private: 214 // Private destructor, to discourage deletion outside of Release(): 215 ~Loader(); 216 217 public: 218 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Loader) 219 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(Loader) 220 221 void DropDocumentReference(); // notification that doc is going away 222 223 void DeregisterFromSheetCache(); 224 void RegisterInSheetCache(); 225 226 void SetCompatibilityMode(nsCompatibility aCompatMode) { 227 mDocumentCompatMode = aCompatMode; 228 } 229 230 using StylePreloadKind = css::StylePreloadKind; 231 232 bool HasLoaded(const SheetLoadDataHashKey& aKey) const { 233 return mLoadsPerformed.Contains(aKey); 234 } 235 236 void WillStartPendingLoad() { 237 MOZ_DIAGNOSTIC_ASSERT(mPendingLoadCount, "Where did this load come from?"); 238 mPendingLoadCount--; 239 } 240 241 nsCompatibility CompatMode(StylePreloadKind aPreloadKind) const { 242 if (css::ShouldAssumeStandardsMode(aPreloadKind)) { 243 return eCompatibility_FullStandards; 244 } 245 return mDocumentCompatMode; 246 } 247 248 // TODO(emilio): Is the complexity of this method and carrying the titles 249 // around worth it? The alternate sheets will load anyhow eventually... 250 void DocumentStyleSheetSetChanged(); 251 252 // XXXbz sort out what the deal is with events! When should they fire? 253 254 /** 255 * Load an inline style sheet. If a successful result is returned and 256 * result.WillNotify() is true, then aObserver is guaranteed to be notified 257 * asynchronously once the sheet is marked complete. If an error is 258 * returned, or if result.WillNotify() is false, aObserver will not be 259 * notified. In addition to parsing the sheet, this method will insert it 260 * into the stylesheet list of this CSSLoader's document. 261 * @param aObserver the observer to notify when the load completes. 262 * May be null. 263 * @param aBuffer the stylesheet data 264 */ 265 Result<LoadSheetResult, nsresult> LoadInlineStyle( 266 const SheetInfo&, const nsAString& aBuffer, 267 nsICSSLoaderObserver* aObserver); 268 269 /** 270 * Load a linked (document) stylesheet. If a successful result is returned, 271 * aObserver is guaranteed to be notified asynchronously once the sheet is 272 * loaded and marked complete, i.e., result.WillNotify() will always return 273 * true. If an error is returned, aObserver will not be notified. In 274 * addition to loading the sheet, this method will insert it into the 275 * stylesheet list of this CSSLoader's document. 276 * @param aObserver the observer to notify when the load completes. 277 * May be null. 278 */ 279 Result<LoadSheetResult, nsresult> LoadStyleLink( 280 const SheetInfo&, nsICSSLoaderObserver* aObserver); 281 282 /** 283 * Load a child (@import-ed) style sheet. In addition to loading the sheet, 284 * this method will insert it into the child sheet list of aParentSheet. If 285 * there is no sheet currently being parsed and the child sheet is not 286 * complete when this method returns, then when the child sheet becomes 287 * complete aParentSheet will be QIed to nsICSSLoaderObserver and 288 * asynchronously notified, just like for LoadStyleLink. Note that if the 289 * child sheet is already complete when this method returns, no 290 * nsICSSLoaderObserver notification will be sent. 291 * 292 * @param aParentSheet the parent of this child sheet 293 * @param aParentData the SheetLoadData corresponding to the load of the 294 * parent sheet. May be null for @import rules inserted via 295 * CSSOM. 296 * @param aURL the URL of the child sheet 297 * @param aMedia the already-parsed media list for the child sheet 298 * @param aSavedSheets any saved style sheets which could be reused 299 * for this load 300 */ 301 nsresult LoadChildSheet(StyleSheet& aParentSheet, SheetLoadData* aParentData, 302 nsIURI* aURL, dom::MediaList* aMedia, 303 LoaderReusableStyleSheets* aSavedSheets); 304 305 /** 306 * Called when we hit the internal memory cache with a complete stylesheet. 307 */ 308 void DidHitCompleteSheetCache(const SheetLoadDataHashKey&, 309 const StyleUseCounters* aCounters); 310 311 enum class UseSystemPrincipal { No, Yes }; 312 313 /** 314 * Synchronously load and return the stylesheet at aURL. Any child sheets 315 * will also be loaded synchronously. Note that synchronous loads over some 316 * protocols may involve spinning up a new event loop, so use of this method 317 * does NOT guarantee not receiving any events before the sheet loads. This 318 * method can be used to load sheets not associated with a document. 319 * 320 * @param aURL the URL of the sheet to load 321 * @param aParsingMode the mode in which to parse the sheet 322 * (see comments at enum SheetParsingMode, above). 323 * @param aUseSystemPrincipal if true, give the resulting sheet the system 324 * principal no matter where it's being loaded from. 325 * 326 * NOTE: At the moment, this method assumes the sheet will be UTF-8, but 327 * ideally it would allow arbitrary encodings. Callers should NOT depend on 328 * non-UTF8 sheets being treated as UTF-8 by this method. 329 * 330 * NOTE: A successful return from this method doesn't indicate anything about 331 * whether the data could be parsed as CSS and doesn't indicate anything 332 * about the status of child sheets of the returned sheet. 333 */ 334 Result<RefPtr<StyleSheet>, nsresult> LoadSheetSync( 335 nsIURI*, SheetParsingMode = eAuthorSheetFeatures, 336 UseSystemPrincipal = UseSystemPrincipal::No); 337 338 /** 339 * Asynchronously load the stylesheet at aURL. If a successful result is 340 * returned, aObserver is guaranteed to be notified asynchronously once the 341 * sheet is loaded and marked complete. This method can be used to load 342 * sheets not associated with a document. 343 * 344 * @param aURL the URL of the sheet to load 345 * @param aParsingMode the mode in which to parse the sheet 346 * (see comments at enum SheetParsingMode, above). 347 * @param aUseSystemPrincipal if true, give the resulting sheet the system 348 * principal no matter where it's being loaded from. 349 * @param aReferrerInfo referrer information of the sheet. 350 * @param aObserver the observer to notify when the load completes. 351 * Must not be null. 352 * @param aEarlyHintPreloaderId to connect back to the early hint preload 353 * channel. Null means no connect back should happen 354 * @return the sheet to load. Note that the sheet may well not be loaded by 355 * the time this method returns. 356 * 357 * NOTE: At the moment, this method assumes the sheet will be UTF-8, but 358 * ideally it would allow arbitrary encodings. Callers should NOT depend on 359 * non-UTF8 sheets being treated as UTF-8 by this method. 360 */ 361 Result<RefPtr<StyleSheet>, nsresult> LoadSheet( 362 nsIURI* aURI, StylePreloadKind, const Encoding* aPreloadEncoding, 363 nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver, 364 uint64_t aEarlyHintPreloaderId, CORSMode aCORSMode, 365 const nsAString& aNonce, const nsAString& aIntegrity, 366 dom::FetchPriority aFetchPriority); 367 368 /** 369 * As above, but without caring for a couple things. 370 * Only to be called by `PreloadedStyleSheet::PreloadAsync`. 371 */ 372 Result<RefPtr<StyleSheet>, nsresult> LoadSheet(nsIURI*, SheetParsingMode, 373 UseSystemPrincipal, 374 nsICSSLoaderObserver*); 375 376 /** 377 * Stop loading all sheets. All nsICSSLoaderObservers involved will be 378 * notified with NS_BINDING_ABORTED as the status, possibly synchronously. 379 */ 380 void Stop(); 381 382 /** 383 * nsresult Loader::StopLoadingSheet(nsIURI* aURL), which notifies the 384 * nsICSSLoaderObserver with NS_BINDING_ABORTED, was removed in Bug 556446. 385 * It can be found in revision 2c44a32052ad. 386 */ 387 388 /** 389 * Whether the loader is enabled or not. 390 * When disabled, processing of new styles is disabled and an attempt 391 * to do so will fail with a return code of 392 * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable 393 * currently loading styles or already processed styles. 394 */ 395 bool GetEnabled() { return mEnabled; } 396 void SetEnabled(bool aEnabled) { mEnabled = aEnabled; } 397 398 uint32_t ParsedSheetCount() const { return mParsedSheetCount; } 399 400 /** 401 * Get the document we live for. May return null. 402 */ 403 dom::Document* GetDocument() const { return mDocument; } 404 405 bool IsDocumentAssociated() const { return mIsDocumentAssociated; } 406 407 /** 408 * Return true if this loader has pending loads (ones that would send 409 * notifications to an nsICSSLoaderObserver attached to this loader). 410 * If called from inside nsICSSLoaderObserver::StyleSheetLoaded, this will 411 * return false if and only if that is the last StyleSheetLoaded 412 * notification the CSSLoader knows it's going to send. In other words, if 413 * two sheets load at once (via load coalescing, e.g.), HasPendingLoads() 414 * will return true during notification for the first one, and false 415 * during notification for the second one. 416 */ 417 bool HasPendingLoads(); 418 419 /** 420 * Add an observer to this loader. The observer will be notified 421 * for all loads that would have notified their own observers (even 422 * if those loads don't have observers attached to them). 423 * Load-specific observers will be notified before generic 424 * observers. The loader holds a reference to the observer. 425 * 426 * aObserver must not be null. 427 */ 428 void AddObserver(nsICSSLoaderObserver* aObserver); 429 430 /** 431 * Remove an observer added via AddObserver. 432 */ 433 void RemoveObserver(nsICSSLoaderObserver* aObserver); 434 435 // These interfaces are public only for the benefit of static functions 436 // within nsCSSLoader.cpp. 437 438 // IsAlternateSheet can change our currently selected style set if none is 439 // selected and aHasAlternateRel is false. 440 IsAlternate IsAlternateSheet(const nsAString& aTitle, bool aHasAlternateRel); 441 442 // Measure our size. 443 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; 444 445 enum class SheetState : uint8_t { 446 NeedsParser = 0, 447 Pending, 448 Loading, 449 Complete 450 }; 451 452 // The loader principal is the document's node principal, if this loader is 453 // owned by a document, or the system principal otherwise. 454 nsIPrincipal* LoaderPrincipal() const; 455 456 // The partitioned principal is the document's partitioned principal, if this 457 // loader is owned by a document, or the system principal otherwise. 458 nsIPrincipal* PartitionedPrincipal() const; 459 460 bool ShouldBypassCache() const; 461 462 // Inserts a style sheet in a document or a ShadowRoot. 463 void InsertSheetInTree(StyleSheet& aSheet); 464 465 enum class PendingLoad { No, Yes }; 466 467 private: 468 friend class mozilla::SharedStyleSheetCache; 469 friend class SheetLoadData; 470 friend class StreamLoader; 471 472 enum class UsePreload : bool { No, Yes }; 473 enum class UseLoadGroup : bool { No, Yes }; 474 475 nsresult NewStyleSheetChannel(SheetLoadData& aLoadData, CORSMode aCorsMode, 476 UsePreload aUsePreload, 477 UseLoadGroup aUseLoadGroup, 478 nsIChannel** aOutChannel); 479 480 // Only to be called by `LoadSheet`. 481 [[nodiscard]] bool MaybeDeferLoad(SheetLoadData& aLoadData, 482 SheetState aSheetState, 483 PendingLoad aPendingLoad, 484 const SheetLoadDataHashKey& aKey); 485 486 // Only to be called by `LoadSheet`. 487 bool MaybeCoalesceLoadAndNotifyOpen(SheetLoadData& aLoadData, 488 SheetState aSheetState, 489 const SheetLoadDataHashKey& aKey, 490 const PreloadHashKey& aPreloadKey); 491 492 // Only to be called by `LoadSheet`. 493 [[nodiscard]] nsresult LoadSheetSyncInternal(SheetLoadData& aLoadData, 494 SheetState aSheetState); 495 496 void AdjustPriority(const SheetLoadData& aLoadData, nsIChannel* aChannel); 497 498 // Only to be called by `LoadSheet`. 499 [[nodiscard]] nsresult LoadSheetAsyncInternal( 500 SheetLoadData& aLoadData, uint64_t aEarlyHintPreloaderId, 501 const SheetLoadDataHashKey& aKey); 502 503 // Helpers to conditionally block onload if mDocument is non-null. 504 void IncrementOngoingLoadCountAndMaybeBlockOnload() { 505 if (!mOngoingLoadCount++) { 506 BlockOnload(); 507 } 508 } 509 510 void DecrementOngoingLoadCountAndMaybeUnblockOnload() { 511 MOZ_DIAGNOSTIC_ASSERT(mOngoingLoadCount); 512 MOZ_DIAGNOSTIC_ASSERT(mOngoingLoadCount > mPendingLoadCount); 513 if (!--mOngoingLoadCount) { 514 UnblockOnload(false); 515 } 516 } 517 518 void BlockOnload(); 519 void UnblockOnload(bool aFireSync); 520 521 nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal, 522 nsIPrincipal* aTriggeringPrincipal, 523 nsIURI* aTargetURI, nsINode* aRequestingNode, 524 const nsAString& aNonce, StylePreloadKind, 525 CORSMode aCORSMode, const nsAString& aIntegrity); 526 527 bool MaybePutIntoLoadsPerformed(SheetLoadData& aLoadData); 528 529 private: 530 std::tuple<RefPtr<StyleSheet>, SheetState, 531 RefPtr<SubResourceNetworkMetadataHolder>> 532 CreateSheet(const SheetInfo& aInfo, css::SheetParsingMode aParsingMode, 533 bool aSyncLoad, css::StylePreloadKind aPreloadKind) { 534 nsIPrincipal* triggeringPrincipal = aInfo.mTriggeringPrincipal 535 ? aInfo.mTriggeringPrincipal.get() 536 : LoaderPrincipal(); 537 return CreateSheet(aInfo.mURI, aInfo.mContent, triggeringPrincipal, 538 aParsingMode, aInfo.mCORSMode, 539 /* aPreloadOrParentDataEncoding = */ nullptr, 540 aInfo.mIntegrity, aSyncLoad, aPreloadKind); 541 } 542 543 // For inline style, the aURI param is null, but the aLinkingContent 544 // must be non-null then. The loader principal must never be null 545 // if aURI is not null. 546 std::tuple<RefPtr<StyleSheet>, SheetState, 547 RefPtr<SubResourceNetworkMetadataHolder>> 548 CreateSheet(nsIURI* aURI, nsIContent* aLinkingContent, 549 nsIPrincipal* aTriggeringPrincipal, css::SheetParsingMode, 550 CORSMode, const Encoding* aPreloadOrParentDataEncoding, 551 const nsAString& aIntegrity, bool aSyncLoad, StylePreloadKind); 552 553 // Pass in either a media string or the MediaList from the CSSParser. Don't 554 // pass both. 555 // 556 // This method will set the sheet's enabled state based on IsAlternate and co. 557 MediaMatched PrepareSheet(StyleSheet&, const nsAString& aTitle, 558 const nsAString& aMediaString, dom::MediaList*, 559 IsAlternate, IsExplicitlyEnabled); 560 561 // Inserts a style sheet into a parent style sheet. 562 void InsertChildSheet(StyleSheet& aSheet, StyleSheet& aParentSheet); 563 564 Result<RefPtr<StyleSheet>, nsresult> InternalLoadNonDocumentSheet( 565 nsIURI* aURL, StylePreloadKind, SheetParsingMode aParsingMode, 566 UseSystemPrincipal, const Encoding* aPreloadEncoding, 567 nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver, 568 CORSMode aCORSMode, const nsAString& aNonce, const nsAString& aIntegrity, 569 uint64_t aEarlyHintPreloaderId, dom::FetchPriority aFetchPriority); 570 571 RefPtr<StyleSheet> LookupInlineSheetInCache(const nsAString&, nsIPrincipal*, 572 nsIURI* aBaseURI); 573 574 // Synchronously notify of a cached load data. 575 void NotifyOfCachedLoad(RefPtr<SheetLoadData>); 576 577 // Notify observers of a cached stylesheet being. 578 void NotifyObserversForCachedSheet(SheetLoadData&); 579 580 // Add the Performance API's Resource Timing entry for the cached load data. 581 void AddPerformanceEntryForCachedSheet(SheetLoadData&); 582 583 // Start the loads of all the sheets in mPendingDatas 584 void StartDeferredLoads(); 585 586 // Note: LoadSheet is responsible for setting the sheet to complete on 587 // failure. 588 nsresult LoadSheet(SheetLoadData&, SheetState, uint64_t aEarlyHintPreloaderId, 589 PendingLoad = PendingLoad::No); 590 591 enum class AllowAsyncParse { 592 Yes, 593 No, 594 }; 595 596 // Parse the stylesheet in the load data. 597 // 598 // Returns whether the parse finished. It may not finish e.g. if the sheet had 599 // an @import. 600 // 601 // If this function returns Completed::Yes, then ParseSheet also called 602 // SheetComplete on aLoadData. 603 Completed ParseSheet(const nsACString&, const RefPtr<SheetLoadDataHolder>&, 604 AllowAsyncParse); 605 606 // The load of the sheet in the load data is done, one way or another. 607 // Do final cleanup. 608 void SheetComplete(SheetLoadData&, nsresult); 609 610 // Notify observers on an individual data. This is different from 611 // SheetComplete for loads that are shared. 612 void NotifyObservers(SheetLoadData&, nsresult); 613 614 // Mark the given SheetLoadData, as well as any of its siblings, parents, etc 615 // transitively, as failed. The idea is to mark as failed any load that was 616 // directly or indirectly @importing the sheet this SheetLoadData represents. 617 // 618 // if aOnlyForLoader is non-null, then only loads for a given loader will be 619 // marked as failing. This is useful to only cancel loads associated to a 620 // given loader, in case they were marked as canceled. 621 static void MarkLoadTreeFailed(SheetLoadData&, 622 Loader* aOnlyForLoader = nullptr); 623 624 // A shorthand to mark a possible link preload as used to supress "unused" 625 // warning in the console. 626 void MaybeNotifyPreloadUsed(SheetLoadData&); 627 628 // A set with all the different loads we've done in a given document, for the 629 // purpose of not posting duplicate performance entries for them. 630 nsTHashtable<const SheetLoadDataHashKey> mLoadsPerformed; 631 632 RefPtr<SharedStyleSheetCache> mSheets; 633 634 // Our array of "global" observers 635 nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver>> mObservers; 636 637 // This reference is nulled by the Document in it's destructor through 638 // DropDocumentReference(). 639 dom::Document* MOZ_NON_OWNING_REF mDocument; // the document we live for 640 641 // For dispatching events via DocGroup::Dispatch() when mDocument is nullptr. 642 RefPtr<dom::DocGroup> mDocGroup; 643 644 nsCompatibility mDocumentCompatMode; 645 646 const nsCOMPtr<nsIConsoleReportCollector> mReporter; 647 648 // Number of datas for asynchronous sheet loads still waiting to be notified. 649 // This includes pending stylesheets whose load hasn't started yet but which 650 // we need to, but not inline or constructable stylesheets, though the 651 // constructable stylesheets bit may change, see bug 1642227. 652 uint32_t mOngoingLoadCount = 0; 653 654 // The number of sheets that have been deferred / are in a pending state. 655 uint32_t mPendingLoadCount = 0; 656 657 // The number of stylesheets that we have parsed, for testing purposes. 658 Atomic<uint32_t, MemoryOrdering::Relaxed> mParsedSheetCount{0}; 659 660 bool mEnabled = true; 661 662 // Whether we had a document at the point of creation. 663 bool mIsDocumentAssociated = false; 664 665 #ifdef DEBUG 666 // Whether we're in a necko callback atm. 667 bool mSyncCallback = false; 668 #endif 669 }; 670 671 } // namespace css 672 } // namespace mozilla 673 674 #endif /* mozilla_css_Loader_h */