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