summaryrefslogtreecommitdiffstats
path: root/layout/style/Loader.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/Loader.h')
-rw-r--r--layout/style/Loader.h665
1 files changed, 665 insertions, 0 deletions
diff --git a/layout/style/Loader.h b/layout/style/Loader.h
new file mode 100644
index 0000000000..ba60218e94
--- /dev/null
+++ b/layout/style/Loader.h
@@ -0,0 +1,665 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* loading of CSS style sheets using the network APIs */
+
+#ifndef mozilla_css_Loader_h
+#define mozilla_css_Loader_h
+
+#include <tuple>
+#include <utility>
+
+#include "mozilla/Attributes.h"
+#include "mozilla/CORSMode.h"
+#include "mozilla/css/StylePreloadKind.h"
+#include "mozilla/dom/LinkStyle.h"
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/UniquePtr.h"
+#include "nsCompatibility.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsStringFwd.h"
+#include "nsTArray.h"
+#include "nsTObserverArray.h"
+#include "nsURIHashKey.h"
+#include "nsRefPtrHashtable.h"
+
+class nsICSSLoaderObserver;
+class nsIConsoleReportCollector;
+class nsIContent;
+class nsIPrincipal;
+
+namespace mozilla {
+
+class PreloadHashKey;
+class SharedStyleSheetCache;
+class SheetLoadDataHashKey;
+class StyleSheet;
+
+namespace dom {
+class DocGroup;
+class Element;
+enum class FetchPriority : uint8_t;
+} // namespace dom
+
+// The load data for a <link> or @import style-sheet.
+//
+// This must contain all the state that affects CSS parsing.
+class SheetLoadDataHashKey : public PLDHashEntryHdr {
+ public:
+ using KeyType = const SheetLoadDataHashKey&;
+ using KeyTypePointer = const SheetLoadDataHashKey*;
+
+ explicit SheetLoadDataHashKey(const SheetLoadDataHashKey* aKey)
+ : mURI(aKey->mURI),
+ mPrincipal(aKey->mPrincipal),
+ mLoaderPrincipal(aKey->mLoaderPrincipal),
+ mPartitionPrincipal(aKey->mPartitionPrincipal),
+ mEncodingGuess(aKey->mEncodingGuess),
+ mCORSMode(aKey->mCORSMode),
+ mParsingMode(aKey->mParsingMode),
+ mCompatMode(aKey->mCompatMode),
+ mSRIMetadata(aKey->mSRIMetadata),
+ mIsLinkRelPreload(aKey->mIsLinkRelPreload) {
+ MOZ_COUNT_CTOR(SheetLoadDataHashKey);
+ }
+
+ 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)
+ : mURI(aURI),
+ mPrincipal(aPrincipal),
+ mLoaderPrincipal(aLoaderPrincipal),
+ mPartitionPrincipal(aPartitionPrincipal),
+ mEncodingGuess(aEncodingGuess),
+ mCORSMode(aCORSMode),
+ mParsingMode(aParsingMode),
+ mCompatMode(aCompatMode),
+ mSRIMetadata(aSRIMetadata),
+ mIsLinkRelPreload(IsLinkRelPreload(aPreloadKind)) {
+ MOZ_ASSERT(aURI);
+ MOZ_ASSERT(aPrincipal);
+ MOZ_ASSERT(aLoaderPrincipal);
+ MOZ_COUNT_CTOR(SheetLoadDataHashKey);
+ }
+
+ SheetLoadDataHashKey(SheetLoadDataHashKey&& toMove)
+ : mURI(std::move(toMove.mURI)),
+ mPrincipal(std::move(toMove.mPrincipal)),
+ mLoaderPrincipal(std::move(toMove.mLoaderPrincipal)),
+ mPartitionPrincipal(std::move(toMove.mPartitionPrincipal)),
+ mEncodingGuess(std::move(toMove.mEncodingGuess)),
+ mCORSMode(std::move(toMove.mCORSMode)),
+ mParsingMode(std::move(toMove.mParsingMode)),
+ mCompatMode(std::move(toMove.mCompatMode)),
+ mSRIMetadata(std::move(toMove.mSRIMetadata)),
+ mIsLinkRelPreload(std::move(toMove.mIsLinkRelPreload)) {
+ MOZ_COUNT_CTOR(SheetLoadDataHashKey);
+ }
+
+ explicit SheetLoadDataHashKey(const css::SheetLoadData&);
+
+ MOZ_COUNTED_DTOR(SheetLoadDataHashKey)
+
+ const SheetLoadDataHashKey& GetKey() const { return *this; }
+ const SheetLoadDataHashKey* GetKeyPointer() const { return this; }
+
+ bool KeyEquals(const SheetLoadDataHashKey* aKey) const {
+ return KeyEquals(*aKey);
+ }
+
+ bool KeyEquals(const SheetLoadDataHashKey&) const;
+
+ static const SheetLoadDataHashKey* KeyToPointer(
+ const SheetLoadDataHashKey& aKey) {
+ return &aKey;
+ }
+ static PLDHashNumber HashKey(const SheetLoadDataHashKey* aKey) {
+ return nsURIHashKey::HashKey(aKey->mURI);
+ }
+
+ nsIURI* URI() const { return mURI; }
+
+ nsIPrincipal* Principal() const { return mPrincipal; }
+
+ nsIPrincipal* LoaderPrincipal() const { return mLoaderPrincipal; }
+
+ nsIPrincipal* PartitionPrincipal() const { return mPartitionPrincipal; }
+
+ css::SheetParsingMode ParsingMode() const { return mParsingMode; }
+
+ enum { ALLOW_MEMMOVE = true };
+
+ protected:
+ const nsCOMPtr<nsIURI> mURI;
+ const nsCOMPtr<nsIPrincipal> mPrincipal;
+ const nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
+ const nsCOMPtr<nsIPrincipal> mPartitionPrincipal;
+ // The encoding guess is the encoding the sheet would get if the request
+ // didn't have any encoding information like @charset or a Content-Encoding
+ // header.
+ const NotNull<const Encoding*> mEncodingGuess;
+ const CORSMode mCORSMode;
+ const css::SheetParsingMode mParsingMode;
+ const nsCompatibility mCompatMode;
+ dom::SRIMetadata mSRIMetadata;
+ const bool mIsLinkRelPreload;
+};
+
+namespace css {
+
+class SheetLoadData;
+class ImportRule;
+
+/*********************
+ * Style sheet reuse *
+ *********************/
+
+class MOZ_RAII LoaderReusableStyleSheets {
+ public:
+ LoaderReusableStyleSheets() = default;
+
+ /**
+ * Look for a reusable sheet (see AddReusableSheet) matching the
+ * given URL. If found, set aResult, remove the reused sheet from
+ * the internal list, and return true. If not found, return false;
+ * in this case, aResult is not modified.
+ *
+ * @param aURL the url to match
+ * @param aResult [out] the style sheet which can be reused
+ */
+ bool FindReusableStyleSheet(nsIURI* aURL, RefPtr<StyleSheet>& aResult);
+
+ /**
+ * Indicate that a certain style sheet is available for reuse if its
+ * URI matches the URI of an @import. Sheets should be added in the
+ * opposite order in which they are intended to be reused.
+ *
+ * @param aSheet the sheet which can be reused
+ */
+ void AddReusableSheet(StyleSheet* aSheet) {
+ mReusableSheets.AppendElement(aSheet);
+ }
+
+ private:
+ LoaderReusableStyleSheets(const LoaderReusableStyleSheets&) = delete;
+ LoaderReusableStyleSheets& operator=(const LoaderReusableStyleSheets&) =
+ delete;
+
+ // The sheets that can be reused.
+ nsTArray<RefPtr<StyleSheet>> mReusableSheets;
+};
+
+class Loader final {
+ using ReferrerPolicy = dom::ReferrerPolicy;
+
+ public:
+ using Completed = dom::LinkStyle::Completed;
+ using HasAlternateRel = dom::LinkStyle::HasAlternateRel;
+ using IsAlternate = dom::LinkStyle::IsAlternate;
+ using IsInline = dom::LinkStyle::IsInline;
+ using IsExplicitlyEnabled = dom::LinkStyle::IsExplicitlyEnabled;
+ using MediaMatched = dom::LinkStyle::MediaMatched;
+ using LoadSheetResult = dom::LinkStyle::Update;
+ using SheetInfo = dom::LinkStyle::SheetInfo;
+
+ Loader();
+ // aDocGroup is used for dispatching SheetLoadData in PostLoadEvent(). It
+ // can be null if you want to use this constructor, and there's no
+ // document when the Loader is constructed.
+ explicit Loader(dom::DocGroup*);
+ explicit Loader(dom::Document*);
+
+ private:
+ // Private destructor, to discourage deletion outside of Release():
+ ~Loader();
+
+ public:
+ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Loader)
+ NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(Loader)
+
+ void DropDocumentReference(); // notification that doc is going away
+
+ void DeregisterFromSheetCache();
+ void RegisterInSheetCache();
+
+ void SetCompatibilityMode(nsCompatibility aCompatMode) {
+ mDocumentCompatMode = aCompatMode;
+ }
+
+ using StylePreloadKind = css::StylePreloadKind;
+
+ bool HasLoaded(const SheetLoadDataHashKey& aKey) const {
+ return mLoadsPerformed.Contains(aKey);
+ }
+
+ void WillStartPendingLoad() {
+ MOZ_DIAGNOSTIC_ASSERT(mPendingLoadCount, "Where did this load come from?");
+ mPendingLoadCount--;
+ }
+
+ nsCompatibility CompatMode(StylePreloadKind aPreloadKind) const {
+ // For Link header preload, we guess non-quirks, because otherwise it is
+ // useless for modern pages.
+ //
+ // Link element preload is generally good because the speculative html
+ // parser deals with quirks mode properly.
+ if (aPreloadKind == StylePreloadKind::FromLinkRelPreloadHeader) {
+ return eCompatibility_FullStandards;
+ }
+ return mDocumentCompatMode;
+ }
+
+ // TODO(emilio): Is the complexity of this method and carrying the titles
+ // around worth it? The alternate sheets will load anyhow eventually...
+ void DocumentStyleSheetSetChanged();
+
+ // XXXbz sort out what the deal is with events! When should they fire?
+
+ /**
+ * Load an inline style sheet. If a successful result is returned and
+ * result.WillNotify() is true, then aObserver is guaranteed to be notified
+ * asynchronously once the sheet is marked complete. If an error is
+ * returned, or if result.WillNotify() is false, aObserver will not be
+ * notified. In addition to parsing the sheet, this method will insert it
+ * into the stylesheet list of this CSSLoader's document.
+ * @param aObserver the observer to notify when the load completes.
+ * May be null.
+ * @param aBuffer the stylesheet data
+ */
+ Result<LoadSheetResult, nsresult> LoadInlineStyle(
+ const SheetInfo&, const nsAString& aBuffer,
+ nsICSSLoaderObserver* aObserver);
+
+ /**
+ * Load a linked (document) stylesheet. If a successful result is returned,
+ * aObserver is guaranteed to be notified asynchronously once the sheet is
+ * loaded and marked complete, i.e., result.WillNotify() will always return
+ * true. If an error is returned, aObserver will not be notified. In
+ * addition to loading the sheet, this method will insert it into the
+ * stylesheet list of this CSSLoader's document.
+ * @param aObserver the observer to notify when the load completes.
+ * May be null.
+ */
+ Result<LoadSheetResult, nsresult> LoadStyleLink(
+ const SheetInfo&, nsICSSLoaderObserver* aObserver);
+
+ /**
+ * Load a child (@import-ed) style sheet. In addition to loading the sheet,
+ * this method will insert it into the child sheet list of aParentSheet. If
+ * there is no sheet currently being parsed and the child sheet is not
+ * complete when this method returns, then when the child sheet becomes
+ * complete aParentSheet will be QIed to nsICSSLoaderObserver and
+ * asynchronously notified, just like for LoadStyleLink. Note that if the
+ * child sheet is already complete when this method returns, no
+ * nsICSSLoaderObserver notification will be sent.
+ *
+ * @param aParentSheet the parent of this child sheet
+ * @param aParentData the SheetLoadData corresponding to the load of the
+ * parent sheet. May be null for @import rules inserted via
+ * CSSOM.
+ * @param aURL the URL of the child sheet
+ * @param aMedia the already-parsed media list for the child sheet
+ * @param aSavedSheets any saved style sheets which could be reused
+ * for this load
+ */
+ nsresult LoadChildSheet(StyleSheet& aParentSheet, SheetLoadData* aParentData,
+ nsIURI* aURL, dom::MediaList* aMedia,
+ LoaderReusableStyleSheets* aSavedSheets);
+
+ /**
+ * Called when we hit the internal memory cache with a complete stylesheet.
+ */
+ void DidHitCompleteSheetCache(const SheetLoadDataHashKey&,
+ const StyleUseCounters* aCounters);
+
+ enum class UseSystemPrincipal { No, Yes };
+
+ /**
+ * Synchronously load and return the stylesheet at aURL. Any child sheets
+ * will also be loaded synchronously. Note that synchronous loads over some
+ * protocols may involve spinning up a new event loop, so use of this method
+ * does NOT guarantee not receiving any events before the sheet loads. This
+ * method can be used to load sheets not associated with a document.
+ *
+ * @param aURL the URL of the sheet to load
+ * @param aParsingMode the mode in which to parse the sheet
+ * (see comments at enum SheetParsingMode, above).
+ * @param aUseSystemPrincipal if true, give the resulting sheet the system
+ * principal no matter where it's being loaded from.
+ *
+ * NOTE: At the moment, this method assumes the sheet will be UTF-8, but
+ * ideally it would allow arbitrary encodings. Callers should NOT depend on
+ * non-UTF8 sheets being treated as UTF-8 by this method.
+ *
+ * NOTE: A successful return from this method doesn't indicate anything about
+ * whether the data could be parsed as CSS and doesn't indicate anything
+ * about the status of child sheets of the returned sheet.
+ */
+ Result<RefPtr<StyleSheet>, nsresult> LoadSheetSync(
+ nsIURI*, SheetParsingMode = eAuthorSheetFeatures,
+ UseSystemPrincipal = UseSystemPrincipal::No);
+
+ /**
+ * Asynchronously load the stylesheet at aURL. If a successful result is
+ * returned, aObserver is guaranteed to be notified asynchronously once the
+ * sheet is loaded and marked complete. This method can be used to load
+ * sheets not associated with a document.
+ *
+ * @param aURL the URL of the sheet to load
+ * @param aParsingMode the mode in which to parse the sheet
+ * (see comments at enum SheetParsingMode, above).
+ * @param aUseSystemPrincipal if true, give the resulting sheet the system
+ * principal no matter where it's being loaded from.
+ * @param aReferrerInfo referrer information of the sheet.
+ * @param aObserver the observer to notify when the load completes.
+ * Must not be null.
+ * @param aEarlyHintPreloaderId to connect back to the early hint preload
+ * channel. Null means no connect back should happen
+ * @return the sheet to load. Note that the sheet may well not be loaded by
+ * the time this method returns.
+ *
+ * NOTE: At the moment, this method assumes the sheet will be UTF-8, but
+ * ideally it would allow arbitrary encodings. Callers should NOT depend on
+ * non-UTF8 sheets being treated as UTF-8 by this method.
+ */
+ Result<RefPtr<StyleSheet>, nsresult> LoadSheet(
+ nsIURI* aURI, StylePreloadKind, const Encoding* aPreloadEncoding,
+ nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
+ uint64_t aEarlyHintPreloaderId, CORSMode aCORSMode,
+ const nsAString& aNonce, const nsAString& aIntegrity,
+ dom::FetchPriority aFetchPriority);
+
+ /**
+ * As above, but without caring for a couple things.
+ * Only to be called by `PreloadedStyleSheet::PreloadAsync`.
+ */
+ Result<RefPtr<StyleSheet>, nsresult> LoadSheet(nsIURI*, SheetParsingMode,
+ UseSystemPrincipal,
+ nsICSSLoaderObserver*);
+
+ /**
+ * Stop loading all sheets. All nsICSSLoaderObservers involved will be
+ * notified with NS_BINDING_ABORTED as the status, possibly synchronously.
+ */
+ void Stop();
+
+ /**
+ * nsresult Loader::StopLoadingSheet(nsIURI* aURL), which notifies the
+ * nsICSSLoaderObserver with NS_BINDING_ABORTED, was removed in Bug 556446.
+ * It can be found in revision 2c44a32052ad.
+ */
+
+ /**
+ * Whether the loader is enabled or not.
+ * When disabled, processing of new styles is disabled and an attempt
+ * to do so will fail with a return code of
+ * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
+ * currently loading styles or already processed styles.
+ */
+ bool GetEnabled() { return mEnabled; }
+ void SetEnabled(bool aEnabled) { mEnabled = aEnabled; }
+
+ uint32_t ParsedSheetCount() const { return mParsedSheetCount; }
+
+ /**
+ * Get the document we live for. May return null.
+ */
+ dom::Document* GetDocument() const { return mDocument; }
+
+ bool IsDocumentAssociated() const { return mIsDocumentAssociated; }
+
+ /**
+ * Return true if this loader has pending loads (ones that would send
+ * notifications to an nsICSSLoaderObserver attached to this loader).
+ * If called from inside nsICSSLoaderObserver::StyleSheetLoaded, this will
+ * return false if and only if that is the last StyleSheetLoaded
+ * notification the CSSLoader knows it's going to send. In other words, if
+ * two sheets load at once (via load coalescing, e.g.), HasPendingLoads()
+ * will return true during notification for the first one, and false
+ * during notification for the second one.
+ */
+ bool HasPendingLoads();
+
+ /**
+ * Add an observer to this loader. The observer will be notified
+ * for all loads that would have notified their own observers (even
+ * if those loads don't have observers attached to them).
+ * Load-specific observers will be notified before generic
+ * observers. The loader holds a reference to the observer.
+ *
+ * aObserver must not be null.
+ */
+ void AddObserver(nsICSSLoaderObserver* aObserver);
+
+ /**
+ * Remove an observer added via AddObserver.
+ */
+ void RemoveObserver(nsICSSLoaderObserver* aObserver);
+
+ // These interfaces are public only for the benefit of static functions
+ // within nsCSSLoader.cpp.
+
+ // IsAlternateSheet can change our currently selected style set if none is
+ // selected and aHasAlternateRel is false.
+ IsAlternate IsAlternateSheet(const nsAString& aTitle, bool aHasAlternateRel);
+
+ // Measure our size.
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
+
+ enum class SheetState : uint8_t {
+ NeedsParser = 0,
+ Pending,
+ Loading,
+ Complete
+ };
+
+ // The loader principal is the document's node principal, if this loader is
+ // owned by a document, or the system principal otherwise.
+ nsIPrincipal* LoaderPrincipal() const;
+
+ // The partitioned principal is the document's partitioned principal, if this
+ // loader is owned by a document, or the system principal otherwise.
+ nsIPrincipal* PartitionedPrincipal() const;
+
+ bool ShouldBypassCache() const;
+
+ enum class PendingLoad { No, Yes };
+
+ private:
+ friend class mozilla::SharedStyleSheetCache;
+ friend class SheetLoadData;
+ friend class StreamLoader;
+
+ // Only to be called by `LoadSheet`.
+ [[nodiscard]] bool MaybeDeferLoad(SheetLoadData& aLoadData,
+ SheetState aSheetState,
+ PendingLoad aPendingLoad,
+ const SheetLoadDataHashKey& aKey);
+
+ // Only to be called by `LoadSheet`.
+ bool MaybeCoalesceLoadAndNotifyOpen(SheetLoadData& aLoadData,
+ SheetState aSheetState,
+ const SheetLoadDataHashKey& aKey,
+ const PreloadHashKey& aPreloadKey);
+
+ // Only to be called by `LoadSheet`.
+ [[nodiscard]] nsresult LoadSheetSyncInternal(SheetLoadData& aLoadData,
+ SheetState aSheetState);
+
+ void AdjustPriority(const SheetLoadData& aLoadData, nsIChannel* aChannel);
+
+ // Only to be called by `LoadSheet`.
+ [[nodiscard]] nsresult LoadSheetAsyncInternal(
+ SheetLoadData& aLoadData, uint64_t aEarlyHintPreloaderId,
+ const SheetLoadDataHashKey& aKey);
+
+ // Helpers to conditionally block onload if mDocument is non-null.
+ void IncrementOngoingLoadCountAndMaybeBlockOnload() {
+ if (!mOngoingLoadCount++) {
+ BlockOnload();
+ }
+ }
+
+ void DecrementOngoingLoadCountAndMaybeUnblockOnload() {
+ MOZ_DIAGNOSTIC_ASSERT(mOngoingLoadCount);
+ MOZ_DIAGNOSTIC_ASSERT(mOngoingLoadCount > mPendingLoadCount);
+ if (!--mOngoingLoadCount) {
+ UnblockOnload(false);
+ }
+ }
+
+ void BlockOnload();
+ void UnblockOnload(bool aFireSync);
+
+ nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
+ nsIPrincipal* aTriggeringPrincipal,
+ nsIURI* aTargetURI, nsINode* aRequestingNode,
+ const nsAString& aNonce, StylePreloadKind);
+
+ std::tuple<RefPtr<StyleSheet>, SheetState> CreateSheet(
+ const SheetInfo& aInfo, css::SheetParsingMode aParsingMode,
+ bool aSyncLoad, css::StylePreloadKind aPreloadKind) {
+ nsIPrincipal* triggeringPrincipal = aInfo.mTriggeringPrincipal
+ ? aInfo.mTriggeringPrincipal.get()
+ : LoaderPrincipal();
+ return CreateSheet(aInfo.mURI, aInfo.mContent, triggeringPrincipal,
+ aParsingMode, aInfo.mCORSMode,
+ /* aPreloadOrParentDataEncoding = */ nullptr,
+ aInfo.mIntegrity, aSyncLoad, aPreloadKind);
+ }
+
+ // For inline style, the aURI param is null, but the aLinkingContent
+ // must be non-null then. The loader principal must never be null
+ // if aURI is not null.
+ std::tuple<RefPtr<StyleSheet>, SheetState> CreateSheet(
+ nsIURI* aURI, nsIContent* aLinkingContent,
+ nsIPrincipal* aTriggeringPrincipal, css::SheetParsingMode, CORSMode,
+ const Encoding* aPreloadOrParentDataEncoding, const nsAString& aIntegrity,
+ bool aSyncLoad, StylePreloadKind);
+
+ // Pass in either a media string or the MediaList from the CSSParser. Don't
+ // pass both.
+ //
+ // This method will set the sheet's enabled state based on IsAlternate and co.
+ MediaMatched PrepareSheet(StyleSheet&, const nsAString& aTitle,
+ const nsAString& aMediaString, dom::MediaList*,
+ IsAlternate, IsExplicitlyEnabled);
+
+ // Inserts a style sheet in a document or a ShadowRoot.
+ void InsertSheetInTree(StyleSheet& aSheet);
+ // Inserts a style sheet into a parent style sheet.
+ void InsertChildSheet(StyleSheet& aSheet, StyleSheet& aParentSheet);
+
+ Result<RefPtr<StyleSheet>, nsresult> InternalLoadNonDocumentSheet(
+ nsIURI* aURL, StylePreloadKind, SheetParsingMode aParsingMode,
+ UseSystemPrincipal, const Encoding* aPreloadEncoding,
+ nsIReferrerInfo* aReferrerInfo, nsICSSLoaderObserver* aObserver,
+ CORSMode aCORSMode, const nsAString& aNonce, const nsAString& aIntegrity,
+ uint64_t aEarlyHintPreloaderId, dom::FetchPriority aFetchPriority);
+
+ RefPtr<StyleSheet> LookupInlineSheetInCache(const nsAString&, nsIPrincipal*);
+
+ // Synchronously notify of a cached load data.
+ void NotifyOfCachedLoad(RefPtr<SheetLoadData>);
+
+ // Start the loads of all the sheets in mPendingDatas
+ void StartDeferredLoads();
+
+ // Note: LoadSheet is responsible for setting the sheet to complete on
+ // failure.
+ nsresult LoadSheet(SheetLoadData&, SheetState, uint64_t aEarlyHintPreloaderId,
+ PendingLoad = PendingLoad::No);
+
+ enum class AllowAsyncParse {
+ Yes,
+ No,
+ };
+
+ // Parse the stylesheet in the load data.
+ //
+ // Returns whether the parse finished. It may not finish e.g. if the sheet had
+ // an @import.
+ //
+ // If this function returns Completed::Yes, then ParseSheet also called
+ // SheetComplete on aLoadData.
+ Completed ParseSheet(const nsACString&, SheetLoadData&, AllowAsyncParse);
+
+ // The load of the sheet in the load data is done, one way or another.
+ // Do final cleanup.
+ void SheetComplete(SheetLoadData&, nsresult);
+
+ // Notify observers on an individual data. This is different from
+ // SheetComplete for loads that are shared.
+ void NotifyObservers(SheetLoadData&, nsresult);
+
+ // Mark the given SheetLoadData, as well as any of its siblings, parents, etc
+ // transitively, as failed. The idea is to mark as failed any load that was
+ // directly or indirectly @importing the sheet this SheetLoadData represents.
+ //
+ // if aOnlyForLoader is non-null, then only loads for a given loader will be
+ // marked as failing. This is useful to only cancel loads associated to a
+ // given loader, in case they were marked as canceled.
+ static void MarkLoadTreeFailed(SheetLoadData&,
+ Loader* aOnlyForLoader = nullptr);
+
+ // A shorthand to mark a possible link preload as used to supress "unused"
+ // warning in the console.
+ void MaybeNotifyPreloadUsed(SheetLoadData&);
+
+ nsRefPtrHashtable<nsStringHashKey, StyleSheet> mInlineSheets;
+
+ // A set with all the different loads we've done in a given document, for the
+ // purpose of not posting duplicate performance entries for them.
+ nsTHashtable<const SheetLoadDataHashKey> mLoadsPerformed;
+
+ RefPtr<SharedStyleSheetCache> mSheets;
+
+ // Our array of "global" observers
+ nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver>> mObservers;
+
+ // This reference is nulled by the Document in it's destructor through
+ // DropDocumentReference().
+ dom::Document* MOZ_NON_OWNING_REF mDocument; // the document we live for
+
+ // For dispatching events via DocGroup::Dispatch() when mDocument is nullptr.
+ RefPtr<dom::DocGroup> mDocGroup;
+
+ nsCompatibility mDocumentCompatMode;
+
+ nsCOMPtr<nsIConsoleReportCollector> mReporter;
+
+ // Number of datas for asynchronous sheet loads still waiting to be notified.
+ // This includes pending stylesheets whose load hasn't started yet but which
+ // we need to, but not inline or constructable stylesheets, though the
+ // constructable stylesheets bit may change, see bug 1642227.
+ uint32_t mOngoingLoadCount = 0;
+
+ // The number of sheets that have been deferred / are in a pending state.
+ uint32_t mPendingLoadCount = 0;
+
+ // The number of stylesheets that we have parsed, for testing purposes.
+ uint32_t mParsedSheetCount = 0;
+
+ bool mEnabled = true;
+
+ // Whether we had a document at the point of creation.
+ bool mIsDocumentAssociated = false;
+
+#ifdef DEBUG
+ // Whether we're in a necko callback atm.
+ bool mSyncCallback = false;
+#endif
+};
+
+} // namespace css
+} // namespace mozilla
+
+#endif /* mozilla_css_Loader_h */