Fix for bug 129006 (Invalid xml crashes mozilla after reload [@nsXMLContentSink::Observe]). r=Pike, sr=jst.

This commit is contained in:
peterv%netscape.com 2002-04-25 11:58:08 +00:00
parent 54ec945d6f
commit f1d35b4a9d
9 changed files with 225 additions and 73 deletions

View File

@ -1377,6 +1377,8 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
const nsRect& aBounds,
PRBool aDoCreation)
{
mTransformMediator = nsnull;
#ifdef NS_PRINT_PREVIEW
mParentWidget = aParentWidget; // not ref counted
#endif
@ -5259,8 +5261,9 @@ nsresult DocumentViewerImpl::DocumentReadyForPrinting()
NS_IMETHODIMP
DocumentViewerImpl::SetTransformMediator(nsITransformMediator* aMediator)
{
NS_ASSERTION(nsnull == mTransformMediator, "nsXMLDocument::SetTransformMediator(): \
Cannot set a second transform mediator\n");
NS_ASSERTION(!mTransformMediator || !aMediator,
"nsXMLDocument::SetTransformMediator(): \
Cannot set a second transform mediator\n");
mTransformMediator = aMediator;
return NS_OK;
}

View File

@ -167,7 +167,6 @@ nsXMLContentSink::nsXMLContentSink()
mDocumentBaseURL = nsnull;
mWebShell = nsnull;
mParser = nsnull;
mRootElement = nsnull;
mDocElement = nsnull;
mContentStack = nsnull;
mNameSpaceStack = nsnull;
@ -178,7 +177,6 @@ nsXMLContentSink::nsXMLContentSink()
mInTitle = PR_FALSE;
mStyleSheetCount = 0;
mCSSLoader = nsnull;
mXSLTransformMediator = nsnull;
mNeedToBlockParser = PR_FALSE;
}
@ -194,7 +192,6 @@ nsXMLContentSink::~nsXMLContentSink()
NS_IF_RELEASE(mDocumentBaseURL);
NS_IF_RELEASE(mWebShell);
NS_IF_RELEASE(mParser);
NS_IF_RELEASE(mRootElement);
NS_IF_RELEASE(mDocElement);
if (nsnull != mNameSpaceStack) {
// There shouldn't be any here except in an error condition
@ -241,7 +238,6 @@ nsXMLContentSink::Init(nsIDocument* aDoc,
mState = eXMLContentSinkState_InProlog;
mDocElement = nsnull;
mRootElement = nsnull;
nsIHTMLContentContainer* htmlContainer = nsnull;
if (NS_SUCCEEDED(aDoc->QueryInterface(NS_GET_IID(nsIHTMLContentContainer), (void**)&htmlContainer))) {
@ -434,17 +430,19 @@ nsXMLContentSink::DidBuildModel(PRInt32 aQualityLevel)
}
// The observe method is called on completion of the transform. The nsISupports argument is an
// nsIDOMElement interface to the root node of the output content model.
// nsIContent interface to the root node of the output content model.
NS_IMETHODIMP
nsXMLContentSink::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
{
nsresult rv = NS_OK;
if (!nsCRT::strcmp(aTopic, "xslt-done")) {
nsCOMPtr<nsIContent> content;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mWebShell));
nsCOMPtr<nsIContentViewer> contentViewer;
docShell->GetContentViewer(getter_AddRefs(contentViewer));
// Set the output content model on the document
content = do_QueryInterface(aSubject, &rv);
nsCOMPtr<nsIContent> content = do_QueryInterface(aSubject, &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDOMDocument> resultDOMDoc;
mXSLTransformMediator->GetResultDocument(getter_AddRefs(resultDOMDoc));
@ -465,33 +463,52 @@ nsXMLContentSink::Observe(nsISupports *aSubject, const char *aTopic, const PRUni
// Start the layout process
StartLayout();
#if 0 /* Disable until this works for XML */
// Scroll to Anchor only if the document was *not* loaded through history means.
PRUint32 documentLoadType = 0;
docShell->GetLoadType(&documentLoadType);
if (!(documentLoadType & nsIDocShell::LOAD_CMD_HISTORY)) {
ScrollToRef();
}
#else
ScrollToRef();
#endif
sourceDoc->EndLoad();
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mWebShell));
nsCOMPtr<nsIContentViewer> contentViewer;
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
if (NS_SUCCEEDED(rv) && contentViewer) {
if (contentViewer) {
contentViewer->LoadComplete(NS_OK);
}
}
else
{
// Transform failed
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mWebShell));
nsCOMPtr<nsIContentViewer> contentViewer;
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
nsCOMPtr<nsIDocumentViewer> documentViewer(do_QueryInterface(contentViewer));
if (documentViewer) {
documentViewer->SetTransformMediator(nsnull);
}
mXSLTransformMediator = nsnull;
mDocument->SetRootContent(mDocElement);
// Start the layout process
StartLayout();
#if 0 /* Disable until this works for XML */
// Scroll to Anchor only if the document was *not* loaded through history means.
PRUint32 documentLoadType = 0;
docShell->GetLoadType(&documentLoadType);
if (!(documentLoadType & nsIDocShell::LOAD_CMD_HISTORY)) {
ScrollToRef();
}
#else
ScrollToRef();
#endif
mDocument->EndLoad();
}
mXSLTransformMediator = nsnull;
}
return rv;
}
@ -1661,11 +1678,15 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
mDocument->GetAndIncrementContentID(&id);
content->SetContentID(id);
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content));
if (isHTML &&
((tagAtom == nsHTMLAtoms::link) ||
(tagAtom == nsHTMLAtoms::style))) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content));
if (ssle) {
ssle->InitStyleLinkElement(mParser, PR_FALSE);
ssle->SetEnableUpdates(PR_FALSE);
if (ssle) {
ssle->InitStyleLinkElement(mParser, PR_FALSE);
ssle->SetEnableUpdates(PR_FALSE);
}
}
content->SetDocument(mDocument, PR_FALSE, PR_TRUE);
@ -1720,10 +1741,9 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName)
FlushText();
nsCOMPtr<nsIContent> currentContent(dont_AddRef(GetCurrentContent()));
nsCOMPtr<nsIAtom> tagAtom;
if (currentContent && currentContent->IsContentOfType(nsIContent::eHTML)) {
nsCOMPtr<nsIAtom> tagAtom;
currentContent->GetTag(*getter_AddRefs(tagAtom));
if (tagAtom.get() == nsHTMLAtoms::script) {
@ -1772,16 +1792,21 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName)
nsINameSpace* nameSpace = PopNameSpaces();
NS_IF_RELEASE(nameSpace);
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content));
if (currentContent &&
currentContent->IsContentOfType(nsIContent::eHTML) &&
((tagAtom == nsHTMLAtoms::link) ||
(tagAtom == nsHTMLAtoms::style))) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content));
if (ssle) {
ssle->SetEnableUpdates(PR_TRUE);
result = ssle->UpdateStyleSheet(nsnull, mStyleSheetCount);
if (NS_SUCCEEDED(result) || (result == NS_ERROR_HTMLPARSER_BLOCK)) {
if (result == NS_ERROR_HTMLPARSER_BLOCK && mParser) {
mParser->BlockParser();
if (ssle) {
ssle->SetEnableUpdates(PR_TRUE);
result = ssle->UpdateStyleSheet(nsnull, mStyleSheetCount);
if (NS_SUCCEEDED(result) || (result == NS_ERROR_HTMLPARSER_BLOCK)) {
if (result == NS_ERROR_HTMLPARSER_BLOCK && mParser) {
mParser->BlockParser();
}
mStyleSheetCount++;
}
mStyleSheetCount++;
}
}
@ -1931,8 +1956,8 @@ nsXMLContentSink::HandleProcessingInstruction(const PRUnichar *aTarget,
nsresult result = NS_OK;
const nsDependentString target(aTarget);
nsAutoString data(aData); // XXX replace this with nsDependentString. Change nsParserUtils APIs
const nsDependentString data(aData);
nsCOMPtr<nsIContent> node;
// ParseProcessingInstruction(text, target, data);
@ -2012,6 +2037,19 @@ nsXMLContentSink::ReportError(const PRUnichar* aErrorText,
}
NS_IF_RELEASE(mDocElement);
if (mXSLTransformMediator) {
// Get rid of the transform mediator.
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mWebShell));
nsCOMPtr<nsIContentViewer> contentViewer;
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
nsCOMPtr<nsIDocumentViewer> documentViewer(do_QueryInterface(contentViewer));
if (documentViewer) {
documentViewer->SetTransformMediator(nsnull);
}
mXSLTransformMediator->SetEnabled(PR_FALSE);
mXSLTransformMediator = nsnull;
}
NS_NAMED_LITERAL_STRING(name, "xmlns");
NS_NAMED_LITERAL_STRING(value, "http://www.mozilla.org/newlayout/xml/parsererror.xml");

View File

@ -187,7 +187,6 @@ protected:
nsIURI* mDocumentBaseURL; // can be set via HTTP headers
nsIWebShell* mWebShell;
nsIParser* mParser;
nsIContent* mRootElement;
nsIContent* mDocElement;
nsAutoVoidArray* mNameSpaceStack;
PRUnichar* mText;

View File

@ -65,13 +65,13 @@ class nsITransformMediator : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITRANSFORM_MEDIATOR_IID);
NS_IMETHOD SetEnabled(PRBool aValue)=0;
NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource)=0;
NS_IMETHOD SetStyleSheetContentModel(nsIDOMNode* aStyle)=0;
NS_IMETHOD SetResultDocument(nsIDOMDocument* aDoc)=0;
NS_IMETHOD GetResultDocument(nsIDOMDocument** aDoc)=0;
NS_IMETHOD SetTransformObserver(nsIObserver* aObserver)=0;
NS_IMETHOD SetEnabled(PRBool aValue) = 0;
NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource) = 0;
NS_IMETHOD SetStyleSheetContentModel(nsIDOMNode* aStyle) = 0;
NS_IMETHOD SetResultDocument(nsIDOMDocument* aDoc) = 0;
NS_IMETHOD GetResultDocument(nsIDOMDocument** aDoc) = 0;
NS_IMETHOD SetTransformObserver(nsIObserver* aObserver) = 0;
NS_IMETHOD SetStyleInvalid(PRBool aInvalid) = 0;
};
extern nsresult NS_NewTransformMediator(nsITransformMediator** aInstancePtrResult,

View File

@ -36,9 +36,13 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsTransformMediator.h"
#include "nsIComponentManager.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMElement.h"
#include "nsIServiceManagerUtils.h"
#include "nsObserverService.h"
#include "nsString.h"
nsresult
@ -60,10 +64,10 @@ NS_NewTransformMediator(nsITransformMediator** aInstancePtrResult,
return CallQueryInterface(it, aInstancePtrResult);
}
nsTransformMediator::nsTransformMediator()
nsTransformMediator::nsTransformMediator() : mEnabled(PR_FALSE),
mStyleInvalid(PR_FALSE)
{
NS_INIT_REFCNT();
mEnabled = PR_FALSE;
}
nsTransformMediator::~nsTransformMediator()
@ -98,13 +102,38 @@ NS_IMPL_ISUPPORTS1(nsTransformMediator, nsITransformMediator)
void
nsTransformMediator::TryToTransform()
{
if (mEnabled && mSourceDOM && mStyleDOM &&
mResultDoc && mObserver && mTransformer)
if (mSourceDOM && mStyleDOM && mResultDoc && mObserver)
{
mTransformer->TransformDocument(mSourceDOM,
mStyleDOM,
mResultDoc,
mObserver);
if (mEnabled && mTransformer) {
mTransformer->TransformDocument(mSourceDOM,
mStyleDOM,
mResultDoc,
mObserver);
}
else if (mStyleInvalid) {
// Copy the error message from the stylesheet document to the result
// result document and notify the observer.
nsCOMPtr<nsIDOMElement> docElement;
mResultDoc->GetDocumentElement(getter_AddRefs(docElement));
nsCOMPtr<nsIDOMNode> newRoot, root;
mResultDoc->ImportNode(mStyleDOM, PR_TRUE, getter_AddRefs(newRoot));
if (docElement) {
nsCOMPtr<nsIDOMNode> origRoot;
root = newRoot;
mResultDoc->ReplaceChild(docElement, root, getter_AddRefs(origRoot));
}
else {
mResultDoc->AppendChild(newRoot, getter_AddRefs(root));
}
nsresult rv;
nsCOMPtr<nsIObserverService> anObserverService =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
anObserverService->AddObserver(mObserver, "xslt-done", PR_TRUE);
anObserverService->NotifyObservers(root, "xslt-done", nsnull);
}
}
}
}
@ -156,3 +185,10 @@ nsTransformMediator::SetTransformObserver(nsIObserver* aObserver)
TryToTransform();
return NS_OK;
}
NS_IMETHODIMP
nsTransformMediator::SetStyleInvalid(PRBool aInvalid)
{
mStyleInvalid = aInvalid;
return NS_OK;
}

