Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Friends
CSSLoaderImpl Class Reference

#include <nsCSSLoader.h>

Inheritance diagram for CSSLoaderImpl:
Inheritance graph
[legend]
Collaboration diagram for CSSLoaderImpl:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 CSSLoaderImpl (void)
virtual ~CSSLoaderImpl (void)
NS_IMETHOD Init (nsIDocument *aDocument)
NS_IMETHOD DropDocumentReference (void)
NS_IMETHOD SetCaseSensitive (PRBool aCaseSensitive)
NS_IMETHOD SetCompatibilityMode (nsCompatibility aCompatMode)
NS_IMETHOD SetPreferredSheet (const nsAString &aTitle)
NS_IMETHOD GetPreferredSheet (nsAString &aTitle)
NS_IMETHOD GetParserFor (nsICSSStyleSheet *aSheet, nsICSSParser **aParser)
NS_IMETHOD RecycleParser (nsICSSParser *aParser)
NS_IMETHOD LoadInlineStyle (nsIContent *aElement, nsIUnicharInputStream *aStream, PRUint32 aLineNumber, const nsSubstring &aTitle, const nsSubstring &aMedia, nsIParser *aParserToUnblock, PRBool &aCompleted, nsICSSLoaderObserver *aObserver)
NS_IMETHOD LoadStyleLink (nsIContent *aElement, nsIURI *aURL, const nsSubstring &aTitle, const nsSubstring &aMedia, nsIParser *aParserToUnblock, PRBool &aCompleted, nsICSSLoaderObserver *aObserver)
NS_IMETHOD LoadChildSheet (nsICSSStyleSheet *aParentSheet, nsIURI *aURL, nsMediaList *aMedia, nsICSSImportRule *aRule)
NS_IMETHOD LoadSheetSync (nsIURI *aURL, PRBool aAllowUnsafeRules, nsICSSStyleSheet **aSheet)
NS_IMETHOD LoadAgentSheet (nsIURI *aURL, nsICSSStyleSheet **aSheet)
NS_IMETHOD LoadAgentSheet (nsIURI *aURL, nsICSSLoaderObserver *aObserver)
NS_IMETHOD Stop (void)
NS_IMETHOD StopLoadingSheet (nsIURI *aURL)
NS_IMETHOD GetEnabled (PRBool *aEnabled)
 Is the loader enabled or not.
NS_IMETHOD SetEnabled (PRBool aEnabled)
PRBool IsAlternate (const nsAString &aTitle)
nsresult LoadSheet (SheetLoadData *aLoadData, StyleSheetState aSheetState)
 LoadSheet handles the actual load of a sheet.
void SheetComplete (SheetLoadData *aLoadData, PRBool aSucceeded)
 SheetComplete is the do-it-all cleanup function.

Static Public Member Functions

static NS_DECL_ISUPPORTS void Shutdown ()

Static Public Attributes

static nsCOMArray< nsICSSParser > * gParsers = nsnull

Protected Member Functions

nsresult ParseSheet (nsIUnicharInputStream *aStream, SheetLoadData *aLoadData, PRBool &aCompleted)
 ParseSheet handles parsing the data stream.

Protected Attributes

nsIDocumentmDocument

Private Member Functions

nsresult CheckLoadAllowed (nsIURI *aSourceURI, nsIURI *aTargetURI, nsISupports *aContext)
 CheckLoadAllowed will return success if the load is allowed, failure otherwise.
nsresult CreateSheet (nsIURI *aURI, nsIContent *aLinkingContent, PRBool aSyncLoad, StyleSheetState &aSheetState, nsICSSStyleSheet **aSheet)
 CreateSheet() creates an nsICSSStyleSheet object for the given URI, if any.
nsresult PrepareSheet (nsICSSStyleSheet *aSheet, const nsSubstring &aTitle, const nsSubstring &aMediaString, nsMediaList *aMediaList)
 PrepareSheet() handles setting the media and title on the sheet, as well as setting the enabled state based on the title.
nsresult InsertSheetInDoc (nsICSSStyleSheet *aSheet, nsIContent *aLinkingContent, nsIDocument *aDocument)
 InsertSheetInDoc handles ordering of sheets in the document.
nsresult InsertChildSheet (nsICSSStyleSheet *aSheet, nsICSSStyleSheet *aParentSheet, nsICSSImportRule *aParentRule)
 InsertChildSheet handles ordering of -ed sheet in their parent sheets.
nsresult InternalLoadAgentSheet (nsIURI *aURL, nsICSSStyleSheet **aSheet, PRBool aAllowUnsafeRules, nsICSSLoaderObserver *aObserver)

Private Attributes

PRPackedBool mCaseSensitive
PRPackedBool mEnabled
nsCompatibility mCompatMode
nsString mPreferredSheet
nsInterfaceHashtable
< nsURIHashKey,
nsICSSStyleSheet
mCompleteSheets
nsDataHashtable< nsURIHashKey,
SheetLoadData * > 
mLoadingDatas
nsDataHashtable< nsURIHashKey,
SheetLoadData * > 
mPendingDatas
nsAutoVoidArray mParsingDatas

Friends

class SheetLoadData

Detailed Description

Definition at line 219 of file nsCSSLoader.h.


Constructor & Destructor Documentation

Definition at line 251 of file nsCSSLoader.cpp.

{
  NS_ASSERTION((!mLoadingDatas.IsInitialized()) || mLoadingDatas.Count() == 0,
               "How did we get destroyed when there are loading data?");
  NS_ASSERTION((!mPendingDatas.IsInitialized()) || mPendingDatas.Count() == 0,
               "How did we get destroyed when there are pending data?");
}

Here is the call graph for this function:


Member Function Documentation

nsresult CSSLoaderImpl::CheckLoadAllowed ( nsIURI aSourceURI,
nsIURI aTargetURI,
nsISupports *  aContext 
) [private]

CheckLoadAllowed will return success if the load is allowed, failure otherwise.

Parameters:
aSourceURIthe uri of the document or parent sheet loading the sheet
aTargetURIthe uri of the sheet to be loaded
aContextthe node owning the sheet. This is the element or document owning the stylesheet (possibly indirectly, for child sheets)

