96364 - Register html tag observers directly to parser service rather than nsObserverService. Doing so, reduces a lot of overhead. Also, the observers are now notified via sink. This eliminates the need for parser bundle.

r=dp,shanjian,sfraser, sr=rpotts.
This commit is contained in:
harishd%netscape.com 2001-09-28 23:08:17 +00:00
parent f780098a4b
commit 6cf7e21d1f
57 changed files with 541 additions and 1544 deletions

View File

@ -100,6 +100,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0) { return NS_OK; }
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue) { return NS_OK; }

View File

@ -158,6 +158,7 @@ const PRBool kBlockByDefault=PR_TRUE;
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
//----------------------------------------------------------------------
@ -239,6 +240,7 @@ public:
NS_IMETHOD DidProcessTokens(void);
NS_IMETHOD WillProcessAToken(void);
NS_IMETHOD DidProcessAToken(void);
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode);
// nsIHTMLContentSink
@ -416,6 +418,8 @@ public:
PRInt32 mDynamicIntervalSwitchThreshold; // Switch between intervals when time is exceeded
PRInt32 mBeginLoadTime;
nsCOMPtr<nsIObserverEntry> mObservers;
void StartLayout();
void ScrollToRef();
@ -907,8 +911,6 @@ HTMLContentSink::CreateContentObject(const nsIParserNode& aNode,
return rv;
}
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
nsresult
NS_CreateHTMLElement(nsIHTMLContent** aResult, nsINodeInfo *aNodeInfo, PRBool aCaseSensitive)
{
@ -2498,6 +2500,17 @@ HTMLContentSink::Init(nsIDocument* aDoc,
mWebShell = aContainer;
NS_ADDREF(aContainer);
mObservers = nsnull;
nsCOMPtr<nsIParserService> service(do_GetService(kParserServiceCID));
if (!service) {
return NS_ERROR_OUT_OF_MEMORY;
}
service->GetTopicObservers(NS_LITERAL_STRING("text/html"),
getter_AddRefs(mObservers));
nsCOMPtr<nsIScriptLoader> loader;
rv = mDocument->GetScriptLoader(getter_AddRefs(loader));
NS_ENSURE_SUCCESS(rv, rv);
@ -3833,6 +3846,13 @@ PRInt32 newMaxTokenProcessingTime = GetMaxTokenProcessingTime();
return NS_OK;
}
#include "nsIElementObserver.h"
NS_IMETHODIMP
HTMLContentSink::NotifyTagObservers(nsIParserNode* aNode)
{
return mObservers? mObservers->Notify(aNode,mParser,mWebShell) : NS_OK;
}
void
HTMLContentSink::StartLayout()

View File

@ -582,22 +582,6 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
NS_PRECONDITION(nsnull != aContainer, "No content viewer container");
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
if(mParser) {
nsCOMPtr<nsISupportsParserBundle> parserBundle;
nsresult result;
parserBundle = do_QueryInterface(mParser, &result);
if(NS_SUCCEEDED(result)) {
// We do this to help consumers who don't have access to the webshell.
nsAutoString theDocShell,theChannel;
theDocShell.AssignWithConversion("docshell");
theChannel.AssignWithConversion("channel");
parserBundle->SetDataIntoBundle(theDocShell,docShell);
parserBundle->SetDataIntoBundle(theChannel,aChannel);
}
}
nsCOMPtr<nsIDocumentCharsetInfo> dcInfo;
docShell->GetDocumentCharsetInfo(getter_AddRefs(dcInfo));
#ifdef IBMBIDI

View File

@ -116,6 +116,7 @@ public:
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
NS_IMETHOD DidProcessAToken(void) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
NS_IMETHOD DoFragment(PRBool aFlag);

View File

@ -113,6 +113,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset);
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIXMLContentSink
NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode);

View File

@ -459,16 +459,6 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand,
docShell = do_QueryInterface(aContainer, &rv);
if(NS_FAILED(rv) || !(docShell)) return rv;
nsCOMPtr<nsISupportsParserBundle> parserBundle;
nsresult result;
parserBundle = do_QueryInterface(mParser, &result);
if(NS_SUCCEEDED(result)) {
// We do this to help consumers who don't have access to the webshell.
nsAutoString theID;
theID.AssignWithConversion("docshell");
parserBundle->SetDataIntoBundle(theID,docShell);
}
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?>
<?xml-stylesheet href="docbook.css" type="text/css"?>
<!DOCTYPE Book System "file:///E|/Program%20Files/SoftQuad/XMetaL/Rules/docbook.dtd">
<!DOCTYPE Book SYSTEM "file:///E|/Program%20Files/SoftQuad/XMetaL/Rules/docbook.dtd">
<Book xmlns:html="http://www.w3.org/1999/xhtml">
<Title>The Book</Title>
<Chapter>

View File

@ -150,6 +150,8 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset);
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIXMLContentSink
NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode);

View File

@ -38,9 +38,11 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIServiceManager.h"
#include "nsIParserService.h"
#include "nsParserCIID.h"
#include "nsEditorParserObserver.h"
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
NS_IMPL_ADDREF(nsEditorParserObserver);
NS_IMPL_RELEASE(nsEditorParserObserver);
@ -62,15 +64,6 @@ nsEditorParserObserver::~nsEditorParserObserver()
{
}
NS_IMETHODIMP_(const char*) nsEditorParserObserver::GetTagNameAt(PRUint32 aTagIndex)
{
nsCString* theString = mWatchTags[aTagIndex];
if (theString)
return theString->get();
else
return nsnull;
}
NS_IMETHODIMP nsEditorParserObserver::Notify(
PRUint32 aDocumentID,
const PRUnichar* aTag,
@ -98,8 +91,11 @@ NS_IMETHODIMP nsEditorParserObserver::Notify(
else
return NS_ERROR_ILLEGAL_VALUE;
}
NS_IMETHODIMP nsEditorParserObserver::Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsStringArray* aKeys, const nsStringArray* aValues)
NS_IMETHODIMP nsEditorParserObserver::Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* aKeys,
const nsStringArray* aValues)
{
Notify();
return NS_OK;
@ -115,26 +111,34 @@ void nsEditorParserObserver::Notify()
mBadTagFound = PR_TRUE;
}
NS_IMETHODIMP nsEditorParserObserver::Start()
NS_IMETHODIMP nsEditorParserObserver::Start(eHTMLTags* aWatchTags)
{
nsresult res = NS_OK;
nsAutoString parserService; parserService.AssignWithConversion("text/html");
nsCOMPtr<nsIParserService> parserService(do_GetService(kParserServiceCID));
if (!parserService) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIObserverService> anObserverService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &res);
if (NS_FAILED(res)) return res;
return anObserverService->AddObserver(this, parserService.get());
res = parserService->RegisterObserver(this,
NS_LITERAL_STRING("text/html"),
aWatchTags);
return res;
}
NS_IMETHODIMP nsEditorParserObserver::End()
{
nsresult res = NS_OK;
nsAutoString parserService; parserService.AssignWithConversion("text/html");
nsCOMPtr<nsIParserService> parserService(do_GetService(kParserServiceCID));
nsCOMPtr<nsIObserverService> anObserverService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &res);
if (NS_FAILED(res)) return res;
if (!parserService) {
return NS_ERROR_OUT_OF_MEMORY;
}
return anObserverService->RemoveObserver(this, parserService.get());
res = parserService->UnregisterObserver(this,
NS_LITERAL_STRING("text/html"));
return res;
}
NS_IMETHODIMP nsEditorParserObserver::GetBadTagFound(PRBool *aFound)
@ -145,12 +149,4 @@ NS_IMETHODIMP nsEditorParserObserver::GetBadTagFound(PRBool *aFound)
}
NS_IMETHODIMP nsEditorParserObserver::RegisterTagToWatch(const char* tagName)
{
nsCString theTagString(tagName);
mWatchTags.AppendCString(theTagString);
return NS_OK;
}

View File

@ -44,6 +44,7 @@
#include "nsWeakReference.h"
#include "nsString.h"
#include "nsVoidArray.h"
#include "nsHTMLTags.h"
class nsEditorParserObserver : public nsSupportsWeakReference,
public nsIElementObserver,
@ -57,27 +58,26 @@ public:
NS_DECL_ISUPPORTS
/* method for nsIElementObserver */
NS_IMETHOD_(const char*) GetTagNameAt(PRUint32 aTagIndex);
NS_IMETHOD Notify(PRUint32 aDocumentID, eHTMLTags aTag, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsStringArray* aKeys, const nsStringArray* aValues);
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* aKeys,
const nsStringArray* aValues);
/* methods for nsIObserver */
NS_DECL_NSIOBSERVER
/* begin and end observing */
NS_IMETHOD Start();
NS_IMETHOD Start(eHTMLTags* aWatchTags);
NS_IMETHOD End();
/* query, did we find a bad tag? */
NS_IMETHOD GetBadTagFound(PRBool *aFound);
/* register a tag to watch for */
NS_IMETHOD RegisterTagToWatch(const char* tagName);
protected:
virtual void Notify();
@ -85,9 +85,6 @@ protected:
protected:
PRBool mBadTagFound;
nsCStringArray mWatchTags;
};

View File

@ -174,6 +174,12 @@ enum {
eComposerController
};
static eHTMLTags gWatchTags[] =
{ eHTMLTag_frameset,
eHTMLTag_iframe,
eHTMLTag_unknown
};
/////////////////////////////////////////////////////////////////////////
// Utility to extract document from a webshell object.
static nsresult
@ -5054,9 +5060,7 @@ nsresult nsEditorShell::StartPageLoad(nsIChannel *aChannel)
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(mParserObserver);
mParserObserver->RegisterTagToWatch("FRAMESET");
mParserObserver->RegisterTagToWatch("IFRAME");
mParserObserver->Start();
mParserObserver->Start(gWatchTags);
}
return NS_OK;

View File

@ -38,9 +38,11 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIServiceManager.h"
#include "nsIParserService.h"
#include "nsParserCIID.h"
#include "nsEditorParserObserver.h"
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
NS_IMPL_ADDREF(nsEditorParserObserver);
NS_IMPL_RELEASE(nsEditorParserObserver);
@ -62,15 +64,6 @@ nsEditorParserObserver::~nsEditorParserObserver()
{
}
NS_IMETHODIMP_(const char*) nsEditorParserObserver::GetTagNameAt(PRUint32 aTagIndex)
{
nsCString* theString = mWatchTags[aTagIndex];
if (theString)
return theString->get();
else
return nsnull;
}
NS_IMETHODIMP nsEditorParserObserver::Notify(
PRUint32 aDocumentID,
const PRUnichar* aTag,
@ -98,8 +91,11 @@ NS_IMETHODIMP nsEditorParserObserver::Notify(
else
return NS_ERROR_ILLEGAL_VALUE;
}
NS_IMETHODIMP nsEditorParserObserver::Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsStringArray* aKeys, const nsStringArray* aValues)
NS_IMETHODIMP nsEditorParserObserver::Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* aKeys,
const nsStringArray* aValues)
{
Notify();
return NS_OK;
@ -115,26 +111,34 @@ void nsEditorParserObserver::Notify()
mBadTagFound = PR_TRUE;
}
NS_IMETHODIMP nsEditorParserObserver::Start()
NS_IMETHODIMP nsEditorParserObserver::Start(eHTMLTags* aWatchTags)
{
nsresult res = NS_OK;
nsAutoString parserService; parserService.AssignWithConversion("text/html");
nsCOMPtr<nsIParserService> parserService(do_GetService(kParserServiceCID));
if (!parserService) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIObserverService> anObserverService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &res);
if (NS_FAILED(res)) return res;
return anObserverService->AddObserver(this, parserService.get());
res = parserService->RegisterObserver(this,
NS_LITERAL_STRING("text/html"),
aWatchTags);
return res;
}
NS_IMETHODIMP nsEditorParserObserver::End()
{
nsresult res = NS_OK;
nsAutoString parserService; parserService.AssignWithConversion("text/html");
nsCOMPtr<nsIParserService> parserService(do_GetService(kParserServiceCID));
nsCOMPtr<nsIObserverService> anObserverService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &res);
if (NS_FAILED(res)) return res;
if (!parserService) {
return NS_ERROR_OUT_OF_MEMORY;
}
return anObserverService->RemoveObserver(this, parserService.get());
res = parserService->UnregisterObserver(this,
NS_LITERAL_STRING("text/html"));
return res;
}
NS_IMETHODIMP nsEditorParserObserver::GetBadTagFound(PRBool *aFound)
@ -145,12 +149,4 @@ NS_IMETHODIMP nsEditorParserObserver::GetBadTagFound(PRBool *aFound)
}
NS_IMETHODIMP nsEditorParserObserver::RegisterTagToWatch(const char* tagName)
{
nsCString theTagString(tagName);
mWatchTags.AppendCString(theTagString);
return NS_OK;
}

