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