View File

@ -39,6 +39,7 @@
#ifndef nsTransformMediator_h__
#define nsTransformMediator_h__
#include "nsCOMPtr.h"
#include "nsITransformMediator.h"
#include "nsIDocumentTransformer.h"
#include "nsIDOMNode.h"
@ -62,11 +63,13 @@ public:
NS_IMETHOD SetResultDocument(nsIDOMDocument* aDoc);
NS_IMETHOD GetResultDocument(nsIDOMDocument** aDoc);
NS_IMETHOD SetTransformObserver(nsIObserver* aObserver);
NS_IMETHOD SetStyleInvalid(PRBool aInvalid);
protected:
void TryToTransform();
PRBool mEnabled;
PRBool mStyleInvalid;
nsCOMPtr<nsIDocumentTransformer> mTransformer; // Strong reference
nsCOMPtr<nsIDOMNode> mSourceDOM; // Strong reference
nsCOMPtr<nsIDOMNode> mStyleDOM; // Strong reference

View File

@ -37,11 +37,13 @@
* ***** END LICENSE BLOCK ***** */
#include "nsXSLContentSink.h"
#include "nsHTMLAtoms.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsITransformMediator.h"
#include "nsIParser.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsITransformMediator.h"
#include "nsIURL.h"
#include "nsString.h"
#include "nsEscape.h"
@ -89,8 +91,14 @@ nsXSLContentSink::Init(nsITransformMediator* aTM,
{
nsresult rv;
rv = nsXMLContentSink::Init(aDoc, aURL, aContainer, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
mXSLTransformMediator = aTM;
nsCOMPtr<nsIScriptLoader> loader;
rv = mDocument->GetScriptLoader(getter_AddRefs(loader));
NS_ENSURE_SUCCESS(rv, rv);
loader->Suspend();
return rv;
}
@ -150,5 +158,76 @@ nsXSLContentSink::ProcessStyleLink(nsIContent* aElement,
const nsString& aType,
const nsString& aMedia)
{
return NS_OK;
return NS_OK;
}
NS_IMETHODIMP
nsXSLContentSink::HandleStartElement(const PRUnichar *aName,
const PRUnichar **aAtts,
PRUint32 aAttsCount,
PRUint32 aIndex,
PRUint32 aLineNumber)
{
nsresult rv = nsXMLContentSink::HandleStartElement(aName, aAtts,
aAttsCount,
aIndex,
aLineNumber);
nsCOMPtr<nsIContent> currentContent(dont_AddRef(GetCurrentContent()));
if (currentContent &&
currentContent->IsContentOfType(nsIContent::eHTML)) {
nsCOMPtr<nsIAtom> tagAtom;
currentContent->GetTag(*getter_AddRefs(tagAtom));
if ((tagAtom == nsHTMLAtoms::link) ||
(tagAtom == nsHTMLAtoms::style)) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle =
do_QueryInterface(currentContent);
if (ssle) {
ssle->InitStyleLinkElement(nsnull, PR_TRUE);
}
}
}
return rv;
}
NS_IMETHODIMP
nsXSLContentSink::HandleProcessingInstruction(const PRUnichar *aTarget,
const PRUnichar *aData)
{
FlushText();
const nsDependentString target(aTarget);
const nsDependentString data(aData);
nsCOMPtr<nsIContent> node;
nsresult rv = NS_NewXMLProcessingInstruction(getter_AddRefs(node),
target, data);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(node));
if (ssle) {
ssle->InitStyleLinkElement(nsnull, PR_TRUE);
}
rv = AddContentAsLeaf(node);
return rv;
}
NS_IMETHODIMP
nsXSLContentSink::ReportError(const PRUnichar* aErrorText,
const PRUnichar* aSourceText)
{
// nsXMLContentSink::ReportError sets mXSLTransformMediator to nsnull
nsCOMPtr<nsITransformMediator> mediator = mXSLTransformMediator;
nsXMLContentSink::ReportError(aErrorText, aSourceText);
if (mediator) {
nsCOMPtr<nsIDOMNode> styleNode = do_QueryInterface(mDocElement);
mediator->SetStyleInvalid(PR_TRUE);
mediator->SetStyleSheetContentModel(styleNode);
}
return NS_OK;
}