View File

@ -44,6 +44,7 @@
#include "nsWeakReference.h"
#include "nsString.h"
#include "nsVoidArray.h"
#include "nsHTMLTags.h"
class nsEditorParserObserver : public nsSupportsWeakReference,
public nsIElementObserver,
@ -57,27 +58,26 @@ public:
NS_DECL_ISUPPORTS
/* method for nsIElementObserver */
NS_IMETHOD_(const char*) GetTagNameAt(PRUint32 aTagIndex);
NS_IMETHOD Notify(PRUint32 aDocumentID, eHTMLTags aTag, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsStringArray* aKeys, const nsStringArray* aValues);
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* aKeys,
const nsStringArray* aValues);
/* methods for nsIObserver */
NS_DECL_NSIOBSERVER
/* begin and end observing */
NS_IMETHOD Start();
NS_IMETHOD Start(eHTMLTags* aWatchTags);
NS_IMETHOD End();
/* query, did we find a bad tag? */
NS_IMETHOD GetBadTagFound(PRBool *aFound);
/* register a tag to watch for */
NS_IMETHOD RegisterTagToWatch(const char* tagName);
protected:
virtual void Notify();
@ -85,9 +85,6 @@ protected:
protected:
PRBool mBadTagFound;
nsCStringArray mWatchTags;
};

View File

@ -174,6 +174,12 @@ enum {
eComposerController
};
static eHTMLTags gWatchTags[] =
{ eHTMLTag_frameset,
eHTMLTag_iframe,
eHTMLTag_unknown
};
/////////////////////////////////////////////////////////////////////////
// Utility to extract document from a webshell object.
static nsresult
@ -5054,9 +5060,7 @@ nsresult nsEditorShell::StartPageLoad(nsIChannel *aChannel)
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(mParserObserver);
mParserObserver->RegisterTagToWatch("FRAMESET");
mParserObserver->RegisterTagToWatch("IFRAME");
mParserObserver->Start();
mParserObserver->Start(gWatchTags);
}
return NS_OK;

View File