Definition at line 850 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::CheckLoadAllowed"));
  
  // Check with the security manager
  nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
  nsresult rv = secMan->CheckLoadURI(aSourceURI, aTargetURI,
                                     nsIScriptSecurityManager::ALLOW_CHROME);
  if (NS_FAILED(rv)) { // failure is normal here; don't warn
    return rv;
  }

  LOG(("  Passed security check"));

  // Check with content policy

  PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
                                 aTargetURI,
                                 aSourceURI,
                                 aContext,
                                 NS_LITERAL_CSTRING("text/css"),
                                 nsnull,                        //extra param
                                 &shouldLoad);

  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
    LOG(("  Load blocked by content policy"));
    return NS_ERROR_CONTENT_BLOCKED;
  }

  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CSSLoaderImpl::CreateSheet ( nsIURI aURI,
nsIContent aLinkingContent,
PRBool  aSyncLoad,
StyleSheetState aSheetState,
nsICSSStyleSheet **  aSheet 
) [private]

CreateSheet() creates an nsICSSStyleSheet object for the given URI, if any.

If there is no URI given, we just create a new style sheet object. Otherwise, we check for an existing style sheet object for that uri in various caches and clone it if we find it. Cloned sheets will have the title/media/enabled state of the sheet they are clones off; make sure to call PrepareSheet() on the result of CreateSheet().

Definition at line 895 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::CreateSheet"));
  NS_PRECONDITION(aSheet, "Null out param!");

  NS_ENSURE_TRUE((mCompleteSheets.IsInitialized() || mCompleteSheets.Init()) &&
                   (mLoadingDatas.IsInitialized() || mLoadingDatas.Init()) &&
                   (mPendingDatas.IsInitialized() || mPendingDatas.Init()),
                 NS_ERROR_OUT_OF_MEMORY);
  
  nsresult rv = NS_OK;
  *aSheet = nsnull;
  aSheetState = eSheetStateUnknown;
  
  if (aURI) {
    aSheetState = eSheetComplete;
    nsCOMPtr<nsICSSStyleSheet> sheet;

    // First, the XUL cache
#ifdef MOZ_XUL
    if (IsChromeURI(aURI)) {
      nsCOMPtr<nsIXULPrototypeCache> cache(do_GetService("@mozilla.org/xul/xul-prototype-cache;1"));
      if (cache) {
        PRBool enabled;
        cache->GetEnabled(&enabled);
        if (enabled) {
          cache->GetStyleSheet(aURI, getter_AddRefs(sheet));
          LOG(("  From XUL cache: %p", sheet.get()));
        }
      }
    }
#endif

    if (!sheet) {
      // Then complete sheets
      mCompleteSheets.Get(aURI, getter_AddRefs(sheet));
      LOG(("  From completed: %p", sheet.get()));
    
      // Then loading sheets
      if (!sheet && !aSyncLoad) {
        aSheetState = eSheetLoading;
        SheetLoadData* loadData = nsnull;
        mLoadingDatas.Get(aURI, &loadData);
        if (loadData) {
          sheet = loadData->mSheet;
          LOG(("  From loading: %p", sheet.get()));
        }

        // Then alternate sheets
        if (!sheet) {
          aSheetState = eSheetPending;
          SheetLoadData* loadData = nsnull;
          mPendingDatas.Get(aURI, &loadData);
          if (loadData) {
            sheet = loadData->mSheet;
            LOG(("  From pending: %p", sheet.get()));
          }
        }
      }
    }

    if (sheet) {
      // We can use this cached sheet if it's either incomplete or unmodified
      PRBool modified = PR_TRUE;
      sheet->IsModified(&modified);
      PRBool complete = PR_FALSE;
      sheet->GetComplete(complete);
      if (!modified || !complete) {
        // Proceed on failures; at worst we'll try to create one below
        sheet->Clone(nsnull, nsnull, nsnull, nsnull, aSheet);
        NS_ASSERTION(complete || aSheetState != eSheetComplete,
                     "Sheet thinks it's not complete while we think it is");
      }
    }
  }

  if (!*aSheet) {
    aSheetState = eSheetNeedsParser;
    nsIURI *sheetURI;
    nsCOMPtr<nsIURI> baseURI;
    nsIURI* originalURI;
    if (!aURI) {
      // Inline style.  Use the document's base URL so that @import in
      // the inline sheet picks up the right base.
      NS_ASSERTION(aLinkingContent, "Inline stylesheet without linking content?");
      baseURI = aLinkingContent->GetBaseURI();
      sheetURI = aLinkingContent->GetDocument()->GetDocumentURI();
      originalURI = sheetURI;
    } else {
      baseURI = aURI;
      sheetURI = aURI;
      originalURI = aURI;
    }      

    rv = NS_NewCSSStyleSheet(aSheet);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsICSSStyleSheet_MOZILLA_1_8_BRANCH> sheet =
      do_QueryInterface(*aSheet);
    sheet->SetURIs18(sheetURI, originalURI, baseURI);
  }

  NS_ASSERTION(*aSheet, "We should have a sheet by now!");
  NS_ASSERTION(aSheetState != eSheetStateUnknown, "Have to set a state!");
  LOG(("  State: %s", gStateStrings[aSheetState]));
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsICSSLoader.

Definition at line 288 of file nsCSSLoader.cpp.

{
  mDocument = nsnull;
  // Flush out pending datas just so we don't leak by accident.  These
  // loads should short-circuit through the mDocument check in
  // LoadSheet and just end up in SheetComplete immediately
  if (mPendingDatas.IsInitialized())
    mPendingDatas.Enumerate(StartAlternateLoads, this);
  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP CSSLoaderImpl::GetEnabled ( PRBool aEnabled) [virtual]

Is the loader 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.

Implements nsICSSLoader.

Definition at line 1954 of file nsCSSLoader.cpp.

{
  NS_ENSURE_ARG_POINTER(aEnabled);
  *aEnabled = mEnabled;
  return NS_OK;
}
NS_IMETHODIMP CSSLoaderImpl::GetParserFor ( nsICSSStyleSheet aSheet,
nsICSSParser **  aParser 
) [virtual]

Implements nsICSSLoader.

Definition at line 348 of file nsCSSLoader.cpp.

{
  NS_PRECONDITION(aParser, "Null out param");

  *aParser = nsnull;

  if (!gParsers) {
    gParsers = new nsCOMArray<nsICSSParser>;
    if (!gParsers) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }

  PRInt32 count = gParsers->Count();
  if (0 < count--) {
    *aParser = gParsers->ObjectAt(count);
    NS_ADDREF(*aParser);
    gParsers->RemoveObjectAt(count);
  }

  nsresult result = NS_OK;
  if (! *aParser) {
    result = NS_NewCSSParser(aParser);
  }
  
  if (*aParser) {
    (*aParser)->SetCaseSensitive(mCaseSensitive);
    (*aParser)->SetQuirkMode(mCompatMode == eCompatibility_NavQuirks);
    if (aSheet) {
      (*aParser)->SetStyleSheet(aSheet);
    }
    (*aParser)->SetChildLoader(this);
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP CSSLoaderImpl::GetPreferredSheet ( nsAString &  aTitle) [virtual]

Implements nsICSSLoader.

Definition at line 341 of file nsCSSLoader.cpp.

{
  aTitle.Assign(mPreferredSheet);
  return NS_OK;
}
NS_IMETHODIMP CSSLoaderImpl::Init ( nsIDocument aDocument) [virtual]

Implements nsICSSLoader.

Definition at line 269 of file nsCSSLoader.cpp.

{
  NS_ASSERTION(! mDocument, "already initialized");

  if (! mDocument) {
    mDocument = aDocument;
    return NS_OK;
  }
  return NS_ERROR_ALREADY_INITIALIZED;
}

Here is the caller graph for this function:

nsresult CSSLoaderImpl::InsertChildSheet ( nsICSSStyleSheet aSheet,
nsICSSStyleSheet aParentSheet,
nsICSSImportRule aParentRule 
) [private]

InsertChildSheet handles ordering of -ed sheet in their parent sheets.

Here we want to just insert based on order of the rules that imported the sheets. In theory we can't just append to the end because the CSSOM can insert rules. In practice, we get the call to load the child sheet before the CSSOM has finished inserting the rule, so we have no idea where to put it anyway. So just append for now.

Definition at line 1156 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::InsertChildSheet"));
  NS_PRECONDITION(aSheet, "Nothing to insert");
  NS_PRECONDITION(aParentSheet, "Need a parent to insert into");
  NS_PRECONDITION(aParentSheet, "How did we get imported?");

  // child sheets should always start out enabled, even if they got
  // cloned off of top-level sheets which were disabled
  aSheet->SetEnabled(PR_TRUE);
  
  aParentSheet->AppendStyleSheet(aSheet);
  aParentRule->SetSheet(aSheet); // This sets the ownerRule on the sheet

  LOG(("  Inserting into parent sheet"));
  //  LOG(("  Inserting into parent sheet at position %d", insertionPoint));

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CSSLoaderImpl::InsertSheetInDoc ( nsICSSStyleSheet aSheet,
nsIContent aLinkingContent,
nsIDocument aDocument 
) [private]

InsertSheetInDoc handles ordering of sheets in the document.

Here we have two types of sheets -- those with linking elements and those without. The latter are loaded by Link: headers. The following constraints are observed: 1) Any sheet with a linking element comes after all sheets without linking elements 2) Sheets without linking elements are inserted in the order in which the inserting requests come in, since all of these are inserted during header data processing in the content sink 3) Sheets with linking elements are ordered based on document order as determined by CompareDocumentPosition.

Definition at line 1061 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::InsertSheetInDoc"));
  NS_PRECONDITION(aSheet, "Nothing to insert");
  NS_PRECONDITION(aDocument, "Must have a document to insert into");

  // all nodes that link in sheets should be implementing nsIDOM3Node
  nsresult rv = NS_OK;
  nsCOMPtr<nsIDOM3Node> linkingNode = do_QueryInterface(aLinkingContent);
  NS_ASSERTION(linkingNode || !aLinkingContent,
               "Need to implement nsIDOM3Node to get insertion order right");

  // XXX Need to cancel pending sheet loads for this element, if any

  PRInt32 sheetCount = aDocument->GetNumberOfStyleSheets();

  /*
   * Start the walk at the _end_ of the list, since in the typical
   * case we'll just want to append anyway.  We want to break out of
   * the loop when insertionPoint points to just before the index we
   * want to insert at.  In other words, when we leave the loop
   * insertionPoint is the index of the stylesheet that immediately
   * precedes the one we're inserting.
   */
  PRInt32 insertionPoint;
  for (insertionPoint = sheetCount - 1; insertionPoint >= 0; --insertionPoint) {
    nsIStyleSheet *curSheet = aDocument->GetStyleSheetAt(insertionPoint);
    NS_ASSERTION(curSheet, "There must be a sheet here!");
    nsCOMPtr<nsIDOMStyleSheet> domSheet = do_QueryInterface(curSheet);
    NS_ASSERTION(domSheet, "All the \"normal\" sheets implement nsIDOMStyleSheet");
    nsCOMPtr<nsIDOMNode> sheetOwner;
    domSheet->GetOwnerNode(getter_AddRefs(sheetOwner));
    if (sheetOwner && !linkingNode) {
      // Keep moving; all sheets with a sheetOwner come after all
      // sheets without a linkingNode 
      continue;
    }

    if (!sheetOwner) {
      // Aha!  The current sheet has no sheet owner, so we want to
      // insert after it no matter whether we have a linkingNode
      break;
    }

    // Have to compare
    PRUint16 comparisonFlags = 0;
    rv = linkingNode->CompareDocumentPosition(sheetOwner, &comparisonFlags);
    // If we can't get the order right, just bail...
    NS_ENSURE_SUCCESS(rv, rv);
    NS_ASSERTION(!(comparisonFlags & nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED),
                 "Why are these elements in different documents?");
#ifdef DEBUG
    {
      PRBool sameNode = PR_FALSE;
      linkingNode->IsSameNode(sheetOwner, &sameNode);
      NS_ASSERTION(!sameNode, "Why do we still have our old sheet?");
    }
#endif // DEBUG
    if (comparisonFlags & nsIDOM3Node::DOCUMENT_POSITION_PRECEDING) {
      // The current sheet comes before us, and it better be the first
      // such, because now we break
      break;
    }
  }

  ++insertionPoint; // adjust the index to the spot we want to insert in
  
  // XXX <meta> elements do not implement nsIStyleSheetLinkingElement;
  // need to fix this for them to be ordered correctly.
  nsCOMPtr<nsIStyleSheetLinkingElement>
    linkingElement = do_QueryInterface(aLinkingContent);
  if (linkingElement) {
    linkingElement->SetStyleSheet(aSheet); // This sets the ownerNode on the sheet
  }

  aDocument->BeginUpdate(UPDATE_STYLE);
  aDocument->InsertStyleSheetAt(aSheet, insertionPoint);
  aDocument->EndUpdate(UPDATE_STYLE);
  LOG(("  Inserting into document at position %d", insertionPoint));

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CSSLoaderImpl::InternalLoadAgentSheet ( nsIURI aURL,
nsICSSStyleSheet **  aSheet,
PRBool  aAllowUnsafeRules,
nsICSSLoaderObserver aObserver 
) [private]

Definition at line 1820 of file nsCSSLoader.cpp.

{
  NS_PRECONDITION(aURL, "Must have a URI to load");
  NS_PRECONDITION((!aSheet || !aObserver) && (aSheet || aObserver),
                  "One or the other please, at most one");
  NS_ASSERTION(mParsingDatas.Count() == 0, "We're in the middle of a parse?");

  LOG_URI("  Agent uri: '%s'", aURL);
  
  if (!mEnabled) {
    LOG_WARN(("  Not enabled"));
    return NS_ERROR_NOT_AVAILABLE;
  }

  StyleSheetState state;
  nsCOMPtr<nsICSSStyleSheet> sheet;
  PRBool syncLoad = (aObserver == nsnull);
  
  nsresult rv = CreateSheet(aURL, nsnull, syncLoad, state,
                            getter_AddRefs(sheet));
  NS_ENSURE_SUCCESS(rv, rv);

  const nsSubstring& empty = EmptyString();
  rv = PrepareSheet(sheet, empty, empty, nsnull);
  NS_ENSURE_SUCCESS(rv, rv);
  
  if (aSheet) {
    *aSheet = nsnull;
  }
  
  if (state == eSheetComplete) {
    LOG(("  Sheet already complete"));
    if (aSheet) {
      *aSheet = sheet;
      NS_ADDREF(*aSheet);
    } else {
      aObserver->StyleSheetLoaded(sheet, PR_TRUE);
    }
    return NS_OK;
  }

  SheetLoadData* data =
    new SheetLoadData(this, aURL, sheet, syncLoad, aAllowUnsafeRules, aObserver);

  if (!data) {
    sheet->SetComplete();
    return NS_ERROR_OUT_OF_MEMORY;
  }
  
  NS_ADDREF(data);
  rv = LoadSheet(data, state);

  if (NS_SUCCEEDED(rv) && aSheet) {
    *aSheet = sheet;
    NS_ADDREF(*aSheet);
  }

  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool CSSLoaderImpl::IsAlternate ( const nsAString &  aTitle)

Definition at line 832 of file nsCSSLoader.cpp.

{
  if (!aTitle.IsEmpty()) {
    return PRBool(! aTitle.Equals(mPreferredSheet, nsCaseInsensitiveStringComparator()));
  }
  return PR_FALSE;
}

Here is the caller graph for this function:

NS_IMETHODIMP CSSLoaderImpl::LoadAgentSheet ( nsIURI aURL,
nsICSSStyleSheet **  aSheet 
) [virtual]

Implements nsICSSLoader.

Definition at line 1804 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadAgentSheet synchronous"));
  return InternalLoadAgentSheet(aURL, aSheet, PR_FALSE, nsnull);
}

Here is the call graph for this function:

Implements nsICSSLoader.

Definition at line 1812 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadAgentSheet asynchronous"));
  return InternalLoadAgentSheet(aURL, nsnull, PR_FALSE, aObserver);
}

Here is the call graph for this function:

NS_IMETHODIMP CSSLoaderImpl::LoadChildSheet ( nsICSSStyleSheet aParentSheet,
nsIURI aURL,
nsMediaList aMedia,
nsICSSImportRule aRule 
) [virtual]

Implements nsICSSLoader.

Definition at line 1675 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadChildSheet"));
  NS_PRECONDITION(aURL, "Must have a URI to load");

  if (!mEnabled) {
    LOG_WARN(("  Not enabled"));
    return NS_ERROR_NOT_AVAILABLE;
  }
  
  LOG_URI("  Child uri: '%s'", aURL);

  // Check whether we should even load
  nsCOMPtr<nsIURI> sheetURI;
  nsresult rv = aParentSheet->GetSheetURI(getter_AddRefs(sheetURI));
  if (NS_FAILED(rv) || !sheetURI) return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMNode> owningNode;

  // check for an owning document: if none, don't bother walking up the parent
  // sheets
  nsCOMPtr<nsIDocument> owningDoc;
  rv = aParentSheet->GetOwningDocument(*getter_AddRefs(owningDoc));
  if (NS_SUCCEEDED(rv) && owningDoc) {
    nsCOMPtr<nsIDOMStyleSheet> nextParentSheet(do_QueryInterface(aParentSheet));
    NS_ENSURE_TRUE(nextParentSheet, NS_ERROR_FAILURE); //Not a stylesheet!?

    nsCOMPtr<nsIDOMStyleSheet> topSheet;
    //traverse our way to the top-most sheet
    do {
      topSheet.swap(nextParentSheet);
      topSheet->GetParentStyleSheet(getter_AddRefs(nextParentSheet));
    } while (nextParentSheet);

    topSheet->GetOwnerNode(getter_AddRefs(owningNode));
  }

  nsISupports* context = owningNode;
  if (!context) {
    context = mDocument;
  }
  
  rv = CheckLoadAllowed(sheetURI, aURL, context);
  if (NS_FAILED(rv)) return rv;

  LOG(("  Passed load check"));
  
  SheetLoadData* parentData = nsnull;
  nsCOMPtr<nsICSSLoaderObserver> observer;

  PRInt32 count = mParsingDatas.Count();
  if (count > 0) {
    LOG(("  Have a parent load"));
    parentData = NS_STATIC_CAST(SheetLoadData*,
                                mParsingDatas.ElementAt(count - 1));
    // Check for cycles
    SheetLoadData* data = parentData;
    while (data && data->mURI) {
      PRBool equal;
      if (NS_SUCCEEDED(data->mURI->Equals(aURL, &equal)) && equal) {
        // Houston, we have a loop, blow off this child and pretend this never
        // happened
        LOG_ERROR(("  @import cycle detected, dropping load"));
        return NS_OK;
      }
      data = data->mParentData;
    }

    NS_ASSERTION(parentData->mSheet == aParentSheet,
                 "Unexpected call to LoadChildSheet");
  } else {
    LOG(("  No parent load; must be CSSOM"));
    // No parent load data, so the sheet will need to be notified when
    // we finish, if it can be, if we do the load asynchronously.
    observer = do_QueryInterface(aParentSheet);
  }

  // Now that we know it's safe to load this (passes security check and not a
  // loop) do so
  nsCOMPtr<nsICSSStyleSheet> sheet;
  StyleSheetState state;
  rv = CreateSheet(aURL, nsnull,
                   parentData ? parentData->mSyncLoad : PR_FALSE,
                   state, getter_AddRefs(sheet));
  NS_ENSURE_SUCCESS(rv, rv);

  const nsSubstring& empty = EmptyString();
  rv = PrepareSheet(sheet, empty, empty, aMedia);
  NS_ENSURE_SUCCESS(rv, rv);
  
  rv = InsertChildSheet(sheet, aParentSheet, aParentRule);
  NS_ENSURE_SUCCESS(rv, rv);
  
  if (state == eSheetComplete) {
    LOG(("  Sheet already complete"));
    // We're completely done.  No need to notify, even, since the
    // @import rule addition/modification will trigger the right style
    // changes automatically.
    return NS_OK;
  }

  
  SheetLoadData* data = new SheetLoadData(this, aURL, sheet, parentData,
                                          observer);

  if (!data) {
    sheet->SetComplete();
    return NS_ERROR_OUT_OF_MEMORY;
  }

  NS_ADDREF(data);

  // Load completion will release the data
  return LoadSheet(data, state);
  
}

