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 "nsIPrincipal.h" 13 #include "nsAutoPtr.h" 14 #include "nsCompatibility.h" 15 #include "nsCycleCollectionParticipant.h" 16 #include "nsDataHashtable.h" 17 #include "nsRefPtrHashtable.h" 18 #include "nsStringFwd.h" 19 #include "nsTArray.h" 20 #include "nsTObserverArray.h" 21 #include "nsURIHashKey.h" 22 #include "mozilla/Attributes.h" 23 #include "mozilla/CORSMode.h" 24 #include "mozilla/StyleSheetInlines.h" 25 #include "mozilla/Maybe.h" 26 #include "mozilla/MemoryReporting.h" 27 #include "mozilla/StyleBackendType.h" 28 #include "mozilla/StyleSheet.h" 29 #include "mozilla/net/ReferrerPolicy.h" 30 31 class nsICSSLoaderObserver; 32 class nsIConsoleReportCollector; 33 class nsIContent; 34 class nsIDocument; 35 class nsIStyleSheetLinkingElement; 36 37 namespace mozilla { 38 namespace dom { 39 class DocGroup; 40 class Element; 41 } // namespace dom 42 } // namespace mozilla 43 44 namespace mozilla { 45 46 class URIPrincipalReferrerPolicyAndCORSModeHashKey : public nsURIHashKey { 47 public: 48 typedef URIPrincipalReferrerPolicyAndCORSModeHashKey* KeyType; 49 typedef const URIPrincipalReferrerPolicyAndCORSModeHashKey* KeyTypePointer; 50 typedef mozilla::net::ReferrerPolicy ReferrerPolicy; 51 URIPrincipalReferrerPolicyAndCORSModeHashKey(const URIPrincipalReferrerPolicyAndCORSModeHashKey * aKey)52 explicit URIPrincipalReferrerPolicyAndCORSModeHashKey( 53 const URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) 54 : nsURIHashKey(aKey->mKey), 55 mPrincipal(aKey->mPrincipal), 56 mCORSMode(aKey->mCORSMode), 57 mReferrerPolicy(aKey->mReferrerPolicy) { 58 MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey); 59 } 60 URIPrincipalReferrerPolicyAndCORSModeHashKey(nsIURI * aURI,nsIPrincipal * aPrincipal,CORSMode aCORSMode,ReferrerPolicy aReferrerPolicy)61 URIPrincipalReferrerPolicyAndCORSModeHashKey(nsIURI* aURI, 62 nsIPrincipal* aPrincipal, 63 CORSMode aCORSMode, 64 ReferrerPolicy aReferrerPolicy) 65 : nsURIHashKey(aURI), 66 mPrincipal(aPrincipal), 67 mCORSMode(aCORSMode), 68 mReferrerPolicy(aReferrerPolicy) { 69 MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey); 70 } URIPrincipalReferrerPolicyAndCORSModeHashKey(const URIPrincipalReferrerPolicyAndCORSModeHashKey & toCopy)71 URIPrincipalReferrerPolicyAndCORSModeHashKey( 72 const URIPrincipalReferrerPolicyAndCORSModeHashKey& toCopy) 73 : nsURIHashKey(toCopy), 74 mPrincipal(toCopy.mPrincipal), 75 mCORSMode(toCopy.mCORSMode), 76 mReferrerPolicy(toCopy.mReferrerPolicy) { 77 MOZ_COUNT_CTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey); 78 } ~URIPrincipalReferrerPolicyAndCORSModeHashKey()79 ~URIPrincipalReferrerPolicyAndCORSModeHashKey() { 80 MOZ_COUNT_DTOR(URIPrincipalReferrerPolicyAndCORSModeHashKey); 81 } 82 GetKey()83 URIPrincipalReferrerPolicyAndCORSModeHashKey* GetKey() const { 84 return const_cast<URIPrincipalReferrerPolicyAndCORSModeHashKey*>(this); 85 } GetKeyPointer()86 const URIPrincipalReferrerPolicyAndCORSModeHashKey* GetKeyPointer() const { 87 return this; 88 } 89 KeyEquals(const URIPrincipalReferrerPolicyAndCORSModeHashKey * aKey)90 bool KeyEquals( 91 const URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) const { 92 if (!nsURIHashKey::KeyEquals(aKey->mKey)) { 93 return false; 94 } 95 96 if (!mPrincipal != !aKey->mPrincipal) { 97 // One or the other has a principal, but not both... not equal 98 return false; 99 } 100 101 if (mCORSMode != aKey->mCORSMode) { 102 // Different CORS modes; we don't match 103 return false; 104 } 105 106 if (mReferrerPolicy != aKey->mReferrerPolicy) { 107 // Different ReferrerPolicy; we don't match 108 return false; 109 } 110 111 bool eq; 112 return !mPrincipal || 113 (NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq); 114 } 115 KeyToPointer(URIPrincipalReferrerPolicyAndCORSModeHashKey * aKey)116 static const URIPrincipalReferrerPolicyAndCORSModeHashKey* KeyToPointer( 117 URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) { 118 return aKey; 119 } HashKey(const URIPrincipalReferrerPolicyAndCORSModeHashKey * aKey)120 static PLDHashNumber HashKey( 121 const URIPrincipalReferrerPolicyAndCORSModeHashKey* aKey) { 122 return nsURIHashKey::HashKey(aKey->mKey); 123 } 124 GetURI()125 nsIURI* GetURI() const { return nsURIHashKey::GetKey(); } 126 127 enum { ALLOW_MEMMOVE = true }; 128 129 protected: 130 nsCOMPtr<nsIPrincipal> mPrincipal; 131 CORSMode mCORSMode; 132 ReferrerPolicy mReferrerPolicy; 133 }; 134 135 namespace css { 136 137 class SheetLoadData; 138 class ImportRule; 139 140 /********************* 141 * Style sheet reuse * 142 *********************/ 143 144 class MOZ_RAII LoaderReusableStyleSheets { 145 public: LoaderReusableStyleSheets()146 LoaderReusableStyleSheets() {} 147 148 /** 149 * Look for a reusable sheet (see AddReusableSheet) matching the 150 * given URL. If found, set aResult, remove the reused sheet from 151 * the internal list, and return true. If not found, return false; 152 * in this case, aResult is not modified. 153 * 154 * @param aURL the url to match 155 * @param aResult [out] the style sheet which can be reused 156 */ 157 bool FindReusableStyleSheet(nsIURI* aURL, RefPtr<StyleSheet>& aResult); 158 159 /** 160 * Indicate that a certain style sheet is available for reuse if its 161 * URI matches the URI of an @import. Sheets should be added in the 162 * opposite order in which they are intended to be reused. 163 * 164 * @param aSheet the sheet which can be reused 165 */ AddReusableSheet(StyleSheet * aSheet)166 void AddReusableSheet(StyleSheet* aSheet) { 167 mReusableSheets.AppendElement(aSheet); 168 } 169 170 private: 171 LoaderReusableStyleSheets(const LoaderReusableStyleSheets&) = delete; 172 LoaderReusableStyleSheets& operator=(const LoaderReusableStyleSheets&) = 173 delete; 174 175 // The sheets that can be reused. 176 nsTArray<RefPtr<StyleSheet>> mReusableSheets; 177 }; 178 179 /*********************************************************************** 180 * Enum that describes the state of the sheet returned by CreateSheet. * 181 ***********************************************************************/ 182 enum StyleSheetState { 183 eSheetStateUnknown = 0, 184 eSheetNeedsParser, 185 eSheetPending, 186 eSheetLoading, 187 eSheetComplete 188 }; 189 190 class Loader final { 191 typedef mozilla::net::ReferrerPolicy ReferrerPolicy; 192 193 public: 194 // aDocGroup is used for dispatching SheetLoadData in PostLoadEvent(). It 195 // can be null if you want to use this constructor, and there's no 196 // document when the Loader is constructed. 197 Loader(StyleBackendType aType, mozilla::dom::DocGroup* aDocGroup); 198 199 explicit Loader(nsIDocument*); 200 201 private: 202 // Private destructor, to discourage deletion outside of Release(): 203 ~Loader(); 204 205 public: 206 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Loader) 207 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(Loader) 208 209 void DropDocumentReference(); // notification that doc is going away 210 SetCompatibilityMode(nsCompatibility aCompatMode)211 void SetCompatibilityMode(nsCompatibility aCompatMode) { 212 mCompatMode = aCompatMode; 213 } GetCompatibilityMode()214 nsCompatibility GetCompatibilityMode() { return mCompatMode; } 215 nsresult SetPreferredSheet(const nsAString& aTitle); 216 217 // XXXbz sort out what the deal is with events! When should they fire? 218 219 /** 220 * Load an inline style sheet. If a successful result is returned and 221 * *aCompleted is false, then aObserver is guaranteed to be notified 222 * asynchronously once the sheet is marked complete. If an error is 223 * returned, or if *aCompleted is true, aObserver will not be notified. In 224 * addition to parsing the sheet, this method will insert it into the 225 * stylesheet list of this CSSLoader's document. 226 * 227 * @param aElement the element linking to the stylesheet. This must not be 228 * null and must implement nsIStyleSheetLinkingElement. 229 * @param aBuffer the stylesheet data 230 * @param aTriggeringPrincipal The principal of the scripted caller that 231 * initiated the load, if available. Otherwise 232 * null. 233 * @param aLineNumber the line number at which the stylesheet data started. 234 * @param aTitle the title of the sheet. 235 * @param aMedia the media string for the sheet. 236 * @param aReferrerPolicy the referrer policy for loading the sheet. 237 * @param aObserver the observer to notify when the load completes. 238 * May be null. 239 * @param [out] aCompleted whether parsing of the sheet completed. 240 * @param [out] aIsAlternate whether the stylesheet ended up being an 241 * alternate sheet. 242 */ 243 nsresult LoadInlineStyle(nsIContent* aElement, const nsAString& aBuffer, 244 nsIPrincipal* aTriggeringPrincipal, 245 uint32_t aLineNumber, const nsAString& aTitle, 246 const nsAString& aMedia, 247 ReferrerPolicy aReferrerPolicy, 248 mozilla::dom::Element* aScopeElement, 249 nsICSSLoaderObserver* aObserver, bool* aCompleted, 250 bool* aIsAlternate); 251 252 /** 253 * Load a linked (document) stylesheet. If a successful result is returned, 254 * aObserver is guaranteed to be notified asynchronously once the sheet is 255 * loaded and marked complete. If an error is returned, aObserver will not 256 * be notified. In addition to loading the sheet, this method will insert it 257 * into the stylesheet list of this CSSLoader's document. 258 * 259 * @param aElement the element linking to the the stylesheet. May be null. 260 * @param aURL the URL of the sheet. 261 * @param aTriggeringPrincipal the triggering principal for the load. May be 262 * null, in which case the NodePrincipal() of the element (or 263 * document if aElement is null) should be used. 264 * @param aTitle the title of the sheet. 265 * @param aMedia the media string for the sheet. 266 * @param aHasAlternateRel whether the rel for this link included 267 * "alternate". 268 * @param aCORSMode the CORS mode for this load. 269 * @param aObserver the observer to notify when the load completes. 270 * May be null. 271 * @param [out] aIsAlternate whether the stylesheet actually ended up beinga 272 * an alternate sheet. Note that this need not match 273 * aHasAlternateRel. 274 */ 275 nsresult LoadStyleLink(nsIContent* aElement, nsIURI* aURL, 276 nsIPrincipal* aTriggeringPrincipal, 277 const nsAString& aTitle, const nsAString& aMedia, 278 bool aHasAlternateRel, CORSMode aCORSMode, 279 ReferrerPolicy aReferrerPolicy, 280 const nsAString& aIntegrity, 281 nsICSSLoaderObserver* aObserver, bool* aIsAlternate); 282 283 /** 284 * Load a child (@import-ed) style sheet. In addition to loading the sheet, 285 * this method will insert it into the child sheet list of aParentSheet. If 286 * there is no sheet currently being parsed and the child sheet is not 287 * complete when this method returns, then when the child sheet becomes 288 * complete aParentSheet will be QIed to nsICSSLoaderObserver and 289 * asynchronously notified, just like for LoadStyleLink. Note that if the 290 * child sheet is already complete when this method returns, no 291 * nsICSSLoaderObserver notification will be sent. 292 * 293 * @param aParentSheet the parent of this child sheet 294 * @param aParentData the SheetLoadData corresponding to the load of the 295 * parent sheet. 296 * @param aURL the URL of the child sheet 297 * @param aMedia the already-parsed media list for the child sheet 298 * @param aGeckoParentRule the @import rule importing this child, when using 299 * Gecko's style system. This is used to properly 300 * order the child sheet list of aParentSheet. 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 ImportRule* aGeckoParentRule, 307 LoaderReusableStyleSheets* aSavedSheets); 308 309 /** 310 * Synchronously load and return the stylesheet at aURL. Any child sheets 311 * will also be loaded synchronously. Note that synchronous loads over some 312 * protocols may involve spinning up a new event loop, so use of this method 313 * does NOT guarantee not receiving any events before the sheet loads. This 314 * method can be used to load sheets not associated with a document. 315 * 316 * @param aURL the URL of the sheet to load 317 * @param aParsingMode the mode in which to parse the sheet 318 * (see comments at enum SheetParsingMode, above). 319 * @param aUseSystemPrincipal if true, give the resulting sheet the system 320 * principal no matter where it's being loaded from. 321 * @param [out] aSheet the loaded, complete sheet. 322 * 323 * NOTE: At the moment, this method assumes the sheet will be UTF-8, but 324 * ideally it would allow arbitrary encodings. Callers should NOT depend on 325 * non-UTF8 sheets being treated as UTF-8 by this method. 326 * 327 * NOTE: A successful return from this method doesn't indicate anything about 328 * whether the data could be parsed as CSS and doesn't indicate anything 329 * about the status of child sheets of the returned sheet. 330 */ 331 nsresult LoadSheetSync(nsIURI* aURL, SheetParsingMode aParsingMode, 332 bool aUseSystemPrincipal, RefPtr<StyleSheet>* aSheet); 333 334 /** 335 * As above, but defaults aParsingMode to eAuthorSheetFeatures and 336 * aUseSystemPrincipal to false. 337 */ LoadSheetSync(nsIURI * aURL,RefPtr<StyleSheet> * aSheet)338 nsresult LoadSheetSync(nsIURI* aURL, RefPtr<StyleSheet>* aSheet) { 339 return LoadSheetSync(aURL, eAuthorSheetFeatures, false, aSheet); 340 } 341 342 /** 343 * Asynchronously load the stylesheet at aURL. If a successful result is 344 * returned, aObserver is guaranteed to be notified asynchronously once the 345 * sheet is loaded and marked complete. This method can be used to load 346 * sheets not associated with a document. 347 * 348 * @param aURL the URL of the sheet to load 349 * @param aParsingMode the mode in which to parse the sheet 350 * (see comments at enum SheetParsingMode, above). 351 * @param aUseSystemPrincipal if true, give the resulting sheet the system 352 * principal no matter where it's being loaded from. 353 * @param aObserver the observer to notify when the load completes. 354 * Must not be null. 355 * @param [out] aSheet the sheet to load. Note that the sheet may well 356 * not be loaded by 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 nsresult LoadSheet(nsIURI* aURL, SheetParsingMode aParsingMode, 363 bool aUseSystemPrincipal, nsICSSLoaderObserver* aObserver, 364 RefPtr<StyleSheet>* aSheet); 365 366 /** 367 * Asynchronously load the stylesheet at aURL. If a successful result is 368 * returned, aObserver is guaranteed to be notified asynchronously once the 369 * sheet is loaded and marked complete. This method can be used to load 370 * sheets not associated with a document. This method cannot be used to 371 * load user or agent sheets. 372 * 373 * @param aURL the URL of the sheet to load 374 * @param aOriginPrincipal the principal to use for security checks. This 375 * can be null to indicate that these checks should 376 * be skipped. 377 * @param aObserver the observer to notify when the load completes. 378 * Must not be null. 379 * @param [out] aSheet the sheet to load. Note that the sheet may well 380 * not be loaded by the time this method returns. 381 */ 382 nsresult LoadSheet(nsIURI* aURL, nsIPrincipal* aOriginPrincipal, 383 nsICSSLoaderObserver* aObserver, 384 RefPtr<StyleSheet>* aSheet); 385 386 /** 387 * Same as above, to be used when the caller doesn't care about the 388 * not-yet-loaded sheet. 389 */ 390 nsresult LoadSheet(nsIURI* aURL, bool aIsPreload, 391 nsIPrincipal* aOriginPrincipal, 392 const Encoding* aPreloadEncoding, 393 nsICSSLoaderObserver* aObserver, 394 CORSMode aCORSMode = CORS_NONE, 395 ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset, 396 const nsAString& aIntegrity = EmptyString()); 397 398 /** 399 * Stop loading all sheets. All nsICSSLoaderObservers involved will be 400 * notified with NS_BINDING_ABORTED as the status, possibly synchronously. 401 */ 402 nsresult Stop(void); 403 404 /** 405 * nsresult Loader::StopLoadingSheet(nsIURI* aURL), which notifies the 406 * nsICSSLoaderObserver with NS_BINDING_ABORTED, was removed in Bug 556446. 407 * It can be found in revision 2c44a32052ad. 408 */ 409 410 /** 411 * Whether the loader is enabled or not. 412 * When disabled, processing of new styles is disabled and an attempt 413 * to do so will fail with a return code of 414 * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable 415 * currently loading styles or already processed styles. 416 */ GetEnabled()417 bool GetEnabled() { return mEnabled; } SetEnabled(bool aEnabled)418 void SetEnabled(bool aEnabled) { mEnabled = aEnabled; } 419 420 /** 421 * Get the document we live for. May return null. 422 */ GetDocument()423 nsIDocument* GetDocument() const { return mDocument; } 424 425 /** 426 * Return true if this loader has pending loads (ones that would send 427 * notifications to an nsICSSLoaderObserver attached to this loader). 428 * If called from inside nsICSSLoaderObserver::StyleSheetLoaded, this will 429 * return false if and only if that is the last StyleSheetLoaded 430 * notification the CSSLoader knows it's going to send. In other words, if 431 * two sheets load at once (via load coalescing, e.g.), HasPendingLoads() 432 * will return true during notification for the first one, and false 433 * during notification for the second one. 434 */ 435 bool HasPendingLoads(); 436 437 /** 438 * Add an observer to this loader. The observer will be notified 439 * for all loads that would have notified their own observers (even 440 * if those loads don't have observers attached to them). 441 * Load-specific observers will be notified before generic 442 * observers. The loader holds a reference to the observer. 443 * 444 * aObserver must not be null. 445 */ 446 nsresult AddObserver(nsICSSLoaderObserver* aObserver); 447 448 /** 449 * Remove an observer added via AddObserver. 450 */ 451 void RemoveObserver(nsICSSLoaderObserver* aObserver); 452 453 // These interfaces are public only for the benefit of static functions 454 // within nsCSSLoader.cpp. 455 456 // IsAlternate can change our currently selected style set if none 457 // is selected and aHasAlternateRel is false. 458 bool IsAlternate(const nsAString& aTitle, bool aHasAlternateRel); 459 460 typedef nsTArray<RefPtr<SheetLoadData>> LoadDataArray; 461 462 // Measure our size. 463 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 464 465 // Marks all the sheets at the given URI obsolete, and removes them from the 466 // cache. 467 nsresult ObsoleteSheet(nsIURI* aURI); 468 469 private: 470 friend class SheetLoadData; 471 friend class StreamLoader; 472 473 // Helpers to conditionally block onload if mDocument is non-null. 474 void BlockOnload(); 475 void UnblockOnload(bool aFireSync); 476 477 // Helper to select the correct dispatch target for asynchronous events for 478 // this loader. 479 already_AddRefed<nsISerialEventTarget> DispatchTarget(); 480 481 nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal, 482 nsIPrincipal* aTriggeringPrincipal, 483 nsIURI* aTargetURI, nsISupports* aContext, 484 bool aIsPreload); 485 486 // For inline style, the aURI param is null, but the aLinkingContent 487 // must be non-null then. The loader principal must never be null 488 // if aURI is not null. 489 // *aIsAlternate is set based on aTitle and aHasAlternateRel. 490 nsresult CreateSheet(nsIURI* aURI, nsIContent* aLinkingContent, 491 nsIPrincipal* aLoaderPrincipal, 492 css::SheetParsingMode aParsingMode, CORSMode aCORSMode, 493 ReferrerPolicy aReferrerPolicy, 494 const nsAString& aIntegrity, bool aSyncLoad, 495 bool aHasAlternateRel, const nsAString& aTitle, 496 StyleSheetState& aSheetState, bool* aIsAlternate, 497 RefPtr<StyleSheet>* aSheet); 498 499 // Pass in either a media string or the MediaList from the CSSParser. Don't 500 // pass both. 501 // 502 // This method will set the sheet's enabled state based on aIsAlternate 503 void PrepareSheet(StyleSheet* aSheet, const nsAString& aTitle, 504 const nsAString& aMediaString, dom::MediaList* aMediaList, 505 dom::Element* aScopeElement, bool aIsAlternate); 506 507 nsresult InsertSheetInDoc(StyleSheet* aSheet, nsIContent* aLinkingContent, 508 nsIDocument* aDocument); 509 510 nsresult InsertChildSheet(StyleSheet* aSheet, StyleSheet* aParentSheet, 511 ImportRule* aGeckoParentRule); 512 513 nsresult InternalLoadNonDocumentSheet( 514 nsIURI* aURL, bool aIsPreload, SheetParsingMode aParsingMode, 515 bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, 516 const Encoding* aPreloadEncoding, RefPtr<StyleSheet>* aSheet, 517 nsICSSLoaderObserver* aObserver, CORSMode aCORSMode = CORS_NONE, 518 ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset, 519 const nsAString& aIntegrity = EmptyString()); 520 521 // Post a load event for aObserver to be notified about aSheet. The 522 // notification will be sent with status NS_OK unless the load event is 523 // canceled at some point (in which case it will be sent with 524 // NS_BINDING_ABORTED). aWasAlternate indicates the state when the load was 525 // initiated, not the state at some later time. aURI should be the URI the 526 // sheet was loaded from (may be null for inline sheets). aElement is the 527 // owning element for this sheet. 528 nsresult PostLoadEvent(nsIURI* aURI, StyleSheet* aSheet, 529 nsICSSLoaderObserver* aObserver, bool aWasAlternate, 530 nsIStyleSheetLinkingElement* aElement); 531 532 // Start the loads of all the sheets in mPendingDatas 533 void StartAlternateLoads(); 534 535 // Handle an event posted by PostLoadEvent 536 void HandleLoadEvent(SheetLoadData* aEvent); 537 538 // Note: LoadSheet is responsible for releasing aLoadData and setting the 539 // sheet to complete on failure. 540 nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState, 541 bool aIsPreLoad); 542 543 // Parse the stylesheet in aLoadData. The sheet data comes from aUTF16 if 544 // UTF-16 and from aUTF8 if UTF-8. 545 // Sets aCompleted to true if the parse finished, false otherwise (e.g. if the 546 // sheet had an @import). If aCompleted is true when this returns, then 547 // ParseSheet also called SheetComplete on aLoadData. 548 nsresult ParseSheet(const nsAString& aUTF16, Span<const uint8_t> aUTF8, 549 SheetLoadData* aLoadData, bool aAllowAsync, 550 bool& aCompleted); 551 552 // 553 // Separate parsing paths for the old and new style systems, so that we can 554 // make parsing asynchronous in the new style system without touching the old 555 // one. Once we drop the old style system, this can be simplified. 556 // 557 558 #ifdef MOZ_OLD_STYLE 559 nsresult DoParseSheetGecko(CSSStyleSheet* aSheet, const nsAString& aUTF16, 560 Span<const uint8_t> aUTF8, 561 SheetLoadData* aLoadData, bool& aCompleted); 562 #endif 563 564 nsresult DoParseSheetServo(ServoStyleSheet* aSheet, const nsAString& aUTF16, 565 Span<const uint8_t> aUTF8, 566 SheetLoadData* aLoadData, bool aAllowAsync, 567 bool& aCompleted); 568 569 // The load of the sheet in aLoadData is done, one way or another. Do final 570 // cleanup, including releasing aLoadData. 571 void SheetComplete(SheetLoadData* aLoadData, nsresult aStatus); 572 573 // The guts of SheetComplete. This may be called recursively on parent datas 574 // or datas that had glommed on to a single load. The array is there so load 575 // datas whose observers need to be notified can be added to it. 576 void DoSheetComplete(SheetLoadData* aLoadData, LoadDataArray& aDatasToNotify); 577 578 // Mark the given SheetLoadData, as well as any of its siblings, parents, etc 579 // transitively, as failed. The idea is to mark as failed any load that was 580 // directly or indirectly @importing the sheet this SheetLoadData represents. 581 void MarkLoadTreeFailed(SheetLoadData* aLoadData); 582 583 StyleBackendType GetStyleBackendType() const; 584 585 struct Sheets { 586 nsBaseHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, 587 RefPtr<StyleSheet>, StyleSheet*> 588 mCompleteSheets; 589 nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, 590 SheetLoadData*> 591 mLoadingDatas; // weak refs 592 nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, 593 SheetLoadData*> 594 mPendingDatas; // weak refs 595 }; 596 nsAutoPtr<Sheets> mSheets; 597 598 // The array of posted stylesheet loaded events (SheetLoadDatas) we have. 599 // Note that these are rare. 600 LoadDataArray mPostedEvents; 601 602 // Our array of "global" observers 603 nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver>> mObservers; 604 605 // This reference is nulled by the Document in it's destructor through 606 // DropDocumentReference(). 607 nsIDocument* MOZ_NON_OWNING_REF mDocument; // the document we live for 608 609 // For dispatching events via DocGroup::Dispatch() when mDocument is nullptr. 610 RefPtr<mozilla::dom::DocGroup> mDocGroup; 611 612 // Number of datas still waiting to be notified on if we're notifying on a 613 // whole bunch at once (e.g. in one of the stop methods). This is used to 614 // make sure that HasPendingLoads() won't return false until we're notifying 615 // on the last data we're working with. 616 uint32_t mDatasToNotifyOn; 617 618 nsCompatibility mCompatMode; 619 nsString mPreferredSheet; // title of preferred sheet 620 621 // Set explicitly when the Loader(StyleBackendType) constructor is used, or 622 // taken from the document when the Loader(nsIDocument*) constructor is used. 623 mozilla::Maybe<StyleBackendType> mStyleBackendType; 624 625 bool mEnabled; // is enabled to load new styles 626 627 nsCOMPtr<nsIConsoleReportCollector> mReporter; 628 629 #ifdef DEBUG 630 bool mSyncCallback; 631 #endif 632 }; 633 634 } // namespace css 635 } // namespace mozilla 636 637 #endif /* mozilla_css_Loader_h */ 638