@ -178,6 +178,14 @@ public:
*/
NS_IMETHOD NotifyError(const nsParserError* aError)=0;
/**
* This gets called by the parser to notify observers of
* the tag
*
* @param aErrorResult the error code
*/
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode)=0;
/**
* Flush all pending notifications so that the content model
* is in sync with the state of the sink.

View File

@ -61,11 +61,6 @@ class nsIElementObserver : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IELEMENTOBSERVER_IID; return iid; }
/*
* This method return the tag which the observer care about
*/
NS_IMETHOD_(const char*)GetTagNameAt(PRUint32 aTagIndex) = 0;
/*
* Subject call observer when the parser hit the tag
* @param aDocumentID- ID of the document
@ -82,8 +77,11 @@ public:
PRUint32 numOfAttributes, const PRUnichar* nameArray[],
const PRUnichar* valueArray[]) = 0;
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsStringArray* aKeys, const nsStringArray* aValues) = 0;
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* aKeys,
const nsStringArray* aValues) = 0;
};

View File

@ -59,10 +59,6 @@
{0x355cbba0, 0xbf7d, 0x11d1, \
{0xaa, 0xd9, 0x00, 0x80, 0x5f, 0x8a, 0x3e, 0x14}}
// {8B6A98A0-260E-11d4-8153-0010A4E0C706}
#define NS_IPARSER_BUNDLE_IID \
{ 0x8b6a98a0, 0x260e, 0x11d4, { 0x81, 0x53, 0x0, 0x10, 0xa4, 0xe0, 0xc7, 0x6 } };
// {41421C60-310A-11d4-816F-000064657374}
#define NS_IDEBUG_DUMP_CONTENT_IID \
{ 0x41421c60, 0x310a, 0x11d4, { 0x81, 0x6f, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } };
@ -139,13 +135,6 @@ public:
NS_IMETHOD DumpContentModel()=0;
};
class nsISupportsParserBundle : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IPARSER_BUNDLE_IID; return iid; }
NS_IMETHOD GetDataFromBundle(const nsString& aKey,nsISupports** anObject)=0;
NS_IMETHOD SetDataIntoBundle(const nsString& aKey,nsISupports* anObject)=0;
};
/**
* This class defines the iparser interface. This XPCOM
* inteface is all that parser clients ever need to see.

View File

@ -41,11 +41,31 @@
#include "nsISupports.h"
#include "nsString.h"
#include "nsHTMLTags.h"
#include "nsIParserNode.h"
#include "nsIParser.h"
#include "nsVoidArray.h"
#include "nsIElementObserver.h"
#define NS_IPARSERSERVICE_IID \
{ 0xa6cf9111, 0x15b3, 0x11d2, \
{ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } }
// {78081E70-AD53-11d5-8498-0010A4E0C706}
#define NS_IOBSERVERENTRY_IID \
{ 0x78081e70, 0xad53, 0x11d5, { 0x84, 0x98, 0x0, 0x10, 0xa4, 0xe0, 0xc7, 0x6 } };
class nsIObserverEntry : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IOBSERVERENTRY_IID)
NS_IMETHOD Notify(nsIParserNode* aNode,
nsIParser* aParser,
nsISupports* aWebShell) = 0;
};
class nsIParserService : public nsISupports {
public:
@ -65,6 +85,17 @@ class nsIParserService : public nsISupports {
NS_IMETHOD IsContainer(PRInt32 aId, PRBool& aIsContainer) const =0;
NS_IMETHOD IsBlock(PRInt32 aId, PRBool& aIsBlock) const =0;
// Observer mechanism
NS_IMETHOD RegisterObserver(nsIElementObserver* aObserver,
const nsAString& aTopic,
const eHTMLTags* aTags = nsnull) = 0;
NS_IMETHOD UnregisterObserver(nsIElementObserver* aObserver,
const nsAString& aTopic) = 0;
NS_IMETHOD GetTopicObservers(const nsAString& aTopic,
nsIObserverEntry** aEntry) = 0;
};
#endif // nsIParserService_h__

View File

@ -107,6 +107,7 @@ public:
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
NS_IMETHOD DidProcessAToken(void) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
NS_IMETHOD DoFragment(PRBool aFlag);
NS_IMETHOD BeginContext(PRInt32 aPosition){ return NS_OK; }

View File

@ -59,7 +59,6 @@
#include "nsTagHandler.h"
#include "nsHTMLTokenizer.h"
#include "nsTime.h"
#include "nsIElementObserver.h"
#include "nsViewSourceHTML.h"
#include "nsParserNode.h"
#include "nsHTMLEntities.h"
@ -189,7 +188,7 @@ CNavDTD::CNavDTD() : nsIDTD(),
mLineNumber(1)
{
NS_INIT_REFCNT();
mBodyContext=new nsDTDContext();
#ifdef RICKG_DEBUG
@ -198,7 +197,6 @@ CNavDTD::CNavDTD() : nsIDTD(),
nsHTMLElement::DebugDumpMembership("c:/temp/membership.out");
nsHTMLElement::DebugDumpContainType("c:/temp/ctnrules.out");
#endif
}
/**
@ -1377,13 +1375,8 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode
STOP_TIMER()
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));
if(mParser) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
const nsISupportsParserBundle* bundle=mParser->GetParserBundle();
result=theService->Notify(aTag,aNode,(void*)bundle, mMimeType, mParser);
}
if (aTag <= NS_HTML_TAG_MAX) {
result = mSink->NotifyTagObservers(&aNode);
}
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));

View File

@ -57,7 +57,6 @@
#include "nsTagHandler.h"
#include "nsHTMLTokenizer.h"
#include "nsTime.h"
#include "nsIElementObserver.h"
#include "nsViewSourceHTML.h"
#include "nsParserNode.h"
#include "nsHTMLEntities.h"
@ -70,7 +69,7 @@ static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kClassIID, NS_IOTHERHTML_DTD_IID);
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
static char* kVerificationDir = "c:/temp";
@ -640,12 +639,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNo
default:
break;
}
CObserverService* theService=mParser->GetObserverService();
if(theService) {
const nsISupportsParserBundle* bundle=mParser->GetParserBundle();
result=theService->Notify(aTag,aNode,(void*)bundle, NS_ConvertASCIItoUCS2(kHTMLTextContentType), mParser);
}
mSink->NotifyTagObservers(&aNode);
}
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));

View File

@ -68,6 +68,7 @@ CPPSRCS = \
nsHTMLTokens.cpp \
nsParser.cpp \
CParserContext.cpp \
nsParserService.cpp \
nsParserModule.cpp \
nsParserNode.cpp \
nsScanner.cpp \

View File

@ -62,6 +62,7 @@ CPPSRCS = \
nsToken.cpp \
nsWellFormedDTD.cpp \
nsViewSourceHTML.cpp\
nsParserService.cpp \
nsParserModule.cpp \
nsParserMsgUtils.cpp \
!ifdef MOZ_DEBUG
@ -87,6 +88,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsToken.obj \
.\$(OBJDIR)\nsWellFormedDTD.obj \
.\$(OBJDIR)\nsViewSourceHTML.obj\
.\$(OBJDIR)\nsParserService.obj \
.\$(OBJDIR)\nsParserModule.obj \
.\$(OBJDIR)\nsParserMsgUtils.obj \
!ifdef MOZ_DEBUG

View File

@ -42,18 +42,14 @@
#include "CNavDTD.h"
#include "nsIParserNode.h"
#include "nsParserNode.h"
#include "nsIChannel.h"
#include "nsIServiceManager.h"
nsIObserverService *CObserverService::gObserverService = NULL;
MOZ_DECL_CTOR_COUNTER(nsEntryStack)
MOZ_DECL_CTOR_COUNTER(nsDTDContext)
MOZ_DECL_CTOR_COUNTER(nsTokenAllocator)
MOZ_DECL_CTOR_COUNTER(CNodeRecycler)
MOZ_DECL_CTOR_COUNTER(CObserverService)
/**************************************************************************************
A few notes about how residual style handling is performed:
@ -1477,313 +1473,131 @@ PRUint32 AccumulateCRC(PRUint32 crc_accum, char *data_blk_ptr, int data_blk_size
return crc_accum;
}
/**************************************************************
Define the nsIElementObserver release class...
**************************************************************/
class nsObserverReleaser: public nsDequeFunctor{
public:
virtual void* operator()(void* anObject) {
nsIElementObserver* theObserver= (nsIElementObserver*)anObject;
NS_RELEASE(theObserver);
return 0;
}
};
/**************************************************************
This defines the topic object used by the observer service.
The observerService uses a list of these, 1 per topic when
registering tags.
**************************************************************/
NS_IMPL_ISUPPORTS1(nsObserverEntry, nsIObserverEntry)
nsObserverTopic::nsObserverTopic(const nsString& aTopic) : mTopic(aTopic) {
nsCRT::zero(mObservers,sizeof(mObservers));
mCharsetKey.AssignWithConversion("charset");
mSourceKey.AssignWithConversion("charsetSource");
mDTDKey.AssignWithConversion("X_COMMAND");
nsObserverEntry::nsObserverEntry(const nsAString& aTopic) : mTopic(aTopic)
{
NS_INIT_ISUPPORTS();
nsCRT::zero(mObservers,sizeof(mObservers));
}
nsObserverTopic::~nsObserverTopic() {
nsObserverReleaser theReleaser;
PRInt32 theIndex=0;
for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){
if(mObservers[theIndex]){
mObservers[theIndex]->ForEach(theReleaser);
delete mObservers[theIndex];
mObservers[theIndex]=0;
nsObserverEntry::~nsObserverEntry() {
for (PRInt32 i = 0; i <= NS_HTML_TAG_MAX; i++){
if (mObservers[i]) {
PRInt32 count = mObservers[i]->Count();
for (PRInt32 j = 0; j < count; j++) {
nsISupports* obs = (nsISupports*)mObservers[i]->ElementAt(j);
NS_IF_RELEASE(obs);
}
delete mObservers[i];
}
}
}
PRBool nsObserverTopic::Matches(const nsString& aString) {
PRBool result=aString.Equals(mTopic);
return result;
}
NS_IMETHODIMP
nsObserverEntry::Notify(nsIParserNode* aNode,
nsIParser* aParser,
nsISupports* aWebShell)
{
NS_ENSURE_ARG_POINTER(aNode);
NS_ENSURE_ARG_POINTER(aParser);
nsDeque* nsObserverTopic::GetObserversForTag(eHTMLTags aTag) {
if(aTag <= NS_HTML_TAG_MAX) {
return mObservers[aTag];
}
return 0;
}
nsresult result = NS_OK;
eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
if (theTag <= NS_HTML_TAG_MAX) {
nsVoidArray* theObservers = mObservers[theTag];
if (theObservers) {
nsAutoString theCharsetValue;
nsCharsetSource theCharsetSource;
aParser->GetDocumentCharset(theCharsetValue,theCharsetSource);
void nsObserverTopic::RegisterObserverForTag(nsIElementObserver *anObserver,eHTMLTags aTag) {
if(anObserver) {
if(mObservers[aTag] == nsnull) {
mObservers[aTag] = new nsDeque(0);
}
NS_ADDREF(anObserver);
mObservers[aTag]->Push(anObserver);
}
}
PRInt32 theAttrCount = aNode->GetAttributeCount();
PRInt32 theObserversCount = theObservers->Count();
if (0 < theObserversCount){
nsStringArray keys(theAttrCount+4), values(theAttrCount+4);
/**
* This method will notify observers registered for specific tags.
*
* @update harishd 08/29/99
* @param aTag - The tag for which observers could be waiting for.
* @param aNode -
* @param aUniqueID - The document ID.
* @param aDTD - The current DTD.
* @param aCharsetValue -
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser) {
nsresult result=NS_OK;
// XXX this and the following code may be a performance issue.
// Every key and value is copied and added to an voidarray (causing at
// least 2 allocations for mImpl, usually more, plus at least 1 per
// string (total = 2*(keys+3) + 2(or more) array allocations )).
PRInt32 index;
for (index = 0; index < theAttrCount; index++) {
keys.AppendString(aNode->GetKeyAt(index));
values.AppendString(aNode->GetValueAt(index));
}
nsDeque* theObservers=GetObserversForTag(aTag);
if(theObservers){
nsAutoString intValue;
nsAutoString theCharsetValue;
nsCharsetSource theCharsetSource;
aParser->GetDocumentCharset(theCharsetValue,theCharsetSource);
PRInt32 theAttrCount =aNode.GetAttributeCount();
PRInt32 theObserversCount=theObservers->GetSize();
if(0<theObserversCount){
nsStringArray keys(theAttrCount+4),values(theAttrCount+4);
// XXX this and the following code may be a performance issue.
// Every key and value is copied and added to an voidarray (causing at
// least 2 allocations for mImpl, usually more, plus at least 1 per
// string (total = 2*(keys+3) + 2(or more) array allocations )).
PRInt32 index;
for(index=0; index<theAttrCount; index++) {
keys.AppendString(aNode.GetKeyAt(index));
values.AppendString(aNode.GetValueAt(index));
}
nsAutoString intValue;
keys.AppendString(mCharsetKey);
values.AppendString(theCharsetValue);
keys.AppendString(NS_LITERAL_STRING("charset"));
values.AppendString(theCharsetValue);
keys.AppendString(mSourceKey);
intValue.AppendInt(PRInt32(theCharsetSource),10);
values.AppendString(intValue);
keys.AppendString(NS_LITERAL_STRING("charsetSource"));
intValue.AppendInt(PRInt32(theCharsetSource),10);
values.AppendString(intValue);
keys.AppendString(mDTDKey);
values.AppendString(mTopic);
keys.AppendString(NS_LITERAL_STRING("X_COMMAND"));
values.AppendString(NS_LITERAL_STRING("text/html"));
nsAutoString theTagStr; theTagStr.AssignWithConversion(nsHTMLTags::GetStringValue(aTag));
for(index=0;index<theObserversCount;index++) {
nsIElementObserver* observer=NS_STATIC_CAST(nsIElementObserver*,theObservers->ObjectAt(index));
if(observer) {
result=observer->Notify((nsISupports*)aUniqueID,theTagStr.get(),&keys,&values);
if(NS_FAILED(result)) {
break;
nsAutoString theTagStr;
theTagStr.AssignWithConversion(nsHTMLTags::GetStringValue(theTag));
nsCOMPtr<nsIChannel> channel;
aParser->GetChannel(getter_AddRefs(channel));
for (index=0;index<theObserversCount;index++) {
nsIElementObserver* observer = NS_STATIC_CAST(nsIElementObserver*,theObservers->ElementAt(index));
if (observer) {
result = observer->Notify(aWebShell,channel,theTagStr.get(),&keys,&values);
if (NS_FAILED(result)) {
break;
}
}
}
}
}
}//if
}
}
}
return result;
}
PRBool
nsObserverEntry::Matches(const nsAString& aString) {
PRBool result = aString.Equals(mTopic);
return result;
}
/******************************************************************************
This class is used to store ref's to tag observers during the parse phase.
Note that for simplicity, this is a singleton that is constructed in the
CNavDTD and shared for the duration of the application session. Later on it
might be nice to use a more dynamic approach that would permit observers to
come and go on a document basis.
I changed the observerservice to store topics so that we can distinguish
observers by topic. Up till now, they've all just be thrown into the same
observer list, which was wrong. This fixes bug #28825.
******************************************************************************/
nsresult
CObserverService::InitGlobals() {
if (!gObserverService) {
nsresult rv = NS_OK;
nsCOMPtr<nsIObserverService> obs(do_GetService(NS_OBSERVERSERVICE_CONTRACTID,&rv));
if (NS_SUCCEEDED(rv)) {
gObserverService = obs.get();
NS_IF_ADDREF(gObserverService);
nsObserverEntry::AddObserver(nsIElementObserver *aObserver,
eHTMLTags aTag)
{
if (aObserver) {
if (!mObservers[aTag]) {
mObservers[aTag] = new nsAutoVoidArray();
if (!mObservers[aTag]) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
NS_ADDREF(aObserver);
mObservers[aTag]->AppendElement(aObserver);
}
return NS_OK;
}
void
CObserverService::ReleaseGlobals() {
NS_IF_RELEASE(gObserverService);
}
CObserverService::CObserverService() : mTopics(0) {
MOZ_COUNT_CTOR(CObserverService);
nsAutoString theHTMLTopic; theHTMLTopic.AssignWithConversion(kHTMLTextContentType);
RegisterObservers(theHTMLTopic);
nsAutoString theXMLTopic; theXMLTopic.AssignWithConversion(kXMLTextContentType); //use the mimetype for the topic
RegisterObservers(theXMLTopic);
theXMLTopic.AssignWithConversion(kXMLApplicationContentType);
RegisterObservers(theXMLTopic);
theXMLTopic.AssignWithConversion(kXHTMLApplicationContentType);
RegisterObservers(theXMLTopic);
}
CObserverService::~CObserverService() {
MOZ_COUNT_DTOR(CObserverService);
nsObserverTopic *theTopic=(nsObserverTopic*)mTopics.Pop();
while(theTopic) {
delete theTopic;
theTopic=(nsObserverTopic*)mTopics.Pop();
}
}
// XXX This may be more efficient as a HashTable instead of linear search
nsObserverTopic* CObserverService::GetTopic(const nsString& aTopic) {
PRInt32 theIndex=0;
nsObserverTopic *theTopic=(nsObserverTopic*)mTopics.ObjectAt(theIndex++);
while(theTopic) {
if(theTopic->Matches(aTopic))
return theTopic;
theTopic=(nsObserverTopic*)mTopics.ObjectAt(theIndex++);
}
return 0;
}
nsObserverTopic* CObserverService::CreateTopic(const nsString& aTopic) {
nsObserverTopic* theTopic=new nsObserverTopic(aTopic);
mTopics.Push(theTopic);
return theTopic;
}
/**
* This method will maintain lists of observers registered for specific tags.
*
* @update rickg 03.23.2000
* @param aTopic - The topic under which observers register for.
* @return if SUCCESS return NS_OK else return ERROR code.
*/
void CObserverService::RegisterObservers(const nsString& aTopic) {
nsresult result = NS_OK;
if (gObserverService) {
nsIEnumerator* theEnum = nsnull;
result = gObserverService->EnumerateObserverList(aTopic.get(), &theEnum);
if(result == NS_OK) {
nsCOMPtr<nsIElementObserver> theElementObserver;
nsISupports *inst = nsnull;
nsObserverTopic *theTopic=0;
for (theEnum->First(); theEnum->IsDone() != NS_OK; theEnum->Next()) {
result = theEnum->CurrentItem(&inst);
if (NS_SUCCEEDED(result)) {
theElementObserver = do_QueryInterface(inst, &result);
NS_RELEASE(inst);
}
if (result == NS_OK) {
const char* theTagStr = nsnull;
PRUint32 theTagIndex = 0;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
while (theTagStr != nsnull) {
eHTMLTags theTag = nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){
theTopic=GetTopic(aTopic);
if(!theTopic)
theTopic=CreateTopic(aTopic);
if(theTopic) {
theTopic->RegisterObserverForTag(theElementObserver,theTag);
}
}
theTagIndex++;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
}
}
void
nsObserverEntry::RemoveObserver(nsIElementObserver *aObserver)
{
for (PRInt32 i=0; i <= NS_HTML_TAG_MAX; i++){
if (mObservers[i]) {
nsISupports* obs = aObserver;
PRBool removed = mObservers[i]->RemoveElement(obs);
if (removed) {
NS_RELEASE(obs);
}
}
NS_IF_RELEASE(theEnum);
}
}
/**
* This method will maintain lists of observers registered for specific tags.
*
* @update rickg 03.23.2000
* @param aTopic - The topic under which observers register for.
* @return if SUCCESS return NS_OK else return ERROR code.
*/
void CObserverService::UnregisterObservers(const nsString& aTopic) {
}
/**
* This method will notify observers registered for specific tags.
*
* @update rickg 03.23.2000
* @param aTag - The tag for which observers could be waiting for.
* @param aNode -
* @param aUniqueID - The document ID.
* @param aDTD - The current DTD.
* @param aCharsetValue -
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult CObserverService::Notify( eHTMLTags aTag,
nsIParserNode& aNode,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser) {
nsresult result=NS_OK;
nsObserverTopic *theTopic=GetTopic(aTopic);
if(theTopic) {
result=theTopic->Notify(aTag,aNode,aUniqueID,aParser);
}
return result;
}
/**
* This method will look for the list of observers registered for
* a specific tag.
*
* @update rickg 03.23.2000
* @param aTag - The tag for which observers could be waiting for.
* @return if FOUND return "observer list" else return nsnull;
*
*/
nsDeque* CObserverService::GetObserversForTagInTopic(eHTMLTags aTag,const nsString& aTopic) {
nsObserverTopic *theTopic=GetTopic(aTopic);
if(theTopic) {
return theTopic->GetObserversForTag(aTag);
}
return 0;
}

View File

@ -56,11 +56,10 @@
#include "nsIDTD.h"
#include "nsITokenizer.h"
#include "nsString.h"
#include "nsIElementObserver.h"
#include "nsIParserNode.h"
#include "nsFixedSizeAllocator.h"
#include "nsVoidArray.h"
#include "nsIObserverService.h"
#include "nsIParserService.h"
#define IF_HOLD(_ptr) \
PR_BEGIN_MACRO \
@ -533,53 +532,23 @@ struct CRCStruct {
registering tags.
**************************************************************/
class nsObserverTopic {
class nsObserverEntry : public nsIObserverEntry {
public:
nsObserverTopic(const nsString& aTopic);
~nsObserverTopic();
PRBool Matches(const nsString& aTopic);
void RegisterObserverForTag(nsIElementObserver *anObserver,eHTMLTags aTag);
nsDeque* GetObserversForTag(eHTMLTags aTag);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser);
NS_DECL_ISUPPORTS
nsObserverEntry(const nsAString& aTopic);
virtual ~nsObserverEntry();
nsString mTopic;
nsString mCharsetKey;
nsString mSourceKey;
nsString mDTDKey;
nsDeque* mObservers[NS_HTML_TAG_MAX + 1];
};
NS_IMETHOD Notify(nsIParserNode* aNode,
nsIParser* aParser,
nsISupports* aWebShell);
/******************************************************************************
This class is used to store ref's to token observers during the parse phase.
Note that for simplicity, this is a singleton that is constructed in the
CNavDTD and shared for the duration of the application session. Later on it
might be nice to use a more dynamic approach that would permit observers to
come and go on a document basis.
******************************************************************************/
class CObserverService {
public:
CObserverService();
~CObserverService();
nsDeque* GetObserversForTagInTopic(eHTMLTags aTag,const nsString& aTopic);
nsresult Notify( eHTMLTags aTag,
nsIParserNode& aNode,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser);
nsObserverTopic* GetTopic(const nsString& aTopic);
nsObserverTopic* CreateTopic(const nsString& aTopic);
// Do allocation and release of gObserverService
// These are called from the module init and shutdown
static nsresult InitGlobals();
static void ReleaseGlobals();
nsresult AddObserver(nsIElementObserver* aObserver,eHTMLTags aTag);
void RemoveObserver(nsIElementObserver* aObserver);
PRBool Matches(const nsAString& aTopic);
protected:
void RegisterObservers(const nsString& aTopic);
void UnregisterObservers(const nsString& aTopic);
nsDeque mTopics; //each topic holds a list of observers per tag.
static nsIObserverService *gObserverService;
nsString mTopic;
nsVoidArray* mObservers[NS_HTML_TAG_MAX + 1];
};
/*********************************************************************************************/

View File

@ -72,6 +72,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() {return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset) {return NS_OK;}
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue);

View File

@ -74,6 +74,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue);

View File

@ -356,7 +356,6 @@ nsParser::nsParser(nsITokenObserver* anObserver) {
mObserversEnabled=PR_TRUE;
mCommand=eViewNormal;
mParserEnabled=PR_TRUE;
mBundle=nsnull;
mPendingContinueEvent=PR_FALSE;
mCanInterrupt=PR_FALSE;
@ -405,7 +404,6 @@ nsParser::~nsParser() {
NS_IF_RELEASE(mProgressEventSink);
NS_IF_RELEASE(mSink);
NS_IF_RELEASE(mParserFilter);
NS_IF_RELEASE(mBundle);
//don't forget to add code here to delete
//what may be several contexts...
@ -456,9 +454,6 @@ nsresult nsParser::QueryInterface(const nsIID& aIID, void** aInstancePtr)
else if(aIID.Equals(kCParserCID)) { //do this class...
*aInstancePtr = (nsParser*)(this);
}
else if(aIID.Equals(NS_GET_IID(nsISupportsParserBundle))) {
*aInstancePtr = (nsISupportsParserBundle*)(this);
}
else {
*aInstancePtr=0;
return NS_NOINTERFACE;
@ -1031,7 +1026,7 @@ static void VerifyPublicIDs()
NS_NOTREACHED("doctype not lower case");
printf("Doctype %s not lower case.\n", kPublicIDs[i].name);
}
}
}
}
}
#endif
@ -1422,7 +1417,6 @@ nsresult nsParser::DidBuildModel(nsresult anErrorCode) {
result = mParserContext->mDTD->DidBuildModel(anErrorCode,PRBool(0==mParserContext->mPrevContext),this,mSink);
}
//Ref. to bug 61462.
NS_IF_RELEASE(mBundle);
}//if
}
@ -2725,133 +2719,4 @@ nsParser::GetDTD(nsIDTD** aDTD)
}
return NS_OK;
}
/**
* Get the observer service
*
* @update rickg 11/22/99
* @return ptr to server or NULL
*/
CObserverService* nsParser::GetObserverService(void) {
//XXX Hack! this should be XPCOM based!
if(mObserversEnabled)
return &mObserverService;
return 0;
}
/**
* Store data into the bundle.
*
* @update harishd 05/10/00
* @param aData - The data to be stored.
* @return NS_OK if all went well else ERROR.
*/
NS_IMETHODIMP
nsParser::SetDataIntoBundle(const nsString& aKey,nsISupports* anObject) {
nsresult result=NS_OK;
if(!mBundle) {
mBundle = new nsParserBundle();
if(mBundle==nsnull) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mBundle);
}
result=mBundle->SetDataIntoBundle(aKey,anObject);
return result;
}
/**
* Retrieve data from the bundle by IID.
* NOTE: The object retireved should not be released
*
* @update harishd 05/10/00
* @param aIID - The ID to identify the correct object in the bundle
* @return Return object if found in bundle else return NULL.
*/
NS_IMETHODIMP
nsParser::GetDataFromBundle(const nsString& aKey,nsISupports** anObject) {
nsresult result=NS_OK;
result=mBundle->GetDataFromBundle(aKey,anObject);
return result;
}
NS_IMPL_ISUPPORTS1(nsParserBundle,
nsISupportsParserBundle
);
/**
* Release data from the Hash table
*
* @update harishd 05/10/00
*/
static PRBool PR_CALLBACK ReleaseData(nsHashKey* aKey, void* aData, void* aClosure) {
nsISupports* object = (nsISupports*)aData;
NS_RELEASE(object);
return PR_TRUE;
}
/**
*
* @update harishd 05/10/00
*/
nsParserBundle::nsParserBundle (){
NS_INIT_REFCNT();
mData=new nsHashtable(5);
}
/**
* Release objects from the bundle.
*
* @update harishd 05/10/00
*/
nsParserBundle::~nsParserBundle () {
mData->Enumerate(ReleaseData);
delete mData;
}
/**
* Store data into the bundle.
*
* @update harishd 05/10/00
* @param aData - The data to be stored.
* @return NS_OK if all went well else ERROR.
*/
NS_IMETHODIMP
nsParserBundle::SetDataIntoBundle(const nsString& aKey,nsISupports* anObject) {
nsresult result=NS_OK;
if(anObject) {
nsStringKey key(aKey);
PRBool found=mData->Exists(&key);
if(!found) {
NS_ADDREF(anObject);
mData->Put(&key,anObject);
}
}
return result;
}
/**
* Retrieve data from the bundle by IID.
* NOTE: The object retrieved should not be released.
*
* @update harishd 05/10/00
* @param aIID - The ID to identify the correct object in the bundle
* @return Return object if found in bundle else return NULL.
*/
NS_IMETHODIMP
nsParserBundle::GetDataFromBundle(const nsString& aKey,nsISupports** anObject) {
nsresult result=NS_OK;
nsStringKey key(aKey);
*anObject=(mData)? (nsISupports*)mData->Get(&key):nsnull;
if(*anObject) {
NS_ADDREF(*anObject);
}
else{
result=NS_ERROR_NULL_POINTER;
}
return result;
}
}

View File

@ -93,7 +93,6 @@ class nsIDTD;
class nsScanner;
class nsIParserFilter;
class nsIProgressEventSink;
class nsParserBundle;
#ifdef XP_WIN
#pragma warning( disable : 4275 )
@ -101,7 +100,6 @@ class nsParserBundle;
class nsParser : public nsIParser,
public nsISupportsParserBundle,
public nsIStreamListener{
@ -287,8 +285,6 @@ class nsParser : public nsIParser,
CParserContext* PopContext();
CParserContext* PeekContext() {return mParserContext;}
const nsParserBundle* GetParserBundle() { return mBundle; }
/**
*
* @update gess 1/22/99
@ -320,20 +316,7 @@ class nsParser : public nsIParser,
* @return NS_OK if successful, NS_ERROR_FAILURE for runtime error
*/
NS_IMETHOD GetDTD(nsIDTD** aDTD);
/**
* Call this to access observer dictionary ( internal to parser )
* @update harishd 06/27/99
* @param
* @return
*/
CObserverService* GetObserverService(void);
// nsISupportsParserBundle
NS_IMETHOD GetDataFromBundle(const nsString& aKey,nsISupports** anObject);
NS_IMETHOD SetDataIntoBundle(const nsString& aKey,nsISupports* anObject);
/**
* Call this method to determine a DTD for a DOCTYPE
*
@ -490,11 +473,9 @@ protected:
nsString mCharset;
nsCharsetSource mCharsetSource;
nsresult mInternalState;
CObserverService mObserverService;
PRBool mObserversEnabled;
nsString mCommandStr;
PRBool mParserEnabled;
nsParserBundle* mBundle;
nsTokenAllocator mTokenAllocator;
nsCOMPtr<nsIEventQueue> mEventQueue;
@ -508,37 +489,5 @@ public:
MOZ_TIMER_DECLARE(mTokenizeTime)
};
// -----------------------------------------------------------------
class nsParserBundle : public nsISupportsParserBundle {
public:
NS_DECL_ISUPPORTS
nsParserBundle ();
virtual ~nsParserBundle ();
/**
* Retrieve data from the bundle by IID.
*
* @update harishd 05/10/00
* @param aIID - The ID to identify the correct object in the bundle
* @return Return object if found in bundle else return NULL.
*/
NS_IMETHOD GetDataFromBundle(const nsString& aKey,nsISupports** anObject);
/**
* Store data into the bundle.
*
* @update harishd 05/10/00
* @param aData - The data to be stored.
* @return NS_OK if all went well else ERROR.
*/
NS_IMETHOD SetDataIntoBundle(const nsString& aKey,nsISupports* anObject);
protected:
nsHashtable* mData;
};
#endif

View File

@ -53,115 +53,13 @@
#include "nsHTMLTokenizer.h"
//#include "nsTextTokenizer.h"
#include "nsExpatTokenizer.h"
#include "nsIParserService.h"
#include "nsElementTable.h"
#include "nsParserService.h"
#ifdef NS_DEBUG
#include "nsLoggingSink.h"
#endif
class nsParserService : public nsIParserService {
public:
nsParserService();
virtual ~nsParserService();
NS_DECL_ISUPPORTS
NS_IMETHOD HTMLAtomTagToId(nsIAtom* aAtom, PRInt32* aId) const;
NS_IMETHOD HTMLStringTagToId(const nsString &aTag, PRInt32* aId) const;
NS_IMETHOD HTMLIdToStringTag(PRInt32 aId, nsString& aTag) const;
NS_IMETHOD HTMLConvertEntityToUnicode(const nsString& aEntity,
PRInt32* aUnicode) const;
NS_IMETHOD HTMLConvertUnicodeToEntity(PRInt32 aUnicode,
nsCString& aEntity) const;
NS_IMETHOD IsContainer(PRInt32 aId, PRBool& aIsContainer) const;
NS_IMETHOD IsBlock(PRInt32 aId, PRBool& aIsBlock) const;
};
nsParserService::nsParserService()
{
NS_INIT_ISUPPORTS();
}
nsParserService::~nsParserService()
{
}
NS_IMPL_ISUPPORTS1(nsParserService, nsIParserService)
NS_IMETHODIMP
nsParserService::HTMLAtomTagToId(nsIAtom* aAtom, PRInt32* aId) const
{
NS_ENSURE_ARG_POINTER(aAtom);
nsAutoString tagName;
aAtom->ToString(tagName);
*aId = nsHTMLTags::LookupTag(tagName);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLStringTagToId(const nsString &aTag, PRInt32* aId) const
{
*aId = nsHTMLTags::LookupTag(aTag);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLIdToStringTag(PRInt32 aId, nsString& aTag) const
{
aTag.AssignWithConversion( nsHTMLTags::GetStringValue((nsHTMLTag)aId) );
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLConvertEntityToUnicode(const nsString& aEntity,
PRInt32* aUnicode) const
{
*aUnicode = nsHTMLEntities::EntityToUnicode(aEntity);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLConvertUnicodeToEntity(PRInt32 aUnicode,
nsCString& aEntity) const
{
const char* str = nsHTMLEntities::UnicodeToEntity(aUnicode);
if (str) {
aEntity.Assign(str);
}
return NS_OK;
}
NS_IMETHODIMP
nsParserService::IsContainer(PRInt32 aId, PRBool& aIsContainer) const
{
aIsContainer = nsHTMLElement::IsContainer((eHTMLTags)aId);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::IsBlock(PRInt32 aId, PRBool& aIsBlock) const
{
if((aId>eHTMLTag_unknown) && (aId<eHTMLTag_userdefined)) {
aIsBlock=((gHTMLElements[aId].IsMemberOf(kBlock)) ||
(gHTMLElements[aId].IsMemberOf(kBlockEntity)) ||
(gHTMLElements[aId].IsMemberOf(kHeading)) ||
(gHTMLElements[aId].IsMemberOf(kPreformatted))||
(gHTMLElements[aId].IsMemberOf(kList)));
}
else {
aIsBlock = PR_FALSE;
}
return NS_OK;
}
//----------------------------------------------------------------------
#ifdef NS_DEBUG
@ -203,7 +101,6 @@ Initialize(nsIModule* aSelf)
nsHTMLEntities::AddRefTable();
InitializeElementTable();
CNewlineToken::AllocNewline();
CObserverService::InitGlobals();
gInitialized = PR_TRUE;
}
return NS_OK;
@ -219,7 +116,6 @@ Shutdown(nsIModule* aSelf)
nsParser::FreeSharedObjects();
DeleteElementTable();
CNewlineToken::FreeNewline();
CObserverService::ReleaseGlobals();
gInitialized = PR_FALSE;
}
}

View File

@ -80,17 +80,16 @@
#include "prtypes.h" //this is here for debug reasons...
#include "prio.h"
#include "plstr.h"
#include "prmem.h"
#ifdef RAPTOR_PERF_METRICS
#include "stopwatch.h"
Stopwatch vsTimer;
#endif
static NS_DEFINE_IID(kClassIID, NS_VIEWSOURCE_HTML_IID);
static NS_DEFINE_IID(kClassIID, NS_VIEWSOURCE_HTML_IID);
static int gErrorThreshold = 10;
// Define this to dump the viewsource stuff to a file
@ -1099,12 +1098,7 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
else result=WriteTag(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE);
if((ePlainText!=mDocType) && mParser && (NS_OK==result)) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
const nsISupportsParserBundle* bundle=mParser->GetParserBundle();
result=theService->Notify(theTag,theContext.mTokenNode,(void*)bundle, mMimeType, mParser);
}
result = mSink->NotifyTagObservers(&theContext.mTokenNode);
}
}
break;

View File

@ -31,7 +31,6 @@ OBJS = \
LLIBS= \
$(DIST)\lib\gkparser.lib \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR) \
$(NULL)

View File

@ -51,8 +51,17 @@
#include "nsIServiceManager.h"
#include "nsObserverBase.h"
#include "nsWeakReference.h"
#include "nsIParserService.h"
#include "nsParserCIID.h"
#include "nsMetaCharsetCID.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
static eHTMLTags gWatchTags[] =
{ eHTMLTag_meta,
eHTMLTag_unknown
};
//-------------------------------------------------------------------------
nsMetaCharsetObserver::nsMetaCharsetObserver()
@ -87,16 +96,6 @@ NS_IMPL_QUERY_INTERFACE4(nsMetaCharsetObserver,
nsIMetaCharsetService,
nsISupportsWeakReference);
//-------------------------------------------------------------------------
NS_IMETHODIMP_(const char*) nsMetaCharsetObserver::GetTagNameAt(PRUint32 aTagIndex)
{
if (aTagIndex == 0) {
return "META";
}else {
return nsnull;
}
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsMetaCharsetObserver::Notify(
PRUint32 aDocumentID,
@ -141,21 +140,24 @@ NS_IMETHODIMP nsMetaCharsetObserver::Notify(
return NS_OK;//Notify((nsISupports*)aDocumentID, &keys, &values);
}
NS_IMETHODIMP nsMetaCharsetObserver::Notify(
nsISupports* aDocumentID,
nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* keys, const nsStringArray* values)
{
if(0 != nsCRT::strcasecmp(aTag, NS_LITERAL_STRING("META").get()))
return NS_ERROR_ILLEGAL_VALUE;
else
return Notify(aDocumentID, keys, values);
return Notify(aWebShell, aChannel, keys, values);
}
#define IS_SPACE_CHARS(ch) (ch == ' ' || ch == '\b' || ch == '\r' || ch == '\n')
NS_IMETHODIMP nsMetaCharsetObserver::Notify(
nsISupports* aDocumentID,
const nsStringArray* keys, const nsStringArray* values)
nsISupports* aWebShell,
nsISupports* aChannel,
const nsStringArray* keys,
const nsStringArray* values)
{
NS_PRECONDITION(keys!=nsnull && values!=nsnull,"Need key-value pair");
@ -289,7 +291,8 @@ NS_IMETHODIMP nsMetaCharsetObserver::Notify(
!preferred.Equals(NS_LITERAL_STRING("UTF-32LE"))) {
// Propagate the error message so that the parser can
// shutdown correctly. - Ref. Bug 96440
res = NotifyWebShell(aDocumentID,
res = NotifyWebShell(aWebShell,
aChannel,
NS_ConvertUCS2toUTF8(preferred).get(),
kCharsetFromMetaTag);
}
@ -305,7 +308,8 @@ NS_IMETHODIMP nsMetaCharsetObserver::Notify(
if (NS_SUCCEEDED(GetCharsetFromCompatibilityTag(keys, values, compatCharset)))
{
if (!compatCharset.IsEmpty()) {
res = NotifyWebShell(aDocumentID,
res = NotifyWebShell(aWebShell,
aChannel,
NS_ConvertUCS2toUTF8(compatCharset).get(),
kCharsetFromMetaTag);
}
@ -391,15 +395,15 @@ NS_IMETHODIMP nsMetaCharsetObserver::Start()
if (bMetaCharsetObserverStarted == PR_FALSE) {
bMetaCharsetObserverStarted = PR_TRUE;
// get the observer service
nsCOMPtr<nsIObserverService> anObserverService =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &res);
if (NS_FAILED(res)) return res;
nsAutoString htmlTopic; htmlTopic.AssignWithConversion(kHTMLTextContentType);
nsCOMPtr<nsIParserService> parserService(do_GetService(kParserServiceCID));
// add self to ObserverService
res = anObserverService->AddObserver(this, htmlTopic.get());
if (!parserService) {
return NS_ERROR_OUT_OF_MEMORY;
}
res = parserService->RegisterObserver(this,
NS_LITERAL_STRING("text/html"),
gWatchTags);
}
return res;
@ -411,12 +415,14 @@ NS_IMETHODIMP nsMetaCharsetObserver::End()
if (bMetaCharsetObserverStarted == PR_TRUE) {
bMetaCharsetObserverStarted = PR_FALSE;
nsCOMPtr<nsIObserverService> anObserverService =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &res);
if (NS_FAILED(res)) return res;
nsAutoString htmlTopic; htmlTopic.AssignWithConversion(kHTMLTextContentType);
res = anObserverService->RemoveObserver(this, htmlTopic.get());
nsCOMPtr<nsIParserService> parserService(do_GetService(kParserServiceCID));
if (!parserService) {
return NS_ERROR_OUT_OF_MEMORY;
}
res = parserService->UnregisterObserver(this,
NS_LITERAL_STRING("text/html"));
}
return res;
}

View File

@ -60,10 +60,6 @@ public:
virtual ~nsMetaCharsetObserver();
/* methode for nsIElementObserver */
/*
* This method return the tag which the observer care about
*/
NS_IMETHOD_(const char*)GetTagNameAt(PRUint32 aTagIndex);
/*
* Subject call observer when the parser hit the tag
@ -78,7 +74,11 @@ public:
NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag, const nsStringArray* keys, const nsStringArray* values);
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* keys,
const nsStringArray* values);
NS_DECL_ISUPPORTS
@ -94,7 +94,10 @@ private:
NS_IMETHOD Notify(PRUint32 aDocumentID, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(nsISupports* aDocumentID, const nsStringArray* keys, const nsStringArray* values);
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const nsStringArray* keys,
const nsStringArray* values);
NS_IMETHOD GetCharsetFromCompatibilityTag(const nsStringArray* keys,
const nsStringArray* values,

View File

@ -57,68 +57,56 @@ static NS_DEFINE_IID(kIDocumentLoaderIID, NS_IDOCUMENTLOADER_IID);
static NS_DEFINE_IID(kIWebShellServicesIID, NS_IWEB_SHELL_SERVICES_IID);
//-------------------------------------------------------------------------
NS_IMETHODIMP nsObserverBase::NotifyWebShell(
nsISupports* aParserBundle, const char* charset, nsCharsetSource source)
NS_IMETHODIMP nsObserverBase::NotifyWebShell(nsISupports* aWebShell,
nsISupports* aChannel,
const char* charset,
nsCharsetSource source)
{
nsresult rv = NS_OK;
nsresult res = NS_OK;
nsCOMPtr<nsISupportsParserBundle> bundle=do_QueryInterface(aParserBundle);
if (bundle) {
nsresult res = NS_OK;
// XXX - Make sure not to reload POST data to prevent bugs such as 27006
nsAutoString theChannelKey;
theChannelKey.AssignWithConversion("channel");
nsCOMPtr<nsIChannel> channel=nsnull;
res=bundle->GetDataFromBundle(theChannelKey,getter_AddRefs(channel));
if(NS_SUCCEEDED(res)) {
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel,&res));
if(NS_SUCCEEDED(res)) {
nsXPIDLCString method;
httpChannel->GetRequestMethod(getter_Copies(method));
if(method) {
if(!PL_strcasecmp(method, "POST"))
return NS_OK;
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aChannel,&res));
if (NS_SUCCEEDED(res)) {
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel,&res));
if (NS_SUCCEEDED(res)) {
nsXPIDLCString method;
httpChannel->GetRequestMethod(getter_Copies(method));
if (method) {
if (!PL_strcasecmp(method, "POST")) {
return NS_OK;
}
}
}
}
nsAutoString theDocShellKey;
theDocShellKey.AssignWithConversion("docshell"); // Key to find docshell from the bundle.
nsCOMPtr<nsIDocShell> docshell=nsnull;
res=bundle->GetDataFromBundle(theDocShellKey,getter_AddRefs(docshell));
if(NS_SUCCEEDED(res)) {
nsCOMPtr<nsIWebShellServices> wss=nsnull;
wss=do_QueryInterface(docshell,&res); // Query webshell service through docshell.
if(NS_SUCCEEDED(res)) {
nsCOMPtr<nsIDocShell> docshell(do_QueryInterface(aWebShell,&res));
if (NS_SUCCEEDED(res)) {
nsCOMPtr<nsIWebShellServices> wss;
wss = do_QueryInterface(docshell,&res); // Query webshell service through docshell.
if (NS_SUCCEEDED(res)) {
#ifndef DONT_INFORM_WEBSHELL
// ask the webshellservice to load the URL
if(NS_FAILED( res = wss->SetRendering(PR_FALSE) ))
rv=res;
// XXX nisheeth, uncomment the following two line to see the reent problem
else if(NS_FAILED(res = wss->StopDocumentLoad())){
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
else if(NS_FAILED(res = wss->ReloadDocument(charset, source))) {
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
else
rv = NS_ERROR_HTMLPARSER_STOPPARSING; // We're reloading a new document...stop loading the current.
#endif
// ask the webshellservice to load the URL
if (NS_FAILED( res = wss->SetRendering(PR_FALSE) ))
rv = res;
// XXX nisheeth, uncomment the following two line to see the reent problem
else if (NS_FAILED(res = wss->StopDocumentLoad())){
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
else if (NS_FAILED(res = wss->ReloadDocument(charset, source))) {
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
else {
rv = NS_ERROR_HTMLPARSER_STOPPARSING; // We're reloading a new document...stop loading the current.
}
#endif
}
}
//if our reload request is not accepted, we should tell parser to go on
}
//if our reload request is not accepted, we should tell parser to go on
if (rv != NS_ERROR_HTMLPARSER_STOPPARSING)
rv = NS_ERROR_HTMLPARSER_CONTINUE;

View File

@ -62,7 +62,8 @@ public:
*/
protected:
NS_IMETHOD NotifyWebShell(nsISupports* aDocumentID,
NS_IMETHOD NotifyWebShell(nsISupports* aWebShell,
nsISupports* aChannel,
const char* charset,
nsCharsetSource source);

View File

@ -53,6 +53,11 @@
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static eHTMLTags gTags[] =
{ eHTMLTag_instruction,
eHTMLTag_unknown
};
//-------------------------------------------------------------------------
nsXMLEncodingObserver::nsXMLEncodingObserver()
{
@ -79,16 +84,6 @@ NS_IMPL_QUERY_INTERFACE4(nsXMLEncodingObserver,
nsIXMLEncodingService,
nsISupportsWeakReference);
//-------------------------------------------------------------------------
NS_IMETHODIMP_(const char*) nsXMLEncodingObserver::GetTagNameAt(PRUint32 aTagIndex)
{
if (aTagIndex == 0) {
return "?XML";
}else {
return nsnull;
}
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsXMLEncodingObserver::Notify(
PRUint32 aDocumentID,
@ -184,7 +179,7 @@ NS_IMETHODIMP nsXMLEncodingObserver::Notify(
{
const char* charsetInCStr = preferred.ToNewCString();
if(nsnull != charsetInCStr) {
res = NotifyWebShell((nsISupports*)aDocumentID, charsetInCStr, kCharsetFromMetaTag );
res = NotifyWebShell(0,0, charsetInCStr, kCharsetFromMetaTag );
delete [] (char*)charsetInCStr;
return res;
}

View File

@ -56,10 +56,6 @@ public:
virtual ~nsXMLEncodingObserver();
/* methode for nsIElementObserver */
/*
* This method return the tag which the observer care about
*/
NS_IMETHOD_(const char*)GetTagNameAt(PRUint32 aTagIndex);
/*
* Subject call observer when the parser hit the tag
@ -73,8 +69,12 @@ public:
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(PRUint32 aDocumentID, const PRUnichar* aTag, PRUint32 numOfAttributes,
const PRUnichar* nameArray[], const PRUnichar* valueArray[]);
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag, const nsStringArray* keys, const nsStringArray* values)
{ return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* keys,
const nsStringArray* values)
{ return NS_ERROR_NOT_IMPLEMENTED; }
NS_DECL_ISUPPORTS

View File

@ -178,6 +178,14 @@ public:
*/
NS_IMETHOD NotifyError(const nsParserError* aError)=0;
/**
* This gets called by the parser to notify observers of
* the tag
*
* @param aErrorResult the error code
*/
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode)=0;
/**
* Flush all pending notifications so that the content model
* is in sync with the state of the sink.

View File

@ -61,11 +61,6 @@ class nsIElementObserver : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IELEMENTOBSERVER_IID; return iid; }
/*
* This method return the tag which the observer care about
*/
NS_IMETHOD_(const char*)GetTagNameAt(PRUint32 aTagIndex) = 0;
/*
* Subject call observer when the parser hit the tag
* @param aDocumentID- ID of the document
@ -82,8 +77,11 @@ public:
PRUint32 numOfAttributes, const PRUnichar* nameArray[],
const PRUnichar* valueArray[]) = 0;
NS_IMETHOD Notify(nsISupports* aDocumentID, const PRUnichar* aTag,
const nsStringArray* aKeys, const nsStringArray* aValues) = 0;
NS_IMETHOD Notify(nsISupports* aWebShell,
nsISupports* aChannel,
const PRUnichar* aTag,
const nsStringArray* aKeys,
const nsStringArray* aValues) = 0;
};

View File

@ -59,10 +59,6 @@
{0x355cbba0, 0xbf7d, 0x11d1, \
{0xaa, 0xd9, 0x00, 0x80, 0x5f, 0x8a, 0x3e, 0x14}}
// {8B6A98A0-260E-11d4-8153-0010A4E0C706}
#define NS_IPARSER_BUNDLE_IID \
{ 0x8b6a98a0, 0x260e, 0x11d4, { 0x81, 0x53, 0x0, 0x10, 0xa4, 0xe0, 0xc7, 0x6 } };
// {41421C60-310A-11d4-816F-000064657374}
#define NS_IDEBUG_DUMP_CONTENT_IID \
{ 0x41421c60, 0x310a, 0x11d4, { 0x81, 0x6f, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } };
@ -139,13 +135,6 @@ public:
NS_IMETHOD DumpContentModel()=0;
};
class nsISupportsParserBundle : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IPARSER_BUNDLE_IID; return iid; }
NS_IMETHOD GetDataFromBundle(const nsString& aKey,nsISupports** anObject)=0;
NS_IMETHOD SetDataIntoBundle(const nsString& aKey,nsISupports* anObject)=0;
};
/**
* This class defines the iparser interface. This XPCOM
* inteface is all that parser clients ever need to see.

View File

@ -41,11 +41,31 @@
#include "nsISupports.h"
#include "nsString.h"
#include "nsHTMLTags.h"
#include "nsIParserNode.h"
#include "nsIParser.h"
#include "nsVoidArray.h"
#include "nsIElementObserver.h"
#define NS_IPARSERSERVICE_IID \
{ 0xa6cf9111, 0x15b3, 0x11d2, \
{ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } }
// {78081E70-AD53-11d5-8498-0010A4E0C706}
#define NS_IOBSERVERENTRY_IID \
{ 0x78081e70, 0xad53, 0x11d5, { 0x84, 0x98, 0x0, 0x10, 0xa4, 0xe0, 0xc7, 0x6 } };
class nsIObserverEntry : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IOBSERVERENTRY_IID)
NS_IMETHOD Notify(nsIParserNode* aNode,
nsIParser* aParser,
nsISupports* aWebShell) = 0;
};
class nsIParserService : public nsISupports {
public:
@ -65,6 +85,17 @@ class nsIParserService : public nsISupports {
NS_IMETHOD IsContainer(PRInt32 aId, PRBool& aIsContainer) const =0;
NS_IMETHOD IsBlock(PRInt32 aId, PRBool& aIsBlock) const =0;
// Observer mechanism
NS_IMETHOD RegisterObserver(nsIElementObserver* aObserver,
const nsAString& aTopic,
const eHTMLTags* aTags = nsnull) = 0;
NS_IMETHOD UnregisterObserver(nsIElementObserver* aObserver,
const nsAString& aTopic) = 0;
NS_IMETHOD GetTopicObservers(const nsAString& aTopic,
nsIObserverEntry** aEntry) = 0;
};
#endif // nsIParserService_h__

View File

@ -107,6 +107,7 @@ public:
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
NS_IMETHOD DidProcessAToken(void) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
NS_IMETHOD DoFragment(PRBool aFlag);
NS_IMETHOD BeginContext(PRInt32 aPosition){ return NS_OK; }

View File

@ -59,7 +59,6 @@
#include "nsTagHandler.h"
#include "nsHTMLTokenizer.h"
#include "nsTime.h"
#include "nsIElementObserver.h"
#include "nsViewSourceHTML.h"
#include "nsParserNode.h"
#include "nsHTMLEntities.h"
@ -189,7 +188,7 @@ CNavDTD::CNavDTD() : nsIDTD(),
mLineNumber(1)
{
NS_INIT_REFCNT();
mBodyContext=new nsDTDContext();
#ifdef RICKG_DEBUG
@ -198,7 +197,6 @@ CNavDTD::CNavDTD() : nsIDTD(),
nsHTMLElement::DebugDumpMembership("c:/temp/membership.out");
nsHTMLElement::DebugDumpContainType("c:/temp/ctnrules.out");
#endif
}
/**
@ -1377,13 +1375,8 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode
STOP_TIMER()
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));
if(mParser) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
const nsISupportsParserBundle* bundle=mParser->GetParserBundle();
result=theService->Notify(aTag,aNode,(void*)bundle, mMimeType, mParser);
}
if (aTag <= NS_HTML_TAG_MAX) {
result = mSink->NotifyTagObservers(&aNode);
}
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));

View File

@ -57,7 +57,6 @@
#include "nsTagHandler.h"
#include "nsHTMLTokenizer.h"
#include "nsTime.h"
#include "nsIElementObserver.h"
#include "nsViewSourceHTML.h"
#include "nsParserNode.h"
#include "nsHTMLEntities.h"
@ -70,7 +69,7 @@ static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kClassIID, NS_IOTHERHTML_DTD_IID);
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
static char* kVerificationDir = "c:/temp";
@ -640,12 +639,7 @@ nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNo
default:
break;
}
CObserverService* theService=mParser->GetObserverService();
if(theService) {
const nsISupportsParserBundle* bundle=mParser->GetParserBundle();
result=theService->Notify(aTag,aNode,(void*)bundle, NS_ConvertASCIItoUCS2(kHTMLTextContentType), mParser);
}
mSink->NotifyTagObservers(&aNode);
}
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: COtherDTD::WillHandleStartTag(), this=%p\n", this));

View File

@ -68,6 +68,7 @@ CPPSRCS = \
nsHTMLTokens.cpp \
nsParser.cpp \
CParserContext.cpp \
nsParserService.cpp \
nsParserModule.cpp \
nsParserNode.cpp \
nsScanner.cpp \

View File

@ -62,6 +62,7 @@ CPPSRCS = \
nsToken.cpp \
nsWellFormedDTD.cpp \
nsViewSourceHTML.cpp\
nsParserService.cpp \
nsParserModule.cpp \
nsParserMsgUtils.cpp \
!ifdef MOZ_DEBUG
@ -87,6 +88,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsToken.obj \
.\$(OBJDIR)\nsWellFormedDTD.obj \
.\$(OBJDIR)\nsViewSourceHTML.obj\
.\$(OBJDIR)\nsParserService.obj \
.\$(OBJDIR)\nsParserModule.obj \
.\$(OBJDIR)\nsParserMsgUtils.obj \
!ifdef MOZ_DEBUG

View File

@ -42,18 +42,14 @@
#include "CNavDTD.h"
#include "nsIParserNode.h"
#include "nsParserNode.h"
#include "nsIChannel.h"
#include "nsIServiceManager.h"
nsIObserverService *CObserverService::gObserverService = NULL;
MOZ_DECL_CTOR_COUNTER(nsEntryStack)
MOZ_DECL_CTOR_COUNTER(nsDTDContext)
MOZ_DECL_CTOR_COUNTER(nsTokenAllocator)
MOZ_DECL_CTOR_COUNTER(CNodeRecycler)
MOZ_DECL_CTOR_COUNTER(CObserverService)
/**************************************************************************************
A few notes about how residual style handling is performed:
@ -1477,313 +1473,131 @@ PRUint32 AccumulateCRC(PRUint32 crc_accum, char *data_blk_ptr, int data_blk_size
return crc_accum;
}
/**************************************************************
Define the nsIElementObserver release class...
**************************************************************/
class nsObserverReleaser: public nsDequeFunctor{
public:
virtual void* operator()(void* anObject) {
nsIElementObserver* theObserver= (nsIElementObserver*)anObject;
NS_RELEASE(theObserver);
return 0;
}
};
/**************************************************************
This defines the topic object used by the observer service.
The observerService uses a list of these, 1 per topic when
registering tags.
**************************************************************/
NS_IMPL_ISUPPORTS1(nsObserverEntry, nsIObserverEntry)
nsObserverTopic::nsObserverTopic(const nsString& aTopic) : mTopic(aTopic) {
nsCRT::zero(mObservers,sizeof(mObservers));
mCharsetKey.AssignWithConversion("charset");
mSourceKey.AssignWithConversion("charsetSource");
mDTDKey.AssignWithConversion("X_COMMAND");
nsObserverEntry::nsObserverEntry(const nsAString& aTopic) : mTopic(aTopic)
{
NS_INIT_ISUPPORTS();
nsCRT::zero(mObservers,sizeof(mObservers));
}
nsObserverTopic::~nsObserverTopic() {
nsObserverReleaser theReleaser;
PRInt32 theIndex=0;
for(theIndex=0;theIndex<=NS_HTML_TAG_MAX;theIndex++){
if(mObservers[theIndex]){
mObservers[theIndex]->ForEach(theReleaser);
delete mObservers[theIndex];
mObservers[theIndex]=0;
nsObserverEntry::~nsObserverEntry() {
for (PRInt32 i = 0; i <= NS_HTML_TAG_MAX; i++){
if (mObservers[i]) {
PRInt32 count = mObservers[i]->Count();
for (PRInt32 j = 0; j < count; j++) {
nsISupports* obs = (nsISupports*)mObservers[i]->ElementAt(j);
NS_IF_RELEASE(obs);
}
delete mObservers[i];
}
}
}
PRBool nsObserverTopic::Matches(const nsString& aString) {
PRBool result=aString.Equals(mTopic);
return result;
}
NS_IMETHODIMP
nsObserverEntry::Notify(nsIParserNode* aNode,
nsIParser* aParser,
nsISupports* aWebShell)
{
NS_ENSURE_ARG_POINTER(aNode);
NS_ENSURE_ARG_POINTER(aParser);
nsDeque* nsObserverTopic::GetObserversForTag(eHTMLTags aTag) {
if(aTag <= NS_HTML_TAG_MAX) {
return mObservers[aTag];
}
return 0;
}
nsresult result = NS_OK;
eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
if (theTag <= NS_HTML_TAG_MAX) {
nsVoidArray* theObservers = mObservers[theTag];
if (theObservers) {
nsAutoString theCharsetValue;
nsCharsetSource theCharsetSource;
aParser->GetDocumentCharset(theCharsetValue,theCharsetSource);
void nsObserverTopic::RegisterObserverForTag(nsIElementObserver *anObserver,eHTMLTags aTag) {
if(anObserver) {
if(mObservers[aTag] == nsnull) {
mObservers[aTag] = new nsDeque(0);
}
NS_ADDREF(anObserver);
mObservers[aTag]->Push(anObserver);
}
}
PRInt32 theAttrCount = aNode->GetAttributeCount();
PRInt32 theObserversCount = theObservers->Count();
if (0 < theObserversCount){
nsStringArray keys(theAttrCount+4), values(theAttrCount+4);
/**
* This method will notify observers registered for specific tags.
*
* @update harishd 08/29/99
* @param aTag - The tag for which observers could be waiting for.
* @param aNode -
* @param aUniqueID - The document ID.
* @param aDTD - The current DTD.
* @param aCharsetValue -
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser) {
nsresult result=NS_OK;
// XXX this and the following code may be a performance issue.
// Every key and value is copied and added to an voidarray (causing at
// least 2 allocations for mImpl, usually more, plus at least 1 per
// string (total = 2*(keys+3) + 2(or more) array allocations )).
PRInt32 index;
for (index = 0; index < theAttrCount; index++) {
keys.AppendString(aNode->GetKeyAt(index));
values.AppendString(aNode->GetValueAt(index));
}
nsDeque* theObservers=GetObserversForTag(aTag);
if(theObservers){
nsAutoString intValue;
nsAutoString theCharsetValue;
nsCharsetSource theCharsetSource;
aParser->GetDocumentCharset(theCharsetValue,theCharsetSource);
PRInt32 theAttrCount =aNode.GetAttributeCount();
PRInt32 theObserversCount=theObservers->GetSize();
if(0<theObserversCount){
nsStringArray keys(theAttrCount+4),values(theAttrCount+4);
// XXX this and the following code may be a performance issue.
// Every key and value is copied and added to an voidarray (causing at
// least 2 allocations for mImpl, usually more, plus at least 1 per
// string (total = 2*(keys+3) + 2(or more) array allocations )).
PRInt32 index;
for(index=0; index<theAttrCount; index++) {
keys.AppendString(aNode.GetKeyAt(index));
values.AppendString(aNode.GetValueAt(index));
}
nsAutoString intValue;
keys.AppendString(mCharsetKey);
values.AppendString(theCharsetValue);
keys.AppendString(NS_LITERAL_STRING("charset"));
values.AppendString(theCharsetValue);
keys.AppendString(mSourceKey);
intValue.AppendInt(PRInt32(theCharsetSource),10);
values.AppendString(intValue);
keys.AppendString(NS_LITERAL_STRING("charsetSource"));
intValue.AppendInt(PRInt32(theCharsetSource),10);
values.AppendString(intValue);
keys.AppendString(mDTDKey);
values.AppendString(mTopic);
keys.AppendString(NS_LITERAL_STRING("X_COMMAND"));
values.AppendString(NS_LITERAL_STRING("text/html"));
nsAutoString theTagStr; theTagStr.AssignWithConversion(nsHTMLTags::GetStringValue(aTag));
for(index=0;index<theObserversCount;index++) {
nsIElementObserver* observer=NS_STATIC_CAST(nsIElementObserver*,theObservers->ObjectAt(index));
if(observer) {
result=observer->Notify((nsISupports*)aUniqueID,theTagStr.get(),&keys,&values);
if(NS_FAILED(result)) {
break;
nsAutoString theTagStr;
theTagStr.AssignWithConversion(nsHTMLTags::GetStringValue(theTag));
nsCOMPtr<nsIChannel> channel;
aParser->GetChannel(getter_AddRefs(channel));
for (index=0;index<theObserversCount;index++) {
nsIElementObserver* observer = NS_STATIC_CAST(nsIElementObserver*,theObservers->ElementAt(index));
if (observer) {
result = observer->Notify(aWebShell,channel,theTagStr.get(),&keys,&values);
if (NS_FAILED(result)) {
break;
}
}
}
}
}
}//if
}
}
}
return result;
}
PRBool
nsObserverEntry::Matches(const nsAString& aString) {
PRBool result = aString.Equals(mTopic);
return result;
}
/******************************************************************************
This class is used to store ref's to tag observers during the parse phase.
Note that for simplicity, this is a singleton that is constructed in the
CNavDTD and shared for the duration of the application session. Later on it
might be nice to use a more dynamic approach that would permit observers to
come and go on a document basis.
I changed the observerservice to store topics so that we can distinguish
observers by topic. Up till now, they've all just be thrown into the same
observer list, which was wrong. This fixes bug #28825.
******************************************************************************/
nsresult
CObserverService::InitGlobals() {
if (!gObserverService) {
nsresult rv = NS_OK;
nsCOMPtr<nsIObserverService> obs(do_GetService(NS_OBSERVERSERVICE_CONTRACTID,&rv));
if (NS_SUCCEEDED(rv)) {
gObserverService = obs.get();
NS_IF_ADDREF(gObserverService);
nsObserverEntry::AddObserver(nsIElementObserver *aObserver,
eHTMLTags aTag)
{
if (aObserver) {
if (!mObservers[aTag]) {
mObservers[aTag] = new nsAutoVoidArray();
if (!mObservers[aTag]) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
NS_ADDREF(aObserver);
mObservers[aTag]->AppendElement(aObserver);
}
return NS_OK;
}
void
CObserverService::ReleaseGlobals() {
NS_IF_RELEASE(gObserverService);
}
CObserverService::CObserverService() : mTopics(0) {
MOZ_COUNT_CTOR(CObserverService);
nsAutoString theHTMLTopic; theHTMLTopic.AssignWithConversion(kHTMLTextContentType);
RegisterObservers(theHTMLTopic);
nsAutoString theXMLTopic; theXMLTopic.AssignWithConversion(kXMLTextContentType); //use the mimetype for the topic
RegisterObservers(theXMLTopic);
theXMLTopic.AssignWithConversion(kXMLApplicationContentType);
RegisterObservers(theXMLTopic);
theXMLTopic.AssignWithConversion(kXHTMLApplicationContentType);
RegisterObservers(theXMLTopic);
}
CObserverService::~CObserverService() {
MOZ_COUNT_DTOR(CObserverService);
nsObserverTopic *theTopic=(nsObserverTopic*)mTopics.Pop();
while(theTopic) {
delete theTopic;
theTopic=(nsObserverTopic*)mTopics.Pop();
}
}
// XXX This may be more efficient as a HashTable instead of linear search
nsObserverTopic* CObserverService::GetTopic(const nsString& aTopic) {
PRInt32 theIndex=0;
nsObserverTopic *theTopic=(nsObserverTopic*)mTopics.ObjectAt(theIndex++);
while(theTopic) {
if(theTopic->Matches(aTopic))
return theTopic;
theTopic=(nsObserverTopic*)mTopics.ObjectAt(theIndex++);
}
return 0;
}
nsObserverTopic* CObserverService::CreateTopic(const nsString& aTopic) {
nsObserverTopic* theTopic=new nsObserverTopic(aTopic);
mTopics.Push(theTopic);
return theTopic;
}
/**
* This method will maintain lists of observers registered for specific tags.
*
* @update rickg 03.23.2000
* @param aTopic - The topic under which observers register for.
* @return if SUCCESS return NS_OK else return ERROR code.
*/
void CObserverService::RegisterObservers(const nsString& aTopic) {
nsresult result = NS_OK;
if (gObserverService) {
nsIEnumerator* theEnum = nsnull;
result = gObserverService->EnumerateObserverList(aTopic.get(), &theEnum);
if(result == NS_OK) {
nsCOMPtr<nsIElementObserver> theElementObserver;
nsISupports *inst = nsnull;
nsObserverTopic *theTopic=0;
for (theEnum->First(); theEnum->IsDone() != NS_OK; theEnum->Next()) {
result = theEnum->CurrentItem(&inst);
if (NS_SUCCEEDED(result)) {
theElementObserver = do_QueryInterface(inst, &result);
NS_RELEASE(inst);
}
if (result == NS_OK) {
const char* theTagStr = nsnull;
PRUint32 theTagIndex = 0;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
while (theTagStr != nsnull) {
eHTMLTags theTag = nsHTMLTags::LookupTag(nsCAutoString(theTagStr));
if((eHTMLTag_userdefined!=theTag) && (theTag <= NS_HTML_TAG_MAX)){
theTopic=GetTopic(aTopic);
if(!theTopic)
theTopic=CreateTopic(aTopic);
if(theTopic) {
theTopic->RegisterObserverForTag(theElementObserver,theTag);
}
}
theTagIndex++;
theTagStr = theElementObserver->GetTagNameAt(theTagIndex);
}
}
void
nsObserverEntry::RemoveObserver(nsIElementObserver *aObserver)
{
for (PRInt32 i=0; i <= NS_HTML_TAG_MAX; i++){
if (mObservers[i]) {
nsISupports* obs = aObserver;
PRBool removed = mObservers[i]->RemoveElement(obs);
if (removed) {
NS_RELEASE(obs);
}
}
NS_IF_RELEASE(theEnum);
}
}
/**
* This method will maintain lists of observers registered for specific tags.
*
* @update rickg 03.23.2000
* @param aTopic - The topic under which observers register for.
* @return if SUCCESS return NS_OK else return ERROR code.
*/
void CObserverService::UnregisterObservers(const nsString& aTopic) {
}
/**
* This method will notify observers registered for specific tags.
*
* @update rickg 03.23.2000
* @param aTag - The tag for which observers could be waiting for.
* @param aNode -
* @param aUniqueID - The document ID.
* @param aDTD - The current DTD.
* @param aCharsetValue -
* @param aCharsetSource -
* @return if SUCCESS return NS_OK else return ERROR code.
*/
nsresult CObserverService::Notify( eHTMLTags aTag,
nsIParserNode& aNode,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser) {
nsresult result=NS_OK;
nsObserverTopic *theTopic=GetTopic(aTopic);
if(theTopic) {
result=theTopic->Notify(aTag,aNode,aUniqueID,aParser);
}
return result;
}
/**
* This method will look for the list of observers registered for
* a specific tag.
*
* @update rickg 03.23.2000
* @param aTag - The tag for which observers could be waiting for.
* @return if FOUND return "observer list" else return nsnull;
*
*/
nsDeque* CObserverService::GetObserversForTagInTopic(eHTMLTags aTag,const nsString& aTopic) {
nsObserverTopic *theTopic=GetTopic(aTopic);
if(theTopic) {
return theTopic->GetObserversForTag(aTag);
}
return 0;
}

View File

@ -56,11 +56,10 @@
#include "nsIDTD.h"
#include "nsITokenizer.h"
#include "nsString.h"
#include "nsIElementObserver.h"
#include "nsIParserNode.h"
#include "nsFixedSizeAllocator.h"
#include "nsVoidArray.h"
#include "nsIObserverService.h"
#include "nsIParserService.h"
#define IF_HOLD(_ptr) \
PR_BEGIN_MACRO \
@ -533,53 +532,23 @@ struct CRCStruct {
registering tags.
**************************************************************/
class nsObserverTopic {
class nsObserverEntry : public nsIObserverEntry {
public:
nsObserverTopic(const nsString& aTopic);
~nsObserverTopic();
PRBool Matches(const nsString& aTopic);
void RegisterObserverForTag(nsIElementObserver *anObserver,eHTMLTags aTag);
nsDeque* GetObserversForTag(eHTMLTags aTag);
nsresult Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniqueID,nsIParser* aParser);
NS_DECL_ISUPPORTS
nsObserverEntry(const nsAString& aTopic);
virtual ~nsObserverEntry();
nsString mTopic;
nsString mCharsetKey;
nsString mSourceKey;
nsString mDTDKey;
nsDeque* mObservers[NS_HTML_TAG_MAX + 1];
};
NS_IMETHOD Notify(nsIParserNode* aNode,
nsIParser* aParser,
nsISupports* aWebShell);
/******************************************************************************
This class is used to store ref's to token observers during the parse phase.
Note that for simplicity, this is a singleton that is constructed in the
CNavDTD and shared for the duration of the application session. Later on it
might be nice to use a more dynamic approach that would permit observers to
come and go on a document basis.
******************************************************************************/
class CObserverService {
public:
CObserverService();
~CObserverService();
nsDeque* GetObserversForTagInTopic(eHTMLTags aTag,const nsString& aTopic);
nsresult Notify( eHTMLTags aTag,
nsIParserNode& aNode,
void* aUniqueID,
const nsString& aTopic,
nsIParser* aParser);
nsObserverTopic* GetTopic(const nsString& aTopic);
nsObserverTopic* CreateTopic(const nsString& aTopic);
// Do allocation and release of gObserverService
// These are called from the module init and shutdown
static nsresult InitGlobals();
static void ReleaseGlobals();
nsresult AddObserver(nsIElementObserver* aObserver,eHTMLTags aTag);
void RemoveObserver(nsIElementObserver* aObserver);
PRBool Matches(const nsAString& aTopic);
protected:
void RegisterObservers(const nsString& aTopic);
void UnregisterObservers(const nsString& aTopic);
nsDeque mTopics; //each topic holds a list of observers per tag.
static nsIObserverService *gObserverService;
nsString mTopic;
nsVoidArray* mObservers[NS_HTML_TAG_MAX + 1];
};
/*********************************************************************************************/

View File

@ -72,6 +72,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() {return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset) {return NS_OK;}
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue);

View File

@ -74,6 +74,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue);

View File

@ -356,7 +356,6 @@ nsParser::nsParser(nsITokenObserver* anObserver) {
mObserversEnabled=PR_TRUE;
mCommand=eViewNormal;
mParserEnabled=PR_TRUE;
mBundle=nsnull;
mPendingContinueEvent=PR_FALSE;
mCanInterrupt=PR_FALSE;
@ -405,7 +404,6 @@ nsParser::~nsParser() {
NS_IF_RELEASE(mProgressEventSink);
NS_IF_RELEASE(mSink);
NS_IF_RELEASE(mParserFilter);
NS_IF_RELEASE(mBundle);
//don't forget to add code here to delete
//what may be several contexts...
@ -456,9 +454,6 @@ nsresult nsParser::QueryInterface(const nsIID& aIID, void** aInstancePtr)
else if(aIID.Equals(kCParserCID)) { //do this class...
*aInstancePtr = (nsParser*)(this);
}
else if(aIID.Equals(NS_GET_IID(nsISupportsParserBundle))) {
*aInstancePtr = (nsISupportsParserBundle*)(this);
}
else {
*aInstancePtr=0;
return NS_NOINTERFACE;
@ -1031,7 +1026,7 @@ static void VerifyPublicIDs()
NS_NOTREACHED("doctype not lower case");
printf("Doctype %s not lower case.\n", kPublicIDs[i].name);
}
}
}
}
}
#endif
@ -1422,7 +1417,6 @@ nsresult nsParser::DidBuildModel(nsresult anErrorCode) {
result = mParserContext->mDTD->DidBuildModel(anErrorCode,PRBool(0==mParserContext->mPrevContext),this,mSink);
}
//Ref. to bug 61462.
NS_IF_RELEASE(mBundle);
}//if
}
@ -2725,133 +2719,4 @@ nsParser::GetDTD(nsIDTD** aDTD)
}
return NS_OK;
}
/**
* Get the observer service
*
* @update rickg 11/22/99
* @return ptr to server or NULL
*/
CObserverService* nsParser::GetObserverService(void) {
//XXX Hack! this should be XPCOM based!
if(mObserversEnabled)
return &mObserverService;
return 0;
}
/**
* Store data into the bundle.
*
* @update harishd 05/10/00
* @param aData - The data to be stored.
* @return NS_OK if all went well else ERROR.
*/
NS_IMETHODIMP
nsParser::SetDataIntoBundle(const nsString& aKey,nsISupports* anObject) {
nsresult result=NS_OK;
if(!mBundle) {
mBundle = new nsParserBundle();
if(mBundle==nsnull) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mBundle);
}
result=mBundle->SetDataIntoBundle(aKey,anObject);
return result;
}
/**
* Retrieve data from the bundle by IID.
* NOTE: The object retireved should not be released
*
* @update harishd 05/10/00
* @param aIID - The ID to identify the correct object in the bundle
* @return Return object if found in bundle else return NULL.
*/
NS_IMETHODIMP
nsParser::GetDataFromBundle(const nsString& aKey,nsISupports** anObject) {
nsresult result=NS_OK;
result=mBundle->GetDataFromBundle(aKey,anObject);
return result;
}
NS_IMPL_ISUPPORTS1(nsParserBundle,
nsISupportsParserBundle
);
/**
* Release data from the Hash table
*
* @update harishd 05/10/00
*/
static PRBool PR_CALLBACK ReleaseData(nsHashKey* aKey, void* aData, void* aClosure) {
nsISupports* object = (nsISupports*)aData;
NS_RELEASE(object);
return PR_TRUE;
}
/**
*
* @update harishd 05/10/00
*/
nsParserBundle::nsParserBundle (){
NS_INIT_REFCNT();
mData=new nsHashtable(5);
}
/**
* Release objects from the bundle.
*
* @update harishd 05/10/00
*/
nsParserBundle::~nsParserBundle () {
mData->Enumerate(ReleaseData);
delete mData;
}
/**
* Store data into the bundle.
*
* @update harishd 05/10/00
* @param aData - The data to be stored.
* @return NS_OK if all went well else ERROR.
*/
NS_IMETHODIMP
nsParserBundle::SetDataIntoBundle(const nsString& aKey,nsISupports* anObject) {
nsresult result=NS_OK;
if(anObject) {
nsStringKey key(aKey);
PRBool found=mData->Exists(&key);
if(!found) {
NS_ADDREF(anObject);
mData->Put(&key,anObject);
}
}
return result;
}
/**
* Retrieve data from the bundle by IID.
* NOTE: The object retrieved should not be released.
*
* @update harishd 05/10/00
* @param aIID - The ID to identify the correct object in the bundle
* @return Return object if found in bundle else return NULL.
*/
NS_IMETHODIMP
nsParserBundle::GetDataFromBundle(const nsString& aKey,nsISupports** anObject) {
nsresult result=NS_OK;
nsStringKey key(aKey);
*anObject=(mData)? (nsISupports*)mData->Get(&key):nsnull;
if(*anObject) {
NS_ADDREF(*anObject);
}
else{
result=NS_ERROR_NULL_POINTER;
}
return result;
}
}

View File

@ -93,7 +93,6 @@ class nsIDTD;
class nsScanner;
class nsIParserFilter;
class nsIProgressEventSink;
class nsParserBundle;
#ifdef XP_WIN
#pragma warning( disable : 4275 )
@ -101,7 +100,6 @@ class nsParserBundle;
class nsParser : public nsIParser,
public nsISupportsParserBundle,
public nsIStreamListener{
@ -287,8 +285,6 @@ class nsParser : public nsIParser,
CParserContext* PopContext();
CParserContext* PeekContext() {return mParserContext;}
const nsParserBundle* GetParserBundle() { return mBundle; }
/**
*
* @update gess 1/22/99
@ -320,20 +316,7 @@ class nsParser : public nsIParser,
* @return NS_OK if successful, NS_ERROR_FAILURE for runtime error
*/
NS_IMETHOD GetDTD(nsIDTD** aDTD);
/**
* Call this to access observer dictionary ( internal to parser )
* @update harishd 06/27/99
* @param
* @return
*/
CObserverService* GetObserverService(void);
// nsISupportsParserBundle
NS_IMETHOD GetDataFromBundle(const nsString& aKey,nsISupports** anObject);
NS_IMETHOD SetDataIntoBundle(const nsString& aKey,nsISupports* anObject);
/**
* Call this method to determine a DTD for a DOCTYPE
*
@ -490,11 +473,9 @@ protected:
nsString mCharset;
nsCharsetSource mCharsetSource;
nsresult mInternalState;
CObserverService mObserverService;
PRBool mObserversEnabled;
nsString mCommandStr;
PRBool mParserEnabled;
nsParserBundle* mBundle;
nsTokenAllocator mTokenAllocator;
nsCOMPtr<nsIEventQueue> mEventQueue;
@ -508,37 +489,5 @@ public:
MOZ_TIMER_DECLARE(mTokenizeTime)
};
// -----------------------------------------------------------------
class nsParserBundle : public nsISupportsParserBundle {
public:
NS_DECL_ISUPPORTS
nsParserBundle ();
virtual ~nsParserBundle ();
/**
* Retrieve data from the bundle by IID.
*
* @update harishd 05/10/00
* @param aIID - The ID to identify the correct object in the bundle
* @return Return object if found in bundle else return NULL.
*/
NS_IMETHOD GetDataFromBundle(const nsString& aKey,nsISupports** anObject);
/**
* Store data into the bundle.
*
* @update harishd 05/10/00
* @param aData - The data to be stored.
* @return NS_OK if all went well else ERROR.
*/
NS_IMETHOD SetDataIntoBundle(const nsString& aKey,nsISupports* anObject);
protected:
nsHashtable* mData;
};
#endif

View File

@ -53,115 +53,13 @@
#include "nsHTMLTokenizer.h"
//#include "nsTextTokenizer.h"
#include "nsExpatTokenizer.h"
#include "nsIParserService.h"
#include "nsElementTable.h"
#include "nsParserService.h"
#ifdef NS_DEBUG
#include "nsLoggingSink.h"
#endif
class nsParserService : public nsIParserService {
public:
nsParserService();
virtual ~nsParserService();
NS_DECL_ISUPPORTS
NS_IMETHOD HTMLAtomTagToId(nsIAtom* aAtom, PRInt32* aId) const;
NS_IMETHOD HTMLStringTagToId(const nsString &aTag, PRInt32* aId) const;
NS_IMETHOD HTMLIdToStringTag(PRInt32 aId, nsString& aTag) const;
NS_IMETHOD HTMLConvertEntityToUnicode(const nsString& aEntity,
PRInt32* aUnicode) const;
NS_IMETHOD HTMLConvertUnicodeToEntity(PRInt32 aUnicode,
nsCString& aEntity) const;
NS_IMETHOD IsContainer(PRInt32 aId, PRBool& aIsContainer) const;
NS_IMETHOD IsBlock(PRInt32 aId, PRBool& aIsBlock) const;
};
nsParserService::nsParserService()
{
NS_INIT_ISUPPORTS();
}
nsParserService::~nsParserService()
{
}
NS_IMPL_ISUPPORTS1(nsParserService, nsIParserService)
NS_IMETHODIMP
nsParserService::HTMLAtomTagToId(nsIAtom* aAtom, PRInt32* aId) const
{
NS_ENSURE_ARG_POINTER(aAtom);
nsAutoString tagName;
aAtom->ToString(tagName);
*aId = nsHTMLTags::LookupTag(tagName);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLStringTagToId(const nsString &aTag, PRInt32* aId) const
{
*aId = nsHTMLTags::LookupTag(aTag);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLIdToStringTag(PRInt32 aId, nsString& aTag) const
{
aTag.AssignWithConversion( nsHTMLTags::GetStringValue((nsHTMLTag)aId) );
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLConvertEntityToUnicode(const nsString& aEntity,
PRInt32* aUnicode) const
{
*aUnicode = nsHTMLEntities::EntityToUnicode(aEntity);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::HTMLConvertUnicodeToEntity(PRInt32 aUnicode,
nsCString& aEntity) const
{
const char* str = nsHTMLEntities::UnicodeToEntity(aUnicode);
if (str) {
aEntity.Assign(str);
}
return NS_OK;
}
NS_IMETHODIMP
nsParserService::IsContainer(PRInt32 aId, PRBool& aIsContainer) const
{
aIsContainer = nsHTMLElement::IsContainer((eHTMLTags)aId);
return NS_OK;
}
NS_IMETHODIMP
nsParserService::IsBlock(PRInt32 aId, PRBool& aIsBlock) const
{
if((aId>eHTMLTag_unknown) && (aId<eHTMLTag_userdefined)) {
aIsBlock=((gHTMLElements[aId].IsMemberOf(kBlock)) ||
(gHTMLElements[aId].IsMemberOf(kBlockEntity)) ||
(gHTMLElements[aId].IsMemberOf(kHeading)) ||
(gHTMLElements[aId].IsMemberOf(kPreformatted))||
(gHTMLElements[aId].IsMemberOf(kList)));
}
else {
aIsBlock = PR_FALSE;
}
return NS_OK;
}
//----------------------------------------------------------------------
#ifdef NS_DEBUG
@ -203,7 +101,6 @@ Initialize(nsIModule* aSelf)
nsHTMLEntities::AddRefTable();
InitializeElementTable();
CNewlineToken::AllocNewline();
CObserverService::InitGlobals();
gInitialized = PR_TRUE;
}
return NS_OK;
@ -219,7 +116,6 @@ Shutdown(nsIModule* aSelf)
nsParser::FreeSharedObjects();
DeleteElementTable();
CNewlineToken::FreeNewline();
CObserverService::ReleaseGlobals();
gInitialized = PR_FALSE;
}
}

View File

@ -80,17 +80,16 @@
#include "prtypes.h" //this is here for debug reasons...
#include "prio.h"
#include "plstr.h"
#include "prmem.h"
#ifdef RAPTOR_PERF_METRICS
#include "stopwatch.h"
Stopwatch vsTimer;
#endif
static NS_DEFINE_IID(kClassIID, NS_VIEWSOURCE_HTML_IID);
static NS_DEFINE_IID(kClassIID, NS_VIEWSOURCE_HTML_IID);
static int gErrorThreshold = 10;
// Define this to dump the viewsource stuff to a file
@ -1099,12 +1098,7 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) {
else result=WriteTag(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE);
if((ePlainText!=mDocType) && mParser && (NS_OK==result)) {
CObserverService* theService=mParser->GetObserverService();
if(theService) {
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
const nsISupportsParserBundle* bundle=mParser->GetParserBundle();
result=theService->Notify(theTag,theContext.mTokenNode,(void*)bundle, mMimeType, mParser);
}
result = mSink->NotifyTagObservers(&theContext.mTokenNode);
}
}
break;

View File

@ -31,7 +31,6 @@ OBJS = \
LLIBS= \
$(DIST)\lib\gkparser.lib \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR) \
$(NULL)

View File

@ -184,6 +184,7 @@ public:
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode=0);
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
NS_IMETHOD SetDocumentCharset(nsAWritableString& aCharset) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
// nsIXMLContentSink
NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode);