From 919aef29e458e18dd3a647d3c03cc07bbbace31d Mon Sep 17 00:00:00 2001 From: "heikki%netscape.com" Date: Fri, 11 Oct 2002 00:38:29 +0000 Subject: [PATCH] Bug 172372, when loading XML as data, we need to disable scripts and styles. r=sicking, sr=bzbarsky, a=asa. --- content/base/public/nsIScriptLoader.idl | 19 ++-- content/base/src/nsScriptLoader.cpp | 22 +++-- content/base/src/nsScriptLoader.h | 2 +- content/base/src/nsSyncLoadService.cpp | 2 +- .../html/document/src/nsHTMLContentSink.cpp | 4 +- content/html/style/public/nsICSSLoader.h | 10 +++ content/html/style/src/nsCSSLoader.cpp | 89 +++++++++++++------ content/xbl/src/nsXBLService.cpp | 9 +- content/xml/document/src/nsXMLContentSink.cpp | 7 ++ content/xml/document/src/nsXMLDocument.cpp | 26 ++++++ content/xsl/document/src/nsXSLContentSink.cpp | 2 +- layout/style/nsCSSLoader.cpp | 89 +++++++++++++------ layout/style/nsICSSLoader.h | 10 +++ 13 files changed, 207 insertions(+), 84 deletions(-) diff --git a/content/base/public/nsIScriptLoader.idl b/content/base/public/nsIScriptLoader.idl index 3779847dd447..c48ea6eac812 100644 --- a/content/base/public/nsIScriptLoader.idl +++ b/content/base/public/nsIScriptLoader.idl @@ -75,18 +75,11 @@ interface nsIScriptLoader : nsISupports { in nsIScriptLoaderObserver aObserver); /** - * Suspend processing of new script elements. Any call to - * processScriptElement() will fail with a return code of - * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT suspend - * currently loading or executing scripts. All calls to - * suspend() must be matched with an equal number of calls - * to resume() before processing of new script elements - * continues. + * Whether the loader is enabled or not. + * When disabled, processing of new script elements is disabled. + * Any call to processScriptElement() will fail with a return code of + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable + * currently loading or executing scripts. */ - void suspend(); - - /** - * Resume processing of new script elements. - */ - void resume(); + attribute boolean enabled; }; diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 5299e83ef572..4eeaf20f1013 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -69,9 +69,9 @@ public: nsCOMPtr mElement; nsCOMPtr mObserver; - PRBool mLoading; // Are we still waiting for a load to complete? - PRBool mWasPending; // Processed immediately or pending - PRBool mIsInline; // Is the script inline or loaded? + PRPackedBool mLoading; // Are we still waiting for a load to complete? + PRPackedBool mWasPending; // Processed immediately or pending + PRPackedBool mIsInline; // Is the script inline or loaded? // nsSharableString mScriptText; // Holds script for loaded scripts nsString mScriptText; const char* mJSVersion; // We don't own this string @@ -124,7 +124,7 @@ nsScriptLoadRequest::FireScriptEvaluated(nsresult aResult) ////////////////////////////////////////////////////////////// nsScriptLoader::nsScriptLoader() - : mDocument(nsnull), mSuspendCount(0) + : mDocument(nsnull), mEnabled(PR_TRUE) { NS_INIT_ISUPPORTS(); } @@ -251,7 +251,7 @@ nsScriptLoader::ProcessScriptElement(nsIDOMHTMLScriptElement *aElement, // Check to see that the element is not in a container that // suppresses script evaluation within it. - if (mSuspendCount || InNonScriptingContainer(aElement)) { + if (!mEnabled || InNonScriptingContainer(aElement)) { return FireErrorNotification(NS_ERROR_NOT_AVAILABLE, aElement, aObserver); } @@ -834,18 +834,16 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader, } NS_IMETHODIMP -nsScriptLoader::Suspend() +nsScriptLoader::GetEnabled(PRBool *aEnabled) { - mSuspendCount++; - + NS_ENSURE_ARG_POINTER(aEnabled); + *aEnabled = mEnabled; return NS_OK; } NS_IMETHODIMP -nsScriptLoader::Resume() +nsScriptLoader::SetEnabled(PRBool aEnabled) { - NS_ASSERTION((mSuspendCount > 0), "nsScriptLoader call to resume() unbalanced"); - mSuspendCount--; - + mEnabled = aEnabled; return NS_OK; } diff --git a/content/base/src/nsScriptLoader.h b/content/base/src/nsScriptLoader.h index 80e967162e71..270b707b27ac 100644 --- a/content/base/src/nsScriptLoader.h +++ b/content/base/src/nsScriptLoader.h @@ -68,7 +68,7 @@ protected: nsIDocument* mDocument; // [WEAK] nsSupportsArray mObservers; nsSupportsArray mPendingRequests; - PRInt32 mSuspendCount; + PRBool mEnabled; }; #endif //__nsScriptLoader_h__ diff --git a/content/base/src/nsSyncLoadService.cpp b/content/base/src/nsSyncLoadService.cpp index 2aa79d05f249..f233509358ed 100644 --- a/content/base/src/nsSyncLoadService.cpp +++ b/content/base/src/nsSyncLoadService.cpp @@ -553,7 +553,7 @@ nsSyncLoadService::LoadLocalXBLDocument(nsIChannel* aChannel, NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr listener; - rv = doc->StartDocumentLoad(kLoadAsData, + rv = doc->StartDocumentLoad("loadAsInteractiveData", aChannel, loadGroup, nsnull, diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index ce1c64e69d3e..6c185bc1350b 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -5612,7 +5612,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) if (mDocument) { mDocument->GetScriptLoader(getter_AddRefs(loader)); if (loader) { - loader->Suspend(); + loader->SetEnabled(PR_FALSE); } } } else { @@ -5645,7 +5645,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) // suspended the script loader. Now that the script content // has been handled let's resume the script loader. if (loader) { - loader->Resume(); + loader->SetEnabled(PR_TRUE); } // If the act of insertion evaluated the script, we're fine. diff --git a/content/html/style/public/nsICSSLoader.h b/content/html/style/public/nsICSSLoader.h index ed1966d0761b..65b0071b3227 100644 --- a/content/html/style/public/nsICSSLoader.h +++ b/content/html/style/public/nsICSSLoader.h @@ -130,6 +130,16 @@ public: // stop loading one sheet NS_IMETHOD StopLoadingSheet(nsIURI* aURL) = 0; + + /** + * Whether the loader is enabled or not. + * When disabled, processing of new styles is disabled and an attempt + * to do so will fail with a return code of + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable + * currently loading styles or already processed styles. + */ + NS_IMETHOD GetEnabled(PRBool *aEnabled) = 0; + NS_IMETHOD SetEnabled(PRBool aEnabled) = 0; }; extern NS_EXPORT nsresult diff --git a/content/html/style/src/nsCSSLoader.cpp b/content/html/style/src/nsCSSLoader.cpp index b84f9b135c6c..f6cc45eb05b0 100644 --- a/content/html/style/src/nsCSSLoader.cpp +++ b/content/html/style/src/nsCSSLoader.cpp @@ -209,7 +209,7 @@ struct PendingSheetData { nsICSSLoaderObserver* mObserver; }; -class CSSLoaderImpl: public nsICSSLoader { +class CSSLoaderImpl : public nsICSSLoader { public: CSSLoaderImpl(void); virtual ~CSSLoaderImpl(void); @@ -291,33 +291,44 @@ public: nsresult LoadSheet(URLKey& aKey, SheetLoadData* aData); - nsIDocument* mDocument; // the document we live for - - PRBool mCaseSensitive; // is document CSS case sensitive - nsCompatibility mCompatMode; - nsString mPreferredSheet; // title of preferred sheet - - nsISupportsArray* mParsers; // array of CSS parsers - - nsHashtable mLoadedSheets; // url to first sheet fully loaded for URL - nsHashtable mLoadingSheets; // all current loads - - // mParsingData is (almost?) always needed, so create with storage - nsAutoVoidArray mParsingData; // array of data for sheets currently parsing - - nsVoidArray mPendingDocSheets; // loaded sheet waiting for doc insertion - nsVoidArray mPendingAlternateSheets; // alternates waiting for load to start - - nsHashtable mSheetMapTable; // map to insertion index arrays - // stop loading all sheets NS_IMETHOD Stop(void); // stop loading one sheet NS_IMETHOD StopLoadingSheet(nsIURI* aURL); + /** + * Is the loader enabled or not. + * When disabled, processing of new styles is disabled and an attempt + * to do so will fail with a return code of + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable + * currently loading styles or already processed styles. + */ + NS_IMETHOD GetEnabled(PRBool *aEnabled); + NS_IMETHOD SetEnabled(PRBool aEnabled); + + nsIDocument* mDocument; // the document we live for + + PRPackedBool mCaseSensitive; // is document CSS case sensitive + PRPackedBool mEnabled; // is enabled to load new styles + nsCompatibility mCompatMode; + nsString mPreferredSheet; // title of preferred sheet + + nsISupportsArray* mParsers; // array of CSS parsers + + nsHashtable mLoadedSheets; // url to first sheet fully loaded for URL + nsHashtable mLoadingSheets; // all current loads + + // mParsingData is (almost?) always needed, so create with storage + nsAutoVoidArray mParsingData; // array of data for sheets currently parsing + + nsVoidArray mPendingDocSheets; // loaded sheet waiting for doc insertion + nsVoidArray mPendingAlternateSheets; // alternates waiting for load to start + + nsHashtable mSheetMapTable; // map to insertion index arrays + #ifdef NS_DEBUG - PRBool mSyncCallback; + PRBool mSyncCallback; #endif }; @@ -427,12 +438,13 @@ SheetLoadData::~SheetLoadData(void) } CSSLoaderImpl::CSSLoaderImpl(void) + : mDocument(nsnull), + mCaseSensitive(PR_FALSE), + mEnabled(PR_TRUE), + mCompatMode(eCompatibility_FullStandards), + mParsers(nsnull) { NS_INIT_ISUPPORTS(); - mDocument = nsnull; - mCaseSensitive = PR_FALSE; - mCompatMode = eCompatibility_FullStandards; - mParsers = nsnull; } static PRBool PR_CALLBACK ReleaseSheet(nsHashKey* aKey, void* aData, void* aClosure) @@ -1636,6 +1648,9 @@ CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement, PRBool& aCompleted, nsICSSLoaderObserver* aObserver) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + NS_ASSERTION(mDocument, "not initialized"); if (! mDocument) { return NS_ERROR_NOT_INITIALIZED; @@ -1679,6 +1694,9 @@ CSSLoaderImpl::LoadStyleLink(nsIContent* aElement, PRBool& aCompleted, nsICSSLoaderObserver* aObserver) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + NS_ASSERTION(mDocument, "not initialized"); if (! mDocument) { return NS_ERROR_NOT_INITIALIZED; @@ -1778,6 +1796,9 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet, PRInt32 aIndex, nsICSSImportRule* aParentRule) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + nsresult result = NS_ERROR_NULL_POINTER; if (aURL) { @@ -1865,6 +1886,9 @@ CSSLoaderImpl::LoadAgentSheet(nsIURI* aURL, PRBool& aCompleted, nsICSSLoaderObserver* aObserver) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + nsresult result = NS_ERROR_NULL_POINTER; if (aURL) { // Get an input stream from the url @@ -1997,3 +2021,18 @@ CSSLoaderImpl::StopLoadingSheet(nsIURI* aURL) } return NS_OK; } + +NS_IMETHODIMP +CSSLoaderImpl::GetEnabled(PRBool *aEnabled) +{ + NS_ENSURE_ARG_POINTER(aEnabled); + *aEnabled = mEnabled; + return NS_OK; +} + +NS_IMETHODIMP +CSSLoaderImpl::SetEnabled(PRBool aEnabled) +{ + mEnabled = aEnabled; + return NS_OK; +} diff --git a/content/xbl/src/nsXBLService.cpp b/content/xbl/src/nsXBLService.cpp index 1f6b3cd16396..5867999e39d2 100644 --- a/content/xbl/src/nsXBLService.cpp +++ b/content/xbl/src/nsXBLService.cpp @@ -1193,16 +1193,17 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun if (!xblSink) return NS_ERROR_FAILURE; - if (NS_FAILED(rv = doc->StartDocumentLoad("loadAsData", - channel, - loadGroup, - nsnull, + if (NS_FAILED(rv = doc->StartDocumentLoad("loadAsInteractiveData", + channel, + loadGroup, + nsnull, getter_AddRefs(listener), PR_TRUE, xblSink))) { NS_ERROR("Failure to init XBL doc prior to load."); return rv; } + // We can be asynchronous nsXBLStreamListener* xblListener = new nsXBLStreamListener(this, listener, aBoundDocument, doc); NS_ENSURE_TRUE(xblListener,NS_ERROR_OUT_OF_MEMORY); diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 6b6a2a560cd4..0d249d301346 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -125,6 +125,8 @@ static char kNameSpaceSeparator = ':'; #define kXSLType "text/xsl" +static const char* kLoadAsData = "loadAsData"; + static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID); static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); @@ -854,6 +856,11 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement, nsresult rv = NS_OK; mPrettyPrintXML = PR_FALSE; + nsAutoString cmd; + if (mParser) mParser->GetCommand(cmd); + if (cmd.EqualsWithConversion(kLoadAsData)) + return NS_OK; // Do not load stylesheets when loading as data + if (aType.EqualsIgnoreCase(kXSLType) || aType.EqualsIgnoreCase(kXMLTextContentType) || aType.EqualsIgnoreCase(kXMLApplicationContentType)) { diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp index e5aff2781320..368ca9585221 100644 --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -469,6 +469,32 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand, PRBool aReset, nsIContentSink* aSink) { + if (nsCRT::strcmp(kLoadAsData, aCommand) == 0) { + // We need to disable script & style loading in this case. + // We leave them disabled even in EndLoad(), and let anyone + // who puts the document on display to worry about enabling. + + // scripts + nsCOMPtr loader; + nsresult rv = GetScriptLoader(getter_AddRefs(loader)); + if (NS_FAILED(rv)) + return rv; + if (loader) { + loader->SetEnabled(PR_FALSE); // Do not load/process scripts when loading as data + } + + // styles + nsCOMPtr cssLoader; + rv = GetCSSLoader(*getter_AddRefs(cssLoader)); + if (NS_FAILED(rv)) + return rv; + if (cssLoader) { + cssLoader->SetEnabled(PR_FALSE); // Do not load/process styles when loading as data + } + } else if (nsCRT::strcmp("loadAsInteractiveData", aCommand) == 0) { + aCommand = kLoadAsData; // XBL, for example, needs scripts and styles + } + nsresult rv = nsDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, diff --git a/content/xsl/document/src/nsXSLContentSink.cpp b/content/xsl/document/src/nsXSLContentSink.cpp index 595f7800dddc..bb69e969414a 100644 --- a/content/xsl/document/src/nsXSLContentSink.cpp +++ b/content/xsl/document/src/nsXSLContentSink.cpp @@ -94,7 +94,7 @@ nsXSLContentSink::Init(nsITransformMediator* aTM, rv = mDocument->GetScriptLoader(getter_AddRefs(loader)); NS_ENSURE_SUCCESS(rv, rv); - loader->Suspend(); + loader->SetEnabled(PR_FALSE); loader->RemoveObserver(this); return rv; diff --git a/layout/style/nsCSSLoader.cpp b/layout/style/nsCSSLoader.cpp index b84f9b135c6c..f6cc45eb05b0 100644 --- a/layout/style/nsCSSLoader.cpp +++ b/layout/style/nsCSSLoader.cpp @@ -209,7 +209,7 @@ struct PendingSheetData { nsICSSLoaderObserver* mObserver; }; -class CSSLoaderImpl: public nsICSSLoader { +class CSSLoaderImpl : public nsICSSLoader { public: CSSLoaderImpl(void); virtual ~CSSLoaderImpl(void); @@ -291,33 +291,44 @@ public: nsresult LoadSheet(URLKey& aKey, SheetLoadData* aData); - nsIDocument* mDocument; // the document we live for - - PRBool mCaseSensitive; // is document CSS case sensitive - nsCompatibility mCompatMode; - nsString mPreferredSheet; // title of preferred sheet - - nsISupportsArray* mParsers; // array of CSS parsers - - nsHashtable mLoadedSheets; // url to first sheet fully loaded for URL - nsHashtable mLoadingSheets; // all current loads - - // mParsingData is (almost?) always needed, so create with storage - nsAutoVoidArray mParsingData; // array of data for sheets currently parsing - - nsVoidArray mPendingDocSheets; // loaded sheet waiting for doc insertion - nsVoidArray mPendingAlternateSheets; // alternates waiting for load to start - - nsHashtable mSheetMapTable; // map to insertion index arrays - // stop loading all sheets NS_IMETHOD Stop(void); // stop loading one sheet NS_IMETHOD StopLoadingSheet(nsIURI* aURL); + /** + * Is the loader enabled or not. + * When disabled, processing of new styles is disabled and an attempt + * to do so will fail with a return code of + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable + * currently loading styles or already processed styles. + */ + NS_IMETHOD GetEnabled(PRBool *aEnabled); + NS_IMETHOD SetEnabled(PRBool aEnabled); + + nsIDocument* mDocument; // the document we live for + + PRPackedBool mCaseSensitive; // is document CSS case sensitive + PRPackedBool mEnabled; // is enabled to load new styles + nsCompatibility mCompatMode; + nsString mPreferredSheet; // title of preferred sheet + + nsISupportsArray* mParsers; // array of CSS parsers + + nsHashtable mLoadedSheets; // url to first sheet fully loaded for URL + nsHashtable mLoadingSheets; // all current loads + + // mParsingData is (almost?) always needed, so create with storage + nsAutoVoidArray mParsingData; // array of data for sheets currently parsing + + nsVoidArray mPendingDocSheets; // loaded sheet waiting for doc insertion + nsVoidArray mPendingAlternateSheets; // alternates waiting for load to start + + nsHashtable mSheetMapTable; // map to insertion index arrays + #ifdef NS_DEBUG - PRBool mSyncCallback; + PRBool mSyncCallback; #endif }; @@ -427,12 +438,13 @@ SheetLoadData::~SheetLoadData(void) } CSSLoaderImpl::CSSLoaderImpl(void) + : mDocument(nsnull), + mCaseSensitive(PR_FALSE), + mEnabled(PR_TRUE), + mCompatMode(eCompatibility_FullStandards), + mParsers(nsnull) { NS_INIT_ISUPPORTS(); - mDocument = nsnull; - mCaseSensitive = PR_FALSE; - mCompatMode = eCompatibility_FullStandards; - mParsers = nsnull; } static PRBool PR_CALLBACK ReleaseSheet(nsHashKey* aKey, void* aData, void* aClosure) @@ -1636,6 +1648,9 @@ CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement, PRBool& aCompleted, nsICSSLoaderObserver* aObserver) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + NS_ASSERTION(mDocument, "not initialized"); if (! mDocument) { return NS_ERROR_NOT_INITIALIZED; @@ -1679,6 +1694,9 @@ CSSLoaderImpl::LoadStyleLink(nsIContent* aElement, PRBool& aCompleted, nsICSSLoaderObserver* aObserver) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + NS_ASSERTION(mDocument, "not initialized"); if (! mDocument) { return NS_ERROR_NOT_INITIALIZED; @@ -1778,6 +1796,9 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet, PRInt32 aIndex, nsICSSImportRule* aParentRule) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + nsresult result = NS_ERROR_NULL_POINTER; if (aURL) { @@ -1865,6 +1886,9 @@ CSSLoaderImpl::LoadAgentSheet(nsIURI* aURL, PRBool& aCompleted, nsICSSLoaderObserver* aObserver) { + if (!mEnabled) + return NS_ERROR_NOT_AVAILABLE; + nsresult result = NS_ERROR_NULL_POINTER; if (aURL) { // Get an input stream from the url @@ -1997,3 +2021,18 @@ CSSLoaderImpl::StopLoadingSheet(nsIURI* aURL) } return NS_OK; } + +NS_IMETHODIMP +CSSLoaderImpl::GetEnabled(PRBool *aEnabled) +{ + NS_ENSURE_ARG_POINTER(aEnabled); + *aEnabled = mEnabled; + return NS_OK; +} + +NS_IMETHODIMP +CSSLoaderImpl::SetEnabled(PRBool aEnabled) +{ + mEnabled = aEnabled; + return NS_OK; +} diff --git a/layout/style/nsICSSLoader.h b/layout/style/nsICSSLoader.h index ed1966d0761b..65b0071b3227 100644 --- a/layout/style/nsICSSLoader.h +++ b/layout/style/nsICSSLoader.h @@ -130,6 +130,16 @@ public: // stop loading one sheet NS_IMETHOD StopLoadingSheet(nsIURI* aURL) = 0; + + /** + * Whether the loader is enabled or not. + * When disabled, processing of new styles is disabled and an attempt + * to do so will fail with a return code of + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable + * currently loading styles or already processed styles. + */ + NS_IMETHOD GetEnabled(PRBool *aEnabled) = 0; + NS_IMETHOD SetEnabled(PRBool aEnabled) = 0; }; extern NS_EXPORT nsresult