зеркало из https://github.com/mozilla/pjs.git
bug 263053: Get rid of the <endnote> tag when parsing fragments with context, since this can fail if the input stream contains another <endnote> tag. Instead, parse the context in different "chunks" from the new buffer, and notify the fragment sink by way of functions. r=peterv sr=bzbarsky
This commit is contained in:
Родитель
da55bc0cf2
Коммит
1983dc1a52
|
@ -137,7 +137,6 @@ HTML_ATOM(em, "em")
|
|||
HTML_ATOM(embed, "embed")
|
||||
HTML_ATOM(encoding, "encoding")
|
||||
HTML_ATOM(enctype, "enctype")
|
||||
HTML_ATOM(endnote, "endnote") // contextual fragments
|
||||
HTML_ATOM(_event, "event")
|
||||
HTML_ATOM(face, "face")
|
||||
HTML_ATOM(fieldset, "fieldset")
|
||||
|
|
|
@ -123,6 +123,8 @@ public:
|
|||
// nsIFragmentContentSink
|
||||
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment);
|
||||
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
|
||||
NS_IMETHOD WillBuildContent();
|
||||
NS_IMETHOD DidBuildContent();
|
||||
|
||||
nsIContent* GetCurrentContent();
|
||||
PRInt32 PushContent(nsIContent *aContent);
|
||||
|
@ -140,13 +142,12 @@ public:
|
|||
|
||||
nsresult Init();
|
||||
|
||||
PRBool mHitSentinel;
|
||||
PRBool mSeenBody;
|
||||
PRPackedBool mAllContent;
|
||||
PRPackedBool mProcessing;
|
||||
PRPackedBool mSeenBody;
|
||||
|
||||
nsIContent* mRoot;
|
||||
nsIParser* mParser;
|
||||
nsIDOMHTMLFormElement* mCurrentForm;
|
||||
nsGenericHTMLElement* mCurrentMap;
|
||||
nsCOMPtr<nsIContent> mRoot;
|
||||
nsCOMPtr<nsIParser> mParser;
|
||||
|
||||
nsVoidArray* mContentStack;
|
||||
|
||||
|
@ -192,22 +193,14 @@ NS_NewHTMLFragmentContentSink(nsIFragmentContentSink** aResult)
|
|||
}
|
||||
|
||||
nsHTMLFragmentContentSink::nsHTMLFragmentContentSink(PRBool aAllContent)
|
||||
: mAllContent(aAllContent),
|
||||
mProcessing(aAllContent),
|
||||
mSeenBody(!aAllContent),
|
||||
mContentStack(nsnull),
|
||||
mText(nsnull),
|
||||
mTextLength(0),
|
||||
mTextSize(0)
|
||||
{
|
||||
if (aAllContent) {
|
||||
mHitSentinel = PR_TRUE;
|
||||
mSeenBody = PR_FALSE;
|
||||
} else {
|
||||
mHitSentinel = PR_FALSE;
|
||||
mSeenBody = PR_TRUE;
|
||||
}
|
||||
mRoot = nsnull;
|
||||
mParser = nsnull;
|
||||
mCurrentForm = nsnull;
|
||||
mCurrentMap = nsnull;
|
||||
mContentStack = nsnull;
|
||||
mText = nsnull;
|
||||
mTextLength = 0;
|
||||
mTextSize = 0;
|
||||
}
|
||||
|
||||
nsHTMLFragmentContentSink::~nsHTMLFragmentContentSink()
|
||||
|
@ -215,10 +208,6 @@ nsHTMLFragmentContentSink::~nsHTMLFragmentContentSink()
|
|||
// Should probably flush the text buffer here, just to make sure:
|
||||
//FlushText();
|
||||
|
||||
NS_IF_RELEASE(mRoot);
|
||||
NS_IF_RELEASE(mParser);
|
||||
NS_IF_RELEASE(mCurrentForm);
|
||||
NS_IF_RELEASE(mCurrentMap);
|
||||
if (nsnull != mContentStack) {
|
||||
// there shouldn't be anything here except in an error condition
|
||||
PRInt32 indx = mContentStack->Count();
|
||||
|
@ -256,7 +245,9 @@ nsHTMLFragmentContentSink::WillBuildModel(void)
|
|||
nsresult rv = NS_NewDocumentFragment(getter_AddRefs(frag), mTargetDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return CallQueryInterface(frag, &mRoot);
|
||||
mRoot = do_QueryInterface(frag, &rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -266,7 +257,7 @@ nsHTMLFragmentContentSink::DidBuildModel(void)
|
|||
|
||||
// Drop our reference to the parser to get rid of a circular
|
||||
// reference.
|
||||
NS_IF_RELEASE(mParser);
|
||||
mParser = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -286,9 +277,7 @@ nsHTMLFragmentContentSink::WillResume(void)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLFragmentContentSink::SetParser(nsIParser* aParser)
|
||||
{
|
||||
NS_IF_RELEASE(mParser);
|
||||
mParser = aParser;
|
||||
NS_IF_ADDREF(mParser);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -449,15 +438,9 @@ nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
|
|||
{
|
||||
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsAutoString tag;
|
||||
nsresult result = NS_OK;
|
||||
|
||||
tag.Assign(aNode.GetText());
|
||||
|
||||
if (nsHTMLAtoms::endnote->Equals(tag)) {
|
||||
mHitSentinel = PR_TRUE;
|
||||
}
|
||||
else if (mHitSentinel) {
|
||||
if (mProcessing) {
|
||||
FlushText();
|
||||
|
||||
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
|
@ -522,7 +505,7 @@ nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLFragmentContentSink::CloseContainer(const nsHTMLTag aTag)
|
||||
{
|
||||
if (mHitSentinel && (nsnull != GetCurrentContent())) {
|
||||
if (mProcessing && (nsnull != GetCurrentContent())) {
|
||||
nsIContent* content;
|
||||
FlushText();
|
||||
content = PopContent();
|
||||
|
@ -597,7 +580,7 @@ nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode)
|
|||
if(nodeType == eHTMLTag_script ||
|
||||
nodeType == eHTMLTag_style ||
|
||||
nodeType == eHTMLTag_textarea ||
|
||||
nodeType == eHTMLTag_xmp) {
|
||||
nodeType == eHTMLTag_server) {
|
||||
|
||||
// Create a text node holding the content
|
||||
nsCOMPtr<nsIDTD> dtd;
|
||||
|
@ -711,6 +694,25 @@ nsHTMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFragmentContentSink::WillBuildContent()
|
||||
{
|
||||
mProcessing = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFragmentContentSink::DidBuildContent()
|
||||
{
|
||||
if (!mAllContent) {
|
||||
FlushText();
|
||||
mProcessing = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsHTMLFragmentContentSink::GetCurrentContent()
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Blake Kaplan <mrbkap@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -87,6 +88,8 @@ public:
|
|||
// nsIFragmentContentSink
|
||||
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment);
|
||||
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
|
||||
NS_IMETHOD WillBuildContent();
|
||||
NS_IMETHOD DidBuildContent();
|
||||
|
||||
protected:
|
||||
virtual PRBool SetDocElement(PRInt32 aNameSpaceID,
|
||||
|
@ -114,7 +117,6 @@ protected:
|
|||
|
||||
// if FALSE, take content inside endnote tag
|
||||
PRPackedBool mAllContent;
|
||||
nsCOMPtr<nsIContent> mEndnote;
|
||||
};
|
||||
|
||||
static nsresult
|
||||
|
@ -171,29 +173,20 @@ nsXMLFragmentContentSink::WillBuildModel(void)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mRoot = do_QueryInterface(frag);
|
||||
PushContent(mRoot); // preload content stack because we know all content goes in the fragment
|
||||
|
||||
if (mAllContent) {
|
||||
// Preload content stack because we know all content goes in the fragment
|
||||
PushContent(mRoot);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLFragmentContentSink::DidBuildModel()
|
||||
{
|
||||
PopContent(); // remove mRoot pushed above
|
||||
|
||||
if (!mAllContent && !mParseError) {
|
||||
NS_ASSERTION(mEndnote, "<endnote> missing in fragment string.");
|
||||
if (mEndnote) {
|
||||
NS_ASSERTION(mRoot->GetChildCount() == 1, "contents have too many children!");
|
||||
// move guts
|
||||
for (PRUint32 child = mEndnote->GetChildCount(); child > 0; child--) {
|
||||
nsCOMPtr<nsIContent> firstchild = mEndnote->GetChildAt(0);
|
||||
mEndnote->RemoveChildAt( 0, PR_FALSE );
|
||||
mRoot->AppendChildTo( firstchild, PR_FALSE, PR_FALSE );
|
||||
}
|
||||
// delete outer content
|
||||
mRoot->RemoveChildAt( 0, PR_FALSE );
|
||||
}
|
||||
// else just leave the content in the fragment. or should we fail?
|
||||
if (mAllContent) {
|
||||
PopContent(); // remove mRoot pushed above
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
|
||||
|
@ -237,11 +230,17 @@ nsXMLFragmentContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsC
|
|||
nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount,
|
||||
aNodeInfo, aLineNumber,
|
||||
aResult, aAppendContent);
|
||||
*aAppendContent = PR_TRUE; // make sure scripts added immediately, not on close.
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aNodeInfo->Equals(nsHTMLAtoms::endnote))
|
||||
mEndnote = *aResult;
|
||||
|
||||
// Make sure that scripts are added immediately, not on close.
|
||||
*aAppendContent = PR_TRUE;
|
||||
|
||||
// However, when we aren't grabbing all of the content we, never open a doc
|
||||
// element, we run into trouble on the first element, so we don't append,
|
||||
// and simply push this onto the content stack.
|
||||
if (!mAllContent && mContentStack.Count() == 0) {
|
||||
*aAppendContent = PR_FALSE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -387,3 +386,28 @@ nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLFragmentContentSink::WillBuildContent()
|
||||
{
|
||||
// If we're taking all of the content, then we've already pushed mRoot
|
||||
// onto the content stack, otherwise, start here.
|
||||
if (!mAllContent) {
|
||||
PushContent(mRoot);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLFragmentContentSink::DidBuildContent()
|
||||
{
|
||||
// If we're taking all of the content, then this is handled in DidBuildModel
|
||||
if (!mAllContent) {
|
||||
// Note: we need to FlushText() here because if we don't, we might not get
|
||||
// an end element to do it for us, so make sure.
|
||||
FlushText();
|
||||
PopContent();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,6 @@ HTML_TAG(dl, SharedList)
|
|||
HTML_TAG(dt, Span)
|
||||
HTML_TAG(em, Span)
|
||||
HTML_TAG(embed, Shared)
|
||||
HTML_TAG(endnote, Span)
|
||||
HTML_TAG(fieldset, FieldSet)
|
||||
HTML_TAG(font, Font)
|
||||
HTML_TAG(form, NOTUSED)
|
||||
|
|
|
@ -63,7 +63,7 @@ enum nsHTMLTag {
|
|||
#undef HTML_TAG
|
||||
#undef HTML_OTHER
|
||||
|
||||
// Currently there are 108 HTML tags. eHTMLTag_text = 110.
|
||||
// Currently there are 107 HTML tags. eHTMLTag_text = 109.
|
||||
#define NS_HTML_TAG_MAX PRInt32(eHTMLTag_text - 1)
|
||||
|
||||
class nsHTMLTags {
|
||||
|
|
|
@ -43,8 +43,8 @@ class nsIDOMDocumentFragment;
|
|||
class nsIDocument;
|
||||
|
||||
#define NS_I_FRAGMENT_CONTENT_SINK_IID \
|
||||
{ 0x2b23c1fb, 0xb83c, 0x436b, \
|
||||
{ 0xb7, 0x2a, 0x9c, 0xbe, 0xf1, 0xe9, 0x9b, 0x20 } };
|
||||
{ 0xe9ea6afb, 0x92f3, 0x4270, \
|
||||
{ 0xb2, 0x67, 0xd2, 0xe3, 0x8d, 0x0e, 0x95, 0x45 } }
|
||||
|
||||
class nsIFragmentContentSink : public nsISupports {
|
||||
public:
|
||||
|
@ -66,11 +66,25 @@ public:
|
|||
* (should not be null)
|
||||
*/
|
||||
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument) = 0;
|
||||
|
||||
/**
|
||||
* This method is used to indicate to the sink that we're done building
|
||||
* the context and should start paying attention to the incoming content
|
||||
*/
|
||||
NS_IMETHOD WillBuildContent() = 0;
|
||||
|
||||
/**
|
||||
* This method is used to indicate to the sink that we're done building
|
||||
* The real content. This is useful if you want to parse additional context
|
||||
* (such as an end context).
|
||||
*/
|
||||
NS_IMETHOD DidBuildContent() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base version takes string nested in context, context ends with <endnote>.
|
||||
* 2 version just loads whole string.
|
||||
* Base version takes string nested in context, content surrounded by
|
||||
* WillBuildContent()/DidBuildContent() calls. The 2nd version just loads
|
||||
* the whole string.
|
||||
*/
|
||||
|
||||
#define NS_HTMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;1"
|
||||
|
|
|
@ -259,6 +259,19 @@ class nsIParser : public nsISupports {
|
|||
|
||||
NS_IMETHOD Terminate(void) = 0;
|
||||
|
||||
/**
|
||||
* This method gets called when you want to parse a fragment of HTML or XML
|
||||
* surrounded by the context |aTagStack|. It requires that the parser have
|
||||
* been given a fragment content sink.
|
||||
*
|
||||
* @param aSourceBuffer The XML or HTML that hasn't been parsed yet.
|
||||
* @param aKey The key used by the parser.
|
||||
* @param aTagStack The context of the source buffer.
|
||||
* @param aXMLMode Whether this is XML or HTML
|
||||
* @param aContentType The content-type of this document.
|
||||
* @param aMode The DTDMode that the parser should parse this fragment in.
|
||||
* @return Success or failure.
|
||||
*/
|
||||
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
|
||||
void* aKey,
|
||||
nsVoidArray& aTagStack,
|
||||
|
|
|
@ -2251,7 +2251,6 @@ void CElementTable::InitializeElements() {
|
|||
|
||||
CPhraseElement::Initialize( mDfltElements[eHTMLTag_em], eHTMLTag_em);
|
||||
CElement::Initialize( mDfltElements[eHTMLTag_embed], eHTMLTag_embed);
|
||||
CBlockElement::Initialize( mDfltElements[eHTMLTag_endnote], eHTMLTag_endnote);
|
||||
|
||||
CElement::Initialize( mDfltElements[eHTMLTag_fieldset], eHTMLTag_fieldset, CBlockElement::GetGroup(), CFlowElement::GetContainedGroups());
|
||||
mDfltElements[eHTMLTag_fieldset].mIncludeKids=kFieldsetKids;
|
||||
|
|
|
@ -545,15 +545,6 @@ void InitializeElementTable(void) {
|
|||
/*special props, prop-range*/ kNonContainer,kDefaultPropRange,
|
||||
/*special parents,kids,skip*/ 0,&gContainsParam,eHTMLTag_unknown);
|
||||
|
||||
Initialize(
|
||||
/*tag*/ eHTMLTag_endnote,
|
||||
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
|
||||
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
|
||||
/*autoclose starttags and endtags*/ 0,0,0,0,
|
||||
/*parent,incl,exclgroups*/ kFlowEntity, kFlowEntity, kNone,
|
||||
/*special props, prop-range*/ kLegalOpen,kDefaultPropRange, // Don't munge the content model around <endnote>. bug 100175
|
||||
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
|
||||
|
||||
Initialize(
|
||||
/*tag*/ eHTMLTag_fieldset,
|
||||
/*requiredAncestor*/ eHTMLTag_unknown,eHTMLTag_unknown,
|
||||
|
|
|
@ -111,8 +111,6 @@ static const PRUnichar sHTMLTagUnicodeName_em[] =
|
|||
{'e', 'm', '\0'};
|
||||
static const PRUnichar sHTMLTagUnicodeName_embed[] =
|
||||
{'e', 'm', 'b', 'e', 'd', '\0'};
|
||||
static const PRUnichar sHTMLTagUnicodeName_endnote[] =
|
||||
{'e', 'n', 'd', 'n', 'o', 't', 'e', '\0'};
|
||||
static const PRUnichar sHTMLTagUnicodeName_fieldset[] =
|
||||
{'f', 'i', 'e', 'l', 'd', 's', 'e', 't', '\0'};
|
||||
static const PRUnichar sHTMLTagUnicodeName_font[] =
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIFragmentContentSink.h"
|
||||
|
||||
#ifdef MOZ_VIEW_SOURCE
|
||||
#include "nsViewSourceHTML.h"
|
||||
|
@ -1804,25 +1805,40 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
|
|||
nsDTDMode aMode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsAutoString theContext, endContext;
|
||||
nsAutoString theContext;
|
||||
PRUint32 theCount = aTagStack.Count();
|
||||
PRUint32 theIndex = 0;
|
||||
|
||||
|
||||
// Disable observers for fragments
|
||||
mFlags &= ~NS_PARSER_FLAG_OBSERVERS_ENABLED;
|
||||
|
||||
for (theIndex = 0; theIndex < theCount; theIndex++) {
|
||||
theContext.AppendLiteral("<");
|
||||
theContext.Append((PRUnichar*)aTagStack.ElementAt(theCount - theIndex - 1));
|
||||
theContext.AppendLiteral(">");
|
||||
}
|
||||
|
||||
// Note duplication: nsHTMLAtoms::endnote == an atom in nsHTMLTags
|
||||
theContext.AppendLiteral("<");
|
||||
theContext.Append(nsHTMLTags::GetStringValue(eHTMLTag_endnote));
|
||||
theContext.AppendLiteral(">");
|
||||
|
||||
if (aXMLMode) {
|
||||
endContext.AppendLiteral("</");
|
||||
endContext.Append(nsHTMLTags::GetStringValue(eHTMLTag_endnote));
|
||||
endContext.AppendLiteral(">");
|
||||
// First, parse the context to build up the DTD's tag stack. Note that we
|
||||
// pass PR_FALSE for the aLastCall parameter.
|
||||
result = Parse(theContext, (void*)&theContext, aMimeType,
|
||||
PR_FALSE, PR_FALSE, aMode);
|
||||
if (NS_FAILED(result)) {
|
||||
mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFragmentContentSink> fragSink = do_QueryInterface(mSink);
|
||||
NS_ASSERTION(fragSink, "ParseFragment requires a fragment content sink");
|
||||
|
||||
fragSink->WillBuildContent();
|
||||
// Now, parse the actual content. Note that this is the last call for HTML
|
||||
// content, but for XML, we will want to build and parse the end tags.
|
||||
result = Parse(aSourceBuffer, (void*)&theContext, aMimeType,
|
||||
PR_FALSE, !aXMLMode, aMode);
|
||||
fragSink->DidBuildContent();
|
||||
|
||||
if (aXMLMode && NS_SUCCEEDED(result)) {
|
||||
nsAutoString endContext;
|
||||
|
||||
for (theIndex = 0; theIndex < theCount; theIndex++) {
|
||||
endContext.AppendLiteral("</");
|
||||
|
@ -1834,12 +1850,11 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
|
|||
endContext.Append( Substring(thisTag,0,endOfTag) );
|
||||
endContext.AppendLiteral(">");
|
||||
}
|
||||
|
||||
result = Parse(endContext, (void*)&theContext, aMimeType,
|
||||
PR_FALSE, PR_TRUE, aMode);
|
||||
}
|
||||
|
||||
//now it's time to try to build the model from this fragment
|
||||
|
||||
mFlags &= ~NS_PARSER_FLAG_OBSERVERS_ENABLED; //disable observers for fragments
|
||||
result = Parse(theContext + aSourceBuffer + endContext,(void*)&theContext,aMimeType,PR_FALSE,PR_TRUE, aMode);
|
||||
mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED; //now reenable.
|
||||
|
||||
return result;
|
||||
|
|
Загрузка…
Ссылка в новой задаче