From a1f3e96bff401e3703f7f8d61f6ed0586e8ba7a6 Mon Sep 17 00:00:00 2001 From: "vidur%netscape.com" Date: Fri, 18 Dec 1998 01:36:41 +0000 Subject: [PATCH] Added asynchronous script and style loading to XML. Moved out stream loader to netlib. --- .../html/document/src/nsHTMLContentSink.cpp | 186 +++----------- content/xml/document/src/nsXMLContentSink.cpp | 239 +++++++++++++----- content/xml/document/src/nsXMLContentSink.h | 12 +- .../html/document/src/nsHTMLContentSink.cpp | 186 +++----------- layout/xml/document/src/nsXMLContentSink.cpp | 239 +++++++++++++----- layout/xml/document/src/nsXMLContentSink.h | 12 +- 6 files changed, 424 insertions(+), 450 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 0ea1e073a2e..0c9495cb454 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -19,6 +19,7 @@ #include "nsIParser.h" #include "nsICSSStyleSheet.h" #include "nsIUnicharInputStream.h" +#include "nsIUnicharStreamLoader.h" #include "nsIHTMLContent.h" #include "nsIURL.h" #include "nsIURLGroup.h" @@ -283,38 +284,6 @@ public: }; -class nsAccumulatingURLLoader; - -typedef void (*nsAccumulationDoneFunc)(nsAccumulatingURLLoader* aLoader, - nsString& aData, - void* aRef, - nsresult aStatus); - -class nsAccumulatingURLLoader : public nsIStreamListener { -public: - - nsAccumulatingURLLoader(nsIURL* aURL, - nsAccumulationDoneFunc aFunc, - void* aRef); - ~nsAccumulatingURLLoader(); - - NS_DECL_ISUPPORTS - - NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType); - NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax); - NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg); - NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult aStatus, const PRUnichar* aMsg); - NS_IMETHOD GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo); - NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream *aIStream, - PRUint32 aLength); - -protected: - nsIURL* mURL; - nsAccumulationDoneFunc mFunc; - void* mRef; - nsString* mData; -}; - //---------------------------------------------------------------------- static void @@ -2106,16 +2075,16 @@ typedef struct { nsIURL* mURL; nsIHTMLContent* mElement; HTMLContentSink* mSink; -} nsAsyncStyleProcessingData; +} nsAsyncStyleProcessingDataHTML; static void -nsDoneLoadingStyle(nsAccumulatingURLLoader* aLoader, +nsDoneLoadingStyle(nsIUnicharStreamLoader* aLoader, nsString& aData, void* aRef, nsresult aStatus) { nsresult rv = NS_OK; - nsAsyncStyleProcessingData* d = (nsAsyncStyleProcessingData*)aRef; + nsAsyncStyleProcessingDataHTML* d = (nsAsyncStyleProcessingDataHTML*)aRef; nsIUnicharInputStream* uin = nsnull; if ((NS_OK == aStatus) && (0 < aData.Length())) { @@ -2220,7 +2189,7 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode) return result; } - nsAsyncStyleProcessingData* d = new nsAsyncStyleProcessingData; + nsAsyncStyleProcessingDataHTML* d = new nsAsyncStyleProcessingDataHTML; if (nsnull == d) { return NS_ERROR_OUT_OF_MEMORY; } @@ -2234,12 +2203,15 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode) d->mSink = this; NS_ADDREF(this); - nsAccumulatingURLLoader* loader = - new nsAccumulatingURLLoader(url, - (nsAccumulationDoneFunc)nsDoneLoadingStyle, - (void *)d); + nsIUnicharStreamLoader* loader; + result = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingStyle, + (void *)d); NS_RELEASE(url); - result = NS_ERROR_HTMLPARSER_BLOCK; + if (NS_OK == result) { + result = NS_ERROR_HTMLPARSER_BLOCK; + } } } @@ -2385,7 +2357,7 @@ HTMLContentSink::EvaluateScript(nsString& aScript, } static void -nsDoneLoadingScript(nsAccumulatingURLLoader* aLoader, +nsDoneLoadingScript(nsIUnicharStreamLoader* aLoader, nsString& aData, void* aRef, nsresult aStatus) @@ -2444,7 +2416,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) // If there is a SRC attribute... if (src.Length() > 0) { - // Use the SRC attribute value to open an accumulating stream + // Use the SRC attribute value to load the URL nsIURL* url = nsnull; nsAutoString absURL; nsIURLGroup* urlGroup; @@ -2468,12 +2440,15 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) // onto it as opaque data. NS_ADDREF(this); - nsAccumulatingURLLoader* loader = - new nsAccumulatingURLLoader(url, - (nsAccumulationDoneFunc)nsDoneLoadingScript, + nsIUnicharStreamLoader* loader; + rv = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingScript, (void *)this); NS_RELEASE(url); - rv = NS_ERROR_HTMLPARSER_BLOCK; + if (NS_OK == rv) { + rv = NS_ERROR_HTMLPARSER_BLOCK; + } } else { // Otherwise, get the text content of the script tag @@ -2579,7 +2554,7 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) } else { // src with immediate style data doesn't add up // XXX what does nav do? - // Use the SRC attribute value to open an accumulating stream + // Use the SRC attribute value to load the URL nsAutoString absURL; nsIURLGroup* urlGroup; (void)mDocumentURL->GetURLGroup(&urlGroup); @@ -2598,7 +2573,7 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) return rv; } - nsAsyncStyleProcessingData* d = new nsAsyncStyleProcessingData; + nsAsyncStyleProcessingDataHTML* d = new nsAsyncStyleProcessingDataHTML; if (nsnull == d) { return NS_ERROR_OUT_OF_MEMORY; } @@ -2612,12 +2587,15 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) d->mSink = this; NS_ADDREF(this); - nsAccumulatingURLLoader* loader = - new nsAccumulatingURLLoader(url, - (nsAccumulationDoneFunc)nsDoneLoadingStyle, - (void *)d); + nsIUnicharStreamLoader* loader; + rv = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingStyle, + (void *)d); NS_RELEASE(url); - rv = NS_ERROR_HTMLPARSER_BLOCK; + if (NS_OK == rv) { + rv = NS_ERROR_HTMLPARSER_BLOCK; + } } NS_RELEASE(element); @@ -2748,103 +2726,3 @@ HTMLContentSink::NotifyError(nsresult aErrorResult) PR_ASSERT(0); return NS_OK; } - -//---------------------------------------------------------------------- - -nsAccumulatingURLLoader::nsAccumulatingURLLoader(nsIURL* aURL, - nsAccumulationDoneFunc aFunc, - void* aRef) -{ - mFunc = aFunc; - mRef = aRef; - mData = new nsString(); - - nsresult rv; - if (aURL) { - rv = NS_OpenURL(aURL, this); - if ((NS_OK != rv) && (nsnull != mFunc)) { - (*mFunc)(this, *mData, mRef, rv); - } - } -} - -nsAccumulatingURLLoader::~nsAccumulatingURLLoader() -{ - if (nsnull != mData) { - delete mData; - } -} - -NS_IMPL_ISUPPORTS(nsAccumulatingURLLoader, kIStreamListenerIID) - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnStartBinding(nsIURL* aURL, - const char *aContentType) -{ - // XXX Should check content type? - - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnProgress(nsIURL* aURL, - PRUint32 aProgress, - PRUint32 aProgressMax) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnStatus(nsIURL* aURL, const PRUnichar* aMsg) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnStopBinding(nsIURL* aURL, - nsresult aStatus, - const PRUnichar* aMsg) -{ - (*mFunc)(this, *mData, mRef, aStatus); - - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo) -{ - return NS_OK; -} - -#define BUF_SIZE 1024 - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnDataAvailable(nsIURL* aURL, - nsIInputStream *aIStream, - PRUint32 aLength) -{ - nsresult rv = NS_OK; - char buffer[BUF_SIZE]; - PRUint32 len, lenRead; - - aIStream->GetLength(&len); - - while (len > 0) { - if (len < BUF_SIZE) { - lenRead = len; - } - else { - lenRead = BUF_SIZE; - } - - rv = aIStream->Read(buffer, 0, lenRead, &lenRead); - if (NS_OK != rv) { - return rv; - } - - mData->Append(buffer, lenRead); - len -= lenRead; - } - - return rv; -} diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index cc8cbb58b4d..795ffb059d4 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -20,11 +20,13 @@ #include "nsXMLContentSink.h" #include "nsIParser.h" #include "nsIUnicharInputStream.h" +#include "nsIUnicharStreamLoader.h" #include "nsIDocument.h" #include "nsIXMLDocument.h" #include "nsIXMLContent.h" #include "nsIScriptObjectOwner.h" #include "nsIURL.h" +#include "nsIURLGroup.h" #include "nsIWebShell.h" #include "nsIContent.h" #include "nsITextContent.h" @@ -59,6 +61,7 @@ static NS_DEFINE_IID(kIXMLContentSinkIID, NS_IXMLCONTENT_SINK_IID); static NS_DEFINE_IID(kIXMLDocumentIID, NS_IXMLDOCUMENT_IID); static NS_DEFINE_IID(kIDOMCommentIID, NS_IDOMCOMMENT_IID); static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); #define XML_PSEUDO_ELEMENT 0 @@ -733,9 +736,13 @@ nsXMLContentSink::AddComment(const nsIParserNode& aNode) } // XXX Borrowed from HTMLContentSink. Should be shared. -nsresult +NS_IMETHODIMP nsXMLContentSink::LoadStyleSheet(nsIURL* aURL, - nsIUnicharInputStream* aUIN) + nsIUnicharInputStream* aUIN, + PRBool aActive, + const nsString& aTitle, + const nsString& aMedia, + nsIContent* aOwner) { /* XXX use repository */ nsICSSParser* parser; @@ -747,7 +754,16 @@ nsXMLContentSink::LoadStyleSheet(nsIURL* aURL, parser->SetCaseSensative(PR_TRUE); parser->Parse(aUIN, aURL, sheet); if (nsnull != sheet) { + sheet->SetTitle(aTitle); + sheet->SetEnabled(aActive); mDocument->AddStyleSheet(sheet); + if (nsnull != aOwner) { + nsIDOMNode* domNode = nsnull; + if (NS_SUCCEEDED(aOwner->QueryInterface(kIDOMNodeIID, (void**)&domNode))) { + sheet->SetOwningNode(domNode); + NS_RELEASE(domNode); + } + } NS_RELEASE(sheet); rv = NS_OK; } else { @@ -794,6 +810,48 @@ GetQuotedAttributeValue(nsString& aSource, return result; } +typedef struct { + nsString mTitle; + nsString mMedia; + PRBool mIsActive; + nsIURL* mURL; + nsIContent* mElement; + nsXMLContentSink* mSink; +} nsAsyncStyleProcessingDataXML; + +static void +nsDoneLoadingStyle(nsIUnicharStreamLoader* aLoader, + nsString& aData, + void* aRef, + nsresult aStatus) +{ + nsresult rv = NS_OK; + nsAsyncStyleProcessingDataXML* d = (nsAsyncStyleProcessingDataXML*)aRef; + nsIUnicharInputStream* uin = nsnull; + + if ((NS_OK == aStatus) && (0 < aData.Length())) { + // wrap the string with the CSS data up in a unicode + // input stream. + rv = NS_NewStringUnicharInputStream(&uin, new nsString(aData)); + if (NS_OK == rv) { + // XXX We have no way of indicating failure. Silently fail? + rv = d->mSink->LoadStyleSheet(d->mURL, uin, d->mIsActive, + d->mTitle, d->mMedia, d->mElement); + } + } + + d->mSink->ResumeParsing(); + + NS_RELEASE(d->mURL); + NS_IF_RELEASE(d->mElement); + NS_RELEASE(d->mSink); + delete d; + + // We added a reference when the loader was created. This + // release should destroy it. + NS_RELEASE(aLoader); +} + NS_IMETHODIMP nsXMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) { @@ -801,7 +859,7 @@ nsXMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) // XXX For now, we don't add the PI to the content model. // We just check for a style sheet PI - nsAutoString text, type, href; + nsAutoString text, type, href, title, media; PRInt32 offset; nsresult result = NS_OK; @@ -821,39 +879,61 @@ nsXMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) if (NS_OK != result) { return result; } - + result = GetQuotedAttributeValue(text, "title", title); + if (NS_OK != result) { + return result; + } + title.CompressWhitespace(); + result = GetQuotedAttributeValue(text, "media", media); + if (NS_OK != result) { + return result; + } + media.ToUpperCase(); + if (type.Equals(kCSSType)) { + // Use the SRC attribute value to load the URL nsIURL* url = nsnull; - nsIUnicharInputStream* uin = nsnull; nsAutoString absURL; nsIURL* docURL = mDocument->GetDocumentURL(); - nsAutoString emptyURL; - emptyURL.Truncate(); - result = NS_MakeAbsoluteURL(docURL, emptyURL, href, absURL); - if (NS_OK != result) { - return result; + nsIURLGroup* urlGroup; + + result = docURL->GetURLGroup(&urlGroup); + + if ((NS_OK == result) && urlGroup) { + result = urlGroup->CreateURL(&url, docURL, href, nsnull); + NS_RELEASE(urlGroup); + } + else { + result = NS_NewURL(&url, absURL); } NS_RELEASE(docURL); - result = NS_NewURL(&url, absURL); if (NS_OK != result) { return result; } - nsIInputStream* iin; - result = NS_OpenURL(url, &iin); - if (NS_OK != result) { - NS_RELEASE(url); - return result; + + nsAsyncStyleProcessingDataXML* d = new nsAsyncStyleProcessingDataXML; + if (nsnull == d) { + return NS_ERROR_OUT_OF_MEMORY; } - result = NS_NewConverterStream(&uin, nsnull, iin); - NS_RELEASE(iin); - if (NS_OK != result) { - NS_RELEASE(url); - return result; - } - - result = LoadStyleSheet(url, uin); - NS_RELEASE(uin); + d->mTitle.SetString(title); + d->mMedia.SetString(media); + d->mIsActive = PR_TRUE; + d->mURL = url; + NS_ADDREF(url); + // XXX Need to create PI node + d->mElement = nsnull; + d->mSink = this; + NS_ADDREF(this); + + nsIUnicharStreamLoader* loader; + result = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingStyle, + (void *)d); NS_RELEASE(url); + if (NS_OK == result) { + result = NS_ERROR_HTMLPARSER_BLOCK; + } } } @@ -901,6 +981,8 @@ nsXMLContentSink::FlushText(PRBool aCreateTextNode, PRBool* aDidFlush) return rv; } +#define NS_ACCUMULATION_BUFFER_SIZE 4096 + NS_IMETHODIMP nsXMLContentSink::AddCharacterData(const nsIParserNode& aNode) { @@ -913,11 +995,11 @@ nsXMLContentSink::AddCharacterData(const nsIParserNode& aNode) // Create buffer when we first need it if (0 == mTextSize) { - mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * 4096); + mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * NS_ACCUMULATION_BUFFER_SIZE); if (nsnull == mText) { return NS_ERROR_OUT_OF_MEMORY; } - mTextSize = 4096; + mTextSize = NS_ACCUMULATION_BUFFER_SIZE; } // Copy data from string into our buffer; flush buffer when it fills up @@ -1110,7 +1192,17 @@ nsXMLContentSink::StartLayout() } } -nsresult +NS_IMETHODIMP +nsXMLContentSink::ResumeParsing() +{ + if (nsnull != mParser) { + mParser->EnableParser(PR_TRUE); + } + + return NS_OK; +} + +NS_IMETHODIMP nsXMLContentSink::EvaluateScript(nsString& aScript, PRUint32 aLineNo) { nsresult rv = NS_OK; @@ -1194,6 +1286,29 @@ IsJavaScriptLanguage(const nsString& aName) } } +static void +nsDoneLoadingScript(nsIUnicharStreamLoader* aLoader, + nsString& aData, + void* aRef, + nsresult aStatus) +{ + nsXMLContentSink* sink = (nsXMLContentSink*)aRef; + + if (NS_OK == aStatus) { + // XXX We have no way of indicating failure. Silently fail? + sink->EvaluateScript(aData, 0); + } + + sink->ResumeParsing(); + + // The url loader held a reference to the sink + NS_RELEASE(sink); + + // We added a reference when the loader was created. This + // release should destroy it. + NS_RELEASE(aLoader); +} + nsresult nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) { @@ -1206,8 +1321,7 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) for (i = 0; i < ac; i++) { const nsString& key = aNode.GetKeyAt(i); if (key.EqualsIgnoreCase("src")) { - src = aNode.GetValueAt(i); - src.Trim("\"", PR_TRUE, PR_TRUE); + GetAttributeValueAt(aNode, i, src); } else if (key.EqualsIgnoreCase("type")) { nsAutoString type; @@ -1226,53 +1340,42 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) // Don't process scripts that aren't JavaScript if (isJavaScript) { nsAutoString script; - - // If there is a SRC attribute, (for now) read from the - // stream synchronously and hold the data in a string. - if (src != "") { - // Use the SRC attribute value to open a blocking stream + + // If there is a SRC attribute... + if (src.Length() > 0) { + // Use the SRC attribute value to load the URL nsIURL* url = nsnull; nsAutoString absURL; nsIURL* docURL = mDocument->GetDocumentURL(); - nsAutoString emptyURL; - emptyURL.Truncate(); - rv = NS_MakeAbsoluteURL(docURL, emptyURL, src, absURL); - if (NS_OK != rv) { - return rv; + nsIURLGroup* urlGroup; + + rv = docURL->GetURLGroup(&urlGroup); + + if ((NS_OK == rv) && urlGroup) { + rv = urlGroup->CreateURL(&url, docURL, src, nsnull); + NS_RELEASE(urlGroup); + } + else { + rv = NS_NewURL(&url, absURL); } NS_RELEASE(docURL); - rv = NS_NewURL(&url, absURL); if (NS_OK != rv) { return rv; } - nsIInputStream* iin; - rv = NS_OpenURL(url, &iin); - if (NS_OK != rv) { - NS_RELEASE(url); - return rv; - } - - // Drain the stream by reading from it a chunk at a time - PRUint32 nb; - nsresult err; - do { - char buf[SCRIPT_BUF_SIZE]; - - err = iin->Read(buf, 0, SCRIPT_BUF_SIZE, &nb); - if (NS_OK == err) { - script.Append((const char *)buf, nb); - } - } while (err == NS_OK); - - if (NS_BASE_STREAM_EOF != err) { - rv = NS_ERROR_FAILURE; - } - - NS_RELEASE(iin); + + // Add a reference to this since the url loader is holding + // onto it as opaque data. + NS_ADDREF(this); + + nsIUnicharStreamLoader* loader; + rv = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingScript, + (void *)this); NS_RELEASE(url); - - rv = EvaluateScript(script, (PRUint32)aNode.GetSourceLineNumber()); - + if (NS_OK == rv) { + rv = NS_ERROR_HTMLPARSER_BLOCK; + } } else { // Wait until we get the script content diff --git a/content/xml/document/src/nsXMLContentSink.h b/content/xml/document/src/nsXMLContentSink.h index e0e3433c381..151c4ef148b 100644 --- a/content/xml/document/src/nsXMLContentSink.h +++ b/content/xml/document/src/nsXMLContentSink.h @@ -76,11 +76,18 @@ public: NS_IMETHOD AddNotation(const nsIParserNode& aNode); NS_IMETHOD AddEntityReference(const nsIParserNode& aNode); + NS_IMETHOD ResumeParsing(); + NS_IMETHOD LoadStyleSheet(nsIURL* aURL, + nsIUnicharInputStream* aUIN, + PRBool aActive, + const nsString& aTitle, + const nsString& aMedia, + nsIContent* aOwner); + NS_IMETHOD EvaluateScript(nsString& aScript, PRUint32 aLineNo); + protected: void StartLayout(); - nsresult LoadStyleSheet(nsIURL* aURL, - nsIUnicharInputStream* aUIN); nsresult FlushText(PRBool aCreateTextNode=PR_TRUE, PRBool* aDidFlush=nsnull); @@ -95,7 +102,6 @@ protected: PRInt32 PushContent(nsIContent *aContent); nsIContent* PopContent(); - nsresult EvaluateScript(nsString& aScript, PRUint32 aLineNo); nsresult ProcessEndSCRIPTTag(const nsIParserNode& aNode); nsresult ProcessStartSCRIPTTag(const nsIParserNode& aNode); diff --git a/layout/html/document/src/nsHTMLContentSink.cpp b/layout/html/document/src/nsHTMLContentSink.cpp index 0ea1e073a2e..0c9495cb454 100644 --- a/layout/html/document/src/nsHTMLContentSink.cpp +++ b/layout/html/document/src/nsHTMLContentSink.cpp @@ -19,6 +19,7 @@ #include "nsIParser.h" #include "nsICSSStyleSheet.h" #include "nsIUnicharInputStream.h" +#include "nsIUnicharStreamLoader.h" #include "nsIHTMLContent.h" #include "nsIURL.h" #include "nsIURLGroup.h" @@ -283,38 +284,6 @@ public: }; -class nsAccumulatingURLLoader; - -typedef void (*nsAccumulationDoneFunc)(nsAccumulatingURLLoader* aLoader, - nsString& aData, - void* aRef, - nsresult aStatus); - -class nsAccumulatingURLLoader : public nsIStreamListener { -public: - - nsAccumulatingURLLoader(nsIURL* aURL, - nsAccumulationDoneFunc aFunc, - void* aRef); - ~nsAccumulatingURLLoader(); - - NS_DECL_ISUPPORTS - - NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType); - NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax); - NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg); - NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult aStatus, const PRUnichar* aMsg); - NS_IMETHOD GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo); - NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream *aIStream, - PRUint32 aLength); - -protected: - nsIURL* mURL; - nsAccumulationDoneFunc mFunc; - void* mRef; - nsString* mData; -}; - //---------------------------------------------------------------------- static void @@ -2106,16 +2075,16 @@ typedef struct { nsIURL* mURL; nsIHTMLContent* mElement; HTMLContentSink* mSink; -} nsAsyncStyleProcessingData; +} nsAsyncStyleProcessingDataHTML; static void -nsDoneLoadingStyle(nsAccumulatingURLLoader* aLoader, +nsDoneLoadingStyle(nsIUnicharStreamLoader* aLoader, nsString& aData, void* aRef, nsresult aStatus) { nsresult rv = NS_OK; - nsAsyncStyleProcessingData* d = (nsAsyncStyleProcessingData*)aRef; + nsAsyncStyleProcessingDataHTML* d = (nsAsyncStyleProcessingDataHTML*)aRef; nsIUnicharInputStream* uin = nsnull; if ((NS_OK == aStatus) && (0 < aData.Length())) { @@ -2220,7 +2189,7 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode) return result; } - nsAsyncStyleProcessingData* d = new nsAsyncStyleProcessingData; + nsAsyncStyleProcessingDataHTML* d = new nsAsyncStyleProcessingDataHTML; if (nsnull == d) { return NS_ERROR_OUT_OF_MEMORY; } @@ -2234,12 +2203,15 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode) d->mSink = this; NS_ADDREF(this); - nsAccumulatingURLLoader* loader = - new nsAccumulatingURLLoader(url, - (nsAccumulationDoneFunc)nsDoneLoadingStyle, - (void *)d); + nsIUnicharStreamLoader* loader; + result = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingStyle, + (void *)d); NS_RELEASE(url); - result = NS_ERROR_HTMLPARSER_BLOCK; + if (NS_OK == result) { + result = NS_ERROR_HTMLPARSER_BLOCK; + } } } @@ -2385,7 +2357,7 @@ HTMLContentSink::EvaluateScript(nsString& aScript, } static void -nsDoneLoadingScript(nsAccumulatingURLLoader* aLoader, +nsDoneLoadingScript(nsIUnicharStreamLoader* aLoader, nsString& aData, void* aRef, nsresult aStatus) @@ -2444,7 +2416,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) // If there is a SRC attribute... if (src.Length() > 0) { - // Use the SRC attribute value to open an accumulating stream + // Use the SRC attribute value to load the URL nsIURL* url = nsnull; nsAutoString absURL; nsIURLGroup* urlGroup; @@ -2468,12 +2440,15 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) // onto it as opaque data. NS_ADDREF(this); - nsAccumulatingURLLoader* loader = - new nsAccumulatingURLLoader(url, - (nsAccumulationDoneFunc)nsDoneLoadingScript, + nsIUnicharStreamLoader* loader; + rv = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingScript, (void *)this); NS_RELEASE(url); - rv = NS_ERROR_HTMLPARSER_BLOCK; + if (NS_OK == rv) { + rv = NS_ERROR_HTMLPARSER_BLOCK; + } } else { // Otherwise, get the text content of the script tag @@ -2579,7 +2554,7 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) } else { // src with immediate style data doesn't add up // XXX what does nav do? - // Use the SRC attribute value to open an accumulating stream + // Use the SRC attribute value to load the URL nsAutoString absURL; nsIURLGroup* urlGroup; (void)mDocumentURL->GetURLGroup(&urlGroup); @@ -2598,7 +2573,7 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) return rv; } - nsAsyncStyleProcessingData* d = new nsAsyncStyleProcessingData; + nsAsyncStyleProcessingDataHTML* d = new nsAsyncStyleProcessingDataHTML; if (nsnull == d) { return NS_ERROR_OUT_OF_MEMORY; } @@ -2612,12 +2587,15 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) d->mSink = this; NS_ADDREF(this); - nsAccumulatingURLLoader* loader = - new nsAccumulatingURLLoader(url, - (nsAccumulationDoneFunc)nsDoneLoadingStyle, - (void *)d); + nsIUnicharStreamLoader* loader; + rv = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingStyle, + (void *)d); NS_RELEASE(url); - rv = NS_ERROR_HTMLPARSER_BLOCK; + if (NS_OK == rv) { + rv = NS_ERROR_HTMLPARSER_BLOCK; + } } NS_RELEASE(element); @@ -2748,103 +2726,3 @@ HTMLContentSink::NotifyError(nsresult aErrorResult) PR_ASSERT(0); return NS_OK; } - -//---------------------------------------------------------------------- - -nsAccumulatingURLLoader::nsAccumulatingURLLoader(nsIURL* aURL, - nsAccumulationDoneFunc aFunc, - void* aRef) -{ - mFunc = aFunc; - mRef = aRef; - mData = new nsString(); - - nsresult rv; - if (aURL) { - rv = NS_OpenURL(aURL, this); - if ((NS_OK != rv) && (nsnull != mFunc)) { - (*mFunc)(this, *mData, mRef, rv); - } - } -} - -nsAccumulatingURLLoader::~nsAccumulatingURLLoader() -{ - if (nsnull != mData) { - delete mData; - } -} - -NS_IMPL_ISUPPORTS(nsAccumulatingURLLoader, kIStreamListenerIID) - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnStartBinding(nsIURL* aURL, - const char *aContentType) -{ - // XXX Should check content type? - - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnProgress(nsIURL* aURL, - PRUint32 aProgress, - PRUint32 aProgressMax) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnStatus(nsIURL* aURL, const PRUnichar* aMsg) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnStopBinding(nsIURL* aURL, - nsresult aStatus, - const PRUnichar* aMsg) -{ - (*mFunc)(this, *mData, mRef, aStatus); - - return NS_OK; -} - -NS_IMETHODIMP -nsAccumulatingURLLoader::GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo) -{ - return NS_OK; -} - -#define BUF_SIZE 1024 - -NS_IMETHODIMP -nsAccumulatingURLLoader::OnDataAvailable(nsIURL* aURL, - nsIInputStream *aIStream, - PRUint32 aLength) -{ - nsresult rv = NS_OK; - char buffer[BUF_SIZE]; - PRUint32 len, lenRead; - - aIStream->GetLength(&len); - - while (len > 0) { - if (len < BUF_SIZE) { - lenRead = len; - } - else { - lenRead = BUF_SIZE; - } - - rv = aIStream->Read(buffer, 0, lenRead, &lenRead); - if (NS_OK != rv) { - return rv; - } - - mData->Append(buffer, lenRead); - len -= lenRead; - } - - return rv; -} diff --git a/layout/xml/document/src/nsXMLContentSink.cpp b/layout/xml/document/src/nsXMLContentSink.cpp index cc8cbb58b4d..795ffb059d4 100644 --- a/layout/xml/document/src/nsXMLContentSink.cpp +++ b/layout/xml/document/src/nsXMLContentSink.cpp @@ -20,11 +20,13 @@ #include "nsXMLContentSink.h" #include "nsIParser.h" #include "nsIUnicharInputStream.h" +#include "nsIUnicharStreamLoader.h" #include "nsIDocument.h" #include "nsIXMLDocument.h" #include "nsIXMLContent.h" #include "nsIScriptObjectOwner.h" #include "nsIURL.h" +#include "nsIURLGroup.h" #include "nsIWebShell.h" #include "nsIContent.h" #include "nsITextContent.h" @@ -59,6 +61,7 @@ static NS_DEFINE_IID(kIXMLContentSinkIID, NS_IXMLCONTENT_SINK_IID); static NS_DEFINE_IID(kIXMLDocumentIID, NS_IXMLDOCUMENT_IID); static NS_DEFINE_IID(kIDOMCommentIID, NS_IDOMCOMMENT_IID); static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); #define XML_PSEUDO_ELEMENT 0 @@ -733,9 +736,13 @@ nsXMLContentSink::AddComment(const nsIParserNode& aNode) } // XXX Borrowed from HTMLContentSink. Should be shared. -nsresult +NS_IMETHODIMP nsXMLContentSink::LoadStyleSheet(nsIURL* aURL, - nsIUnicharInputStream* aUIN) + nsIUnicharInputStream* aUIN, + PRBool aActive, + const nsString& aTitle, + const nsString& aMedia, + nsIContent* aOwner) { /* XXX use repository */ nsICSSParser* parser; @@ -747,7 +754,16 @@ nsXMLContentSink::LoadStyleSheet(nsIURL* aURL, parser->SetCaseSensative(PR_TRUE); parser->Parse(aUIN, aURL, sheet); if (nsnull != sheet) { + sheet->SetTitle(aTitle); + sheet->SetEnabled(aActive); mDocument->AddStyleSheet(sheet); + if (nsnull != aOwner) { + nsIDOMNode* domNode = nsnull; + if (NS_SUCCEEDED(aOwner->QueryInterface(kIDOMNodeIID, (void**)&domNode))) { + sheet->SetOwningNode(domNode); + NS_RELEASE(domNode); + } + } NS_RELEASE(sheet); rv = NS_OK; } else { @@ -794,6 +810,48 @@ GetQuotedAttributeValue(nsString& aSource, return result; } +typedef struct { + nsString mTitle; + nsString mMedia; + PRBool mIsActive; + nsIURL* mURL; + nsIContent* mElement; + nsXMLContentSink* mSink; +} nsAsyncStyleProcessingDataXML; + +static void +nsDoneLoadingStyle(nsIUnicharStreamLoader* aLoader, + nsString& aData, + void* aRef, + nsresult aStatus) +{ + nsresult rv = NS_OK; + nsAsyncStyleProcessingDataXML* d = (nsAsyncStyleProcessingDataXML*)aRef; + nsIUnicharInputStream* uin = nsnull; + + if ((NS_OK == aStatus) && (0 < aData.Length())) { + // wrap the string with the CSS data up in a unicode + // input stream. + rv = NS_NewStringUnicharInputStream(&uin, new nsString(aData)); + if (NS_OK == rv) { + // XXX We have no way of indicating failure. Silently fail? + rv = d->mSink->LoadStyleSheet(d->mURL, uin, d->mIsActive, + d->mTitle, d->mMedia, d->mElement); + } + } + + d->mSink->ResumeParsing(); + + NS_RELEASE(d->mURL); + NS_IF_RELEASE(d->mElement); + NS_RELEASE(d->mSink); + delete d; + + // We added a reference when the loader was created. This + // release should destroy it. + NS_RELEASE(aLoader); +} + NS_IMETHODIMP nsXMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) { @@ -801,7 +859,7 @@ nsXMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) // XXX For now, we don't add the PI to the content model. // We just check for a style sheet PI - nsAutoString text, type, href; + nsAutoString text, type, href, title, media; PRInt32 offset; nsresult result = NS_OK; @@ -821,39 +879,61 @@ nsXMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) if (NS_OK != result) { return result; } - + result = GetQuotedAttributeValue(text, "title", title); + if (NS_OK != result) { + return result; + } + title.CompressWhitespace(); + result = GetQuotedAttributeValue(text, "media", media); + if (NS_OK != result) { + return result; + } + media.ToUpperCase(); + if (type.Equals(kCSSType)) { + // Use the SRC attribute value to load the URL nsIURL* url = nsnull; - nsIUnicharInputStream* uin = nsnull; nsAutoString absURL; nsIURL* docURL = mDocument->GetDocumentURL(); - nsAutoString emptyURL; - emptyURL.Truncate(); - result = NS_MakeAbsoluteURL(docURL, emptyURL, href, absURL); - if (NS_OK != result) { - return result; + nsIURLGroup* urlGroup; + + result = docURL->GetURLGroup(&urlGroup); + + if ((NS_OK == result) && urlGroup) { + result = urlGroup->CreateURL(&url, docURL, href, nsnull); + NS_RELEASE(urlGroup); + } + else { + result = NS_NewURL(&url, absURL); } NS_RELEASE(docURL); - result = NS_NewURL(&url, absURL); if (NS_OK != result) { return result; } - nsIInputStream* iin; - result = NS_OpenURL(url, &iin); - if (NS_OK != result) { - NS_RELEASE(url); - return result; + + nsAsyncStyleProcessingDataXML* d = new nsAsyncStyleProcessingDataXML; + if (nsnull == d) { + return NS_ERROR_OUT_OF_MEMORY; } - result = NS_NewConverterStream(&uin, nsnull, iin); - NS_RELEASE(iin); - if (NS_OK != result) { - NS_RELEASE(url); - return result; - } - - result = LoadStyleSheet(url, uin); - NS_RELEASE(uin); + d->mTitle.SetString(title); + d->mMedia.SetString(media); + d->mIsActive = PR_TRUE; + d->mURL = url; + NS_ADDREF(url); + // XXX Need to create PI node + d->mElement = nsnull; + d->mSink = this; + NS_ADDREF(this); + + nsIUnicharStreamLoader* loader; + result = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingStyle, + (void *)d); NS_RELEASE(url); + if (NS_OK == result) { + result = NS_ERROR_HTMLPARSER_BLOCK; + } } } @@ -901,6 +981,8 @@ nsXMLContentSink::FlushText(PRBool aCreateTextNode, PRBool* aDidFlush) return rv; } +#define NS_ACCUMULATION_BUFFER_SIZE 4096 + NS_IMETHODIMP nsXMLContentSink::AddCharacterData(const nsIParserNode& aNode) { @@ -913,11 +995,11 @@ nsXMLContentSink::AddCharacterData(const nsIParserNode& aNode) // Create buffer when we first need it if (0 == mTextSize) { - mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * 4096); + mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * NS_ACCUMULATION_BUFFER_SIZE); if (nsnull == mText) { return NS_ERROR_OUT_OF_MEMORY; } - mTextSize = 4096; + mTextSize = NS_ACCUMULATION_BUFFER_SIZE; } // Copy data from string into our buffer; flush buffer when it fills up @@ -1110,7 +1192,17 @@ nsXMLContentSink::StartLayout() } } -nsresult +NS_IMETHODIMP +nsXMLContentSink::ResumeParsing() +{ + if (nsnull != mParser) { + mParser->EnableParser(PR_TRUE); + } + + return NS_OK; +} + +NS_IMETHODIMP nsXMLContentSink::EvaluateScript(nsString& aScript, PRUint32 aLineNo) { nsresult rv = NS_OK; @@ -1194,6 +1286,29 @@ IsJavaScriptLanguage(const nsString& aName) } } +static void +nsDoneLoadingScript(nsIUnicharStreamLoader* aLoader, + nsString& aData, + void* aRef, + nsresult aStatus) +{ + nsXMLContentSink* sink = (nsXMLContentSink*)aRef; + + if (NS_OK == aStatus) { + // XXX We have no way of indicating failure. Silently fail? + sink->EvaluateScript(aData, 0); + } + + sink->ResumeParsing(); + + // The url loader held a reference to the sink + NS_RELEASE(sink); + + // We added a reference when the loader was created. This + // release should destroy it. + NS_RELEASE(aLoader); +} + nsresult nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) { @@ -1206,8 +1321,7 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) for (i = 0; i < ac; i++) { const nsString& key = aNode.GetKeyAt(i); if (key.EqualsIgnoreCase("src")) { - src = aNode.GetValueAt(i); - src.Trim("\"", PR_TRUE, PR_TRUE); + GetAttributeValueAt(aNode, i, src); } else if (key.EqualsIgnoreCase("type")) { nsAutoString type; @@ -1226,53 +1340,42 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) // Don't process scripts that aren't JavaScript if (isJavaScript) { nsAutoString script; - - // If there is a SRC attribute, (for now) read from the - // stream synchronously and hold the data in a string. - if (src != "") { - // Use the SRC attribute value to open a blocking stream + + // If there is a SRC attribute... + if (src.Length() > 0) { + // Use the SRC attribute value to load the URL nsIURL* url = nsnull; nsAutoString absURL; nsIURL* docURL = mDocument->GetDocumentURL(); - nsAutoString emptyURL; - emptyURL.Truncate(); - rv = NS_MakeAbsoluteURL(docURL, emptyURL, src, absURL); - if (NS_OK != rv) { - return rv; + nsIURLGroup* urlGroup; + + rv = docURL->GetURLGroup(&urlGroup); + + if ((NS_OK == rv) && urlGroup) { + rv = urlGroup->CreateURL(&url, docURL, src, nsnull); + NS_RELEASE(urlGroup); + } + else { + rv = NS_NewURL(&url, absURL); } NS_RELEASE(docURL); - rv = NS_NewURL(&url, absURL); if (NS_OK != rv) { return rv; } - nsIInputStream* iin; - rv = NS_OpenURL(url, &iin); - if (NS_OK != rv) { - NS_RELEASE(url); - return rv; - } - - // Drain the stream by reading from it a chunk at a time - PRUint32 nb; - nsresult err; - do { - char buf[SCRIPT_BUF_SIZE]; - - err = iin->Read(buf, 0, SCRIPT_BUF_SIZE, &nb); - if (NS_OK == err) { - script.Append((const char *)buf, nb); - } - } while (err == NS_OK); - - if (NS_BASE_STREAM_EOF != err) { - rv = NS_ERROR_FAILURE; - } - - NS_RELEASE(iin); + + // Add a reference to this since the url loader is holding + // onto it as opaque data. + NS_ADDREF(this); + + nsIUnicharStreamLoader* loader; + rv = NS_NewUnicharStreamLoader(&loader, + url, + (nsStreamCompleteFunc)nsDoneLoadingScript, + (void *)this); NS_RELEASE(url); - - rv = EvaluateScript(script, (PRUint32)aNode.GetSourceLineNumber()); - + if (NS_OK == rv) { + rv = NS_ERROR_HTMLPARSER_BLOCK; + } } else { // Wait until we get the script content diff --git a/layout/xml/document/src/nsXMLContentSink.h b/layout/xml/document/src/nsXMLContentSink.h index e0e3433c381..151c4ef148b 100644 --- a/layout/xml/document/src/nsXMLContentSink.h +++ b/layout/xml/document/src/nsXMLContentSink.h @@ -76,11 +76,18 @@ public: NS_IMETHOD AddNotation(const nsIParserNode& aNode); NS_IMETHOD AddEntityReference(const nsIParserNode& aNode); + NS_IMETHOD ResumeParsing(); + NS_IMETHOD LoadStyleSheet(nsIURL* aURL, + nsIUnicharInputStream* aUIN, + PRBool aActive, + const nsString& aTitle, + const nsString& aMedia, + nsIContent* aOwner); + NS_IMETHOD EvaluateScript(nsString& aScript, PRUint32 aLineNo); + protected: void StartLayout(); - nsresult LoadStyleSheet(nsIURL* aURL, - nsIUnicharInputStream* aUIN); nsresult FlushText(PRBool aCreateTextNode=PR_TRUE, PRBool* aDidFlush=nsnull); @@ -95,7 +102,6 @@ protected: PRInt32 PushContent(nsIContent *aContent); nsIContent* PopContent(); - nsresult EvaluateScript(nsString& aScript, PRUint32 aLineNo); nsresult ProcessEndSCRIPTTag(const nsIParserNode& aNode); nsresult ProcessStartSCRIPTTag(const nsIParserNode& aNode);