Bug 1879449 [wpt PR 44489] - [wptrunner] Add `infrastructure/expected-fail/` test...
[gecko.git] / layout / style / SheetLoadData.h
blob6621af35bdfb704592ed46a46e8aef8f7e550df9
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/. */
7 #ifndef mozilla_css_SheetLoadData_h
8 #define mozilla_css_SheetLoadData_h
10 #include "mozilla/css/Loader.h"
11 #include "mozilla/css/SheetParsingMode.h"
12 #include "mozilla/Encoding.h"
13 #include "mozilla/PreloaderBase.h"
14 #include "mozilla/SharedSubResourceCache.h"
15 #include "mozilla/NotNull.h"
16 #include "nsProxyRelease.h"
18 namespace mozilla {
19 namespace dom {
20 enum class FetchPriority : uint8_t;
21 } // namespace dom
22 class AsyncEventDispatcher;
23 class StyleSheet;
24 } // namespace mozilla
25 class nsICSSLoaderObserver;
26 class nsINode;
27 class nsIPrincipal;
28 class nsIURI;
29 class nsIReferrerInfo;
31 namespace mozilla::css {
33 /*********************************************
34 * Data needed to properly load a stylesheet *
35 *********************************************/
37 static_assert(eAuthorSheetFeatures == 0 && eUserSheetFeatures == 1 &&
38 eAgentSheetFeatures == 2,
39 "sheet parsing mode constants won't fit "
40 "in SheetLoadData::mParsingMode");
42 enum class SyncLoad : bool { No, Yes };
44 class SheetLoadData final
45 : public PreloaderBase,
46 public SharedSubResourceCacheLoadingValueBase<SheetLoadData> {
47 using MediaMatched = dom::LinkStyle::MediaMatched;
48 using IsAlternate = dom::LinkStyle::IsAlternate;
49 using UseSystemPrincipal = css::Loader::UseSystemPrincipal;
51 protected:
52 virtual ~SheetLoadData();
54 public:
55 static void PrioritizeAsPreload(nsIChannel* aChannel);
57 // If this is a deferred load, start it now.
58 void StartPendingLoad();
60 // Data for loading a sheet linked from a document
61 SheetLoadData(css::Loader*, const nsAString& aTitle, nsIURI*, StyleSheet*,
62 SyncLoad, nsINode* aOwningNode, IsAlternate, MediaMatched,
63 StylePreloadKind, nsICSSLoaderObserver* aObserver,
64 nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo*,
65 const nsAString& aNonce, dom::FetchPriority aFetchPriority);
67 // Data for loading a sheet linked from an @import rule
68 SheetLoadData(css::Loader*, nsIURI*, StyleSheet*, SheetLoadData* aParentData,
69 nsICSSLoaderObserver* aObserver,
70 nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo*);
72 // Data for loading a non-document sheet
73 SheetLoadData(css::Loader*, nsIURI*, StyleSheet*, SyncLoad,
74 UseSystemPrincipal, StylePreloadKind,
75 const Encoding* aPreloadEncoding,
76 nsICSSLoaderObserver* aObserver,
77 nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo*,
78 const nsAString& aNonce, dom::FetchPriority aFetchPriority);
80 nsIReferrerInfo* ReferrerInfo() const { return mReferrerInfo; }
82 const nsString& Nonce() const { return mNonce; }
84 already_AddRefed<AsyncEventDispatcher> PrepareLoadEventIfNeeded();
86 NotNull<const Encoding*> DetermineNonBOMEncoding(const nsACString& aSegment,
87 nsIChannel*) const;
89 // The caller may have the bytes for the stylesheet split across two strings,
90 // so aBytes1 and aBytes2 refer to those pieces.
91 nsresult VerifySheetReadyToParse(nsresult aStatus, const nsACString& aBytes1,
92 const nsACString& aBytes2,
93 nsIChannel* aChannel,
94 nsIURI* aFinalChannelURI,
95 nsIPrincipal* aPrincipal);
97 NS_DECL_ISUPPORTS
99 css::Loader& Loader() { return *mLoader; }
101 void DidCancelLoad() { mIsCancelled = true; }
103 // Hold a ref to the CSSLoader so we can call back to it to let it
104 // know the load finished
105 const RefPtr<css::Loader> mLoader;
107 // Title needed to pull datas out of the pending datas table when
108 // the preferred title is changed
109 const nsString mTitle;
111 // The encoding we decided to use for the sheet
112 const Encoding* mEncoding;
114 // URI we're loading. Null for inline or constructable sheets.
115 nsCOMPtr<nsIURI> mURI;
117 // The sheet we're loading data for
118 const RefPtr<StyleSheet> mSheet;
120 // Load data for the sheet that @import-ed us if we were @import-ed
121 // during the parse
122 const RefPtr<SheetLoadData> mParentData;
124 // The expiration time of the channel that has loaded this data, if
125 // applicable.
126 uint32_t mExpirationTime = 0;
128 // Number of sheets we @import-ed that are still loading
129 uint32_t mPendingChildren;
131 // mSyncLoad is true when the load needs to be synchronous.
132 // For LoadSheetSync, <link> to chrome stylesheets in UA Widgets,
133 // and children of sync loads.
134 const bool mSyncLoad : 1;
136 // mIsNonDocumentSheet is true if the load was triggered by LoadSheetSync or
137 // LoadSheet or an @import from such a sheet. Non-document sheet loads can
138 // proceed even if we have no document.
139 const bool mIsNonDocumentSheet : 1;
141 // Whether this stylesheet is for a child sheet load. This is necessary
142 // because the sheet could be detached mid-load by CSSOM.
143 const bool mIsChildSheet : 1;
145 // mIsBeingParsed is true if this stylesheet is currently being parsed.
146 bool mIsBeingParsed : 1;
148 // mIsLoading is set to true when a sheet load is initiated. This field is
149 // also used by the SharedSubResourceCache to avoid having multiple loads for
150 // the same resource.
151 bool mIsLoading : 1;
153 // mIsCancelled is set to true when a sheet load is stopped by
154 // Stop() or StopLoadingSheet() (which was removed in Bug 556446).
155 // SheetLoadData::OnStreamComplete() checks this to avoid parsing
156 // sheets that have been cancelled and such.
157 bool mIsCancelled : 1;
159 // mMustNotify is true if the load data is being loaded async and the original
160 // function call that started the load has returned.
162 // This applies only to observer notifications; load/error events are fired
163 // for any SheetLoadData that has a non-null owner node (though mMustNotify is
164 // used to avoid an event loop round-trip in that case).
165 bool mMustNotify : 1;
167 // Whether we had an owner node at the point of creation. This allows
168 // differentiating between "Link" header stylesheets and LinkStyle-owned
169 // stylesheets.
170 const bool mHadOwnerNode : 1;
172 // mWasAlternate is true if the sheet was an alternate
173 // (https://html.spec.whatwg.org/#rel-alternate) when the load data was
174 // created.
175 const bool mWasAlternate : 1;
177 // mMediaMatched is true if the sheet matched its medialist when the load data
178 // was created.
179 const bool mMediaMatched : 1;
181 // mUseSystemPrincipal is true if the system principal should be used for
182 // this sheet, no matter what the channel principal is. Only true for sync
183 // loads.
184 const bool mUseSystemPrincipal : 1;
186 // If true, this SheetLoadData is being used as a way to handle
187 // async observer notification for an already-complete sheet.
188 bool mSheetAlreadyComplete : 1;
190 // If true, the sheet is being loaded cross-origin without CORS permissions.
191 // This is completely normal and CORS isn't needed for such loads. This
192 // flag is simply useful in determining whether to set mBlockResourceTiming
193 // for a child sheet.
194 bool mIsCrossOriginNoCORS : 1;
196 // If this flag is true, LoadSheet will call SetReportResourceTiming(false)
197 // on the timedChannel. This is to mark resources that are loaded by a
198 // cross-origin stylesheet with a no-cors policy.
199 // https://www.w3.org/TR/resource-timing/#processing-model
200 bool mBlockResourceTiming : 1;
202 // Boolean flag indicating whether the load has failed. This will be set
203 // to true if this load, or the load of any descendant import, fails.
204 bool mLoadFailed : 1;
206 // Whether this is a preload, and which kind of preload it is.
208 // TODO(emilio): This can become a bitfield once we build with a GCC version
209 // that has the fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414,
210 // which causes a false positive warning here.
211 const StylePreloadKind mPreloadKind;
213 nsINode* GetRequestingNode() const;
215 // The observer that wishes to be notified of load completion
216 nsCOMPtr<nsICSSLoaderObserver> mObserver;
218 // The principal that identifies who started loading us.
219 const nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
221 // Referrer info of the load.
222 const nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
224 // The cryptographic nonce of the load used for CSP checks.
225 const nsString mNonce;
227 const dom::FetchPriority mFetchPriority;
229 // The encoding guessed from attributes and the document character set.
230 const NotNull<const Encoding*> mGuessedEncoding;
232 // The quirks mode of the loader at the time the load was triggered.
233 const nsCompatibility mCompatMode;
235 // Whether SheetComplete was called.
236 bool mSheetCompleteCalled = false;
238 // Whether we intentionally are not calling SheetComplete because nobody is
239 // listening for the load.
240 bool mIntentionallyDropped = false;
242 const bool mRecordErrors;
244 bool ShouldDefer() const { return mWasAlternate || !mMediaMatched; }
246 RefPtr<StyleSheet> ValueForCache() const;
247 uint32_t ExpirationTime() const { return mExpirationTime; }
249 // If there are no child sheets outstanding, mark us as complete.
250 // Otherwise, the children are holding strong refs to the data
251 // and will call SheetComplete() on it when they complete.
252 void SheetFinishedParsingAsync() {
253 MOZ_ASSERT(mIsBeingParsed);
254 mIsBeingParsed = false;
255 if (!mPendingChildren) {
256 mLoader->SheetComplete(*this, NS_OK);
260 bool IsPreload() const { return mPreloadKind != StylePreloadKind::None; }
261 bool IsLinkRelPreload() const { return css::IsLinkRelPreload(mPreloadKind); }
263 bool BlocksLoadEvent() const {
264 const auto& root = RootLoadData();
265 return !root.IsLinkRelPreload() && !root.IsSyncLoad();
268 bool IsSyncLoad() const override { return mSyncLoad; }
269 bool IsLoading() const override { return mIsLoading; }
270 bool IsCancelled() const override { return mIsCancelled; }
272 void StartLoading() override { mIsLoading = true; }
273 void SetLoadCompleted() override { mIsLoading = false; }
274 void Cancel() override { mIsCancelled = true; }
276 private:
277 const SheetLoadData& RootLoadData() const {
278 const auto* top = this;
279 while (top->mParentData) {
280 top = top->mParentData;
282 return *top;
286 using SheetLoadDataHolder = nsMainThreadPtrHolder<SheetLoadData>;
288 } // namespace mozilla::css
290 #endif // mozilla_css_SheetLoadData_h