Here is the call graph for this function:

NS_IMETHODIMP CSSLoaderImpl::LoadInlineStyle ( nsIContent aElement,
nsIUnicharInputStream aStream,
PRUint32  aLineNumber,
const nsSubstring aTitle,
const nsSubstring aMedia,
nsIParser aParserToUnblock,
PRBool aCompleted,
nsICSSLoaderObserver aObserver 
) [virtual]

Implements nsICSSLoader.

Definition at line 1532 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadInlineStyle"));
  NS_PRECONDITION(aStream, "Must have a stream to parse!");
  NS_ASSERTION(mParsingDatas.Count() == 0, "We're in the middle of a parse?");

  aCompleted = PR_TRUE;

  if (!mEnabled) {
    LOG_WARN(("  Not enabled"));
    return NS_ERROR_NOT_AVAILABLE;
  }

  NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);

  nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
  NS_ASSERTION(owningElement, "Element is not a style linking element!");
  
  StyleSheetState state;
  nsCOMPtr<nsICSSStyleSheet> sheet;
  nsresult rv = CreateSheet(nsnull, aElement, PR_FALSE, state,
                            getter_AddRefs(sheet));
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ASSERTION(state == eSheetNeedsParser,
               "Inline sheets should not be cached");

  rv = PrepareSheet(sheet, aTitle, aMedia, nsnull);
  NS_ENSURE_SUCCESS(rv, rv);
  
  rv = InsertSheetInDoc(sheet, aElement, mDocument);
  NS_ENSURE_SUCCESS(rv, rv);
  
  SheetLoadData* data = new SheetLoadData(this, aTitle, aParserToUnblock,
                                          nsnull, sheet, owningElement,
                                          aObserver);

  if (!data) {
    sheet->SetComplete();
    return NS_ERROR_OUT_OF_MEMORY;
  }

  NS_ADDREF(data);
  data->mLineNumber = aLineNumber;
  // Parse completion releases the load data
  return ParseSheet(aStream, data, aCompleted);
}        

Here is the call graph for this function:

nsresult CSSLoaderImpl::LoadSheet ( SheetLoadData aLoadData,
StyleSheetState  aSheetState 
)

LoadSheet handles the actual load of a sheet.

If the load is supposed to be synchronous it just opens a channel synchronously using the given uri, wraps the resulting stream in a converter stream and calls ParseSheet. Otherwise it tries to look for an existing load for this URI and piggyback on it. Failing all that, a new load is kicked off asynchronously.

Definition at line 1187 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadSheet"));
  NS_PRECONDITION(aLoadData, "Need a load data");
  NS_PRECONDITION(aLoadData->mURI, "Need a URI to load");
  NS_PRECONDITION(aLoadData->mSheet, "Need a sheet to load into");
  NS_PRECONDITION(aSheetState != eSheetComplete, "Why bother?");
  NS_ASSERTION(mLoadingDatas.IsInitialized(), "mLoadingDatas should be initialized by now.");

  LOG_URI("  Load from: '%s'", aLoadData->mURI);
  
  nsresult rv = NS_OK;  

  if (!mDocument && !aLoadData->mIsAgent) {
    // No point starting the load; just release all the data and such.
    LOG_WARN(("  No document and not agent sheet; pre-dropping load"));
    SheetComplete(aLoadData, PR_FALSE);
    return NS_OK;
  }

  if (aLoadData->mSyncLoad) {
    LOG(("  Synchronous load"));
    NS_ASSERTION(aSheetState == eSheetNeedsParser,
                 "Sync loads can't reuse existing async loads");

    // Just load it
    nsCOMPtr<nsIInputStream> stream;
    rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI);
    if (NS_FAILED(rv)) {
      LOG_ERROR(("  Failed to open URI synchronously"));
      SheetComplete(aLoadData, PR_FALSE);
      return rv;
    }

    nsCOMPtr<nsIConverterInputStream> converterStream = 
      do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
    
    if (NS_FAILED(rv)) {
      LOG_ERROR(("  Failed to create converter stream"));
      SheetComplete(aLoadData, PR_FALSE);
      return rv;
    }

    // This forces UA sheets to be UTF-8.  We should really look for
    // @charset rules here via ReadSegments on the raw stream...

    // 8192 is a nice magic number that happens to be what a lot of
    // other things use for buffer sizes.
    rv = converterStream->Init(stream, "UTF-8",
                               8192,
                               nsIConverterInputStream::
                                    DEFAULT_REPLACEMENT_CHARACTER);
    
    if (NS_FAILED(rv)) {
      LOG_ERROR(("  Failed to initialize converter stream"));
      SheetComplete(aLoadData, PR_FALSE);
      return rv;
    }

    PRBool completed;
    rv = ParseSheet(converterStream, aLoadData, completed);
    NS_ASSERTION(completed, "sync load did not complete");
    return rv;
  }

  SheetLoadData* existingData = nsnull;

  if (aSheetState == eSheetLoading) {
    mLoadingDatas.Get(aLoadData->mURI, &existingData);
    NS_ASSERTION(existingData, "CreateSheet lied about the state");
  }
  else if (aSheetState == eSheetPending){
    mPendingDatas.Get(aLoadData->mURI, &existingData);
    NS_ASSERTION(existingData, "CreateSheet lied about the state");
  }
  
  if (existingData) {
    LOG(("  Glomming on to existing load"));
    SheetLoadData* data = existingData;
    while (data->mNext) {
      data = data->mNext;
    }
    data->mNext = aLoadData; // transfer ownership
    if (aSheetState == eSheetPending && !IsAlternate(aLoadData->mTitle)) {
      // Kick the load off; someone cares about it right away

#ifdef DEBUG
      SheetLoadData* removedData;
      NS_ASSERTION(mPendingDatas.Get(aLoadData->mURI, &removedData) &&
                   removedData == existingData,
                   "Bad pending table.");
#endif

      mPendingDatas.Remove(aLoadData->mURI);

      LOG(("  Forcing load of pending data"));
      LoadSheet(existingData, eSheetNeedsParser);
    }
    // All done here; once the load completes we'll be marked complete
    // automatically
    return NS_OK;
  }

#ifdef DEBUG
  mSyncCallback = PR_TRUE;
#endif
  nsCOMPtr<nsILoadGroup> loadGroup;
  if (mDocument) {
    loadGroup = mDocument->GetDocumentLoadGroup();
    NS_ASSERTION(loadGroup,
                 "No loadgroup for stylesheet; onload will fire early");
  }

#ifdef MOZ_TIMELINE
  NS_TIMELINE_MARK_URI("Loading style sheet: %s", aLoadData->mURI);
  NS_TIMELINE_INDENT();
#endif
  
  nsCOMPtr<nsIChannel> channel;
  rv = NS_NewChannel(getter_AddRefs(channel),
                     aLoadData->mURI, nsnull, loadGroup,
                     nsnull, nsIChannel::LOAD_NORMAL);
  
  if (NS_FAILED(rv)) {
    LOG_ERROR(("  Failed to create channel"));
    SheetComplete(aLoadData, PR_FALSE);
    return rv;
  }

  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  if (httpChannel) {
    // send a minimal Accept header for text/css
    httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                  NS_LITERAL_CSTRING("text/css,*/*;q=0.1"),
                                  PR_FALSE);
    nsCOMPtr<nsIURI> referrerURI = aLoadData->GetReferrerURI();
    if (referrerURI)
      httpChannel->SetReferrer(referrerURI);
  }

  // Now tell the channel we expect text/css data back....  We do
  // this before opening it, so it's only treated as a hint.
  channel->SetContentType(NS_LITERAL_CSTRING("text/css"));

  // We don't have to hold on to the stream loader.  The ownership
  // model is: Necko owns the stream loader, which owns the load data,
  // which owns us
  nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
  rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader),
                                 channel, aLoadData);

#ifdef DEBUG
  mSyncCallback = PR_FALSE;
#endif

  if (NS_FAILED(rv)) {
    LOG_ERROR(("  Failed to create stream loader"));
    SheetComplete(aLoadData, PR_FALSE);
    return rv;
  }

  mLoadingDatas.Put(aLoadData->mURI, aLoadData);
  aLoadData->mIsLoading = PR_TRUE;
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP CSSLoaderImpl::LoadSheetSync ( nsIURI aURL,
PRBool  aAllowUnsafeRules,
nsICSSStyleSheet **  aSheet 
) [virtual]

Implements nsICSSLoader_MOZILLA_1_8_BRANCH.

Definition at line 1796 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadAgentSheet synchronous"));
  return InternalLoadAgentSheet(aURL, aSheet, aAllowUnsafeRules, nsnull);
}

Here is the call graph for this function:

NS_IMETHODIMP CSSLoaderImpl::LoadStyleLink ( nsIContent aElement,
nsIURI aURL,
const nsSubstring aTitle,
const nsSubstring aMedia,
nsIParser aParserToUnblock,
PRBool aCompleted,
nsICSSLoaderObserver aObserver 
) [virtual]

Implements nsICSSLoader.

Definition at line 1587 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::LoadStyleLink"));
  NS_PRECONDITION(aURL, "Must have URL to load");
  NS_ASSERTION(mParsingDatas.Count() == 0, "We're in the middle of a parse?");

  LOG_URI("  Link uri: '%s'", aURL);
  
  aCompleted = PR_TRUE;

  if (!mEnabled) {
    LOG_WARN(("  Not enabled"));
    return NS_ERROR_NOT_AVAILABLE;
  }
  
  NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);

  // Check whether we should even load
  nsIURI *docURI = mDocument->GetDocumentURI();
  if (!docURI) return NS_ERROR_FAILURE;

  nsISupports* context = aElement;
  if (!context) {
    context = mDocument;
  }
  nsresult rv = CheckLoadAllowed(docURI, aURL, context);
  if (NS_FAILED(rv)) return rv;

  LOG(("  Passed load check"));
  
  StyleSheetState state;
  nsCOMPtr<nsICSSStyleSheet> sheet;
  rv = CreateSheet(aURL, aElement, PR_FALSE, state,
                   getter_AddRefs(sheet));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = PrepareSheet(sheet, aTitle, aMedia, nsnull);
  NS_ENSURE_SUCCESS(rv, rv);
  
  rv = InsertSheetInDoc(sheet, aElement, mDocument);
  NS_ENSURE_SUCCESS(rv, rv);

  if (state == eSheetComplete) {
    LOG(("  Sheet already complete"));
    // We're completely done; this sheet is fully loaded, clean, and so forth
    if (aObserver) {
      aObserver->StyleSheetLoaded(sheet, PR_TRUE);
    }
    return NS_OK;
  }

  nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));

  // Now we need to actually load it
  SheetLoadData* data = new SheetLoadData(this, aTitle, aParserToUnblock, aURL,
                                          sheet, owningElement, aObserver);
  if (!data) {
    sheet->SetComplete();
    if (aObserver) {
      aObserver->StyleSheetLoaded(sheet, PR_TRUE);
    }
    return NS_ERROR_OUT_OF_MEMORY;
  }

  NS_ADDREF(data);

  // Caller gets to wait for the sheet to load.
  aCompleted = PR_FALSE;

  // If we have to parse and it's an alternate non-inline, defer it
  if (aURL && state == eSheetNeedsParser && mLoadingDatas.Count() != 0 &&
      IsAlternate(aTitle)) {
    LOG(("  Deferring alternate sheet load"));
    mPendingDatas.Put(aURL, data);
    return NS_OK;
  }

  // Load completion will free the data
  return LoadSheet(data, state);
}

