1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/Loader.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,527 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* loading of CSS style sheets using the network APIs */ 1.10 + 1.11 +#ifndef mozilla_css_Loader_h 1.12 +#define mozilla_css_Loader_h 1.13 + 1.14 +#include "nsIPrincipal.h" 1.15 +#include "nsAString.h" 1.16 +#include "nsAutoPtr.h" 1.17 +#include "nsCompatibility.h" 1.18 +#include "nsDataHashtable.h" 1.19 +#include "nsInterfaceHashtable.h" 1.20 +#include "nsRefPtrHashtable.h" 1.21 +#include "nsTArray.h" 1.22 +#include "nsTObserverArray.h" 1.23 +#include "nsURIHashKey.h" 1.24 +#include "mozilla/Attributes.h" 1.25 +#include "mozilla/CORSMode.h" 1.26 +#include "mozilla/MemoryReporting.h" 1.27 + 1.28 +class nsIAtom; 1.29 +class nsICSSLoaderObserver; 1.30 +class nsCSSStyleSheet; 1.31 +class nsIContent; 1.32 +class nsIDocument; 1.33 +class nsCSSParser; 1.34 +class nsMediaList; 1.35 +class nsIStyleSheetLinkingElement; 1.36 +class nsCycleCollectionTraversalCallback; 1.37 + 1.38 +namespace mozilla { 1.39 +namespace dom { 1.40 +class Element; 1.41 +} 1.42 +} 1.43 + 1.44 +namespace mozilla { 1.45 + 1.46 +class URIPrincipalAndCORSModeHashKey : public nsURIHashKey 1.47 +{ 1.48 +public: 1.49 + typedef URIPrincipalAndCORSModeHashKey* KeyType; 1.50 + typedef const URIPrincipalAndCORSModeHashKey* KeyTypePointer; 1.51 + 1.52 + URIPrincipalAndCORSModeHashKey(const URIPrincipalAndCORSModeHashKey* aKey) 1.53 + : nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal), 1.54 + mCORSMode(aKey->mCORSMode) 1.55 + { 1.56 + MOZ_COUNT_CTOR(URIPrincipalAndCORSModeHashKey); 1.57 + } 1.58 + URIPrincipalAndCORSModeHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal, 1.59 + CORSMode aCORSMode) 1.60 + : nsURIHashKey(aURI), mPrincipal(aPrincipal), mCORSMode(aCORSMode) 1.61 + { 1.62 + MOZ_COUNT_CTOR(URIPrincipalAndCORSModeHashKey); 1.63 + } 1.64 + URIPrincipalAndCORSModeHashKey(const URIPrincipalAndCORSModeHashKey& toCopy) 1.65 + : nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal), 1.66 + mCORSMode(toCopy.mCORSMode) 1.67 + { 1.68 + MOZ_COUNT_CTOR(URIPrincipalAndCORSModeHashKey); 1.69 + } 1.70 + ~URIPrincipalAndCORSModeHashKey() 1.71 + { 1.72 + MOZ_COUNT_DTOR(URIPrincipalAndCORSModeHashKey); 1.73 + } 1.74 + 1.75 + URIPrincipalAndCORSModeHashKey* GetKey() const { 1.76 + return const_cast<URIPrincipalAndCORSModeHashKey*>(this); 1.77 + } 1.78 + const URIPrincipalAndCORSModeHashKey* GetKeyPointer() const { return this; } 1.79 + 1.80 + bool KeyEquals(const URIPrincipalAndCORSModeHashKey* aKey) const { 1.81 + if (!nsURIHashKey::KeyEquals(aKey->mKey)) { 1.82 + return false; 1.83 + } 1.84 + 1.85 + if (!mPrincipal != !aKey->mPrincipal) { 1.86 + // One or the other has a principal, but not both... not equal 1.87 + return false; 1.88 + } 1.89 + 1.90 + if (mCORSMode != aKey->mCORSMode) { 1.91 + // Different CORS modes; we don't match 1.92 + return false; 1.93 + } 1.94 + 1.95 + bool eq; 1.96 + return !mPrincipal || 1.97 + (NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq); 1.98 + } 1.99 + 1.100 + static const URIPrincipalAndCORSModeHashKey* 1.101 + KeyToPointer(URIPrincipalAndCORSModeHashKey* aKey) { return aKey; } 1.102 + static PLDHashNumber HashKey(const URIPrincipalAndCORSModeHashKey* aKey) { 1.103 + return nsURIHashKey::HashKey(aKey->mKey); 1.104 + } 1.105 + 1.106 + nsIURI* GetURI() const { return nsURIHashKey::GetKey(); } 1.107 + 1.108 + enum { ALLOW_MEMMOVE = true }; 1.109 + 1.110 +protected: 1.111 + nsCOMPtr<nsIPrincipal> mPrincipal; 1.112 + CORSMode mCORSMode; 1.113 +}; 1.114 + 1.115 + 1.116 + 1.117 +namespace css { 1.118 + 1.119 +class SheetLoadData; 1.120 +class ImportRule; 1.121 + 1.122 +/*********************************************************************** 1.123 + * Enum that describes the state of the sheet returned by CreateSheet. * 1.124 + ***********************************************************************/ 1.125 +enum StyleSheetState { 1.126 + eSheetStateUnknown = 0, 1.127 + eSheetNeedsParser, 1.128 + eSheetPending, 1.129 + eSheetLoading, 1.130 + eSheetComplete 1.131 +}; 1.132 + 1.133 +class Loader MOZ_FINAL { 1.134 +public: 1.135 + Loader(); 1.136 + Loader(nsIDocument*); 1.137 + 1.138 + private: 1.139 + // Private destructor, to discourage deletion outside of Release(): 1.140 + ~Loader(); 1.141 + 1.142 + public: 1.143 + NS_INLINE_DECL_REFCOUNTING(Loader) 1.144 + 1.145 + void DropDocumentReference(); // notification that doc is going away 1.146 + 1.147 + void SetCompatibilityMode(nsCompatibility aCompatMode) 1.148 + { mCompatMode = aCompatMode; } 1.149 + nsCompatibility GetCompatibilityMode() { return mCompatMode; } 1.150 + nsresult SetPreferredSheet(const nsAString& aTitle); 1.151 + 1.152 + // XXXbz sort out what the deal is with events! When should they fire? 1.153 + 1.154 + /** 1.155 + * Load an inline style sheet. If a successful result is returned and 1.156 + * *aCompleted is false, then aObserver is guaranteed to be notified 1.157 + * asynchronously once the sheet is marked complete. If an error is 1.158 + * returned, or if *aCompleted is true, aObserver will not be notified. In 1.159 + * addition to parsing the sheet, this method will insert it into the 1.160 + * stylesheet list of this CSSLoader's document. 1.161 + * 1.162 + * @param aElement the element linking to the stylesheet. This must not be 1.163 + * null and must implement nsIStyleSheetLinkingElement. 1.164 + * @param aBuffer the stylesheet data 1.165 + * @param aLineNumber the line number at which the stylesheet data started. 1.166 + * @param aTitle the title of the sheet. 1.167 + * @param aMedia the media string for the sheet. 1.168 + * @param aObserver the observer to notify when the load completes. 1.169 + * May be null. 1.170 + * @param [out] aCompleted whether parsing of the sheet completed. 1.171 + * @param [out] aIsAlternate whether the stylesheet ended up being an 1.172 + * alternate sheet. 1.173 + */ 1.174 + nsresult LoadInlineStyle(nsIContent* aElement, 1.175 + const nsAString& aBuffer, 1.176 + uint32_t aLineNumber, 1.177 + const nsAString& aTitle, 1.178 + const nsAString& aMedia, 1.179 + mozilla::dom::Element* aScopeElement, 1.180 + nsICSSLoaderObserver* aObserver, 1.181 + bool* aCompleted, 1.182 + bool* aIsAlternate); 1.183 + 1.184 + /** 1.185 + * Load a linked (document) stylesheet. If a successful result is returned, 1.186 + * aObserver is guaranteed to be notified asynchronously once the sheet is 1.187 + * loaded and marked complete. If an error is returned, aObserver will not 1.188 + * be notified. In addition to loading the sheet, this method will insert it 1.189 + * into the stylesheet list of this CSSLoader's document. 1.190 + * 1.191 + * @param aElement the element linking to the the stylesheet. May be null. 1.192 + * @param aURL the URL of the sheet. 1.193 + * @param aTitle the title of the sheet. 1.194 + * @param aMedia the media string for the sheet. 1.195 + * @param aHasAlternateRel whether the rel for this link included 1.196 + * "alternate". 1.197 + * @param aCORSMode the CORS mode for this load. 1.198 + * @param aObserver the observer to notify when the load completes. 1.199 + * May be null. 1.200 + * @param [out] aIsAlternate whether the stylesheet actually ended up beinga 1.201 + * an alternate sheet. Note that this need not match 1.202 + * aHasAlternateRel. 1.203 + */ 1.204 + nsresult LoadStyleLink(nsIContent* aElement, 1.205 + nsIURI* aURL, 1.206 + const nsAString& aTitle, 1.207 + const nsAString& aMedia, 1.208 + bool aHasAlternateRel, 1.209 + CORSMode aCORSMode, 1.210 + nsICSSLoaderObserver* aObserver, 1.211 + bool* aIsAlternate); 1.212 + 1.213 + /** 1.214 + * Load a child (@import-ed) style sheet. In addition to loading the sheet, 1.215 + * this method will insert it into the child sheet list of aParentSheet. If 1.216 + * there is no sheet currently being parsed and the child sheet is not 1.217 + * complete when this method returns, then when the child sheet becomes 1.218 + * complete aParentSheet will be QIed to nsICSSLoaderObserver and 1.219 + * asynchronously notified, just like for LoadStyleLink. Note that if the 1.220 + * child sheet is already complete when this method returns, no 1.221 + * nsICSSLoaderObserver notification will be sent. 1.222 + * 1.223 + * @param aParentSheet the parent of this child sheet 1.224 + * @param aURL the URL of the child sheet 1.225 + * @param aMedia the already-parsed media list for the child sheet 1.226 + * @param aRule the @import rule importing this child. This is used to 1.227 + * properly order the child sheet list of aParentSheet. 1.228 + */ 1.229 + nsresult LoadChildSheet(nsCSSStyleSheet* aParentSheet, 1.230 + nsIURI* aURL, 1.231 + nsMediaList* aMedia, 1.232 + ImportRule* aRule); 1.233 + 1.234 + /** 1.235 + * Synchronously load and return the stylesheet at aURL. Any child sheets 1.236 + * will also be loaded synchronously. Note that synchronous loads over some 1.237 + * protocols may involve spinning up a new event loop, so use of this method 1.238 + * does NOT guarantee not receiving any events before the sheet loads. This 1.239 + * method can be used to load sheets not associated with a document. 1.240 + * 1.241 + * @param aURL the URL of the sheet to load 1.242 + * @param aEnableUnsafeRules whether unsafe rules are enabled for this 1.243 + * sheet load 1.244 + * Unsafe rules are rules that can violate key Gecko invariants if misused. 1.245 + * In particular, most anonymous box pseudoelements must be very carefully 1.246 + * styled or we will have severe problems. Therefore unsafe rules should 1.247 + * never be enabled for stylesheets controlled by untrusted sites; preferably 1.248 + * unsafe rules should only be enabled for agent sheets. 1.249 + * @param aUseSystemPrincipal if true, give the resulting sheet the system 1.250 + * principal no matter where it's being loaded from. 1.251 + * @param [out] aSheet the loaded, complete sheet. 1.252 + * 1.253 + * NOTE: At the moment, this method assumes the sheet will be UTF-8, but 1.254 + * ideally it would allow arbitrary encodings. Callers should NOT depend on 1.255 + * non-UTF8 sheets being treated as UTF-8 by this method. 1.256 + * 1.257 + * NOTE: A successful return from this method doesn't indicate anything about 1.258 + * whether the data could be parsed as CSS and doesn't indicate anything 1.259 + * about the status of child sheets of the returned sheet. 1.260 + */ 1.261 + nsresult LoadSheetSync(nsIURI* aURL, bool aEnableUnsafeRules, 1.262 + bool aUseSystemPrincipal, 1.263 + nsCSSStyleSheet** aSheet); 1.264 + 1.265 + /** 1.266 + * As above, but aUseSystemPrincipal and aEnableUnsafeRules are assumed false. 1.267 + */ 1.268 + nsresult LoadSheetSync(nsIURI* aURL, nsCSSStyleSheet** aSheet) { 1.269 + return LoadSheetSync(aURL, false, false, aSheet); 1.270 + } 1.271 + 1.272 + /** 1.273 + * Asynchronously load the stylesheet at aURL. If a successful result is 1.274 + * returned, aObserver is guaranteed to be notified asynchronously once the 1.275 + * sheet is loaded and marked complete. This method can be used to load 1.276 + * sheets not associated with a document. 1.277 + * 1.278 + * @param aURL the URL of the sheet to load 1.279 + * @param aOriginPrincipal the principal to use for security checks. This 1.280 + * can be null to indicate that these checks should 1.281 + * be skipped. 1.282 + * @param aCharset the encoding to use for converting the sheet data 1.283 + * from bytes to Unicode. May be empty to indicate that the 1.284 + * charset of the CSSLoader's document should be used. This 1.285 + * is only used if neither the network transport nor the 1.286 + * sheet itself indicate an encoding. 1.287 + * @param aObserver the observer to notify when the load completes. 1.288 + * Must not be null. 1.289 + * @param [out] aSheet the sheet to load. Note that the sheet may well 1.290 + * not be loaded by the time this method returns. 1.291 + */ 1.292 + nsresult LoadSheet(nsIURI* aURL, 1.293 + nsIPrincipal* aOriginPrincipal, 1.294 + const nsCString& aCharset, 1.295 + nsICSSLoaderObserver* aObserver, 1.296 + nsCSSStyleSheet** aSheet); 1.297 + 1.298 + /** 1.299 + * Same as above, to be used when the caller doesn't care about the 1.300 + * not-yet-loaded sheet. 1.301 + */ 1.302 + nsresult LoadSheet(nsIURI* aURL, 1.303 + nsIPrincipal* aOriginPrincipal, 1.304 + const nsCString& aCharset, 1.305 + nsICSSLoaderObserver* aObserver, 1.306 + CORSMode aCORSMode = CORS_NONE); 1.307 + 1.308 + /** 1.309 + * Stop loading all sheets. All nsICSSLoaderObservers involved will be 1.310 + * notified with NS_BINDING_ABORTED as the status, possibly synchronously. 1.311 + */ 1.312 + nsresult Stop(void); 1.313 + 1.314 + /** 1.315 + * nsresult Loader::StopLoadingSheet(nsIURI* aURL), which notifies the 1.316 + * nsICSSLoaderObserver with NS_BINDING_ABORTED, was removed in Bug 556446. 1.317 + * It can be found in revision 2c44a32052ad. 1.318 + */ 1.319 + 1.320 + /** 1.321 + * Whether the loader is enabled or not. 1.322 + * When disabled, processing of new styles is disabled and an attempt 1.323 + * to do so will fail with a return code of 1.324 + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable 1.325 + * currently loading styles or already processed styles. 1.326 + */ 1.327 + bool GetEnabled() { return mEnabled; } 1.328 + void SetEnabled(bool aEnabled) { mEnabled = aEnabled; } 1.329 + 1.330 + /** 1.331 + * Get the document we live for. May return null. 1.332 + */ 1.333 + nsIDocument* GetDocument() const { return mDocument; } 1.334 + 1.335 + /** 1.336 + * Return true if this loader has pending loads (ones that would send 1.337 + * notifications to an nsICSSLoaderObserver attached to this loader). 1.338 + * If called from inside nsICSSLoaderObserver::StyleSheetLoaded, this will 1.339 + * return false if and only if that is the last StyleSheetLoaded 1.340 + * notification the CSSLoader knows it's going to send. In other words, if 1.341 + * two sheets load at once (via load coalescing, e.g.), HasPendingLoads() 1.342 + * will return true during notification for the first one, and false 1.343 + * during notification for the second one. 1.344 + */ 1.345 + bool HasPendingLoads(); 1.346 + 1.347 + /** 1.348 + * Add an observer to this loader. The observer will be notified 1.349 + * for all loads that would have notified their own observers (even 1.350 + * if those loads don't have observers attached to them). 1.351 + * Load-specific observers will be notified before generic 1.352 + * observers. The loader holds a reference to the observer. 1.353 + * 1.354 + * aObserver must not be null. 1.355 + */ 1.356 + nsresult AddObserver(nsICSSLoaderObserver* aObserver); 1.357 + 1.358 + /** 1.359 + * Remove an observer added via AddObserver. 1.360 + */ 1.361 + void RemoveObserver(nsICSSLoaderObserver* aObserver); 1.362 + 1.363 + // These interfaces are public only for the benefit of static functions 1.364 + // within nsCSSLoader.cpp. 1.365 + 1.366 + // IsAlternate can change our currently selected style set if none 1.367 + // is selected and aHasAlternateRel is false. 1.368 + bool IsAlternate(const nsAString& aTitle, bool aHasAlternateRel); 1.369 + 1.370 + typedef nsTArray<nsRefPtr<SheetLoadData> > LoadDataArray; 1.371 + 1.372 + // Traverse the cached stylesheets we're holding on to. This should 1.373 + // only be called from the document that owns this loader. 1.374 + void TraverseCachedSheets(nsCycleCollectionTraversalCallback& cb); 1.375 + 1.376 + // Unlink the cached stylesheets we're holding on to. Again, this 1.377 + // should only be called from the document that owns this loader. 1.378 + void UnlinkCachedSheets(); 1.379 + 1.380 + // Measure our size. 1.381 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 1.382 + 1.383 + // Marks all the sheets at the given URI obsolete, and removes them from the 1.384 + // cache. 1.385 + nsresult ObsoleteSheet(nsIURI* aURI); 1.386 + 1.387 +private: 1.388 + friend class SheetLoadData; 1.389 + 1.390 + static PLDHashOperator 1.391 + RemoveEntriesWithURI(URIPrincipalAndCORSModeHashKey* aKey, 1.392 + nsRefPtr<nsCSSStyleSheet> &aSheet, 1.393 + void* aUserData); 1.394 + 1.395 + // Note: null aSourcePrincipal indicates that the content policy and 1.396 + // CheckLoadURI checks should be skipped. 1.397 + nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, 1.398 + nsIURI* aTargetURI, 1.399 + nsISupports* aContext); 1.400 + 1.401 + 1.402 + // For inline style, the aURI param is null, but the aLinkingContent 1.403 + // must be non-null then. The loader principal must never be null 1.404 + // if aURI is not null. 1.405 + // *aIsAlternate is set based on aTitle and aHasAlternateRel. 1.406 + nsresult CreateSheet(nsIURI* aURI, 1.407 + nsIContent* aLinkingContent, 1.408 + nsIPrincipal* aLoaderPrincipal, 1.409 + CORSMode aCORSMode, 1.410 + bool aSyncLoad, 1.411 + bool aHasAlternateRel, 1.412 + const nsAString& aTitle, 1.413 + StyleSheetState& aSheetState, 1.414 + bool *aIsAlternate, 1.415 + nsCSSStyleSheet** aSheet); 1.416 + 1.417 + // Pass in either a media string or the nsMediaList from the 1.418 + // CSSParser. Don't pass both. 1.419 + // This method will set the sheet's enabled state based on isAlternate 1.420 + void PrepareSheet(nsCSSStyleSheet* aSheet, 1.421 + const nsAString& aTitle, 1.422 + const nsAString& aMediaString, 1.423 + nsMediaList* aMediaList, 1.424 + dom::Element* aScopeElement, 1.425 + bool isAlternate); 1.426 + 1.427 + nsresult InsertSheetInDoc(nsCSSStyleSheet* aSheet, 1.428 + nsIContent* aLinkingContent, 1.429 + nsIDocument* aDocument); 1.430 + 1.431 + nsresult InsertChildSheet(nsCSSStyleSheet* aSheet, 1.432 + nsCSSStyleSheet* aParentSheet, 1.433 + ImportRule* aParentRule); 1.434 + 1.435 + nsresult InternalLoadNonDocumentSheet(nsIURI* aURL, 1.436 + bool aAllowUnsafeRules, 1.437 + bool aUseSystemPrincipal, 1.438 + nsIPrincipal* aOriginPrincipal, 1.439 + const nsCString& aCharset, 1.440 + nsCSSStyleSheet** aSheet, 1.441 + nsICSSLoaderObserver* aObserver, 1.442 + CORSMode aCORSMode = CORS_NONE); 1.443 + 1.444 + // Post a load event for aObserver to be notified about aSheet. The 1.445 + // notification will be sent with status NS_OK unless the load event is 1.446 + // canceled at some point (in which case it will be sent with 1.447 + // NS_BINDING_ABORTED). aWasAlternate indicates the state when the load was 1.448 + // initiated, not the state at some later time. aURI should be the URI the 1.449 + // sheet was loaded from (may be null for inline sheets). aElement is the 1.450 + // owning element for this sheet. 1.451 + nsresult PostLoadEvent(nsIURI* aURI, 1.452 + nsCSSStyleSheet* aSheet, 1.453 + nsICSSLoaderObserver* aObserver, 1.454 + bool aWasAlternate, 1.455 + nsIStyleSheetLinkingElement* aElement); 1.456 + 1.457 + // Start the loads of all the sheets in mPendingDatas 1.458 + void StartAlternateLoads(); 1.459 + 1.460 + // Handle an event posted by PostLoadEvent 1.461 + void HandleLoadEvent(SheetLoadData* aEvent); 1.462 + 1.463 + // Note: LoadSheet is responsible for releasing aLoadData and setting the 1.464 + // sheet to complete on failure. 1.465 + nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState); 1.466 + 1.467 + // Parse the stylesheet in aLoadData. The sheet data comes from aInput. 1.468 + // Set aCompleted to true if the parse finished, false otherwise (e.g. if the 1.469 + // sheet had an @import). If aCompleted is true when this returns, then 1.470 + // ParseSheet also called SheetComplete on aLoadData. 1.471 + nsresult ParseSheet(const nsAString& aInput, 1.472 + SheetLoadData* aLoadData, 1.473 + bool& aCompleted); 1.474 + 1.475 + // The load of the sheet in aLoadData is done, one way or another. Do final 1.476 + // cleanup, including releasing aLoadData. 1.477 + void SheetComplete(SheetLoadData* aLoadData, nsresult aStatus); 1.478 + 1.479 + // The guts of SheetComplete. This may be called recursively on parent datas 1.480 + // or datas that had glommed on to a single load. The array is there so load 1.481 + // datas whose observers need to be notified can be added to it. 1.482 + void DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus, 1.483 + LoadDataArray& aDatasToNotify); 1.484 + 1.485 + struct Sheets { 1.486 + nsRefPtrHashtable<URIPrincipalAndCORSModeHashKey, nsCSSStyleSheet> 1.487 + mCompleteSheets; 1.488 + nsDataHashtable<URIPrincipalAndCORSModeHashKey, SheetLoadData*> 1.489 + mLoadingDatas; // weak refs 1.490 + nsDataHashtable<URIPrincipalAndCORSModeHashKey, SheetLoadData*> 1.491 + mPendingDatas; // weak refs 1.492 + }; 1.493 + nsAutoPtr<Sheets> mSheets; 1.494 + 1.495 + // We're not likely to have many levels of @import... But likely to have 1.496 + // some. Allocate some storage, what the hell. 1.497 + nsAutoTArray<SheetLoadData*, 8> mParsingDatas; 1.498 + 1.499 + // The array of posted stylesheet loaded events (SheetLoadDatas) we have. 1.500 + // Note that these are rare. 1.501 + LoadDataArray mPostedEvents; 1.502 + 1.503 + // Our array of "global" observers 1.504 + // XXXbz these are strong refs; should we be cycle collecting CSS loaders? 1.505 + nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver> > mObservers; 1.506 + 1.507 + // the load data needs access to the document... 1.508 + nsIDocument* mDocument; // the document we live for 1.509 + 1.510 + 1.511 + // Number of datas still waiting to be notified on if we're notifying on a 1.512 + // whole bunch at once (e.g. in one of the stop methods). This is used to 1.513 + // make sure that HasPendingLoads() won't return false until we're notifying 1.514 + // on the last data we're working with. 1.515 + uint32_t mDatasToNotifyOn; 1.516 + 1.517 + nsCompatibility mCompatMode; 1.518 + nsString mPreferredSheet; // title of preferred sheet 1.519 + 1.520 + bool mEnabled; // is enabled to load new styles 1.521 + 1.522 +#ifdef DEBUG 1.523 + bool mSyncCallback; 1.524 +#endif 1.525 +}; 1.526 + 1.527 +} // namespace css 1.528 +} // namespace mozilla 1.529 + 1.530 +#endif /* mozilla_css_Loader_h */