diff --git a/content/base/src/mozSanitizingSerializer.h b/content/base/src/mozSanitizingSerializer.h index b1fea54cf7e..55a785e07da 100644 --- a/content/base/src/mozSanitizingSerializer.h +++ b/content/base/src/mozSanitizingSerializer.h @@ -107,7 +107,7 @@ public: NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode); virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset); - NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } + virtual nsISupports *GetTarget() { return nsnull; } // nsIHTMLContentSink NS_IMETHOD OpenHTML(const nsIParserNode& aNode); @@ -124,6 +124,7 @@ public: NS_IMETHOD OpenFrameset(const nsIParserNode& aNode); NS_IMETHOD CloseFrameset(); NS_IMETHOD IsEnabled(PRInt32 aTag, PRBool* aReturn); + NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; } NS_IMETHOD BeginContext(PRInt32 aPosition) { return NS_OK; } NS_IMETHOD EndContext(PRInt32 aPosition) { return NS_OK; } diff --git a/content/base/src/nsPlainTextSerializer.h b/content/base/src/nsPlainTextSerializer.h index e30aff43770..a1e1894058d 100644 --- a/content/base/src/nsPlainTextSerializer.h +++ b/content/base/src/nsPlainTextSerializer.h @@ -103,7 +103,7 @@ public: NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode) { return NS_OK; } virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } - NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } + virtual nsISupports *GetTarget() { return nsnull; } // nsIHTMLContentSink NS_IMETHOD SetTitle(const nsString& aValue) { return NS_OK; } @@ -120,6 +120,7 @@ public: NS_IMETHOD OpenFrameset(const nsIParserNode& aNode); NS_IMETHOD CloseFrameset(); NS_IMETHOD IsEnabled(PRInt32 aTag, PRBool* aReturn); + NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; } NS_IMETHOD BeginContext(PRInt32 aPosition) { return NS_OK; } diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index d48ec85e3a7..0f126c9269a 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -231,6 +231,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser); virtual void FlushContent(PRBool aNotify); NS_IMETHOD SetDocumentCharset(nsACString& aCharset); + virtual nsISupports *GetTarget(); // nsIHTMLContentSink NS_IMETHOD OpenContainer(const nsIParserNode& aNode); @@ -4409,6 +4410,12 @@ HTMLContentSink::SetDocumentCharset(nsACString& aCharset) return NS_OK; } +nsISupports * +HTMLContentSink::GetTarget() +{ + return mDocument; +} + #ifdef DEBUG /** * This will dump content model into the output file. diff --git a/content/html/document/src/nsHTMLFragmentContentSink.cpp b/content/html/document/src/nsHTMLFragmentContentSink.cpp index 14e7ba03920..de3a1c1322e 100644 --- a/content/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp @@ -86,6 +86,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser); virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } + virtual nsISupports *GetTarget() { return mTargetDocument; } // nsIHTMLContentSink NS_IMETHOD BeginContext(PRInt32 aID); diff --git a/content/xml/document/public/nsIXMLContentSink.h b/content/xml/document/public/nsIXMLContentSink.h index 006a3ac9445..9a32fc44c11 100644 --- a/content/xml/document/public/nsIXMLContentSink.h +++ b/content/xml/document/public/nsIXMLContentSink.h @@ -46,8 +46,8 @@ class nsIURI; class nsIChannel; #define NS_IXMLCONTENT_SINK_IID \ - { 0xa6cf90c9, 0x15b3, 0x11d2, \ - { 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } } + { 0x63fedea0, 0x9b0f, 0x4d64, \ + { 0x9b, 0xa5, 0x37, 0xc6, 0x99, 0x73, 0x29, 0x35 } } /** * This interface represents a content sink for generic XML files. diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 70ae1da646c..bd28d11b799 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -753,6 +753,12 @@ nsXMLContentSink::SetDocumentCharset(nsACString& aCharset) return NS_OK; } +nsISupports * +nsXMLContentSink::GetTarget() +{ + return mDocument; +} + nsresult nsXMLContentSink::FlushText(PRBool aCreateTextNode, PRBool* aDidFlush) { diff --git a/content/xml/document/src/nsXMLContentSink.h b/content/xml/document/src/nsXMLContentSink.h index bf54c6b696c..cc14750e640 100644 --- a/content/xml/document/src/nsXMLContentSink.h +++ b/content/xml/document/src/nsXMLContentSink.h @@ -87,6 +87,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser); virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset); + virtual nsISupports *GetTarget(); // nsITransformObserver NS_IMETHOD OnDocumentCreated(nsIDOMDocument *aResultDocument); diff --git a/content/xml/document/src/nsXMLFragmentContentSink.cpp b/content/xml/document/src/nsXMLFragmentContentSink.cpp index 11f724d4b5a..101a303ae69 100644 --- a/content/xml/document/src/nsXMLFragmentContentSink.cpp +++ b/content/xml/document/src/nsXMLFragmentContentSink.cpp @@ -77,6 +77,7 @@ public: NS_IMETHOD WillBuildModel(void); NS_IMETHOD DidBuildModel(); NS_IMETHOD SetDocumentCharset(nsACString& aCharset); + virtual nsISupports *GetTarget(); // nsIXMLContentSink @@ -207,6 +208,12 @@ nsXMLFragmentContentSink::SetDocumentCharset(nsACString& aCharset) return NS_OK; } +nsISupports * +nsXMLFragmentContentSink::GetTarget() +{ + return mTargetDocument; +} + //////////////////////////////////////////////////////////////////////// PRBool diff --git a/content/xul/document/public/nsIXULContentSink.h b/content/xul/document/public/nsIXULContentSink.h index 0a5e5a4819c..f64a591cd9b 100644 --- a/content/xul/document/public/nsIXULContentSink.h +++ b/content/xul/document/public/nsIXULContentSink.h @@ -44,10 +44,10 @@ class nsIDocument; class nsIXULPrototypeDocument; -// {E49AA620-C16C-11d2-A6AA-00104BDE6048} +// {f9da9ee5-d353-4994-9560-6a4e06310e2d} #define NS_IXULCONTENTSINK_IID \ -{ 0xe49aa620, 0xc16c, 0x11d2, { 0xa6, 0xaa, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } } - +{ 0xf9da9ee5, 0xd353, 0x4994, \ +{ 0x95, 0x60, 0x6a, 0x4e, 0x06, 0x31, 0x0e, 0x2d } } class nsIXULContentSink : public nsIXMLContentSink { diff --git a/content/xul/document/src/nsXULContentSink.cpp b/content/xul/document/src/nsXULContentSink.cpp index 799fb1d7e2f..642191f627a 100644 --- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -137,6 +137,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser); virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset); + virtual nsISupports *GetTarget(); // nsIXULContentSink NS_IMETHOD Init(nsIDocument* aDocument, nsIXULPrototypeDocument* aPrototype); @@ -567,6 +568,13 @@ XULContentSinkImpl::SetDocumentCharset(nsACString& aCharset) return NS_OK; } +nsISupports * +XULContentSinkImpl::GetTarget() +{ + nsCOMPtr doc = do_QueryReferent(mDocument); + return doc; +} + //---------------------------------------------------------------------- // // nsIXULContentSink interface diff --git a/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp b/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp index 62a5f719937..ebaf5118d7f 100644 --- a/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp +++ b/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp @@ -114,6 +114,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; } virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } + virtual nsISupports *GetTarget() { return nsnull; } private: nsRefPtr mCompiler; diff --git a/netwerk/base/public/Makefile.in b/netwerk/base/public/Makefile.in index 016a4d77f6f..62388c4527c 100644 --- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -57,6 +57,7 @@ SDK_XPIDLSRCS = \ nsIURL.idl \ nsIFileURL.idl \ nsIUploadChannel.idl \ + nsIUnicharStreamListener.idl \ $(NULL) XPIDLSRCS = \ diff --git a/netwerk/base/public/nsIUnicharStreamListener.idl b/netwerk/base/public/nsIUnicharStreamListener.idl new file mode 100644 index 00000000000..79fef425404 --- /dev/null +++ b/netwerk/base/public/nsIUnicharStreamListener.idl @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johnny Stenback + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIRequestObserver.idl" + +/** + * nsIUnicharStreamListener is very similar to nsIStreamListener with + * the difference being that this interface gives notifications about + * data being available after the raw data has been converted to + * UTF-16. + * + * nsIUnicharStreamListener + * + * @status FROZEN + */ +[scriptable, uuid(4a7e9b62-fef8-400d-9865-d6820f630b4c)] +interface nsIUnicharStreamListener : nsIRequestObserver +{ + /** + * Called when the next chunk of data (corresponding to the + * request) is available. + * + * @param aRequest request corresponding to the source of the data + * @param aContext user defined context + * @param aData the data chunk + * + * An exception thrown from onUnicharDataAvailable has the + * side-effect of causing the request to be canceled. + */ + void onUnicharDataAvailable(in nsIRequest aRequest, + in nsISupports aContext, in AString aData); +}; diff --git a/parser/htmlparser/public/Makefile.in b/parser/htmlparser/public/Makefile.in index 0b092308d21..e6e253c064f 100644 --- a/parser/htmlparser/public/Makefile.in +++ b/parser/htmlparser/public/Makefile.in @@ -68,6 +68,10 @@ EXPORTS = \ nsToken.h \ $(NULL) +SDK_HEADERS = \ + nsParserDataListener.h \ + $(NULL) + ifdef MOZ_DEBUG EXPORTS += \ nsILoggingSink.h \ diff --git a/parser/htmlparser/public/nsIContentSink.h b/parser/htmlparser/public/nsIContentSink.h index 733ed1343e0..4343b484d23 100644 --- a/parser/htmlparser/public/nsIContentSink.h +++ b/parser/htmlparser/public/nsIContentSink.h @@ -54,8 +54,7 @@ class nsIParser; #define NS_ICONTENT_SINK_IID \ -{ 0xa6cf9052, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} - +{0x7f459e15, 0xd559, 0x4c50, {0x91, 0x30, 0x3a, 0xe7, 0x31, 0x46, 0x67, 0xa9}} // The base value for the content ID counter. // Values greater than or equal to this base value are used // by each of the content sinks to assign unique values @@ -122,6 +121,13 @@ public: * document itself. */ NS_IMETHOD SetDocumentCharset(nsACString& aCharset)=0; + + /** + * Returns the target object (often a document object) into which + * the content built by this content sink is being added, if any + * (IOW, may return null). + */ + virtual nsISupports *GetTarget()=0; }; #endif /* nsIContentSink_h___ */ diff --git a/parser/htmlparser/public/nsIHTMLContentSink.h b/parser/htmlparser/public/nsIHTMLContentSink.h index 42fbed76137..c5430fd4e45 100644 --- a/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/parser/htmlparser/public/nsIHTMLContentSink.h @@ -86,8 +86,7 @@ #include "nsHTMLTags.h" #define NS_IHTML_CONTENT_SINK_IID \ - { 0xa6cf9051, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} - + { 0x59929de5, 0xe60b, 0x48b1,{0x81, 0x69, 0x48, 0x47, 0xb5, 0xc9, 0x44, 0x29}} #ifdef XP_MAC #define MAX_REFLOW_DEPTH 75 //setting to 75 to prevent layout from crashing on mac. Bug 55095. diff --git a/parser/htmlparser/public/nsParserDataListener.h b/parser/htmlparser/public/nsParserDataListener.h new file mode 100644 index 00000000000..80ef95e8ac5 --- /dev/null +++ b/parser/htmlparser/public/nsParserDataListener.h @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johnny Stenback + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsParserDataListener_h__ +#define __nsParserDataListener_h__ + +/* + * Include this header if you're implementing a parser data + * listener. To make a component a parser data listener you'll need to + * make your component implement the interface + * nsIUnicharStreamListener. That interface has three methods (one + + * two inherited ones, not counting what's defined in + * nsISupports). The methods are: + * + * void onStartRequest(in nsIRequest aRequest, + * in nsISupports aContext); + * void onUnicharDataAvailable(in nsIRequest aRequest, + * in nsISupports aContext, in AString aData); + * void onStopRequest(in nsIRequest aRequest, + * in nsISupports aContext, + * in nsresult aStatusCode); + * + * All those methods are called for every network request that ends up + * feeding data to the parser. The method are called in the order + * shown above, first one call to onStartRequest(), then one call to + * onUnicharDataAvailable() per chunk of data received and converted + * to UTF-16, and finally one call to onStopRequest(). + * + * The nsIRequest passed into these methods will be the same object + * for all these calls for a given network request. If the request + * pointer is used to uniquely identify an ongoing request, the + * pointer should be QueryInterface()'d to nsISupports to ensure that + * the pointer used is the identity pointer to the object. + * + * The context argument passed to these methods will be the document + * (nsIDOMDocument) parsed from the stream, or null when not + * available. + * + * Any errors returned from any of these calls will end up canceling + * the stream, and the data that is passed to the call in question + * will *not* be seen by the parser. So unless you intend to interrupt + * a request, *make sure* that you return NS_OK from these methods! + */ + +#include "nsIUnicharStreamListener.h" + +/* + * To register a component to be a parser data listener the + * component's contract id should be registered with the category + * manager (nsICategoryManager), with the category + * PARSER_DATA_LISTENER_CATEGORY, defined here. + */ +#define PARSER_DATA_LISTENER_CATEGORY "Parser data listener" + +#endif // __nsParserDataListener_h__ diff --git a/parser/htmlparser/robot/nsRobotSink.cpp b/parser/htmlparser/robot/nsRobotSink.cpp index f8387397bf2..7a09ff263b1 100644 --- a/parser/htmlparser/robot/nsRobotSink.cpp +++ b/parser/htmlparser/robot/nsRobotSink.cpp @@ -106,6 +106,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; } virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } + virtual nsISupports *GetTarget() { return nsnull; } NS_IMETHOD WillProcessTokens(void) { return NS_OK; } NS_IMETHOD DidProcessTokens(void) { return NS_OK; } NS_IMETHOD WillProcessAToken(void) { return NS_OK; } diff --git a/parser/htmlparser/src/nsLoggingSink.h b/parser/htmlparser/src/nsLoggingSink.h index f7d56c7fc58..db245b2714c 100644 --- a/parser/htmlparser/src/nsLoggingSink.h +++ b/parser/htmlparser/src/nsLoggingSink.h @@ -74,7 +74,7 @@ public: NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode); virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } - NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } + virtual nsISupports *GetTarget() { return nsnull; } // nsIHTMLContentSink NS_IMETHOD SetTitle(const nsString& aValue); @@ -91,6 +91,7 @@ public: NS_IMETHOD OpenFrameset(const nsIParserNode& aNode); NS_IMETHOD CloseFrameset(); NS_IMETHOD IsEnabled(PRInt32 aTag, PRBool* aReturn) { return NS_OK; } + NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; } NS_IMETHOD BeginContext(PRInt32 aPosition); diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp index dadb259ceb5..d447e681bfd 100644 --- a/parser/htmlparser/src/nsParser.cpp +++ b/parser/htmlparser/src/nsParser.cpp @@ -63,7 +63,8 @@ #include "nsIEventQueueService.h" #include "nsExpatDriver.h" #include "nsIServiceManager.h" -//#define rickgdebug +#include "nsICategoryManager.h" +#include "nsISupportsPrimitives.h" #ifdef MOZ_VIEW_SOURCE #include "nsViewSourceHTML.h" @@ -84,6 +85,8 @@ static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID); static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); //------------------------------------------------------------------- + +nsCOMArray *nsParser::sParserDataListeners; class CDTDDeallocator: public nsDequeFunctor{ @@ -251,7 +254,7 @@ static CSharedParserObjects* gSharedParserObjects=0; //------------------------------------------------------------------------- -nsresult +static nsresult GetSharedObjects(CSharedParserObjects** aSharedParserObjects) { if (!gSharedParserObjects) { gSharedParserObjects = new CSharedParserObjects(); @@ -263,16 +266,81 @@ GetSharedObjects(CSharedParserObjects** aSharedParserObjects) { return NS_OK; } +static void +FreeSharedObjects(void) { + if (gSharedParserObjects) { + delete gSharedParserObjects; + gSharedParserObjects=0; + } +} + + +/** + * This gets called when the htmlparser module is initialized. + */ +// static +nsresult nsParser::Init() +{ + nsresult rv; + nsCOMPtr cm = + do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr e; + rv = cm->EnumerateCategory("Parser data listener", getter_AddRefs(e)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCAutoString categoryEntry; + nsXPIDLCString contractId; + nsCOMPtr entry; + + while (NS_SUCCEEDED(e->GetNext(getter_AddRefs(entry)))) { + nsCOMPtr category(do_QueryInterface(entry)); + + if (!category) { + NS_WARNING("Category entry not an nsISupportsCString!"); + + continue; + } + + rv = category->GetData(categoryEntry); + NS_ENSURE_SUCCESS(rv, rv); + + rv = cm->GetCategoryEntry("Parser data listener", categoryEntry.get(), + getter_Copies(contractId)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr listener = + do_CreateInstance(contractId.get()); + + if (listener) { + if (!sParserDataListeners) { + sParserDataListeners = new nsCOMArray(); + + if (!sParserDataListeners) + return NS_ERROR_OUT_OF_MEMORY; + } + + sParserDataListeners->AppendObject(listener); + } + } + + return NS_OK; +} + + /** * This gets called when the htmlparser module is shutdown. * * @update gess 01/04/99 */ -void nsParser::FreeSharedObjects(void) { - if (gSharedParserObjects) { - delete gSharedParserObjects; - gSharedParserObjects=0; - } +// static +void nsParser::Shutdown() +{ + FreeSharedObjects(); + + delete sParserDataListeners; + sParserDataListeners = nsnull; } @@ -1425,6 +1493,34 @@ void nsParser::HandleParserContinueEvent() { ContinueParsing(); } +nsresult nsParser::DataAdded(const nsSubstring& aData) +{ + NS_ASSERTION(sParserDataListeners, + "Don't call this with no parser data listeners!"); + + if (!mSink || !mParserContext || !mParserContext->mRequest) { + return NS_OK; + } + + nsISupports *ctx = mSink->GetTarget(); + PRInt32 count = sParserDataListeners->Count(); + nsresult rv = NS_OK; + PRBool canceled = PR_FALSE; + + while (count--) { + rv |= sParserDataListeners->ObjectAt(count)-> + OnUnicharDataAvailable(mParserContext->mRequest, ctx, aData); + + if (NS_FAILED(rv) && !canceled) { + mParserContext->mRequest->Cancel(rv); + + canceled = PR_TRUE; + } + } + + return rv; +} + PRBool nsParser::CanInterrupt(void) { return mFlags & NS_PARSER_FLAG_CAN_INTERRUPT; } @@ -1484,6 +1580,13 @@ nsParser::Parse(nsIURI* aURL, pc->mContextType=CParserContext::eCTURL; pc->mDTDMode=aMode; PushContext(*pc); + + // Here, and only here, hand this parser off to the scanner. We + // only want to do that here since the only reason the scanner + // needs the parser is to call DataAdded() on it, and that's + // only ever wanted when parsing from an URI. + theScanner->SetParser(this); + result=NS_OK; } else{ @@ -1994,7 +2097,19 @@ nsresult nsParser::OnStartRequest(nsIRequest *request, nsISupports* aContext) { gOutFile= new fstream("c:/temp/out.file",ios::trunc); #endif - return NS_OK; + rv = NS_OK; + + if (sParserDataListeners && mSink) { + nsISupports *ctx = mSink->GetTarget(); + PRInt32 count = sParserDataListeners->Count(); + + while (count--) { + rv |= sParserDataListeners->ObjectAt(count)-> + OnStartRequest(request, ctx); + } + } + + return rv; } @@ -2475,24 +2590,25 @@ nsresult nsParser::OnStopRequest(nsIRequest *request, nsISupports* aContext, nsresult status) { - nsresult result=NS_OK; - - if(eOnStart==mParserContext->mStreamListenerState) { - //If you're here, then OnDataAvailable() never got called. - //Prior to necko, we never dealt with this case, but the problem may have existed. - //Everybody can live with an empty input stream, so just resume parsing. - result=ResumeParse(PR_TRUE,PR_TRUE); + nsresult rv = NS_OK; + + if (eOnStart == mParserContext->mStreamListenerState) { + //If you're here, then OnDataAvailable() never got called. Prior + //to necko, we never dealt with this case, but the problem may + //have existed. Everybody can live with an empty input stream, so + //just resume parsing. + rv = ResumeParse(PR_TRUE, PR_TRUE); } - mParserContext->mStreamListenerState=eOnStop; - mStreamStatus=status; + mParserContext->mStreamListenerState = eOnStop; + mStreamStatus = status; - if(mParserFilter) - mParserFilter->Finish(); + if (mParserFilter) + mParserFilter->Finish(); mParserContext->mScanner->SetIncremental(PR_FALSE); - result=ResumeParse(PR_TRUE,PR_TRUE); - + rv = ResumeParse(PR_TRUE, PR_TRUE); + // If the parser isn't enabled, we don't finish parsing till // it is reenabled. @@ -2507,11 +2623,21 @@ nsresult nsParser::OnStopRequest(nsIRequest *request, nsISupports* aContext, if(gOutFile){ gOutFile->close(); delete gOutFile; - gOutFile=0; + gOutFile = 0; } #endif - return result; + if (sParserDataListeners && mSink) { + nsISupports *ctx = mSink->GetTarget(); + PRInt32 count = sParserDataListeners->Count(); + + while (count--) { + rv |= sParserDataListeners->ObjectAt(count)->OnStopRequest(request, ctx, + status); + } + } + + return rv; } diff --git a/parser/htmlparser/src/nsParser.h b/parser/htmlparser/src/nsParser.h index 0d50ed75860..41bf057f708 100644 --- a/parser/htmlparser/src/nsParser.h +++ b/parser/htmlparser/src/nsParser.h @@ -87,6 +87,8 @@ #include "nsIEventQueue.h" #include "nsIContentSink.h" #include "nsIParserFilter.h" +#include "nsCOMArray.h" +#include "nsIUnicharStreamListener.h" class nsIDTD; class nsScanner; @@ -103,7 +105,15 @@ class nsParser : public nsIParser, public: friend class CTokenHandler; - static void FreeSharedObjects(void); + /** + * Called on module init + */ + static nsresult Init(); + + /** + * Called on module shutdown + */ + static void Shutdown(); NS_DECL_ISUPPORTS @@ -375,6 +385,14 @@ class nsParser : public nsIParser, */ void HandleParserContinueEvent(void); + /** + * Called by top-level scanners when data from necko is added to + * the scanner. + */ + nsresult DataAdded(const nsSubstring& aData); + + static nsCOMArray *sParserDataListeners; + protected: /** diff --git a/parser/htmlparser/src/nsParserModule.cpp b/parser/htmlparser/src/nsParserModule.cpp index cfb5d010a95..60558500ea9 100644 --- a/parser/htmlparser/src/nsParserModule.cpp +++ b/parser/htmlparser/src/nsParserModule.cpp @@ -116,7 +116,8 @@ Initialize(nsIModule* aSelf) CNewlineToken::AllocNewline(); gInitialized = PR_TRUE; } - return NS_OK; + + return nsParser::Init(); } PR_STATIC_CALLBACK(void) @@ -126,7 +127,7 @@ Shutdown(nsIModule* aSelf) nsHTMLTags::ReleaseTable(); nsHTMLEntities::ReleaseTable(); nsDTDContext::ReleaseGlobalObjects(); - nsParser::FreeSharedObjects(); + nsParser::Shutdown(); DeleteElementTable(); CNewlineToken::FreeNewline(); gInitialized = PR_FALSE; diff --git a/parser/htmlparser/src/nsScanner.cpp b/parser/htmlparser/src/nsScanner.cpp index b004aea3346..f9d16713805 100644 --- a/parser/htmlparser/src/nsScanner.cpp +++ b/parser/htmlparser/src/nsScanner.cpp @@ -48,6 +48,7 @@ #include "nsNetUtil.h" #include "nsUTF8Utils.h" // for LossyConvertEncoding #include "nsCRT.h" +#include "nsParser.h" static NS_DEFINE_CID(kCharsetAliasCID, NS_CHARSETALIAS_CID); @@ -92,7 +93,9 @@ MOZ_DECL_CTOR_COUNTER(nsScanner) * @param aMode represents the parser mode (nav, other) * @return */ -nsScanner::nsScanner(const nsAString& anHTMLString, const nsACString& aCharset, PRInt32 aSource) +nsScanner::nsScanner(const nsAString& anHTMLString, const nsACString& aCharset, + PRInt32 aSource) + : mParser(nsnull) { MOZ_COUNT_CTOR(nsScanner); @@ -118,8 +121,9 @@ nsScanner::nsScanner(const nsAString& anHTMLString, const nsACString& aCharset, * @param aFilename -- * @return */ -nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsACString& aCharset, PRInt32 aSource) : - mFilename(aFilename) +nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, + const nsACString& aCharset, PRInt32 aSource) + : mFilename(aFilename), mParser(nsnull) { MOZ_COUNT_CTOR(nsScanner); @@ -162,8 +166,9 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsACString& * @param aFilename -- * @return */ -nsScanner::nsScanner(const nsAString& aFilename,nsIInputStream* aStream,const nsACString& aCharset, PRInt32 aSource) : - mFilename(aFilename) +nsScanner::nsScanner(const nsAString& aFilename, nsIInputStream* aStream, + const nsACString& aCharset, PRInt32 aSource) + : mFilename(aFilename), mParser(nsnull) { MOZ_COUNT_CTOR(nsScanner); @@ -1326,6 +1331,14 @@ void nsScanner::ReplaceCharacter(nsScannerIterator& aPosition, void nsScanner::AppendToBuffer(nsScannerString::Buffer* aBuf) { + if (nsParser::sParserDataListeners && mParser && + NS_FAILED(mParser->DataAdded(Substring(aBuf->DataStart(), + aBuf->DataEnd())))) { + // Don't actually append on failure. + + return; + } + if (!mSlidingBuffer) { mSlidingBuffer = new nsScannerString(aBuf); mSlidingBuffer->BeginReading(mCurrentPosition); diff --git a/parser/htmlparser/src/nsScanner.h b/parser/htmlparser/src/nsScanner.h index 04439784650..45c7b58362c 100644 --- a/parser/htmlparser/src/nsScanner.h +++ b/parser/htmlparser/src/nsScanner.h @@ -59,6 +59,8 @@ #include "nsScannerString.h" #include "nsIInputStream.h" +class nsParser; + class nsReadEndCondition { public: const PRUnichar *mChars; @@ -364,6 +366,11 @@ class nsScanner { return mFirstNonWhitespacePosition; } + void SetParser(nsParser *aParser) + { + mParser = aParser; + } + protected: @@ -395,6 +402,7 @@ class nsScanner { PRInt32 mCharsetSource; nsCString mCharset; nsIUnicodeDecoder *mUnicodeDecoder; + nsParser *mParser; }; #endif diff --git a/rdf/base/public/nsIRDFContentSink.h b/rdf/base/public/nsIRDFContentSink.h index b146fe6b151..ff62ef90a68 100644 --- a/rdf/base/public/nsIRDFContentSink.h +++ b/rdf/base/public/nsIRDFContentSink.h @@ -50,9 +50,9 @@ class nsIDocument; class nsIRDFDataSource; class nsIURI; -// {751843E2-8309-11d2-8EAC-00805F29F370} +// {3a7459d7-d723-483c-aef0-404fc48e09b8} #define NS_IRDFCONTENTSINK_IID \ -{ 0x751843e2, 0x8309, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } +{ 0x3a7459d7, 0xd723, 0x483c, { 0xae, 0xf0, 0x40, 0x4f, 0xc4, 0x8e, 0x09, 0xb8 } } /** * This interface represents a content sink for RDF files. diff --git a/rdf/base/src/nsRDFContentSink.cpp b/rdf/base/src/nsRDFContentSink.cpp index 09a46182bc1..4f080a564cb 100644 --- a/rdf/base/src/nsRDFContentSink.cpp +++ b/rdf/base/src/nsRDFContentSink.cpp @@ -174,6 +174,7 @@ public: NS_IMETHOD SetParser(nsIParser* aParser); virtual void FlushContent(PRBool aNotify) { } NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } + virtual nsISupports *GetTarget() { return nsnull; } // nsIRDFContentSink NS_IMETHOD Init(nsIURI* aURL);