mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-11 14:28:42 +00:00
added load agent sheet
added support for non-blocking inline sheets
This commit is contained in:
parent
0850b6eea4
commit
87f3c44c23
@ -21,7 +21,7 @@
|
||||
#include "nsICSSStyleSheet.h"
|
||||
|
||||
#include "nsIParser.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsIDocument.h"
|
||||
@ -134,10 +134,12 @@ public:
|
||||
struct SheetLoadData {
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
const nsString& aTitle, const nsString& aMedia,
|
||||
nsIHTMLContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIParser* aParserToUnblock, PRBool aIsInline);
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL, const nsString& aMedia,
|
||||
nsICSSStyleSheet* aParentSheet, PRInt32 aSheetIndex);
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL, nsCSSLoaderCallbackFunc aCallback,
|
||||
void* aData);
|
||||
~SheetLoadData(void);
|
||||
|
||||
CSSLoaderImpl* mLoader;
|
||||
@ -146,8 +148,9 @@ struct SheetLoadData {
|
||||
nsString mMedia;
|
||||
PRInt32 mSheetIndex;
|
||||
|
||||
nsIHTMLContent* mOwningElement;
|
||||
nsIContent* mOwningElement;
|
||||
nsIParser* mParserToUnblock;
|
||||
PRBool mDidBlockParser;
|
||||
|
||||
nsICSSStyleSheet* mParentSheet;
|
||||
|
||||
@ -157,11 +160,15 @@ struct SheetLoadData {
|
||||
PRUint32 mPendingChildren;
|
||||
|
||||
PRBool mIsInline;
|
||||
PRBool mIsAgent;
|
||||
|
||||
nsCSSLoaderCallbackFunc mCallback;
|
||||
void* mCallbackData;
|
||||
};
|
||||
|
||||
struct PendingSheetData {
|
||||
PendingSheetData(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement)
|
||||
nsIContent* aElement)
|
||||
: mSheet(aSheet),
|
||||
mDocIndex(aDocIndex),
|
||||
mOwningElement(aElement),
|
||||
@ -179,7 +186,7 @@ struct PendingSheetData {
|
||||
|
||||
nsICSSStyleSheet* mSheet;
|
||||
PRInt32 mDocIndex;
|
||||
nsIHTMLContent* mOwningElement;
|
||||
nsIContent* mOwningElement;
|
||||
PRBool mNotify;
|
||||
};
|
||||
|
||||
@ -191,6 +198,7 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Init(nsIDocument* aDocument);
|
||||
NS_IMETHOD DropDocumentReference(void);
|
||||
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive);
|
||||
NS_IMETHOD SetPreferredSheet(const nsString& aTitle);
|
||||
@ -199,7 +207,7 @@ public:
|
||||
nsICSSParser** aParser);
|
||||
NS_IMETHOD RecycleParser(nsICSSParser* aParser);
|
||||
|
||||
NS_IMETHOD LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
NS_IMETHOD LoadInlineStyle(nsIContent* aElement,
|
||||
nsIUnicharInputStream* aIn,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -207,7 +215,7 @@ public:
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted);
|
||||
|
||||
NS_IMETHOD LoadStyleLink(nsIHTMLContent* aElement,
|
||||
NS_IMETHOD LoadStyleLink(nsIContent* aElement,
|
||||
nsIURL* aURL,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -220,12 +228,18 @@ public:
|
||||
const nsString& aMedia,
|
||||
PRInt32 aIndex);
|
||||
|
||||
NS_IMETHOD LoadAgentSheet(nsIURL* aURL,
|
||||
nsICSSStyleSheet*& aSheet,
|
||||
PRBool& aCompleted,
|
||||
nsCSSLoaderCallbackFunc aCallback,
|
||||
void *aData);
|
||||
|
||||
// local helper methods (public for access from statics)
|
||||
void Cleanup(URLKey& aKey, SheetLoadData* aLoadData);
|
||||
nsresult SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData);
|
||||
|
||||
nsresult ParseSheet(nsIUnicharInputStream* aIn, SheetLoadData* aLoadData,
|
||||
PRBool& aCompleted);
|
||||
PRBool& aCompleted, nsICSSStyleSheet*& aSheet);
|
||||
|
||||
void DidLoadStyle(nsIUnicharStreamLoader* aLoader,
|
||||
nsString& aStyleData,
|
||||
@ -238,12 +252,12 @@ public:
|
||||
const nsString& aMedia);
|
||||
|
||||
nsresult AddPendingSheet(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement);
|
||||
nsIContent* aElement);
|
||||
|
||||
PRBool IsAlternate(const nsString& aTitle);
|
||||
|
||||
nsresult InsertSheetInDoc(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement, PRBool aNotify);
|
||||
nsIContent* aElement, PRBool aNotify);
|
||||
|
||||
nsresult InsertChildSheet(nsICSSStyleSheet* aSheet, nsICSSStyleSheet* aParentSheet,
|
||||
PRInt32 aIndex);
|
||||
@ -270,7 +284,7 @@ public:
|
||||
|
||||
SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
const nsString& aTitle, const nsString& aMedia,
|
||||
nsIHTMLContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIParser* aParserToUnblock, PRBool aIsInline)
|
||||
: mLoader(aLoader),
|
||||
mURL(aURL),
|
||||
@ -279,11 +293,15 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
mOwningElement(aOwner),
|
||||
mSheetIndex(aDocIndex),
|
||||
mParserToUnblock(aParserToUnblock),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(nsnull),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(aIsInline)
|
||||
mIsInline(aIsInline),
|
||||
mIsAgent(PR_FALSE),
|
||||
mCallback(nsnull),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
@ -301,17 +319,45 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
mSheetIndex(aSheetIndex),
|
||||
mOwningElement(nsnull),
|
||||
mParserToUnblock(nsnull),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(aParentSheet),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(PR_FALSE)
|
||||
mIsInline(PR_FALSE),
|
||||
mIsAgent(PR_FALSE),
|
||||
mCallback(nsnull),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
NS_ADDREF(mParentSheet);
|
||||
}
|
||||
|
||||
SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
nsCSSLoaderCallbackFunc aCallback, void* aData)
|
||||
: mLoader(aLoader),
|
||||
mURL(aURL),
|
||||
mTitle(),
|
||||
mMedia(),
|
||||
mSheetIndex(-1),
|
||||
mOwningElement(nsnull),
|
||||
mParserToUnblock(nsnull),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(nsnull),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(PR_FALSE),
|
||||
mIsAgent(PR_TRUE),
|
||||
mCallback(aCallback),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
}
|
||||
|
||||
|
||||
SheetLoadData::~SheetLoadData(void)
|
||||
{
|
||||
NS_RELEASE(mLoader);
|
||||
@ -390,6 +436,13 @@ CSSLoaderImpl::Init(nsIDocument* aDocument)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::DropDocumentReference(void)
|
||||
{
|
||||
mDocument = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::SetCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
@ -510,7 +563,7 @@ AreAllPendingAlternateSheets(void* aPendingData, void* aLoader)
|
||||
void
|
||||
CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
{
|
||||
// unblock parser
|
||||
// notify any parents that child is done
|
||||
SheetLoadData* data = aLoadData;
|
||||
do {
|
||||
if (data->mParentData) {
|
||||
@ -519,11 +572,6 @@ CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
SheetComplete(data->mParentSheet, data->mParentData);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->mParserToUnblock) {
|
||||
data->mParserToUnblock->EnableParser(PR_TRUE);
|
||||
break;
|
||||
}
|
||||
data = data->mNext;
|
||||
} while (data);
|
||||
|
||||
@ -531,6 +579,16 @@ CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
mLoadingSheets.Remove(&aKey);
|
||||
}
|
||||
|
||||
// unblock parser
|
||||
data = aLoadData;
|
||||
do {
|
||||
if (data->mParserToUnblock && data->mDidBlockParser) {
|
||||
data->mParserToUnblock->EnableParser(PR_TRUE); // this may result in re-entrant calls to loader
|
||||
break;
|
||||
}
|
||||
data = data->mNext;
|
||||
} while (data);
|
||||
|
||||
// if all loads complete, put pending sheets into doc
|
||||
if (0 == mLoadingSheets.Count()) {
|
||||
PRInt32 count = mPendingDocSheets.Count();
|
||||
@ -569,14 +627,19 @@ CSSLoaderImpl::SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData)
|
||||
SheetLoadData* data = aLoadData;
|
||||
do { // add to parent sheet, parent doc or pending doc sheet list
|
||||
PrepareSheet(aSheet, data->mTitle, data->mMedia);
|
||||
if (data->mParentSheet) {
|
||||
if (data->mParentSheet) { // is child sheet
|
||||
InsertChildSheet(aSheet, data->mParentSheet, data->mSheetIndex);
|
||||
}
|
||||
else {
|
||||
if (data->mParserToUnblock || data->mIsInline) {
|
||||
else if (data->mIsAgent) { // is agent sheet
|
||||
if (data->mCallback) {
|
||||
(*(data->mCallback))(aSheet, data->mCallbackData);
|
||||
}
|
||||
}
|
||||
else { // doc sheet
|
||||
if (data->mParserToUnblock) { // if blocking, insert it immediately
|
||||
InsertSheetInDoc(aSheet, data->mSheetIndex, data->mOwningElement, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
else { // otherwise wait until all are loaded (even inlines)
|
||||
AddPendingSheet(aSheet, data->mSheetIndex, data->mOwningElement);
|
||||
}
|
||||
}
|
||||
@ -602,27 +665,30 @@ CSSLoaderImpl::SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData)
|
||||
nsresult
|
||||
CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aIn,
|
||||
SheetLoadData* aLoadData,
|
||||
PRBool& aCompleted)
|
||||
PRBool& aCompleted,
|
||||
nsICSSStyleSheet*& aSheet)
|
||||
{
|
||||
nsresult result;
|
||||
PRBool failed = PR_TRUE;
|
||||
|
||||
aCompleted = PR_TRUE;
|
||||
nsICSSStyleSheet* sheet = nsnull;
|
||||
result = NS_NewCSSStyleSheet(&sheet, aLoadData->mURL);
|
||||
aSheet = nsnull;
|
||||
result = NS_NewCSSStyleSheet(&aSheet, aLoadData->mURL);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsICSSParser* parser;
|
||||
result = GetParserFor(sheet, &parser);
|
||||
result = GetParserFor(aSheet, &parser);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mParsingData.AppendElement(aLoadData);
|
||||
result = parser->Parse(aIn, aLoadData->mURL, sheet); // this may result in re-entrant load child sheet calls
|
||||
result = parser->Parse(aIn, aLoadData->mURL, aSheet); // this may result in re-entrant load child sheet calls
|
||||
mParsingData.RemoveElementAt(mParsingData.Count() - 1);
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
failed = PR_FALSE;
|
||||
if (0 == aLoadData->mPendingChildren) { // sheet isn't still loading children
|
||||
if (aLoadData->mIsInline) {
|
||||
NS_IF_RELEASE(aLoadData->mParserToUnblock); // don't need to unblock, we're done and won't block
|
||||
aLoadData->mDidBlockParser = PR_FALSE; // don't need to unblock, we're done and won't block
|
||||
}
|
||||
SheetComplete(sheet, aLoadData);
|
||||
SheetComplete(aSheet, aLoadData);
|
||||
}
|
||||
else { // else sheet is still waiting for children to load, last child will complete it
|
||||
aCompleted = PR_FALSE;
|
||||
@ -630,7 +696,10 @@ CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aIn,
|
||||
}
|
||||
RecycleParser(parser);
|
||||
}
|
||||
NS_RELEASE(sheet);
|
||||
}
|
||||
if (failed) {
|
||||
URLKey key(aLoadData->mURL);
|
||||
Cleanup(key, aLoadData);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -649,10 +718,16 @@ CSSLoaderImpl::DidLoadStyle(nsIUnicharStreamLoader* aLoader,
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// XXX We have no way of indicating failure. Silently fail?
|
||||
PRBool completed;
|
||||
result = ParseSheet(uin, aLoadData, completed);
|
||||
nsICSSStyleSheet* sheet;
|
||||
result = ParseSheet(uin, aLoadData, completed, sheet);
|
||||
NS_IF_RELEASE(sheet);
|
||||
|
||||
NS_RELEASE(uin);
|
||||
}
|
||||
else {
|
||||
URLKey key(aLoadData->mURL);
|
||||
Cleanup(key, aLoadData);
|
||||
}
|
||||
}
|
||||
else { // load failed, cleanup
|
||||
URLKey key(aLoadData->mURL);
|
||||
@ -743,6 +818,7 @@ static PRBool MediumEnumFunc(const nsString& aSubString, void* aData)
|
||||
nsresult
|
||||
CSSLoaderImpl::SetMedia(nsICSSStyleSheet* aSheet, const nsString& aMedia)
|
||||
{
|
||||
aSheet->ClearMedia();
|
||||
if (0 < aMedia.Length()) {
|
||||
EnumerateMediaString(aMedia, MediumEnumFunc, aSheet);
|
||||
}
|
||||
@ -761,7 +837,7 @@ CSSLoaderImpl::PrepareSheet(nsICSSStyleSheet* aSheet, const nsString& aTitle,
|
||||
|
||||
nsresult
|
||||
CSSLoaderImpl::AddPendingSheet(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement)
|
||||
nsIContent* aElement)
|
||||
{
|
||||
PendingSheetData* data = new PendingSheetData(aSheet, aDocIndex, aElement);
|
||||
if (data) {
|
||||
@ -782,7 +858,7 @@ CSSLoaderImpl::IsAlternate(const nsString& aTitle)
|
||||
|
||||
nsresult
|
||||
CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement, PRBool aNotify)
|
||||
nsIContent* aElement, PRBool aNotify)
|
||||
{
|
||||
if ((! mDocument) || (! aSheet)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
@ -910,7 +986,7 @@ CSSLoaderImpl::LoadSheet(URLKey& aKey, SheetLoadData* aData)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement,
|
||||
nsIUnicharInputStream* aIn,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -918,6 +994,11 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted)
|
||||
{
|
||||
NS_ASSERTION(mDocument, "not initialized");
|
||||
if (! mDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX need to add code to cancel any pending sheets for element
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aIn) {
|
||||
@ -927,7 +1008,12 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
aElement,
|
||||
aDocIndex, aParserToUnblock,
|
||||
PR_TRUE);
|
||||
result = ParseSheet(aIn, data, aCompleted);
|
||||
nsICSSStyleSheet* sheet;
|
||||
result = ParseSheet(aIn, data, aCompleted, sheet);
|
||||
NS_IF_RELEASE(sheet);
|
||||
if ((! aCompleted) && (aParserToUnblock)) {
|
||||
data->mDidBlockParser = PR_TRUE;
|
||||
}
|
||||
NS_RELEASE(docURL);
|
||||
}
|
||||
return result;
|
||||
@ -935,7 +1021,7 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
CSSLoaderImpl::LoadStyleLink(nsIContent* aElement,
|
||||
nsIURL* aURL,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -943,6 +1029,11 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted)
|
||||
{
|
||||
NS_ASSERTION(mDocument, "not initialized");
|
||||
if (! mDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX need to add code to cancel any pending sheets for element
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
|
||||
@ -962,7 +1053,7 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
if (aParserToUnblock) { // stick it in now, parser is waiting for it
|
||||
result = InsertSheetInDoc(clone, aDocIndex, aElement, PR_TRUE);
|
||||
}
|
||||
else { // add to pending list?
|
||||
else { // add to pending list
|
||||
result = AddPendingSheet(clone, aDocIndex, aElement);
|
||||
}
|
||||
NS_RELEASE(clone);
|
||||
@ -982,6 +1073,9 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
result = LoadSheet(key, data);
|
||||
}
|
||||
aCompleted = PR_FALSE;
|
||||
if (aParserToUnblock) {
|
||||
data->mDidBlockParser = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -1039,6 +1133,34 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadAgentSheet(nsIURL* aURL,
|
||||
nsICSSStyleSheet*& aSheet,
|
||||
PRBool& aCompleted,
|
||||
nsCSSLoaderCallbackFunc aCallback,
|
||||
void *aData)
|
||||
{
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aURL) {
|
||||
// Get an input stream from the url
|
||||
nsIInputStream* in;
|
||||
result = NS_OpenURL(aURL, &in);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Translate the input using the argument character set id into unicode
|
||||
nsIUnicharInputStream* uin;
|
||||
result = NS_NewConverterStream(&uin, nsnull, in);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
SheetLoadData* data = new SheetLoadData(this, aURL, aCallback, aData);
|
||||
URLKey key(aURL);
|
||||
mLoadingSheets.Put(&key, data);
|
||||
result = ParseSheet(uin, data, aCompleted, aSheet);
|
||||
NS_RELEASE(uin);
|
||||
}
|
||||
NS_RELEASE(in);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsresult NS_NewCSSLoader(nsIDocument* aDocument, nsICSSLoader** aLoader)
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "nsICSSStyleSheet.h"
|
||||
|
||||
#include "nsIParser.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsIDocument.h"
|
||||
@ -134,10 +134,12 @@ public:
|
||||
struct SheetLoadData {
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
const nsString& aTitle, const nsString& aMedia,
|
||||
nsIHTMLContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIParser* aParserToUnblock, PRBool aIsInline);
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL, const nsString& aMedia,
|
||||
nsICSSStyleSheet* aParentSheet, PRInt32 aSheetIndex);
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL, nsCSSLoaderCallbackFunc aCallback,
|
||||
void* aData);
|
||||
~SheetLoadData(void);
|
||||
|
||||
CSSLoaderImpl* mLoader;
|
||||
@ -146,8 +148,9 @@ struct SheetLoadData {
|
||||
nsString mMedia;
|
||||
PRInt32 mSheetIndex;
|
||||
|
||||
nsIHTMLContent* mOwningElement;
|
||||
nsIContent* mOwningElement;
|
||||
nsIParser* mParserToUnblock;
|
||||
PRBool mDidBlockParser;
|
||||
|
||||
nsICSSStyleSheet* mParentSheet;
|
||||
|
||||
@ -157,11 +160,15 @@ struct SheetLoadData {
|
||||
PRUint32 mPendingChildren;
|
||||
|
||||
PRBool mIsInline;
|
||||
PRBool mIsAgent;
|
||||
|
||||
nsCSSLoaderCallbackFunc mCallback;
|
||||
void* mCallbackData;
|
||||
};
|
||||
|
||||
struct PendingSheetData {
|
||||
PendingSheetData(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement)
|
||||
nsIContent* aElement)
|
||||
: mSheet(aSheet),
|
||||
mDocIndex(aDocIndex),
|
||||
mOwningElement(aElement),
|
||||
@ -179,7 +186,7 @@ struct PendingSheetData {
|
||||
|
||||
nsICSSStyleSheet* mSheet;
|
||||
PRInt32 mDocIndex;
|
||||
nsIHTMLContent* mOwningElement;
|
||||
nsIContent* mOwningElement;
|
||||
PRBool mNotify;
|
||||
};
|
||||
|
||||
@ -191,6 +198,7 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Init(nsIDocument* aDocument);
|
||||
NS_IMETHOD DropDocumentReference(void);
|
||||
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive);
|
||||
NS_IMETHOD SetPreferredSheet(const nsString& aTitle);
|
||||
@ -199,7 +207,7 @@ public:
|
||||
nsICSSParser** aParser);
|
||||
NS_IMETHOD RecycleParser(nsICSSParser* aParser);
|
||||
|
||||
NS_IMETHOD LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
NS_IMETHOD LoadInlineStyle(nsIContent* aElement,
|
||||
nsIUnicharInputStream* aIn,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -207,7 +215,7 @@ public:
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted);
|
||||
|
||||
NS_IMETHOD LoadStyleLink(nsIHTMLContent* aElement,
|
||||
NS_IMETHOD LoadStyleLink(nsIContent* aElement,
|
||||
nsIURL* aURL,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -220,12 +228,18 @@ public:
|
||||
const nsString& aMedia,
|
||||
PRInt32 aIndex);
|
||||
|
||||
NS_IMETHOD LoadAgentSheet(nsIURL* aURL,
|
||||
nsICSSStyleSheet*& aSheet,
|
||||
PRBool& aCompleted,
|
||||
nsCSSLoaderCallbackFunc aCallback,
|
||||
void *aData);
|
||||
|
||||
// local helper methods (public for access from statics)
|
||||
void Cleanup(URLKey& aKey, SheetLoadData* aLoadData);
|
||||
nsresult SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData);
|
||||
|
||||
nsresult ParseSheet(nsIUnicharInputStream* aIn, SheetLoadData* aLoadData,
|
||||
PRBool& aCompleted);
|
||||
PRBool& aCompleted, nsICSSStyleSheet*& aSheet);
|
||||
|
||||
void DidLoadStyle(nsIUnicharStreamLoader* aLoader,
|
||||
nsString& aStyleData,
|
||||
@ -238,12 +252,12 @@ public:
|
||||
const nsString& aMedia);
|
||||
|
||||
nsresult AddPendingSheet(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement);
|
||||
nsIContent* aElement);
|
||||
|
||||
PRBool IsAlternate(const nsString& aTitle);
|
||||
|
||||
nsresult InsertSheetInDoc(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement, PRBool aNotify);
|
||||
nsIContent* aElement, PRBool aNotify);
|
||||
|
||||
nsresult InsertChildSheet(nsICSSStyleSheet* aSheet, nsICSSStyleSheet* aParentSheet,
|
||||
PRInt32 aIndex);
|
||||
@ -270,7 +284,7 @@ public:
|
||||
|
||||
SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
const nsString& aTitle, const nsString& aMedia,
|
||||
nsIHTMLContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIParser* aParserToUnblock, PRBool aIsInline)
|
||||
: mLoader(aLoader),
|
||||
mURL(aURL),
|
||||
@ -279,11 +293,15 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
mOwningElement(aOwner),
|
||||
mSheetIndex(aDocIndex),
|
||||
mParserToUnblock(aParserToUnblock),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(nsnull),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(aIsInline)
|
||||
mIsInline(aIsInline),
|
||||
mIsAgent(PR_FALSE),
|
||||
mCallback(nsnull),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
@ -301,17 +319,45 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
mSheetIndex(aSheetIndex),
|
||||
mOwningElement(nsnull),
|
||||
mParserToUnblock(nsnull),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(aParentSheet),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(PR_FALSE)
|
||||
mIsInline(PR_FALSE),
|
||||
mIsAgent(PR_FALSE),
|
||||
mCallback(nsnull),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
NS_ADDREF(mParentSheet);
|
||||
}
|
||||
|
||||
SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
nsCSSLoaderCallbackFunc aCallback, void* aData)
|
||||
: mLoader(aLoader),
|
||||
mURL(aURL),
|
||||
mTitle(),
|
||||
mMedia(),
|
||||
mSheetIndex(-1),
|
||||
mOwningElement(nsnull),
|
||||
mParserToUnblock(nsnull),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(nsnull),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(PR_FALSE),
|
||||
mIsAgent(PR_TRUE),
|
||||
mCallback(aCallback),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
}
|
||||
|
||||
|
||||
SheetLoadData::~SheetLoadData(void)
|
||||
{
|
||||
NS_RELEASE(mLoader);
|
||||
@ -390,6 +436,13 @@ CSSLoaderImpl::Init(nsIDocument* aDocument)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::DropDocumentReference(void)
|
||||
{
|
||||
mDocument = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::SetCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
@ -510,7 +563,7 @@ AreAllPendingAlternateSheets(void* aPendingData, void* aLoader)
|
||||
void
|
||||
CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
{
|
||||
// unblock parser
|
||||
// notify any parents that child is done
|
||||
SheetLoadData* data = aLoadData;
|
||||
do {
|
||||
if (data->mParentData) {
|
||||
@ -519,11 +572,6 @@ CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
SheetComplete(data->mParentSheet, data->mParentData);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->mParserToUnblock) {
|
||||
data->mParserToUnblock->EnableParser(PR_TRUE);
|
||||
break;
|
||||
}
|
||||
data = data->mNext;
|
||||
} while (data);
|
||||
|
||||
@ -531,6 +579,16 @@ CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
mLoadingSheets.Remove(&aKey);
|
||||
}
|
||||
|
||||
// unblock parser
|
||||
data = aLoadData;
|
||||
do {
|
||||
if (data->mParserToUnblock && data->mDidBlockParser) {
|
||||
data->mParserToUnblock->EnableParser(PR_TRUE); // this may result in re-entrant calls to loader
|
||||
break;
|
||||
}
|
||||
data = data->mNext;
|
||||
} while (data);
|
||||
|
||||
// if all loads complete, put pending sheets into doc
|
||||
if (0 == mLoadingSheets.Count()) {
|
||||
PRInt32 count = mPendingDocSheets.Count();
|
||||
@ -569,14 +627,19 @@ CSSLoaderImpl::SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData)
|
||||
SheetLoadData* data = aLoadData;
|
||||
do { // add to parent sheet, parent doc or pending doc sheet list
|
||||
PrepareSheet(aSheet, data->mTitle, data->mMedia);
|
||||
if (data->mParentSheet) {
|
||||
if (data->mParentSheet) { // is child sheet
|
||||
InsertChildSheet(aSheet, data->mParentSheet, data->mSheetIndex);
|
||||
}
|
||||
else {
|
||||
if (data->mParserToUnblock || data->mIsInline) {
|
||||
else if (data->mIsAgent) { // is agent sheet
|
||||
if (data->mCallback) {
|
||||
(*(data->mCallback))(aSheet, data->mCallbackData);
|
||||
}
|
||||
}
|
||||
else { // doc sheet
|
||||
if (data->mParserToUnblock) { // if blocking, insert it immediately
|
||||
InsertSheetInDoc(aSheet, data->mSheetIndex, data->mOwningElement, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
else { // otherwise wait until all are loaded (even inlines)
|
||||
AddPendingSheet(aSheet, data->mSheetIndex, data->mOwningElement);
|
||||
}
|
||||
}
|
||||
@ -602,27 +665,30 @@ CSSLoaderImpl::SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData)
|
||||
nsresult
|
||||
CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aIn,
|
||||
SheetLoadData* aLoadData,
|
||||
PRBool& aCompleted)
|
||||
PRBool& aCompleted,
|
||||
nsICSSStyleSheet*& aSheet)
|
||||
{
|
||||
nsresult result;
|
||||
PRBool failed = PR_TRUE;
|
||||
|
||||
aCompleted = PR_TRUE;
|
||||
nsICSSStyleSheet* sheet = nsnull;
|
||||
result = NS_NewCSSStyleSheet(&sheet, aLoadData->mURL);
|
||||
aSheet = nsnull;
|
||||
result = NS_NewCSSStyleSheet(&aSheet, aLoadData->mURL);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsICSSParser* parser;
|
||||
result = GetParserFor(sheet, &parser);
|
||||
result = GetParserFor(aSheet, &parser);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mParsingData.AppendElement(aLoadData);
|
||||
result = parser->Parse(aIn, aLoadData->mURL, sheet); // this may result in re-entrant load child sheet calls
|
||||
result = parser->Parse(aIn, aLoadData->mURL, aSheet); // this may result in re-entrant load child sheet calls
|
||||
mParsingData.RemoveElementAt(mParsingData.Count() - 1);
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
failed = PR_FALSE;
|
||||
if (0 == aLoadData->mPendingChildren) { // sheet isn't still loading children
|
||||
if (aLoadData->mIsInline) {
|
||||
NS_IF_RELEASE(aLoadData->mParserToUnblock); // don't need to unblock, we're done and won't block
|
||||
aLoadData->mDidBlockParser = PR_FALSE; // don't need to unblock, we're done and won't block
|
||||
}
|
||||
SheetComplete(sheet, aLoadData);
|
||||
SheetComplete(aSheet, aLoadData);
|
||||
}
|
||||
else { // else sheet is still waiting for children to load, last child will complete it
|
||||
aCompleted = PR_FALSE;
|
||||
@ -630,7 +696,10 @@ CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aIn,
|
||||
}
|
||||
RecycleParser(parser);
|
||||
}
|
||||
NS_RELEASE(sheet);
|
||||
}
|
||||
if (failed) {
|
||||
URLKey key(aLoadData->mURL);
|
||||
Cleanup(key, aLoadData);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -649,10 +718,16 @@ CSSLoaderImpl::DidLoadStyle(nsIUnicharStreamLoader* aLoader,
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// XXX We have no way of indicating failure. Silently fail?
|
||||
PRBool completed;
|
||||
result = ParseSheet(uin, aLoadData, completed);
|
||||
nsICSSStyleSheet* sheet;
|
||||
result = ParseSheet(uin, aLoadData, completed, sheet);
|
||||
NS_IF_RELEASE(sheet);
|
||||
|
||||
NS_RELEASE(uin);
|
||||
}
|
||||
else {
|
||||
URLKey key(aLoadData->mURL);
|
||||
Cleanup(key, aLoadData);
|
||||
}
|
||||
}
|
||||
else { // load failed, cleanup
|
||||
URLKey key(aLoadData->mURL);
|
||||
@ -743,6 +818,7 @@ static PRBool MediumEnumFunc(const nsString& aSubString, void* aData)
|
||||
nsresult
|
||||
CSSLoaderImpl::SetMedia(nsICSSStyleSheet* aSheet, const nsString& aMedia)
|
||||
{
|
||||
aSheet->ClearMedia();
|
||||
if (0 < aMedia.Length()) {
|
||||
EnumerateMediaString(aMedia, MediumEnumFunc, aSheet);
|
||||
}
|
||||
@ -761,7 +837,7 @@ CSSLoaderImpl::PrepareSheet(nsICSSStyleSheet* aSheet, const nsString& aTitle,
|
||||
|
||||
nsresult
|
||||
CSSLoaderImpl::AddPendingSheet(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement)
|
||||
nsIContent* aElement)
|
||||
{
|
||||
PendingSheetData* data = new PendingSheetData(aSheet, aDocIndex, aElement);
|
||||
if (data) {
|
||||
@ -782,7 +858,7 @@ CSSLoaderImpl::IsAlternate(const nsString& aTitle)
|
||||
|
||||
nsresult
|
||||
CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement, PRBool aNotify)
|
||||
nsIContent* aElement, PRBool aNotify)
|
||||
{
|
||||
if ((! mDocument) || (! aSheet)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
@ -910,7 +986,7 @@ CSSLoaderImpl::LoadSheet(URLKey& aKey, SheetLoadData* aData)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement,
|
||||
nsIUnicharInputStream* aIn,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -918,6 +994,11 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted)
|
||||
{
|
||||
NS_ASSERTION(mDocument, "not initialized");
|
||||
if (! mDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX need to add code to cancel any pending sheets for element
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aIn) {
|
||||
@ -927,7 +1008,12 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
aElement,
|
||||
aDocIndex, aParserToUnblock,
|
||||
PR_TRUE);
|
||||
result = ParseSheet(aIn, data, aCompleted);
|
||||
nsICSSStyleSheet* sheet;
|
||||
result = ParseSheet(aIn, data, aCompleted, sheet);
|
||||
NS_IF_RELEASE(sheet);
|
||||
if ((! aCompleted) && (aParserToUnblock)) {
|
||||
data->mDidBlockParser = PR_TRUE;
|
||||
}
|
||||
NS_RELEASE(docURL);
|
||||
}
|
||||
return result;
|
||||
@ -935,7 +1021,7 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
CSSLoaderImpl::LoadStyleLink(nsIContent* aElement,
|
||||
nsIURL* aURL,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -943,6 +1029,11 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted)
|
||||
{
|
||||
NS_ASSERTION(mDocument, "not initialized");
|
||||
if (! mDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX need to add code to cancel any pending sheets for element
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
|
||||
@ -962,7 +1053,7 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
if (aParserToUnblock) { // stick it in now, parser is waiting for it
|
||||
result = InsertSheetInDoc(clone, aDocIndex, aElement, PR_TRUE);
|
||||
}
|
||||
else { // add to pending list?
|
||||
else { // add to pending list
|
||||
result = AddPendingSheet(clone, aDocIndex, aElement);
|
||||
}
|
||||
NS_RELEASE(clone);
|
||||
@ -982,6 +1073,9 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
result = LoadSheet(key, data);
|
||||
}
|
||||
aCompleted = PR_FALSE;
|
||||
if (aParserToUnblock) {
|
||||
data->mDidBlockParser = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -1039,6 +1133,34 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadAgentSheet(nsIURL* aURL,
|
||||
nsICSSStyleSheet*& aSheet,
|
||||
PRBool& aCompleted,
|
||||
nsCSSLoaderCallbackFunc aCallback,
|
||||
void *aData)
|
||||
{
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aURL) {
|
||||
// Get an input stream from the url
|
||||
nsIInputStream* in;
|
||||
result = NS_OpenURL(aURL, &in);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Translate the input using the argument character set id into unicode
|
||||
nsIUnicharInputStream* uin;
|
||||
result = NS_NewConverterStream(&uin, nsnull, in);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
SheetLoadData* data = new SheetLoadData(this, aURL, aCallback, aData);
|
||||
URLKey key(aURL);
|
||||
mLoadingSheets.Put(&key, data);
|
||||
result = ParseSheet(uin, data, aCompleted, aSheet);
|
||||
NS_RELEASE(uin);
|
||||
}
|
||||
NS_RELEASE(in);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsresult NS_NewCSSLoader(nsIDocument* aDocument, nsICSSLoader** aLoader)
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "nsICSSStyleSheet.h"
|
||||
|
||||
#include "nsIParser.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsIDocument.h"
|
||||
@ -134,10 +134,12 @@ public:
|
||||
struct SheetLoadData {
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
const nsString& aTitle, const nsString& aMedia,
|
||||
nsIHTMLContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIParser* aParserToUnblock, PRBool aIsInline);
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL, const nsString& aMedia,
|
||||
nsICSSStyleSheet* aParentSheet, PRInt32 aSheetIndex);
|
||||
SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL, nsCSSLoaderCallbackFunc aCallback,
|
||||
void* aData);
|
||||
~SheetLoadData(void);
|
||||
|
||||
CSSLoaderImpl* mLoader;
|
||||
@ -146,8 +148,9 @@ struct SheetLoadData {
|
||||
nsString mMedia;
|
||||
PRInt32 mSheetIndex;
|
||||
|
||||
nsIHTMLContent* mOwningElement;
|
||||
nsIContent* mOwningElement;
|
||||
nsIParser* mParserToUnblock;
|
||||
PRBool mDidBlockParser;
|
||||
|
||||
nsICSSStyleSheet* mParentSheet;
|
||||
|
||||
@ -157,11 +160,15 @@ struct SheetLoadData {
|
||||
PRUint32 mPendingChildren;
|
||||
|
||||
PRBool mIsInline;
|
||||
PRBool mIsAgent;
|
||||
|
||||
nsCSSLoaderCallbackFunc mCallback;
|
||||
void* mCallbackData;
|
||||
};
|
||||
|
||||
struct PendingSheetData {
|
||||
PendingSheetData(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement)
|
||||
nsIContent* aElement)
|
||||
: mSheet(aSheet),
|
||||
mDocIndex(aDocIndex),
|
||||
mOwningElement(aElement),
|
||||
@ -179,7 +186,7 @@ struct PendingSheetData {
|
||||
|
||||
nsICSSStyleSheet* mSheet;
|
||||
PRInt32 mDocIndex;
|
||||
nsIHTMLContent* mOwningElement;
|
||||
nsIContent* mOwningElement;
|
||||
PRBool mNotify;
|
||||
};
|
||||
|
||||
@ -191,6 +198,7 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Init(nsIDocument* aDocument);
|
||||
NS_IMETHOD DropDocumentReference(void);
|
||||
|
||||
NS_IMETHOD SetCaseSensitive(PRBool aCaseSensitive);
|
||||
NS_IMETHOD SetPreferredSheet(const nsString& aTitle);
|
||||
@ -199,7 +207,7 @@ public:
|
||||
nsICSSParser** aParser);
|
||||
NS_IMETHOD RecycleParser(nsICSSParser* aParser);
|
||||
|
||||
NS_IMETHOD LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
NS_IMETHOD LoadInlineStyle(nsIContent* aElement,
|
||||
nsIUnicharInputStream* aIn,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -207,7 +215,7 @@ public:
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted);
|
||||
|
||||
NS_IMETHOD LoadStyleLink(nsIHTMLContent* aElement,
|
||||
NS_IMETHOD LoadStyleLink(nsIContent* aElement,
|
||||
nsIURL* aURL,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -220,12 +228,18 @@ public:
|
||||
const nsString& aMedia,
|
||||
PRInt32 aIndex);
|
||||
|
||||
NS_IMETHOD LoadAgentSheet(nsIURL* aURL,
|
||||
nsICSSStyleSheet*& aSheet,
|
||||
PRBool& aCompleted,
|
||||
nsCSSLoaderCallbackFunc aCallback,
|
||||
void *aData);
|
||||
|
||||
// local helper methods (public for access from statics)
|
||||
void Cleanup(URLKey& aKey, SheetLoadData* aLoadData);
|
||||
nsresult SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData);
|
||||
|
||||
nsresult ParseSheet(nsIUnicharInputStream* aIn, SheetLoadData* aLoadData,
|
||||
PRBool& aCompleted);
|
||||
PRBool& aCompleted, nsICSSStyleSheet*& aSheet);
|
||||
|
||||
void DidLoadStyle(nsIUnicharStreamLoader* aLoader,
|
||||
nsString& aStyleData,
|
||||
@ -238,12 +252,12 @@ public:
|
||||
const nsString& aMedia);
|
||||
|
||||
nsresult AddPendingSheet(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement);
|
||||
nsIContent* aElement);
|
||||
|
||||
PRBool IsAlternate(const nsString& aTitle);
|
||||
|
||||
nsresult InsertSheetInDoc(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement, PRBool aNotify);
|
||||
nsIContent* aElement, PRBool aNotify);
|
||||
|
||||
nsresult InsertChildSheet(nsICSSStyleSheet* aSheet, nsICSSStyleSheet* aParentSheet,
|
||||
PRInt32 aIndex);
|
||||
@ -270,7 +284,7 @@ public:
|
||||
|
||||
SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
const nsString& aTitle, const nsString& aMedia,
|
||||
nsIHTMLContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIContent* aOwner, PRInt32 aDocIndex,
|
||||
nsIParser* aParserToUnblock, PRBool aIsInline)
|
||||
: mLoader(aLoader),
|
||||
mURL(aURL),
|
||||
@ -279,11 +293,15 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
mOwningElement(aOwner),
|
||||
mSheetIndex(aDocIndex),
|
||||
mParserToUnblock(aParserToUnblock),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(nsnull),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(aIsInline)
|
||||
mIsInline(aIsInline),
|
||||
mIsAgent(PR_FALSE),
|
||||
mCallback(nsnull),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
@ -301,17 +319,45 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
mSheetIndex(aSheetIndex),
|
||||
mOwningElement(nsnull),
|
||||
mParserToUnblock(nsnull),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(aParentSheet),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(PR_FALSE)
|
||||
mIsInline(PR_FALSE),
|
||||
mIsAgent(PR_FALSE),
|
||||
mCallback(nsnull),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
NS_ADDREF(mParentSheet);
|
||||
}
|
||||
|
||||
SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, nsIURL* aURL,
|
||||
nsCSSLoaderCallbackFunc aCallback, void* aData)
|
||||
: mLoader(aLoader),
|
||||
mURL(aURL),
|
||||
mTitle(),
|
||||
mMedia(),
|
||||
mSheetIndex(-1),
|
||||
mOwningElement(nsnull),
|
||||
mParserToUnblock(nsnull),
|
||||
mDidBlockParser(PR_FALSE),
|
||||
mParentSheet(nsnull),
|
||||
mNext(nsnull),
|
||||
mParentData(nsnull),
|
||||
mPendingChildren(0),
|
||||
mIsInline(PR_FALSE),
|
||||
mIsAgent(PR_TRUE),
|
||||
mCallback(aCallback),
|
||||
mCallbackData(nsnull)
|
||||
{
|
||||
NS_ADDREF(mLoader);
|
||||
NS_ADDREF(mURL);
|
||||
}
|
||||
|
||||
|
||||
SheetLoadData::~SheetLoadData(void)
|
||||
{
|
||||
NS_RELEASE(mLoader);
|
||||
@ -390,6 +436,13 @@ CSSLoaderImpl::Init(nsIDocument* aDocument)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::DropDocumentReference(void)
|
||||
{
|
||||
mDocument = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::SetCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
@ -510,7 +563,7 @@ AreAllPendingAlternateSheets(void* aPendingData, void* aLoader)
|
||||
void
|
||||
CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
{
|
||||
// unblock parser
|
||||
// notify any parents that child is done
|
||||
SheetLoadData* data = aLoadData;
|
||||
do {
|
||||
if (data->mParentData) {
|
||||
@ -519,11 +572,6 @@ CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
SheetComplete(data->mParentSheet, data->mParentData);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->mParserToUnblock) {
|
||||
data->mParserToUnblock->EnableParser(PR_TRUE);
|
||||
break;
|
||||
}
|
||||
data = data->mNext;
|
||||
} while (data);
|
||||
|
||||
@ -531,6 +579,16 @@ CSSLoaderImpl::Cleanup(URLKey& aKey, SheetLoadData* aLoadData)
|
||||
mLoadingSheets.Remove(&aKey);
|
||||
}
|
||||
|
||||
// unblock parser
|
||||
data = aLoadData;
|
||||
do {
|
||||
if (data->mParserToUnblock && data->mDidBlockParser) {
|
||||
data->mParserToUnblock->EnableParser(PR_TRUE); // this may result in re-entrant calls to loader
|
||||
break;
|
||||
}
|
||||
data = data->mNext;
|
||||
} while (data);
|
||||
|
||||
// if all loads complete, put pending sheets into doc
|
||||
if (0 == mLoadingSheets.Count()) {
|
||||
PRInt32 count = mPendingDocSheets.Count();
|
||||
@ -569,14 +627,19 @@ CSSLoaderImpl::SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData)
|
||||
SheetLoadData* data = aLoadData;
|
||||
do { // add to parent sheet, parent doc or pending doc sheet list
|
||||
PrepareSheet(aSheet, data->mTitle, data->mMedia);
|
||||
if (data->mParentSheet) {
|
||||
if (data->mParentSheet) { // is child sheet
|
||||
InsertChildSheet(aSheet, data->mParentSheet, data->mSheetIndex);
|
||||
}
|
||||
else {
|
||||
if (data->mParserToUnblock || data->mIsInline) {
|
||||
else if (data->mIsAgent) { // is agent sheet
|
||||
if (data->mCallback) {
|
||||
(*(data->mCallback))(aSheet, data->mCallbackData);
|
||||
}
|
||||
}
|
||||
else { // doc sheet
|
||||
if (data->mParserToUnblock) { // if blocking, insert it immediately
|
||||
InsertSheetInDoc(aSheet, data->mSheetIndex, data->mOwningElement, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
else { // otherwise wait until all are loaded (even inlines)
|
||||
AddPendingSheet(aSheet, data->mSheetIndex, data->mOwningElement);
|
||||
}
|
||||
}
|
||||
@ -602,27 +665,30 @@ CSSLoaderImpl::SheetComplete(nsICSSStyleSheet* aSheet, SheetLoadData* aLoadData)
|
||||
nsresult
|
||||
CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aIn,
|
||||
SheetLoadData* aLoadData,
|
||||
PRBool& aCompleted)
|
||||
PRBool& aCompleted,
|
||||
nsICSSStyleSheet*& aSheet)
|
||||
{
|
||||
nsresult result;
|
||||
PRBool failed = PR_TRUE;
|
||||
|
||||
aCompleted = PR_TRUE;
|
||||
nsICSSStyleSheet* sheet = nsnull;
|
||||
result = NS_NewCSSStyleSheet(&sheet, aLoadData->mURL);
|
||||
aSheet = nsnull;
|
||||
result = NS_NewCSSStyleSheet(&aSheet, aLoadData->mURL);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsICSSParser* parser;
|
||||
result = GetParserFor(sheet, &parser);
|
||||
result = GetParserFor(aSheet, &parser);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mParsingData.AppendElement(aLoadData);
|
||||
result = parser->Parse(aIn, aLoadData->mURL, sheet); // this may result in re-entrant load child sheet calls
|
||||
result = parser->Parse(aIn, aLoadData->mURL, aSheet); // this may result in re-entrant load child sheet calls
|
||||
mParsingData.RemoveElementAt(mParsingData.Count() - 1);
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
failed = PR_FALSE;
|
||||
if (0 == aLoadData->mPendingChildren) { // sheet isn't still loading children
|
||||
if (aLoadData->mIsInline) {
|
||||
NS_IF_RELEASE(aLoadData->mParserToUnblock); // don't need to unblock, we're done and won't block
|
||||
aLoadData->mDidBlockParser = PR_FALSE; // don't need to unblock, we're done and won't block
|
||||
}
|
||||
SheetComplete(sheet, aLoadData);
|
||||
SheetComplete(aSheet, aLoadData);
|
||||
}
|
||||
else { // else sheet is still waiting for children to load, last child will complete it
|
||||
aCompleted = PR_FALSE;
|
||||
@ -630,7 +696,10 @@ CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aIn,
|
||||
}
|
||||
RecycleParser(parser);
|
||||
}
|
||||
NS_RELEASE(sheet);
|
||||
}
|
||||
if (failed) {
|
||||
URLKey key(aLoadData->mURL);
|
||||
Cleanup(key, aLoadData);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -649,10 +718,16 @@ CSSLoaderImpl::DidLoadStyle(nsIUnicharStreamLoader* aLoader,
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// XXX We have no way of indicating failure. Silently fail?
|
||||
PRBool completed;
|
||||
result = ParseSheet(uin, aLoadData, completed);
|
||||
nsICSSStyleSheet* sheet;
|
||||
result = ParseSheet(uin, aLoadData, completed, sheet);
|
||||
NS_IF_RELEASE(sheet);
|
||||
|
||||
NS_RELEASE(uin);
|
||||
}
|
||||
else {
|
||||
URLKey key(aLoadData->mURL);
|
||||
Cleanup(key, aLoadData);
|
||||
}
|
||||
}
|
||||
else { // load failed, cleanup
|
||||
URLKey key(aLoadData->mURL);
|
||||
@ -743,6 +818,7 @@ static PRBool MediumEnumFunc(const nsString& aSubString, void* aData)
|
||||
nsresult
|
||||
CSSLoaderImpl::SetMedia(nsICSSStyleSheet* aSheet, const nsString& aMedia)
|
||||
{
|
||||
aSheet->ClearMedia();
|
||||
if (0 < aMedia.Length()) {
|
||||
EnumerateMediaString(aMedia, MediumEnumFunc, aSheet);
|
||||
}
|
||||
@ -761,7 +837,7 @@ CSSLoaderImpl::PrepareSheet(nsICSSStyleSheet* aSheet, const nsString& aTitle,
|
||||
|
||||
nsresult
|
||||
CSSLoaderImpl::AddPendingSheet(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement)
|
||||
nsIContent* aElement)
|
||||
{
|
||||
PendingSheetData* data = new PendingSheetData(aSheet, aDocIndex, aElement);
|
||||
if (data) {
|
||||
@ -782,7 +858,7 @@ CSSLoaderImpl::IsAlternate(const nsString& aTitle)
|
||||
|
||||
nsresult
|
||||
CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, PRInt32 aDocIndex,
|
||||
nsIHTMLContent* aElement, PRBool aNotify)
|
||||
nsIContent* aElement, PRBool aNotify)
|
||||
{
|
||||
if ((! mDocument) || (! aSheet)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
@ -910,7 +986,7 @@ CSSLoaderImpl::LoadSheet(URLKey& aKey, SheetLoadData* aData)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement,
|
||||
nsIUnicharInputStream* aIn,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -918,6 +994,11 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted)
|
||||
{
|
||||
NS_ASSERTION(mDocument, "not initialized");
|
||||
if (! mDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX need to add code to cancel any pending sheets for element
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aIn) {
|
||||
@ -927,7 +1008,12 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
aElement,
|
||||
aDocIndex, aParserToUnblock,
|
||||
PR_TRUE);
|
||||
result = ParseSheet(aIn, data, aCompleted);
|
||||
nsICSSStyleSheet* sheet;
|
||||
result = ParseSheet(aIn, data, aCompleted, sheet);
|
||||
NS_IF_RELEASE(sheet);
|
||||
if ((! aCompleted) && (aParserToUnblock)) {
|
||||
data->mDidBlockParser = PR_TRUE;
|
||||
}
|
||||
NS_RELEASE(docURL);
|
||||
}
|
||||
return result;
|
||||
@ -935,7 +1021,7 @@ CSSLoaderImpl::LoadInlineStyle(nsIHTMLContent* aElement,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
CSSLoaderImpl::LoadStyleLink(nsIContent* aElement,
|
||||
nsIURL* aURL,
|
||||
const nsString& aTitle,
|
||||
const nsString& aMedia,
|
||||
@ -943,6 +1029,11 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
nsIParser* aParserToUnblock,
|
||||
PRBool& aCompleted)
|
||||
{
|
||||
NS_ASSERTION(mDocument, "not initialized");
|
||||
if (! mDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX need to add code to cancel any pending sheets for element
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
|
||||
@ -962,7 +1053,7 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
if (aParserToUnblock) { // stick it in now, parser is waiting for it
|
||||
result = InsertSheetInDoc(clone, aDocIndex, aElement, PR_TRUE);
|
||||
}
|
||||
else { // add to pending list?
|
||||
else { // add to pending list
|
||||
result = AddPendingSheet(clone, aDocIndex, aElement);
|
||||
}
|
||||
NS_RELEASE(clone);
|
||||
@ -982,6 +1073,9 @@ CSSLoaderImpl::LoadStyleLink(nsIHTMLContent* aElement,
|
||||
result = LoadSheet(key, data);
|
||||
}
|
||||
aCompleted = PR_FALSE;
|
||||
if (aParserToUnblock) {
|
||||
data->mDidBlockParser = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -1039,6 +1133,34 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSLoaderImpl::LoadAgentSheet(nsIURL* aURL,
|
||||
nsICSSStyleSheet*& aSheet,
|
||||
PRBool& aCompleted,
|
||||
nsCSSLoaderCallbackFunc aCallback,
|
||||
void *aData)
|
||||
{
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aURL) {
|
||||
// Get an input stream from the url
|
||||
nsIInputStream* in;
|
||||
result = NS_OpenURL(aURL, &in);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Translate the input using the argument character set id into unicode
|
||||
nsIUnicharInputStream* uin;
|
||||
result = NS_NewConverterStream(&uin, nsnull, in);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
SheetLoadData* data = new SheetLoadData(this, aURL, aCallback, aData);
|
||||
URLKey key(aURL);
|
||||
mLoadingSheets.Put(&key, data);
|
||||
result = ParseSheet(uin, data, aCompleted, aSheet);
|
||||
NS_RELEASE(uin);
|
||||
}
|
||||
NS_RELEASE(in);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsresult NS_NewCSSLoader(nsIDocument* aDocument, nsICSSLoader** aLoader)
|
||||
|
Loading…
x
Reference in New Issue
Block a user