View File

@ -55,29 +55,20 @@ public:
nsIURI* aURL,
nsIWebShell* aContainer);
// nsISupports
//NS_DECL_ISUPPORTS
// nsIContentSink
NS_IMETHOD WillBuildModel(void);
NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel);
//NS_IMETHOD WillInterrupt(void);
//NS_IMETHOD WillResume(void);
//NS_IMETHOD SetParser(nsIParser* aParser);
//NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
//NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
//NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
//NS_IMETHOD AddComment(const nsIParserNode& aNode);
//NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
//NS_IMETHOD NotifyError(const nsParserError* aError);
//NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
// nsIXMLContentSink
//NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode);
//NS_IMETHOD AddCharacterData(const nsIParserNode& aNode);
//NS_IMETHOD AddUnparsedEntity(const nsIParserNode& aNode);
//NS_IMETHOD AddNotation(const nsIParserNode& aNode);
//NS_IMETHOD AddEntityReference(const nsIParserNode& aNode);
// nsIExpatSink
NS_IMETHOD HandleStartElement(const PRUnichar *aName,
const PRUnichar **aAtts,
PRUint32 aAttsCount,
PRUint32 aIndex,
PRUint32 aLineNumber);
NS_IMETHOD HandleProcessingInstruction(const PRUnichar *aTarget,
const PRUnichar *aData);
NS_IMETHOD ReportError(const PRUnichar *aErrorText,
const PRUnichar *aSourceText);
protected:
NS_IMETHOD ProcessStyleLink(nsIContent* aElement,

View File

@ -1377,6 +1377,8 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
const nsRect& aBounds,
PRBool aDoCreation)
{
mTransformMediator = nsnull;
#ifdef NS_PRINT_PREVIEW
mParentWidget = aParentWidget; // not ref counted
#endif
@ -5259,8 +5261,9 @@ nsresult DocumentViewerImpl::DocumentReadyForPrinting()
NS_IMETHODIMP
DocumentViewerImpl::SetTransformMediator(nsITransformMediator* aMediator)
{
NS_ASSERTION(nsnull == mTransformMediator, "nsXMLDocument::SetTransformMediator(): \
Cannot set a second transform mediator\n");
NS_ASSERTION(!mTransformMediator || !aMediator,
"nsXMLDocument::SetTransformMediator(): \
Cannot set a second transform mediator\n");
mTransformMediator = aMediator;
return NS_OK;
}