Added asynchronous script and style loading to XML. Moved out stream loader to netlib.

This commit is contained in:
vidur%netscape.com 1998-12-18 01:36:41 +00:00
Родитель df3ac56c3c
Коммит ef7751a987
6 изменённых файлов: 424 добавлений и 450 удалений

Просмотреть файл

@ -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,14 +2203,17 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
d->mSink = this;
NS_ADDREF(this);
nsAccumulatingURLLoader* loader =
new nsAccumulatingURLLoader(url,
(nsAccumulationDoneFunc)nsDoneLoadingStyle,
nsIUnicharStreamLoader* loader;
result = NS_NewUnicharStreamLoader(&loader,
url,
(nsStreamCompleteFunc)nsDoneLoadingStyle,
(void *)d);
NS_RELEASE(url);
if (NS_OK == result) {
result = NS_ERROR_HTMLPARSER_BLOCK;
}
}
}
NS_RELEASE(element);
return result;
@ -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,13 +2440,16 @@ 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);
if (NS_OK == rv) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
}
else {
// Otherwise, get the text content of the script tag
script = aNode.GetSkippedContent();
@ -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,13 +2587,16 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode)
d->mSink = this;
NS_ADDREF(this);
nsAccumulatingURLLoader* loader =
new nsAccumulatingURLLoader(url,
(nsAccumulationDoneFunc)nsDoneLoadingStyle,
nsIUnicharStreamLoader* loader;
rv = NS_NewUnicharStreamLoader(&loader,
url,
(nsStreamCompleteFunc)nsDoneLoadingStyle,
(void *)d);
NS_RELEASE(url);
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;
}

Просмотреть файл

@ -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;
}
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);
nsAsyncStyleProcessingDataXML* d = new nsAsyncStyleProcessingDataXML;
if (nsnull == d) {
return NS_ERROR_OUT_OF_MEMORY;
}
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;
@ -1227,52 +1341,41 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode)
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) {
// 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);
return rv;
if (NS_OK == rv) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
// 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);
NS_RELEASE(url);
rv = EvaluateScript(script, (PRUint32)aNode.GetSourceLineNumber());
}
else {
// Wait until we get the script content

Просмотреть файл

@ -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);

Просмотреть файл

@ -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,14 +2203,17 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
d->mSink = this;
NS_ADDREF(this);
nsAccumulatingURLLoader* loader =
new nsAccumulatingURLLoader(url,
(nsAccumulationDoneFunc)nsDoneLoadingStyle,
nsIUnicharStreamLoader* loader;
result = NS_NewUnicharStreamLoader(&loader,
url,
(nsStreamCompleteFunc)nsDoneLoadingStyle,
(void *)d);
NS_RELEASE(url);
if (NS_OK == result) {
result = NS_ERROR_HTMLPARSER_BLOCK;
}
}
}
NS_RELEASE(element);
return result;
@ -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,13 +2440,16 @@ 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);
if (NS_OK == rv) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
}
else {
// Otherwise, get the text content of the script tag
script = aNode.GetSkippedContent();
@ -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,13 +2587,16 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode)
d->mSink = this;
NS_ADDREF(this);
nsAccumulatingURLLoader* loader =
new nsAccumulatingURLLoader(url,
(nsAccumulationDoneFunc)nsDoneLoadingStyle,
nsIUnicharStreamLoader* loader;
rv = NS_NewUnicharStreamLoader(&loader,
url,
(nsStreamCompleteFunc)nsDoneLoadingStyle,
(void *)d);
NS_RELEASE(url);
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;
}

Просмотреть файл

@ -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;
}
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);
nsAsyncStyleProcessingDataXML* d = new nsAsyncStyleProcessingDataXML;
if (nsnull == d) {
return NS_ERROR_OUT_OF_MEMORY;
}
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;
@ -1227,52 +1341,41 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode)
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) {
// 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);
return rv;
if (NS_OK == rv) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
// 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);
NS_RELEASE(url);
rv = EvaluateScript(script, (PRUint32)aNode.GetSourceLineNumber());
}
else {
// Wait until we get the script content

Просмотреть файл

@ -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);