From 271bb8c07c254bd1e2a98bc42a63d9c87f50ab53 Mon Sep 17 00:00:00 2001 From: "rbs%maths.uq.edu.au" Date: Fri, 15 Mar 2002 09:45:31 +0000 Subject: [PATCH] perf bug 124570 - configure mathml.css as a catalog stylesheet that is loaded on demand rather than at startup, r=harishd, sr=jst, a=asa --- build/mac/build_scripts/MozillaBuildList.pm | 13 +- content/base/public/nsIDocument.h | 4 +- content/base/src/nsDocument.cpp | 9 +- content/base/src/nsDocument.h | 6 +- content/html/document/src/nsHTMLDocument.cpp | 7 +- content/html/document/src/nsHTMLDocument.h | 3 +- content/xml/document/public/nsIXMLDocument.h | 2 + content/xml/document/src/nsXMLContentSink.cpp | 23 +- content/xml/document/src/nsXMLDocument.cpp | 21 +- content/xml/document/src/nsXMLDocument.h | 7 +- content/xul/document/src/nsXULContentSink.cpp | 3 +- content/xul/document/src/nsXULDocument.cpp | 10 +- content/xul/document/src/nsXULDocument.h | 4 +- editor/libeditor/base/nsStyleSheetTxns.cpp | 4 +- htmlparser/public/nsIExpatSink.idl | 5 +- htmlparser/src/nsExpatDriver.cpp | 330 ++++++++++-------- htmlparser/src/nsExpatDriver.h | 23 +- layout/mathml/content/src/Makefile.in | 1 - layout/mathml/content/src/makefile.win | 1 - parser/htmlparser/public/nsIExpatSink.idl | 5 +- parser/htmlparser/src/nsExpatDriver.cpp | 330 ++++++++++-------- parser/htmlparser/src/nsExpatDriver.h | 23 +- rdf/base/src/nsRDFContentSink.cpp | 3 +- 23 files changed, 474 insertions(+), 363 deletions(-) diff --git a/build/mac/build_scripts/MozillaBuildList.pm b/build/mac/build_scripts/MozillaBuildList.pm index 38d85b637db..fd1025b2d84 100644 --- a/build/mac/build_scripts/MozillaBuildList.pm +++ b/build/mac/build_scripts/MozillaBuildList.pm @@ -186,20 +186,13 @@ sub InstallNonChromeResources() MakeAlias(":mozilla:layout:svg:base:src:svg.dtd", "$resource_dir"."dtd:"); } - if (! $main::options{mathml}) - { - MakeAlias(":mozilla:layout:html:document:src:ua.css", "$resource_dir"); - } - else + if ($main::options{mathml}) { MakeAlias(":mozilla:layout:mathml:content:src:mathml.dtd", "$resource_dir"."dtd:"); - #// Building MathML so include the mathml.css file in ua.css MakeAlias(":mozilla:layout:mathml:content:src:mathml.css", "$resource_dir"); - copy(":mozilla:layout:html:document:src:ua.css", "$resource_dir"."ua.css"); - @ARGV = ("$resource_dir"."ua.css"); - do ":mozilla:layout:mathml:content:src:mathml-css.pl"; } - + + MakeAlias(":mozilla:layout:html:document:src:ua.css", "$resource_dir"); MakeAlias(":mozilla:layout:html:document:src:html.css", "$resource_dir"); MakeAlias(":mozilla:layout:html:document:src:forms.css", "$resource_dir"); MakeAlias(":mozilla:layout:html:document:src:quirk.css", "$resource_dir"); diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index d290547b7f8..869475736de 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -256,13 +256,13 @@ public: NS_IMETHOD GetNumberOfStyleSheets(PRInt32* aCount) = 0; NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsIStyleSheet** aSheet) = 0; NS_IMETHOD GetIndexOfStyleSheet(nsIStyleSheet* aSheet, PRInt32* aIndex) = 0; - virtual void AddStyleSheet(nsIStyleSheet* aSheet) = 0; + virtual void AddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags) = 0; virtual void RemoveStyleSheet(nsIStyleSheet* aSheet) = 0; NS_IMETHOD UpdateStyleSheets(nsISupportsArray* aOldSheets, nsISupportsArray* aNewSheets) = 0; NS_IMETHOD InsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex, PRBool aNotify) = 0; virtual void SetStyleSheetDisabledState(nsIStyleSheet* aSheet, - PRBool mDisabled) = 0; + PRBool aDisabled) = 0; /** * Set the object from which a document can get a script context. diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 37f4cf8be01..07a8e032ea0 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1254,7 +1254,8 @@ nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet, PRInt32* aIndex) return NS_OK; } -void nsDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet) // subclass hook for sheet ordering +// subclass hooks for sheet ordering +void nsDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags) { mStyleSheets.AppendElement(aSheet); } @@ -1274,10 +1275,10 @@ void nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet) } } -void nsDocument::AddStyleSheet(nsIStyleSheet* aSheet) +void nsDocument::AddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags) { NS_PRECONDITION(nsnull != aSheet, "null arg"); - InternalAddStyleSheet(aSheet); + InternalAddStyleSheet(aSheet, aFlags); NS_ADDREF(aSheet); aSheet->SetOwningDocument(this); @@ -1378,7 +1379,7 @@ nsDocument::UpdateStyleSheets(nsISupportsArray* aOldSheets, nsISupportsArray* aN aNewSheets->GetElementAt(i, getter_AddRefs(supp)); sheet = do_QueryInterface(supp); if (sheet) { - InternalAddStyleSheet(sheet); + InternalAddStyleSheet(sheet, 0); nsIStyleSheet* sheetPtr = sheet; NS_ADDREF(sheetPtr); sheet->SetOwningDocument(this); diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index cf77fee6871..11fb6174a65 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -392,7 +392,7 @@ public: NS_IMETHOD GetNumberOfStyleSheets(PRInt32* aCount); NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsIStyleSheet** aSheet); NS_IMETHOD GetIndexOfStyleSheet(nsIStyleSheet* aSheet, PRInt32* aIndex); - virtual void AddStyleSheet(nsIStyleSheet* aSheet); + virtual void AddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags); virtual void RemoveStyleSheet(nsIStyleSheet* aSheet); NS_IMETHOD UpdateStyleSheets(nsISupportsArray* aOldSheets, @@ -560,7 +560,9 @@ public: protected: NS_IMETHOD GetDTD(nsIDTD** aDTD) const; - virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet); // subclass hooks for sheet ordering + // subclass hooks for sheet ordering + virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet, + PRUint32 aFlags); virtual void InternalInsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex); diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 71ed7cb2573..23f7b2354b3 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -477,7 +477,7 @@ nsHTMLDocument::BaseResetToURI(nsIURI *aURL) result = mAttrStyleSheet->Reset(aURL); } if (NS_SUCCEEDED(result)) { - AddStyleSheet(mAttrStyleSheet); // tell the world about our new style sheet + AddStyleSheet(mAttrStyleSheet, 0); // tell the world about our new style sheet if (!mStyleAttrStyleSheet) { result = NS_NewHTMLCSSStyleSheet(&mStyleAttrStyleSheet, aURL, this); @@ -486,7 +486,7 @@ nsHTMLDocument::BaseResetToURI(nsIURI *aURL) result = mStyleAttrStyleSheet->Reset(aURL); } if (NS_SUCCEEDED(result)) { - AddStyleSheet(mStyleAttrStyleSheet); // tell the world about our new style sheet + AddStyleSheet(mStyleAttrStyleSheet, 0); // tell the world about our new style sheet } } } @@ -1161,8 +1161,9 @@ nsHTMLDocument::GetInlineStyleSheet(nsIHTMLCSSStyleSheet** aResult) return NS_OK; } +// subclass hooks for sheet ordering void -nsHTMLDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet) // subclass hook for sheet ordering +nsHTMLDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags) { if (aSheet == mAttrStyleSheet) { // always first mStyleSheets.InsertElementAt(aSheet, 0); diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index f60e80c7529..abb3409fc30 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -196,7 +196,8 @@ protected: nsIContent *MatchId(nsIContent *aContent, const nsAReadableString& aId); - virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet); + virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet, + PRUint32 aFlags); virtual void InternalInsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex); static PRBool MatchLinks(nsIContent *aContent, nsString* aData); diff --git a/content/xml/document/public/nsIXMLDocument.h b/content/xml/document/public/nsIXMLDocument.h index 58446086ee4..6c302a01493 100644 --- a/content/xml/document/public/nsIXMLDocument.h +++ b/content/xml/document/public/nsIXMLDocument.h @@ -46,6 +46,8 @@ class nsIURI; { 0xa6cf90ca, 0x15b3, 0x11d2, \ { 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } } +#define NS_STYLESHEET_FROM_CATALOG 0x1 + /** * XML document extensions to nsIDocument */ diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 3a207b1d683..96a58a3fe58 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -1460,7 +1460,8 @@ nsXMLContentSink::HandleCDataSection(const PRUnichar *aData, NS_IMETHODIMP nsXMLContentSink::HandleDoctypeDecl(const PRUnichar *aDoctype, - PRUint32 aLength) + PRUint32 aLength, + nsISupports* aCatalogData) { nsresult rv = NS_OK; @@ -1487,7 +1488,6 @@ nsXMLContentSink::HandleDoctypeDecl(const PRUnichar *aDoctype, // The rest is the internal subset (minus whitespace) str.Trim(kWhitespace); - nsCOMPtr oldDocType; nsCOMPtr docType; // Create a new doctype node @@ -1498,6 +1498,25 @@ nsXMLContentSink::HandleDoctypeDecl(const PRUnichar *aDoctype, return rv; } + if (aCatalogData && mCSSLoader && mDocument) { + // bug 124570 - we only expect additional agent sheets for now -- ignore + // exit codes, error are not fatal here, just that the stylesheet won't apply + nsCOMPtr uri(do_QueryInterface(aCatalogData)); + if (uri) { + PRBool complete; + nsCOMPtr sheet; + mCSSLoader->LoadAgentSheet(uri, *getter_AddRefs(sheet), complete, nsnull); +#ifdef NS_DEBUG + nsCAutoString uriStr; + uri->GetSpec(uriStr); + printf("Loading catalog stylesheet: %s ... %s\n", uriStr.get(), sheet.get() ? "Done" : "Failed"); +#endif + if (sheet) { + mDocument->AddStyleSheet(sheet, NS_STYLESHEET_FROM_CATALOG); + } + } + } + nsCOMPtr tmpNode; return doc->AppendChild(docType, getter_AddRefs(tmpNode)); diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp index 22bfab4b37d..e018b5c60ae 100644 --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -216,7 +216,7 @@ NS_NewXMLDocument(nsIDocument** aInstancePtrResult) nsXMLDocument::nsXMLDocument() : mAttrStyleSheet(nsnull), mInlineStyleSheet(nsnull), - mParser(nsnull) + mCountCatalogSheets(0), mParser(nsnull) { } @@ -700,10 +700,16 @@ nsXMLDocument::GetInlineStyleSheet(nsIHTMLCSSStyleSheet** aResult) return NS_OK; } -void nsXMLDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet) // subclass hook for sheet ordering +// subclass hook for sheet ordering +void nsXMLDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags) { - if (aSheet == mAttrStyleSheet) { // always first - mStyleSheets.InsertElementAt(aSheet, 0); + if (aFlags & NS_STYLESHEET_FROM_CATALOG) { + // always after other catalog sheets + mStyleSheets.InsertElementAt(aSheet, mCountCatalogSheets); + ++mCountCatalogSheets; + } + else if (aSheet == mAttrStyleSheet) { // always after catalog sheets + mStyleSheets.InsertElementAt(aSheet, mCountCatalogSheets); } else if (aSheet == mInlineStyleSheet) { // always last mStyleSheets.AppendElement(aSheet); @@ -723,7 +729,8 @@ void nsXMLDocument::InternalAddStyleSheet(nsIStyleSheet* aSheet) // subclass ho void nsXMLDocument::InternalInsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex) { - mStyleSheets.InsertElementAt(aSheet, aIndex + 1); // offset one for the attr style sheet + // offset w.r.t. catalog style sheets and the attr style sheet + mStyleSheets.InsertElementAt(aSheet, aIndex + mCountCatalogSheets + 1); } // nsIDOMDocument interface @@ -1005,11 +1012,11 @@ nsXMLDocument::SetDefaultStylesheets(nsIURI* aUrl) } } if (NS_OK == result) { - AddStyleSheet(mAttrStyleSheet); // tell the world about our new style sheet + AddStyleSheet(mAttrStyleSheet, 0); // tell the world about our new style sheet result = NS_NewHTMLCSSStyleSheet(&mInlineStyleSheet, aUrl, this); if (NS_OK == result) { - AddStyleSheet(mInlineStyleSheet); // tell the world about our new style sheet + AddStyleSheet(mInlineStyleSheet, 0); // tell the world about our new style sheet } } } diff --git a/content/xml/document/src/nsXMLDocument.h b/content/xml/document/src/nsXMLDocument.h index e854fa57442..b5e746f9009 100644 --- a/content/xml/document/src/nsXMLDocument.h +++ b/content/xml/document/src/nsXMLDocument.h @@ -122,7 +122,8 @@ public: NS_DECL_NSIDOMXMLDOCUMENT protected: - virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet); // subclass hook for sheet ordering + // subclass hooks for sheet ordering + virtual void InternalAddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags); virtual void InternalInsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex); nsresult CreateElement(nsINodeInfo *aNodeInfo, nsIDOMElement** aResult); @@ -131,6 +132,10 @@ protected: // XXX This is not clean, but is there a better way? nsIHTMLStyleSheet* mAttrStyleSheet; nsIHTMLCSSStyleSheet* mInlineStyleSheet; + // For additional catalog sheets (if any) needed to layout the XML vocabulary + // of the document. Catalog sheets are kept at the beginning of our array of + // style sheets and this counter is used as an offset to distinguish them + PRInt32 mCountCatalogSheets; nsString mBaseTarget; nsIParser *mParser; diff --git a/content/xul/document/src/nsXULContentSink.cpp b/content/xul/document/src/nsXULContentSink.cpp index 8efa44275bd..6239865f44e 100644 --- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -1025,7 +1025,8 @@ XULContentSinkImpl::HandleCDataSection(const PRUnichar *aData, PRUint32 aLength) } NS_IMETHODIMP -XULContentSinkImpl::HandleDoctypeDecl(const PRUnichar *aDoctype, PRUint32 aLength) +XULContentSinkImpl::HandleDoctypeDecl(const PRUnichar *aDoctype, PRUint32 aLength, + nsISupports* aCatalogData) { return NS_OK; } diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index fa9301da76d..122b161665e 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -671,7 +671,7 @@ nsXULDocument::PrepareStyleSheets(nsIURI* anURL) getter_AddRefs(sheet)))) { if (NS_SUCCEEDED(rv = sheet->Init(anURL, this))) { mAttrStyleSheet = sheet; - AddStyleSheet(mAttrStyleSheet); + AddStyleSheet(mAttrStyleSheet, 0); } } @@ -689,7 +689,7 @@ nsXULDocument::PrepareStyleSheets(nsIURI* anURL) (void**)&inlineSheet))) { if (NS_SUCCEEDED(rv = inlineSheet->Init(anURL, this))) { mInlineStyleSheet = dont_QueryInterface(inlineSheet); - AddStyleSheet(mInlineStyleSheet); + AddStyleSheet(mInlineStyleSheet, 0); } NS_RELEASE(inlineSheet); } @@ -1224,7 +1224,7 @@ nsXULDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet) } void -nsXULDocument::AddStyleSheet(nsIStyleSheet* aSheet) +nsXULDocument::AddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags) { NS_PRECONDITION(aSheet, "null arg"); if (!aSheet) @@ -1644,7 +1644,7 @@ nsXULDocument::EndLoad() if (useXULCache && IsChromeURI(sheetURL)) { mCurrentPrototype->AddStyleSheetReference(sheetURL); } - AddStyleSheet(sheet); + AddStyleSheet(sheet, 0); } } } @@ -6488,7 +6488,7 @@ nsXULDocument::AddPrototypeSheets() rv = sheet->Clone(*getter_AddRefs(newsheet)); if (NS_FAILED(rv)) return rv; - AddStyleSheet(newsheet); + AddStyleSheet(newsheet, 0); } return NS_OK; diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h index ccf64d67df7..604f465dde9 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/nsXULDocument.h @@ -240,7 +240,7 @@ public: NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsIStyleSheet** aSheet); NS_IMETHOD GetIndexOfStyleSheet(nsIStyleSheet* aSheet, PRInt32* aIndex); - virtual void AddStyleSheet(nsIStyleSheet* aSheet); + virtual void AddStyleSheet(nsIStyleSheet* aSheet, PRUint32 aFlags); virtual void RemoveStyleSheet(nsIStyleSheet* aSheet); NS_IMETHOD UpdateStyleSheets(nsISupportsArray* aOldSheets, nsISupportsArray* aNewSheets); void AddStyleSheetToStyleSets(nsIStyleSheet* aSheet); @@ -249,7 +249,7 @@ public: NS_IMETHOD InsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex, PRBool aNotify); virtual void SetStyleSheetDisabledState(nsIStyleSheet* aSheet, - PRBool mDisabled); + PRBool aDisabled); NS_IMETHOD GetCSSLoader(nsICSSLoader*& aLoader); diff --git a/editor/libeditor/base/nsStyleSheetTxns.cpp b/editor/libeditor/base/nsStyleSheetTxns.cpp index 1d7758c615e..49e3612d21e 100644 --- a/editor/libeditor/base/nsStyleSheetTxns.cpp +++ b/editor/libeditor/base/nsStyleSheetTxns.cpp @@ -107,7 +107,7 @@ AddStyleSheetTxn::DoTransaction() rv = presShell->GetDocument(getter_AddRefs(document)); if (NS_SUCCEEDED(rv) && document) - document->AddStyleSheet(styleSheet); + document->AddStyleSheet(styleSheet, 0); } } @@ -270,7 +270,7 @@ RemoveStyleSheetTxn::UndoTransaction() rv = presShell->GetDocument(getter_AddRefs(document)); if (NS_SUCCEEDED(rv) && document) - document->AddStyleSheet(styleSheet); + document->AddStyleSheet(styleSheet, 0); } } diff --git a/htmlparser/public/nsIExpatSink.idl b/htmlparser/public/nsIExpatSink.idl index 2a0e1043e37..feee46c0c84 100644 --- a/htmlparser/public/nsIExpatSink.idl +++ b/htmlparser/public/nsIExpatSink.idl @@ -53,9 +53,10 @@ interface nsIExpatSink : nsISupports void HandleCDataSection(in wstring aData, in unsigned long aLength); - + void HandleDoctypeDecl(in wstring aDoctype, - in unsigned long aLength); + in unsigned long aLength, + in nsISupports aCatalogData); void HandleCharacterData(in wstring aData, in unsigned long aLength); diff --git a/htmlparser/src/nsExpatDriver.cpp b/htmlparser/src/nsExpatDriver.cpp index 88e4957c7c4..a5cfb6da1c6 100644 --- a/htmlparser/src/nsExpatDriver.cpp +++ b/htmlparser/src/nsExpatDriver.cpp @@ -165,61 +165,125 @@ Driver_HandleEndDoctypeDecl(void *aUserData) } } - PR_STATIC_CALLBACK(int) -Driver_HandleExternalEntityRef(XML_Parser parser, +Driver_HandleExternalEntityRef(void* aExternalEntityRefHandler, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - int result = PR_TRUE; - - // Load the external entity into a buffer - nsCOMPtr in; - nsAutoString absURL; - - nsresult rv = nsExpatDriver::OpenInputStream(publicId, systemId, base, getter_AddRefs(in), absURL); - - if (NS_FAILED(rv)) { - return result; + NS_ASSERTION(aExternalEntityRefHandler, "expat driver should exist"); + if (aExternalEntityRefHandler) { + return NS_STATIC_CAST(nsExpatDriver*, + aExternalEntityRefHandler)->HandleExternalEntityRef( + (const PRUnichar*)openEntityNames, (const PRUnichar*)base, + (const PRUnichar*)systemId, (const PRUnichar*)publicId); } - - nsCOMPtr uniIn; - - NS_NewUTF8ConverterStream(getter_AddRefs(uniIn), in, 1024); - - if (uniIn) { - XML_Parser entParser = - XML_ExternalEntityParserCreate(parser, 0, (const XML_Char*) NS_LITERAL_STRING("UTF-16").get()); - - if (entParser) { - PRUint32 readCount = 0; - PRUnichar tmpBuff[1024] = {0}; - PRUnichar *uniBuf = tmpBuff; - - XML_SetBase(entParser, (const XML_Char*) absURL.get()); - - while (NS_SUCCEEDED(uniIn->Read(uniBuf, 0, 1024, &readCount)) && result) { - if (readCount) { - // Pass the buffer to expat for parsing - result = XML_Parse(entParser, (char *)uniBuf, readCount * sizeof(PRUnichar), 0); - } - else { - // done reading - result = XML_Parse(entParser, nsnull, 0, 1); - break; - } - } - XML_ParserFree(entParser); - } - } - - return result; + return 1; } /***************************** END CALL BACKS *********************************/ +/***************************** CATALOG UTILS **********************************/ + +// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus +// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses. +// Since Mozilla is not validating, no need to fetch a *huge* file at each click. +// XXX The cleanest solution here would be to fix Bug 98413: Implement XML Catalogs +struct nsCatalogData { + const char* mPublicID; + const char* mLocalDTD; + const char* mAgentSheet; +}; + +// The order of this table is guestimated to be in the optimum order +static const nsCatalogData kCatalogTable[] = { + {"-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.1//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML Basic 1.0//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "mathml.dtd", "resource:/res/mathml.css" }, + {"-//W3C//DTD SVG 20001102//EN", "svg.dtd", nsnull }, + {nsnull, nsnull, nsnull} +}; + +static const nsCatalogData* +LookupCatalogData(const PRUnichar* aPublicID) +{ + nsCAutoString publicID; + publicID.AssignWithConversion(aPublicID); + + // linear search for now since the number of entries is going to + // be negligible, and the fix for bug 98413 would get rid of this + // code anyway + const nsCatalogData* data = kCatalogTable; + while (data->mPublicID) { + if (publicID.Equals(data->mPublicID)) { + return data; + } + ++data; + } + return nsnull; +} + +// aCatalogData can be null. If not null, it provides a hook to additional +// built-in knowledge on the resource that we are trying to load. +// aDTD is an in/out parameter. Returns true if the local DTD specified in the +// catalog data exists or if the filename contained within the url exists in +// the special DTD directory. If either of this exists, aDTD is set to the +// file: url that points to the DTD file found in the local DTD directory AND +// the old URI is relased. +static PRBool +IsLoadableDTD(const nsCatalogData* aCatalogData, nsCOMPtr* aDTD) +{ + PRBool isLoadable = PR_FALSE; + nsresult res = NS_OK; + + if (!aDTD || !*aDTD) { + NS_ASSERTION(0, "Null parameter."); + return PR_FALSE; + } + + nsCAutoString fileName; + if (aCatalogData) { + // remap the DTD to a known local DTD + fileName.Assign(aCatalogData->mLocalDTD); + } + if (fileName.IsEmpty()) { + // try to see if the user has installed the DTD file -- we extract the + // filename.ext of the DTD here. Hence, for any DTD for which we have + // no predefined mapping, users just have to copy the DTD file to our + // special DTD directory and it will be picked + nsCOMPtr dtdURL; + dtdURL = do_QueryInterface(*aDTD, &res); + if (NS_FAILED(res)) { + return PR_FALSE; + } + res = dtdURL->GetFileName(fileName); + if (NS_FAILED(res) || fileName.IsEmpty()) { + return PR_FALSE; + } + } + nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); + dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); + if (dtdPath.Exists()) { + // The DTD was found in the local DTD directory. + // Set aDTD to a file: url pointing to the local DTD + nsFileURL dtdFile(dtdPath); + nsCOMPtr dtdURI; + NS_NewURI(getter_AddRefs(dtdURI), dtdFile.GetURLString()); + if (dtdURI) { + *aDTD = dtdURI; + isLoadable = PR_TRUE; + } + } + + return isLoadable; +} + +/***************************** END CATALOG UTILS ******************************/ + NS_IMPL_ISUPPORTS2(nsExpatDriver, nsITokenizer, nsIDTD); @@ -241,7 +305,8 @@ nsExpatDriver::nsExpatDriver() mBytesParsed(0), mBytePosition(0), mInternalState(NS_OK), - mDoctypePos(-1) + mDoctypePos(-1), + mCatalogData(nsnull) { NS_INIT_REFCNT(); } @@ -386,7 +451,15 @@ nsExpatDriver::HandleEndDoctypeDecl() const PRUnichar* doctypeEnd = mBuffer + ( XML_GetCurrentByteIndex(mExpatParser) - mBytesParsed ) / 2; if(mSink) { - mInternalState = mSink->HandleDoctypeDecl(doctypeStart, doctypeEnd - doctypeStart); + // let the sink know any additional knowledge that we have about the document + // (currently, from bug 124570, we only expect to pass additional agent sheets + // needed to layout the XML vocabulary of the document) + nsIURI* data = nsnull; + if (mCatalogData && mCatalogData->mAgentSheet) { + NS_NewURI(&data, mCatalogData->mAgentSheet); + } + mInternalState = mSink->HandleDoctypeDecl(doctypeStart, doctypeEnd - doctypeStart, data); + NS_IF_RELEASE(data); } mDoctypePos = kNotInDoctype; @@ -394,130 +467,90 @@ nsExpatDriver::HandleEndDoctypeDecl() return NS_OK; } -// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus -// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses. -// Since Mozilla is not validating, no need to fetch a *huge* file at each click. -// XXX The cleanest solution here would be to fix Bug 98413: Implement XML Catalogs -struct nsCatalogEntry { - const char* mPublicID; - const char* mLocalDTD; -}; - -// The order of this table is guestimated to be in the optimum order -static const nsCatalogEntry kCatalogTable[] = { - {"-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.1//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML Basic 1.0//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "mathml.dtd" }, - {"-//W3C//DTD SVG 20001102//EN", "svg.dtd" }, - {nsnull, nsnull} -}; - -static void -RemapDTD(const XML_Char* aPublicID, nsAWritableCString& aLocalDTD) +int +nsExpatDriver::HandleExternalEntityRef(const PRUnichar *openEntityNames, + const PRUnichar *base, + const PRUnichar *systemId, + const PRUnichar *publicId) { - nsCAutoString publicID; - publicID.AssignWithConversion((const PRUnichar*)aPublicID); + int result = 1; - // linear search for now since the number of entries is going to - // be negligible, and the fix for bug 98413 would get rid of this - // code anyway - aLocalDTD.Truncate(); - const nsCatalogEntry* data = kCatalogTable; - while (data->mPublicID) { - if (publicID.Equals(data->mPublicID)) { - aLocalDTD = data->mLocalDTD; - return; - } - ++data; - } -} + // Load the external entity into a buffer + nsCOMPtr in; + nsAutoString absURL; -// aDTD is an in/out parameter. Returns true if the aDTD is a chrome url or if the -// filename contained within the url exists in the special DTD directory. -// For the latter case, aDTD is set to the file: url that points to the DTD -// file found in the local DTD directory AND the old URI is relased. -static PRBool -IsLoadableDTD(const XML_Char* aFPIStr, nsCOMPtr* aDTD) -{ - PRBool isLoadable = PR_FALSE; - nsresult res = NS_OK; + nsresult rv = OpenInputStream(publicId, systemId, base, getter_AddRefs(in), absURL); - if (!aDTD || !*aDTD) { - NS_ASSERTION(0, "Null parameter."); - return PR_FALSE; + if (NS_FAILED(rv)) { + return result; } - // Return true if the url is a chrome url - res = (*aDTD)->SchemeIs("chrome", &isLoadable); + nsCOMPtr uniIn; - // If the url is not a chrome url, check to see if a DTD file of the same name - // exists in the special DTD directory - if (!isLoadable) { - // try to see if we can map the public ID to a known local DTD - nsCAutoString fileName; - if (aFPIStr) { - RemapDTD(aFPIStr, fileName); - } - if (fileName.IsEmpty()) { - // try to see if the user has installed the DTD file -- we extract the - // filename.ext of the DTD here. Hence, for any DTD for which we have - // no predefined mapping, users just have to copy the DTD file to our - // special DTD directory and it will be picked - nsCOMPtr dtdURL; - dtdURL = do_QueryInterface(*aDTD, &res); - if (NS_FAILED(res)) { - return PR_FALSE; - } - res = dtdURL->GetFileName(fileName); - if (NS_FAILED(res) || fileName.IsEmpty()) { - return PR_FALSE; - } - } - nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); - dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); - if (dtdPath.Exists()) { - // The DTD was found in the local DTD directory. - // Set aDTD to a file: url pointing to the local DTD - nsFileURL dtdFile(dtdPath); - nsCOMPtr dtdURI; - NS_NewURI(getter_AddRefs(dtdURI), nsDependentCString(dtdFile.GetURLString())); - if (dtdURI) { - *aDTD = dtdURI; - isLoadable = PR_TRUE; + NS_NewUTF8ConverterStream(getter_AddRefs(uniIn), in, 1024); + + if (uniIn) { + XML_Parser entParser = + XML_ExternalEntityParserCreate(mExpatParser, 0, (const XML_Char*) NS_LITERAL_STRING("UTF-16").get()); + + if (entParser) { + PRUint32 readCount = 0; + PRUnichar tmpBuff[1024] = {0}; + PRUnichar *uniBuf = tmpBuff; + + XML_SetBase(entParser, (const XML_Char*) absURL.get()); + + while (NS_SUCCEEDED(uniIn->Read(uniBuf, 0, 1024, &readCount)) && result) { + if (readCount) { + // Pass the buffer to expat for parsing + result = XML_Parse(entParser, (char *)uniBuf, readCount * sizeof(PRUnichar), 0); + } + else { + // done reading + result = XML_Parse(entParser, nsnull, 0, 1); + break; + } } + XML_ParserFree(entParser); } } - - return isLoadable; + + return result; } nsresult -nsExpatDriver::OpenInputStream(const XML_Char* aFPIStr, - const XML_Char* aURLStr, - const XML_Char* aBaseURL, +nsExpatDriver::OpenInputStream(const PRUnichar* aFPIStr, + const PRUnichar* aURLStr, + const PRUnichar* aBaseURL, nsIInputStream** in, nsAString& aAbsURL) { nsresult rv; nsCOMPtr baseURI; - rv = NS_NewURI(getter_AddRefs(baseURI), NS_ConvertUCS2toUTF8((const PRUnichar*)aBaseURL)); + rv = NS_NewURI(getter_AddRefs(baseURI), NS_ConvertUCS2toUTF8(aBaseURL).get()); if (NS_SUCCEEDED(rv) && baseURI) { nsCOMPtr uri; - rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8((const PRUnichar*)aURLStr), nsnull, baseURI); + rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8(aURLStr).get(), baseURI); if (NS_SUCCEEDED(rv) && uri) { - if (IsLoadableDTD(aFPIStr, address_of(uri))) { - rv = NS_OpenURI(in, uri); - nsCAutoString absURL; - uri->GetSpec(absURL); - aAbsURL = NS_ConvertUTF8toUCS2(absURL); - } - else { - rv = NS_ERROR_NOT_IMPLEMENTED; + // check if it is alright to load this uri + PRBool isChrome = PR_FALSE; + uri->SchemeIs("chrome", &isChrome); + if (!isChrome) { + // since the url is not a chrome url, check to see if we can map the DTD + // to a known local DTD, or if a DTD file of the same name exists in the + // special DTD directory + if (aFPIStr) { + // see if the Formal Public Identifier (FPI) maps to a catalog entry + mCatalogData = LookupCatalogData(aFPIStr); + } + if (!IsLoadableDTD(mCatalogData, address_of(uri))) + return NS_ERROR_NOT_IMPLEMENTED; } - } + rv = NS_OpenURI(in, uri); + nsCAutoString absURL; + uri->GetSpec(absURL); + aAbsURL = NS_ConvertUTF8toUCS2(absURL); + } } return rv; } @@ -813,6 +846,7 @@ nsExpatDriver::WillBuildModel(const CParserContext& aParserContext, XML_SetProcessingInstructionHandler(mExpatParser, Driver_HandleProcessingInstruction); XML_SetDefaultHandlerExpand(mExpatParser, Driver_HandleDefault); XML_SetExternalEntityRefHandler(mExpatParser, Driver_HandleExternalEntityRef); + XML_SetExternalEntityRefHandlerArg(mExpatParser, this); XML_SetCommentHandler(mExpatParser, Driver_HandleComment); XML_SetCdataSectionHandler(mExpatParser, Driver_HandleStartCdataSection, Driver_HandleEndCdataSection); diff --git a/htmlparser/src/nsExpatDriver.h b/htmlparser/src/nsExpatDriver.h index 46fa652c445..83344cc72e0 100644 --- a/htmlparser/src/nsExpatDriver.h +++ b/htmlparser/src/nsExpatDriver.h @@ -46,6 +46,7 @@ #include "nsFileSpec.h" class nsIExpatSink; +struct nsCatalogData; class nsExpatDriver : public nsIDTD, public nsITokenizer @@ -58,13 +59,10 @@ public: nsExpatDriver(); virtual ~nsExpatDriver(); - // Load up an external stream to get external entity information - static nsresult OpenInputStream(const XML_Char* aFPIStr, - const XML_Char* aURLStr, - const XML_Char* aBaseURL, - nsIInputStream** in, - nsAString& aAbsURL); - + int HandleExternalEntityRef(const PRUnichar *openEntityNames, + const PRUnichar *base, + const PRUnichar *systemId, + const PRUnichar *publicId); nsresult HandleStartElement(const PRUnichar *aName, const PRUnichar **aAtts); nsresult HandleEndElement(const PRUnichar *aName); nsresult HandleCharacterData(const PRUnichar *aCData, const PRUint32 aLength); @@ -77,7 +75,14 @@ public: nsresult HandleEndDoctypeDecl(); protected: - + + // Load up an external stream to get external entity information + nsresult OpenInputStream(const PRUnichar* aFPIStr, + const PRUnichar* aURLStr, + const PRUnichar* aBaseURL, + nsIInputStream** in, + nsAString& aAbsURL); + nsresult ParseBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal); nsresult HandleError(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal); void GetLine(const char* aSourceBuffer, PRUint32 aLength, PRUint32 aOffset, nsString& aLine); @@ -93,7 +98,7 @@ protected: nsresult mInternalState; PRUint32 mBytesParsed; PRUint32 mDoctypePos; - + const nsCatalogData* mCatalogData; // weak }; nsresult NS_NewExpatDriver(nsIDTD** aDriver); diff --git a/layout/mathml/content/src/Makefile.in b/layout/mathml/content/src/Makefile.in index ca8f422010a..0690d2fe914 100644 --- a/layout/mathml/content/src/Makefile.in +++ b/layout/mathml/content/src/Makefile.in @@ -61,4 +61,3 @@ EXPORT_RESOURCE_CONTENT = \ libs:: $(INSTALL) $(EXPORT_RESOURCE_CONTENT) $(DIST)/bin/res/dtd $(INSTALL) $(srcdir)/mathml.css $(DIST)/bin/res - $(PERL) $(srcdir)/mathml-css.pl $(DIST)/bin/res/ua.css diff --git a/layout/mathml/content/src/makefile.win b/layout/mathml/content/src/makefile.win index 0822f77cb15..e4fcf4db855 100644 --- a/layout/mathml/content/src/makefile.win +++ b/layout/mathml/content/src/makefile.win @@ -53,7 +53,6 @@ libs:: $(LIBRARY) libs:: $(MAKE_INSTALL) mathml.dtd $(DIST)\bin\res\dtd $(MAKE_INSTALL) mathml.css $(DIST)\bin\res - $(PERL) mathml-css.pl $(DIST)\bin\res\ua.css clobber:: rm -f $(DIST)\lib\$(LIBRARY_NAME).lib diff --git a/parser/htmlparser/public/nsIExpatSink.idl b/parser/htmlparser/public/nsIExpatSink.idl index 2a0e1043e37..feee46c0c84 100644 --- a/parser/htmlparser/public/nsIExpatSink.idl +++ b/parser/htmlparser/public/nsIExpatSink.idl @@ -53,9 +53,10 @@ interface nsIExpatSink : nsISupports void HandleCDataSection(in wstring aData, in unsigned long aLength); - + void HandleDoctypeDecl(in wstring aDoctype, - in unsigned long aLength); + in unsigned long aLength, + in nsISupports aCatalogData); void HandleCharacterData(in wstring aData, in unsigned long aLength); diff --git a/parser/htmlparser/src/nsExpatDriver.cpp b/parser/htmlparser/src/nsExpatDriver.cpp index 88e4957c7c4..a5cfb6da1c6 100644 --- a/parser/htmlparser/src/nsExpatDriver.cpp +++ b/parser/htmlparser/src/nsExpatDriver.cpp @@ -165,61 +165,125 @@ Driver_HandleEndDoctypeDecl(void *aUserData) } } - PR_STATIC_CALLBACK(int) -Driver_HandleExternalEntityRef(XML_Parser parser, +Driver_HandleExternalEntityRef(void* aExternalEntityRefHandler, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { - int result = PR_TRUE; - - // Load the external entity into a buffer - nsCOMPtr in; - nsAutoString absURL; - - nsresult rv = nsExpatDriver::OpenInputStream(publicId, systemId, base, getter_AddRefs(in), absURL); - - if (NS_FAILED(rv)) { - return result; + NS_ASSERTION(aExternalEntityRefHandler, "expat driver should exist"); + if (aExternalEntityRefHandler) { + return NS_STATIC_CAST(nsExpatDriver*, + aExternalEntityRefHandler)->HandleExternalEntityRef( + (const PRUnichar*)openEntityNames, (const PRUnichar*)base, + (const PRUnichar*)systemId, (const PRUnichar*)publicId); } - - nsCOMPtr uniIn; - - NS_NewUTF8ConverterStream(getter_AddRefs(uniIn), in, 1024); - - if (uniIn) { - XML_Parser entParser = - XML_ExternalEntityParserCreate(parser, 0, (const XML_Char*) NS_LITERAL_STRING("UTF-16").get()); - - if (entParser) { - PRUint32 readCount = 0; - PRUnichar tmpBuff[1024] = {0}; - PRUnichar *uniBuf = tmpBuff; - - XML_SetBase(entParser, (const XML_Char*) absURL.get()); - - while (NS_SUCCEEDED(uniIn->Read(uniBuf, 0, 1024, &readCount)) && result) { - if (readCount) { - // Pass the buffer to expat for parsing - result = XML_Parse(entParser, (char *)uniBuf, readCount * sizeof(PRUnichar), 0); - } - else { - // done reading - result = XML_Parse(entParser, nsnull, 0, 1); - break; - } - } - XML_ParserFree(entParser); - } - } - - return result; + return 1; } /***************************** END CALL BACKS *********************************/ +/***************************** CATALOG UTILS **********************************/ + +// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus +// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses. +// Since Mozilla is not validating, no need to fetch a *huge* file at each click. +// XXX The cleanest solution here would be to fix Bug 98413: Implement XML Catalogs +struct nsCatalogData { + const char* mPublicID; + const char* mLocalDTD; + const char* mAgentSheet; +}; + +// The order of this table is guestimated to be in the optimum order +static const nsCatalogData kCatalogTable[] = { + {"-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.1//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML Basic 1.0//EN", "xhtml11.dtd", nsnull }, + {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "mathml.dtd", "resource:/res/mathml.css" }, + {"-//W3C//DTD SVG 20001102//EN", "svg.dtd", nsnull }, + {nsnull, nsnull, nsnull} +}; + +static const nsCatalogData* +LookupCatalogData(const PRUnichar* aPublicID) +{ + nsCAutoString publicID; + publicID.AssignWithConversion(aPublicID); + + // linear search for now since the number of entries is going to + // be negligible, and the fix for bug 98413 would get rid of this + // code anyway + const nsCatalogData* data = kCatalogTable; + while (data->mPublicID) { + if (publicID.Equals(data->mPublicID)) { + return data; + } + ++data; + } + return nsnull; +} + +// aCatalogData can be null. If not null, it provides a hook to additional +// built-in knowledge on the resource that we are trying to load. +// aDTD is an in/out parameter. Returns true if the local DTD specified in the +// catalog data exists or if the filename contained within the url exists in +// the special DTD directory. If either of this exists, aDTD is set to the +// file: url that points to the DTD file found in the local DTD directory AND +// the old URI is relased. +static PRBool +IsLoadableDTD(const nsCatalogData* aCatalogData, nsCOMPtr* aDTD) +{ + PRBool isLoadable = PR_FALSE; + nsresult res = NS_OK; + + if (!aDTD || !*aDTD) { + NS_ASSERTION(0, "Null parameter."); + return PR_FALSE; + } + + nsCAutoString fileName; + if (aCatalogData) { + // remap the DTD to a known local DTD + fileName.Assign(aCatalogData->mLocalDTD); + } + if (fileName.IsEmpty()) { + // try to see if the user has installed the DTD file -- we extract the + // filename.ext of the DTD here. Hence, for any DTD for which we have + // no predefined mapping, users just have to copy the DTD file to our + // special DTD directory and it will be picked + nsCOMPtr dtdURL; + dtdURL = do_QueryInterface(*aDTD, &res); + if (NS_FAILED(res)) { + return PR_FALSE; + } + res = dtdURL->GetFileName(fileName); + if (NS_FAILED(res) || fileName.IsEmpty()) { + return PR_FALSE; + } + } + nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); + dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); + if (dtdPath.Exists()) { + // The DTD was found in the local DTD directory. + // Set aDTD to a file: url pointing to the local DTD + nsFileURL dtdFile(dtdPath); + nsCOMPtr dtdURI; + NS_NewURI(getter_AddRefs(dtdURI), dtdFile.GetURLString()); + if (dtdURI) { + *aDTD = dtdURI; + isLoadable = PR_TRUE; + } + } + + return isLoadable; +} + +/***************************** END CATALOG UTILS ******************************/ + NS_IMPL_ISUPPORTS2(nsExpatDriver, nsITokenizer, nsIDTD); @@ -241,7 +305,8 @@ nsExpatDriver::nsExpatDriver() mBytesParsed(0), mBytePosition(0), mInternalState(NS_OK), - mDoctypePos(-1) + mDoctypePos(-1), + mCatalogData(nsnull) { NS_INIT_REFCNT(); } @@ -386,7 +451,15 @@ nsExpatDriver::HandleEndDoctypeDecl() const PRUnichar* doctypeEnd = mBuffer + ( XML_GetCurrentByteIndex(mExpatParser) - mBytesParsed ) / 2; if(mSink) { - mInternalState = mSink->HandleDoctypeDecl(doctypeStart, doctypeEnd - doctypeStart); + // let the sink know any additional knowledge that we have about the document + // (currently, from bug 124570, we only expect to pass additional agent sheets + // needed to layout the XML vocabulary of the document) + nsIURI* data = nsnull; + if (mCatalogData && mCatalogData->mAgentSheet) { + NS_NewURI(&data, mCatalogData->mAgentSheet); + } + mInternalState = mSink->HandleDoctypeDecl(doctypeStart, doctypeEnd - doctypeStart, data); + NS_IF_RELEASE(data); } mDoctypePos = kNotInDoctype; @@ -394,130 +467,90 @@ nsExpatDriver::HandleEndDoctypeDecl() return NS_OK; } -// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus -// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses. -// Since Mozilla is not validating, no need to fetch a *huge* file at each click. -// XXX The cleanest solution here would be to fix Bug 98413: Implement XML Catalogs -struct nsCatalogEntry { - const char* mPublicID; - const char* mLocalDTD; -}; - -// The order of this table is guestimated to be in the optimum order -static const nsCatalogEntry kCatalogTable[] = { - {"-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.1//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML Basic 1.0//EN", "xhtml11.dtd" }, - {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "mathml.dtd" }, - {"-//W3C//DTD SVG 20001102//EN", "svg.dtd" }, - {nsnull, nsnull} -}; - -static void -RemapDTD(const XML_Char* aPublicID, nsAWritableCString& aLocalDTD) +int +nsExpatDriver::HandleExternalEntityRef(const PRUnichar *openEntityNames, + const PRUnichar *base, + const PRUnichar *systemId, + const PRUnichar *publicId) { - nsCAutoString publicID; - publicID.AssignWithConversion((const PRUnichar*)aPublicID); + int result = 1; - // linear search for now since the number of entries is going to - // be negligible, and the fix for bug 98413 would get rid of this - // code anyway - aLocalDTD.Truncate(); - const nsCatalogEntry* data = kCatalogTable; - while (data->mPublicID) { - if (publicID.Equals(data->mPublicID)) { - aLocalDTD = data->mLocalDTD; - return; - } - ++data; - } -} + // Load the external entity into a buffer + nsCOMPtr in; + nsAutoString absURL; -// aDTD is an in/out parameter. Returns true if the aDTD is a chrome url or if the -// filename contained within the url exists in the special DTD directory. -// For the latter case, aDTD is set to the file: url that points to the DTD -// file found in the local DTD directory AND the old URI is relased. -static PRBool -IsLoadableDTD(const XML_Char* aFPIStr, nsCOMPtr* aDTD) -{ - PRBool isLoadable = PR_FALSE; - nsresult res = NS_OK; + nsresult rv = OpenInputStream(publicId, systemId, base, getter_AddRefs(in), absURL); - if (!aDTD || !*aDTD) { - NS_ASSERTION(0, "Null parameter."); - return PR_FALSE; + if (NS_FAILED(rv)) { + return result; } - // Return true if the url is a chrome url - res = (*aDTD)->SchemeIs("chrome", &isLoadable); + nsCOMPtr uniIn; - // If the url is not a chrome url, check to see if a DTD file of the same name - // exists in the special DTD directory - if (!isLoadable) { - // try to see if we can map the public ID to a known local DTD - nsCAutoString fileName; - if (aFPIStr) { - RemapDTD(aFPIStr, fileName); - } - if (fileName.IsEmpty()) { - // try to see if the user has installed the DTD file -- we extract the - // filename.ext of the DTD here. Hence, for any DTD for which we have - // no predefined mapping, users just have to copy the DTD file to our - // special DTD directory and it will be picked - nsCOMPtr dtdURL; - dtdURL = do_QueryInterface(*aDTD, &res); - if (NS_FAILED(res)) { - return PR_FALSE; - } - res = dtdURL->GetFileName(fileName); - if (NS_FAILED(res) || fileName.IsEmpty()) { - return PR_FALSE; - } - } - nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); - dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); - if (dtdPath.Exists()) { - // The DTD was found in the local DTD directory. - // Set aDTD to a file: url pointing to the local DTD - nsFileURL dtdFile(dtdPath); - nsCOMPtr dtdURI; - NS_NewURI(getter_AddRefs(dtdURI), nsDependentCString(dtdFile.GetURLString())); - if (dtdURI) { - *aDTD = dtdURI; - isLoadable = PR_TRUE; + NS_NewUTF8ConverterStream(getter_AddRefs(uniIn), in, 1024); + + if (uniIn) { + XML_Parser entParser = + XML_ExternalEntityParserCreate(mExpatParser, 0, (const XML_Char*) NS_LITERAL_STRING("UTF-16").get()); + + if (entParser) { + PRUint32 readCount = 0; + PRUnichar tmpBuff[1024] = {0}; + PRUnichar *uniBuf = tmpBuff; + + XML_SetBase(entParser, (const XML_Char*) absURL.get()); + + while (NS_SUCCEEDED(uniIn->Read(uniBuf, 0, 1024, &readCount)) && result) { + if (readCount) { + // Pass the buffer to expat for parsing + result = XML_Parse(entParser, (char *)uniBuf, readCount * sizeof(PRUnichar), 0); + } + else { + // done reading + result = XML_Parse(entParser, nsnull, 0, 1); + break; + } } + XML_ParserFree(entParser); } } - - return isLoadable; + + return result; } nsresult -nsExpatDriver::OpenInputStream(const XML_Char* aFPIStr, - const XML_Char* aURLStr, - const XML_Char* aBaseURL, +nsExpatDriver::OpenInputStream(const PRUnichar* aFPIStr, + const PRUnichar* aURLStr, + const PRUnichar* aBaseURL, nsIInputStream** in, nsAString& aAbsURL) { nsresult rv; nsCOMPtr baseURI; - rv = NS_NewURI(getter_AddRefs(baseURI), NS_ConvertUCS2toUTF8((const PRUnichar*)aBaseURL)); + rv = NS_NewURI(getter_AddRefs(baseURI), NS_ConvertUCS2toUTF8(aBaseURL).get()); if (NS_SUCCEEDED(rv) && baseURI) { nsCOMPtr uri; - rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8((const PRUnichar*)aURLStr), nsnull, baseURI); + rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8(aURLStr).get(), baseURI); if (NS_SUCCEEDED(rv) && uri) { - if (IsLoadableDTD(aFPIStr, address_of(uri))) { - rv = NS_OpenURI(in, uri); - nsCAutoString absURL; - uri->GetSpec(absURL); - aAbsURL = NS_ConvertUTF8toUCS2(absURL); - } - else { - rv = NS_ERROR_NOT_IMPLEMENTED; + // check if it is alright to load this uri + PRBool isChrome = PR_FALSE; + uri->SchemeIs("chrome", &isChrome); + if (!isChrome) { + // since the url is not a chrome url, check to see if we can map the DTD + // to a known local DTD, or if a DTD file of the same name exists in the + // special DTD directory + if (aFPIStr) { + // see if the Formal Public Identifier (FPI) maps to a catalog entry + mCatalogData = LookupCatalogData(aFPIStr); + } + if (!IsLoadableDTD(mCatalogData, address_of(uri))) + return NS_ERROR_NOT_IMPLEMENTED; } - } + rv = NS_OpenURI(in, uri); + nsCAutoString absURL; + uri->GetSpec(absURL); + aAbsURL = NS_ConvertUTF8toUCS2(absURL); + } } return rv; } @@ -813,6 +846,7 @@ nsExpatDriver::WillBuildModel(const CParserContext& aParserContext, XML_SetProcessingInstructionHandler(mExpatParser, Driver_HandleProcessingInstruction); XML_SetDefaultHandlerExpand(mExpatParser, Driver_HandleDefault); XML_SetExternalEntityRefHandler(mExpatParser, Driver_HandleExternalEntityRef); + XML_SetExternalEntityRefHandlerArg(mExpatParser, this); XML_SetCommentHandler(mExpatParser, Driver_HandleComment); XML_SetCdataSectionHandler(mExpatParser, Driver_HandleStartCdataSection, Driver_HandleEndCdataSection); diff --git a/parser/htmlparser/src/nsExpatDriver.h b/parser/htmlparser/src/nsExpatDriver.h index 46fa652c445..83344cc72e0 100644 --- a/parser/htmlparser/src/nsExpatDriver.h +++ b/parser/htmlparser/src/nsExpatDriver.h @@ -46,6 +46,7 @@ #include "nsFileSpec.h" class nsIExpatSink; +struct nsCatalogData; class nsExpatDriver : public nsIDTD, public nsITokenizer @@ -58,13 +59,10 @@ public: nsExpatDriver(); virtual ~nsExpatDriver(); - // Load up an external stream to get external entity information - static nsresult OpenInputStream(const XML_Char* aFPIStr, - const XML_Char* aURLStr, - const XML_Char* aBaseURL, - nsIInputStream** in, - nsAString& aAbsURL); - + int HandleExternalEntityRef(const PRUnichar *openEntityNames, + const PRUnichar *base, + const PRUnichar *systemId, + const PRUnichar *publicId); nsresult HandleStartElement(const PRUnichar *aName, const PRUnichar **aAtts); nsresult HandleEndElement(const PRUnichar *aName); nsresult HandleCharacterData(const PRUnichar *aCData, const PRUint32 aLength); @@ -77,7 +75,14 @@ public: nsresult HandleEndDoctypeDecl(); protected: - + + // Load up an external stream to get external entity information + nsresult OpenInputStream(const PRUnichar* aFPIStr, + const PRUnichar* aURLStr, + const PRUnichar* aBaseURL, + nsIInputStream** in, + nsAString& aAbsURL); + nsresult ParseBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal); nsresult HandleError(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal); void GetLine(const char* aSourceBuffer, PRUint32 aLength, PRUint32 aOffset, nsString& aLine); @@ -93,7 +98,7 @@ protected: nsresult mInternalState; PRUint32 mBytesParsed; PRUint32 mDoctypePos; - + const nsCatalogData* mCatalogData; // weak }; nsresult NS_NewExpatDriver(nsIDTD** aDriver); diff --git a/rdf/base/src/nsRDFContentSink.cpp b/rdf/base/src/nsRDFContentSink.cpp index 1f2eb6443c1..652796f9342 100644 --- a/rdf/base/src/nsRDFContentSink.cpp +++ b/rdf/base/src/nsRDFContentSink.cpp @@ -603,7 +603,8 @@ RDFContentSinkImpl::HandleCDataSection(const PRUnichar *aData, } NS_IMETHODIMP -RDFContentSinkImpl::HandleDoctypeDecl(const PRUnichar *aDoctype, PRUint32 aLength) +RDFContentSinkImpl::HandleDoctypeDecl(const PRUnichar *aDoctype, PRUint32 aLength, + nsISupports *aCatalogData) { return NS_OK; }