Here is the call graph for this function:

nsresult CSSLoaderImpl::ParseSheet ( nsIUnicharInputStream aStream,
SheetLoadData aLoadData,
PRBool aCompleted 
) [protected]

ParseSheet handles parsing the data stream.

The main idea here is to push the current load data onto the parse stack before letting the CSS parser at the data stream. That lets us handle correctly.

Definition at line 1361 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::ParseSheet"));
  NS_PRECONDITION(aStream, "Must have data to parse");
  NS_PRECONDITION(aLoadData, "Must have load data");
  NS_PRECONDITION(aLoadData->mSheet, "Must have sheet to parse into");

  aCompleted = PR_FALSE;

  nsCOMPtr<nsICSSParser> parser;
  nsresult rv = GetParserFor(aLoadData->mSheet, getter_AddRefs(parser));
  if (NS_FAILED(rv)) {
    LOG_ERROR(("  Failed to get CSS parser"));
    SheetComplete(aLoadData, PR_FALSE);
    return rv;
  }

  // The parser insists on passing out a strong ref to the sheet it
  // parsed.  We don't care.
  nsCOMPtr<nsICSSStyleSheet> dummySheet;
  // Push our load data on the stack so any kids can pick it up
  mParsingDatas.AppendElement(aLoadData);
  nsCOMPtr<nsIURI> sheetURI, baseURI;
  aLoadData->mSheet->GetSheetURI(getter_AddRefs(sheetURI));
  aLoadData->mSheet->GetBaseURI(getter_AddRefs(baseURI));
  nsCOMPtr<nsICSSParser_MOZILLA_1_8_BRANCH> parser18 = do_QueryInterface(parser);
  rv = parser18->Parse(aStream, sheetURI, baseURI, aLoadData->mLineNumber,
                       aLoadData->mAllowUnsafeRules,
                       *getter_AddRefs(dummySheet));
  mParsingDatas.RemoveElementAt(mParsingDatas.Count() - 1);
  RecycleParser(parser);

  NS_ASSERTION(aLoadData->mPendingChildren == 0 || !aLoadData->mSyncLoad,
               "Sync load has leftover pending children!");
  
  if (aLoadData->mPendingChildren == 0) {
    LOG(("  No pending kids from parse"));
    aCompleted = PR_TRUE;
    if (!aLoadData->mURI) {
      // inline sheet and we're all done with no kids, so we will not
      // be blocking the parser
      LOG(("  Inline sheet with no pending kids; nulling out parser"));
      aLoadData->mParserToUnblock = nsnull;
    }
    SheetComplete(aLoadData, PR_TRUE);
  }
  // Otherwise, the children are holding strong refs to the data and
  // will call SheetComplete() on it when they complete.
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult CSSLoaderImpl::PrepareSheet ( nsICSSStyleSheet aSheet,
const nsSubstring aTitle,
const nsSubstring aMediaString,
nsMediaList aMediaList 
) [private]

PrepareSheet() handles setting the media and title on the sheet, as well as setting the enabled state based on the title.

Definition at line 1013 of file nsCSSLoader.cpp.

{
  NS_PRECONDITION(aSheet, "Must have a sheet!");

  nsresult rv;
  nsCOMPtr<nsMediaList> mediaList(aMediaList);

  if (!aMediaString.IsEmpty()) {
    NS_ASSERTION(!aMediaList,
                 "must not provide both aMediaString and aMediaList");
    mediaList = new nsMediaList();
    NS_ENSURE_TRUE(mediaList, NS_ERROR_OUT_OF_MEMORY);
    nsCOMPtr<nsICSSParser> mediumParser;
    nsresult rv = GetParserFor(nsnull, getter_AddRefs(mediumParser));
    NS_ENSURE_SUCCESS(rv, rv);
    // We have aMediaString only when linked from link elements, style
    // elements, or PIs, so pass PR_TRUE.
    rv = mediumParser->ParseMediaList(aMediaString, nsnull, 0, mediaList,
                                      PR_TRUE);
    NS_ENSURE_SUCCESS(rv, rv);
    RecycleParser(mediumParser);
  }

  rv = aSheet->SetMedia(mediaList);
  NS_ENSURE_SUCCESS(rv, rv);

  aSheet->SetTitle(aTitle);
  aSheet->SetEnabled(! IsAlternate(aTitle));
  return NS_OK;    
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsICSSLoader.

Definition at line 386 of file nsCSSLoader.cpp.

{
  NS_PRECONDITION(aParser, "Recycle only good parsers, please");
  NS_ENSURE_TRUE(gParsers, NS_ERROR_UNEXPECTED);

  if (!gParsers->AppendObject(aParser)) {
    return NS_ERROR_FAILURE;
  }
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP CSSLoaderImpl::SetCaseSensitive ( PRBool  aCaseSensitive) [virtual]

Implements nsICSSLoader.

Definition at line 300 of file nsCSSLoader.cpp.

{
  mCaseSensitive = aCaseSensitive;
  return NS_OK;
}

Implements nsICSSLoader.

Definition at line 307 of file nsCSSLoader.cpp.

{
  mCompatMode = aCompatMode;
  return NS_OK;
}

Implements nsICSSLoader.

Definition at line 1962 of file nsCSSLoader.cpp.

{
  mEnabled = aEnabled;
  return NS_OK;
}
NS_IMETHODIMP CSSLoaderImpl::SetPreferredSheet ( const nsAString &  aTitle) [virtual]

Implements nsICSSLoader.

Definition at line 330 of file nsCSSLoader.cpp.

{
  mPreferredSheet = aTitle;

  // start any pending alternates that aren't alternates anymore
  if (mPendingDatas.IsInitialized())
    mPendingDatas.Enumerate(StartNonAlternates, this);
  return NS_OK;
}

Here is the call graph for this function:

void CSSLoaderImpl::SheetComplete ( SheetLoadData aLoadData,
PRBool  aSucceeded 
)

SheetComplete is the do-it-all cleanup function.

It removes the load data from the "loading" hashtable, adds the sheet to the "completed" hashtable, massages the XUL cache, handles siblings of the load data (other loads for the same URI, handles unblocking blocked parent loads as needed, and most importantly calls NS_RELEASE on the load data to destroy the whole mess.

Definition at line 1424 of file nsCSSLoader.cpp.

{
  LOG(("CSSLoaderImpl::SheetComplete"));
  NS_PRECONDITION(aLoadData, "Must have a load data!");
  NS_PRECONDITION(aLoadData->mSheet, "Must have a sheet");
  NS_ASSERTION(mLoadingDatas.IsInitialized(),"mLoadingDatas should be initialized by now.");

  LOG(("Load completed: %d", aSucceeded));

  // Twiddle the hashtables
  if (aLoadData->mURI) {
    LOG_URI("  Finished loading: '%s'", aLoadData->mURI);
    // Remove the data from the list of loading datas
    if (aLoadData->mIsLoading) {
#ifdef DEBUG
      SheetLoadData *loadingData;
      NS_ASSERTION(mLoadingDatas.Get(aLoadData->mURI, &loadingData) &&
                   loadingData == aLoadData,
                   "Bad loading table");
#endif

      mLoadingDatas.Remove(aLoadData->mURI);
      aLoadData->mIsLoading = PR_FALSE;
    }
  }
  

  // This is a mess.  If we have a document.write() that writes out
  // two <link> elements pointing to the same url, we will actually
  // end up blocking the same parser twice.  This seems very wrong --
  // if we blocked it the first time, why is more stuff getting
  // written??  In any case, we only want to unblock it once.
  // Otherwise we get icky things like crashes in layout...  We need
  // to stop blocking the parser.  We really do.
  PRBool seenParser = PR_FALSE;

  // Go through and deal with the whole linked list.
  SheetLoadData* data = aLoadData;
  while (data) {

    data->mSheet->SetModified(PR_FALSE); // it's clean
    data->mSheet->SetComplete();
    if (data->mObserver) {
      data->mObserver->StyleSheetLoaded(data->mSheet, PR_TRUE);
    }
                           
    if (data->mParserToUnblock) {
      LOG(("Parser to unblock: %p", data->mParserToUnblock.get()));
      if (!seenParser) {
        LOG(("Unblocking parser: %p", data->mParserToUnblock.get()));
        seenParser = PR_TRUE;
        data->mParserToUnblock->ContinueParsing();
      }
      data->mParserToUnblock = nsnull; // drop the ref, just in case
    }

    NS_ASSERTION(!data->mParentData ||
                 data->mParentData->mPendingChildren != 0,
                 "Broken pending child count on our parent");

    // If we have a parent, our parent is no longer being parsed, and
    // we are the last pending child, then our load completion
    // completes the parent too.  Note that the parent _can_ still be
    // being parsed (eg if the child (us) failed to open the channel
    // or some such).
    if (data->mParentData &&
        --(data->mParentData->mPendingChildren) == 0 &&
        mParsingDatas.IndexOf(data->mParentData) == -1) {
      SheetComplete(data->mParentData, aSucceeded);
    }
    
    data = data->mNext;
  }

  // Now that it's marked complete, put the sheet in our cache
  if (aSucceeded && aLoadData->mURI) {
#ifdef MOZ_XUL
    if (IsChromeURI(aLoadData->mURI)) {
      nsCOMPtr<nsIXULPrototypeCache> cache(do_GetService("@mozilla.org/xul/xul-prototype-cache;1"));
      if (cache) {
        PRBool enabled;
        cache->GetEnabled(&enabled);
        if (enabled) {
          nsCOMPtr<nsICSSStyleSheet> sheet;
          cache->GetStyleSheet(aLoadData->mURI, getter_AddRefs(sheet));
          if (!sheet) {
            LOG(("  Putting sheet in XUL prototype cache"));
            cache->PutStyleSheet(aLoadData->mSheet);
          }
        }
      }
    }
    else {
#endif
      mCompleteSheets.Put(aLoadData->mURI, aLoadData->mSheet);
#ifdef MOZ_XUL
    }
#endif
  }

  NS_RELEASE(aLoadData);  // this will release parents and siblings and all that
  if (mLoadingDatas.Count() == 0 && mPendingDatas.Count() > 0) {
    LOG(("  No more loading sheets; starting alternates"));
    mPendingDatas.Enumerate(StartAlternateLoads, this);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 262 of file nsCSSLoader.cpp.

{
  delete gParsers;
  gParsers = nsnull;
}

Implements nsICSSLoader.

Definition at line 1917 of file nsCSSLoader.cpp.

Here is the call graph for this function:

Implements nsICSSLoader.

Definition at line 1929 of file nsCSSLoader.cpp.

{
  NS_ENSURE_TRUE(aURL, NS_ERROR_NULL_POINTER);
  if (mLoadingDatas.Count() > 0 || mPendingDatas.Count() > 0) {
    
    SheetLoadData* loadData = nsnull;
    mLoadingDatas.Get(aURL, &loadData);
    if (!loadData) {
      mPendingDatas.Get(aURL, &loadData);
      if (loadData) {
        // have to remove from mPendingDatas ourselves, since
        // SheetComplete won't do that.
        mPendingDatas.Remove(aURL);
      }
    }
    
    if (loadData) {
      loadData->mIsCancelled = PR_TRUE;
      SheetComplete(loadData, PR_FALSE);
    }
  }
  return NS_OK;
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class SheetLoadData [friend]

Definition at line 329 of file nsCSSLoader.h.


Member Data Documentation

Definition at line 340 of file nsCSSLoader.h.

Definition at line 351 of file nsCSSLoader.h.

Definition at line 353 of file nsCSSLoader.h.

Definition at line 356 of file nsCSSLoader.h.

Definition at line 344 of file nsCSSLoader.h.

Definition at line 352 of file nsCSSLoader.h.

Definition at line 357 of file nsCSSLoader.h.

nsAutoVoidArray CSSLoaderImpl::mParsingDatas [private]

Definition at line 362 of file nsCSSLoader.h.

Definition at line 358 of file nsCSSLoader.h.

Definition at line 354 of file nsCSSLoader.h.


The documentation for this class was generated from the following files: