зеркало из https://github.com/mozilla/gecko-dev.git
Fixed a crash my making sure that the CNavDTD and HTMLContentSink stacks are synchronized when handling a FORM. b=133410, r=heikki, sr=jst
This commit is contained in:
Родитель
2cc4de292f
Коммит
cd7eee0829
|
@ -193,11 +193,12 @@ static PRLogModuleInfo* gSinkLogModuleInfo;
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#define NS_SINK_FLAG_SCRIPT_ENABLED 0x8
|
||||
#define NS_SINK_FLAG_FRAMES_ENABLED 0x10
|
||||
#define NS_SINK_FLAG_SCRIPT_ENABLED 0x8
|
||||
#define NS_SINK_FLAG_FRAMES_ENABLED 0x10
|
||||
#define NS_SINK_FLAG_CAN_INTERRUPT_PARSER 0x20 //Interrupt parsing when mMaxTokenProcessingTime is exceeded
|
||||
#define NS_SINK_FLAG_DYNAMIC_LOWER_VALUE 0x40 // Lower the value for mNotificationInterval and mMaxTokenProcessingTime
|
||||
#define NS_SINK_FLAG_IS_BASE_HREF_SET 0x80 //Set a flag as soon as Base Href is set for the document
|
||||
#define NS_SINK_FLAG_DYNAMIC_LOWER_VALUE 0x40 // Lower the value for mNotificationInterval and mMaxTokenProcessingTime
|
||||
#define NS_SINK_FLAG_IS_BASE_HREF_SET 0x80 //Set a flag as soon as Base Href is set for the document
|
||||
#define NS_SINK_FLAG_FORM_ON_STACK 0x100
|
||||
|
||||
#define NS_DELAY_FOR_WINDOW_CREATION 500000 // 1/2 second fudge factor for window creation
|
||||
#define NS_MAX_TOKENS_DEFLECTED_IN_LOW_FREQ_MODE 200 //200 determined empirically to provide good user response without
|
||||
|
@ -268,6 +269,7 @@ public:
|
|||
NS_IMETHOD OpenMap(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseMap(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref);
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack();
|
||||
|
||||
|
||||
NS_IMETHOD DoFragment(PRBool aFlag);
|
||||
|
@ -1592,6 +1594,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
|
||||
case eHTMLTag_form:
|
||||
{
|
||||
mSink->mFlags &= ~NS_SINK_FLAG_FORM_ON_STACK;
|
||||
nsHTMLTag parserNodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
|
||||
// If there's a FORM on the stack, but this close tag doesn't
|
||||
|
@ -2936,9 +2939,16 @@ HTMLContentSink::SetParser(nsIParser* aParser)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
HTMLContentSink::IsFormOnStack()
|
||||
{
|
||||
return mFlags & NS_SINK_FLAG_FORM_ON_STACK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLContentSink::BeginContext(PRInt32 aPosition)
|
||||
{
|
||||
{
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::BeginContext()\n"));
|
||||
MOZ_TIMER_START(mWatch);
|
||||
NS_PRECONDITION(aPosition > -1, "out of bounds");
|
||||
|
@ -3289,6 +3299,7 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode)
|
|||
result = AddLeaf(aNode);
|
||||
}
|
||||
else {
|
||||
mFlags |= NS_SINK_FLAG_FORM_ON_STACK;
|
||||
// Otherwise the form can be a content parent.
|
||||
result = mCurrentContext->OpenContainer(aNode);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
|
@ -3326,6 +3337,7 @@ HTMLContentSink::CloseForm(const nsIParserNode& aNode)
|
|||
// Check if this is a well-formed form
|
||||
if (mCurrentContext->IsCurrentContainer(eHTMLTag_form)) {
|
||||
result = mCurrentContext->CloseContainer(aNode);
|
||||
mFlags &= ~NS_SINK_FLAG_FORM_ON_STACK;
|
||||
}
|
||||
else if (mCurrentContext->IsAncestorContainer(eHTMLTag_form)) {
|
||||
result = mCurrentContext->DemoteForm(aNode);
|
||||
|
|
|
@ -108,6 +108,8 @@ public:
|
|||
NS_IMETHOD OpenNoscript(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseNoscript(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD OpenMap(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseMap(const nsIParserNode& aNode);
|
||||
NS_IMETHOD FlushPendingNotifications() { return NS_OK; }
|
||||
|
|
|
@ -336,6 +336,13 @@ public:
|
|||
*/
|
||||
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode)=0;
|
||||
|
||||
/**
|
||||
* Call this method to determnine if a FORM is on the sink's stack
|
||||
*
|
||||
* @return PR_TRUE if found else PR_FALSE
|
||||
*/
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() = 0;
|
||||
|
||||
};
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -345,3 +352,4 @@ extern nsresult NS_NewHTMLNullSink(nsIContentSink** aInstancePtrResult);
|
|||
#endif
|
||||
|
||||
#endif /* nsIHTMLContentSink_h___ */
|
||||
|
||||
|
|
|
@ -90,6 +90,8 @@ public:
|
|||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseTopmostContainer();
|
||||
|
|
|
@ -117,7 +117,6 @@ static char gShowCRC;
|
|||
#define NS_DTD_FLAG_HAD_FRAMESET 0x00000010
|
||||
#define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE 0x00000020
|
||||
#define NS_DTD_FLAG_REQUESTED_HEAD 0x00000040
|
||||
#define NS_DTD_FLAG_IS_FORM_CONTAINER 0x00000080
|
||||
#define NS_DTD_FLAG_SCRIPT_ENABLED 0x00000100
|
||||
#define NS_DTD_FLAG_FRAMES_ENABLED 0x00000200
|
||||
#define NS_DTD_FLAG_ALTERNATE_CONTENT 0x00000400 // NOFRAMES, NOSCRIPT
|
||||
|
@ -579,7 +578,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
|
|||
result=HandleToken(theTableToken,mParser);
|
||||
}
|
||||
}
|
||||
if(result==NS_OK) {
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
eHTMLTags theTarget;
|
||||
|
||||
//now let's disable style handling to save time when closing remaining stack members...
|
||||
|
@ -2034,14 +2033,15 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
|
|||
PRInt32 attrCount;
|
||||
PRInt32 theTopIndex = anIndex + 1;
|
||||
PRInt32 theTagCount = mBodyContext->GetCount();
|
||||
//eHTMLTags theParentTag= mBodyContext->TagAt(anIndex);
|
||||
|
||||
//XXX In the content sink, FORM behaves as a container for parents
|
||||
//other than eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_col,
|
||||
//eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup.In those cases the stack
|
||||
//position, in the parser, should be synchronized with the sink. -- Ref: Bug 20087.
|
||||
|
||||
if (!(~mFlags & (NS_DTD_FLAG_HAS_OPEN_FORM | NS_DTD_FLAG_IS_FORM_CONTAINER))) anIndex++;
|
||||
if (mSink && mSink->IsFormOnStack()) {
|
||||
// Do this to synchronize dtd stack and the sink stack.
|
||||
// Note: FORM is never on the dtd stack because its always
|
||||
// considered as a leaf. However, in the sink FORM can either
|
||||
// be a container or a leaf. Therefore, we have to check
|
||||
// with the sink -- Ref: Bug 20087.
|
||||
anIndex++;
|
||||
}
|
||||
|
||||
STOP_TIMER()
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleSavedTokensAbove(), this=%p\n", this));
|
||||
|
@ -3188,18 +3188,8 @@ nsresult CNavDTD::CloseBody(const nsIParserNode *aNode){
|
|||
* @return TRUE if ok, FALSE if error
|
||||
*/
|
||||
nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){
|
||||
static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,
|
||||
eHTMLTag_tfoot,eHTMLTag_thead,
|
||||
eHTMLTag_col,eHTMLTag_colgroup};
|
||||
nsresult result=NS_OK;
|
||||
if(!(mFlags & NS_DTD_FLAG_HAS_OPEN_FORM)) { // discard nested forms - bug 72639
|
||||
|
||||
// Check if the parent is a table, tbody, thead, tfoot, tr, col or
|
||||
// colgroup. If so, treat form as a leaf content. [ Ex. bug 92530 ]
|
||||
if(!FindTagInSet(mBodyContext->Last(),gTableElements,
|
||||
sizeof(gTableElements)/sizeof(eHTMLTag_unknown))) {
|
||||
mFlags |= NS_DTD_FLAG_IS_FORM_CONTAINER;
|
||||
}
|
||||
|
||||
STOP_TIMER();
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenForm(), this=%p\n", this));
|
||||
|
@ -3238,8 +3228,6 @@ nsresult CNavDTD::CloseForm(const nsIParserNode *aNode){
|
|||
|
||||
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseForm(), this=%p\n", this));
|
||||
START_TIMER();
|
||||
|
||||
mFlags &= ~NS_DTD_FLAG_IS_FORM_CONTAINER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,8 @@ public:
|
|||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD WillProcessTokens(void) { return NS_OK; }
|
||||
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
|
||||
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
|
||||
|
|
|
@ -630,6 +630,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,
|
|||
PRBool isUsableAttr = PR_TRUE;
|
||||
const nsAString& key=theToken->GetKey();
|
||||
const nsAString& text=theToken->GetValue();
|
||||
|
||||
// support XML like syntax to fix bugs like 44186
|
||||
if(!key.IsEmpty() && kForwardSlash==key.First() && text.IsEmpty()) {
|
||||
isUsableAttr = PRBool(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE); // Fix bug 103095
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD DoFragment(PRBool aFlag);
|
||||
NS_IMETHOD BeginContext(PRInt32 aPosition);
|
||||
NS_IMETHOD EndContext(PRInt32 aPosition);
|
||||
|
@ -119,3 +121,4 @@ protected:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -336,6 +336,13 @@ public:
|
|||
*/
|
||||
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode)=0;
|
||||
|
||||
/**
|
||||
* Call this method to determnine if a FORM is on the sink's stack
|
||||
*
|
||||
* @return PR_TRUE if found else PR_FALSE
|
||||
*/
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() = 0;
|
||||
|
||||
};
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -345,3 +352,4 @@ extern nsresult NS_NewHTMLNullSink(nsIContentSink** aInstancePtrResult);
|
|||
#endif
|
||||
|
||||
#endif /* nsIHTMLContentSink_h___ */
|
||||
|
||||
|
|
|
@ -90,6 +90,8 @@ public:
|
|||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseTopmostContainer();
|
||||
|
|
|
@ -117,7 +117,6 @@ static char gShowCRC;
|
|||
#define NS_DTD_FLAG_HAD_FRAMESET 0x00000010
|
||||
#define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE 0x00000020
|
||||
#define NS_DTD_FLAG_REQUESTED_HEAD 0x00000040
|
||||
#define NS_DTD_FLAG_IS_FORM_CONTAINER 0x00000080
|
||||
#define NS_DTD_FLAG_SCRIPT_ENABLED 0x00000100
|
||||
#define NS_DTD_FLAG_FRAMES_ENABLED 0x00000200
|
||||
#define NS_DTD_FLAG_ALTERNATE_CONTENT 0x00000400 // NOFRAMES, NOSCRIPT
|
||||
|
@ -579,7 +578,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
|
|||
result=HandleToken(theTableToken,mParser);
|
||||
}
|
||||
}
|
||||
if(result==NS_OK) {
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
eHTMLTags theTarget;
|
||||
|
||||
//now let's disable style handling to save time when closing remaining stack members...
|
||||
|
@ -2034,14 +2033,15 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
|
|||
PRInt32 attrCount;
|
||||
PRInt32 theTopIndex = anIndex + 1;
|
||||
PRInt32 theTagCount = mBodyContext->GetCount();
|
||||
//eHTMLTags theParentTag= mBodyContext->TagAt(anIndex);
|
||||
|
||||
//XXX In the content sink, FORM behaves as a container for parents
|
||||
//other than eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_col,
|
||||
//eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup.In those cases the stack
|
||||
//position, in the parser, should be synchronized with the sink. -- Ref: Bug 20087.
|
||||
|
||||
if (!(~mFlags & (NS_DTD_FLAG_HAS_OPEN_FORM | NS_DTD_FLAG_IS_FORM_CONTAINER))) anIndex++;
|
||||
if (mSink && mSink->IsFormOnStack()) {
|
||||
// Do this to synchronize dtd stack and the sink stack.
|
||||
// Note: FORM is never on the dtd stack because its always
|
||||
// considered as a leaf. However, in the sink FORM can either
|
||||
// be a container or a leaf. Therefore, we have to check
|
||||
// with the sink -- Ref: Bug 20087.
|
||||
anIndex++;
|
||||
}
|
||||
|
||||
STOP_TIMER()
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleSavedTokensAbove(), this=%p\n", this));
|
||||
|
@ -3188,18 +3188,8 @@ nsresult CNavDTD::CloseBody(const nsIParserNode *aNode){
|
|||
* @return TRUE if ok, FALSE if error
|
||||
*/
|
||||
nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){
|
||||
static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,
|
||||
eHTMLTag_tfoot,eHTMLTag_thead,
|
||||
eHTMLTag_col,eHTMLTag_colgroup};
|
||||
nsresult result=NS_OK;
|
||||
if(!(mFlags & NS_DTD_FLAG_HAS_OPEN_FORM)) { // discard nested forms - bug 72639
|
||||
|
||||
// Check if the parent is a table, tbody, thead, tfoot, tr, col or
|
||||
// colgroup. If so, treat form as a leaf content. [ Ex. bug 92530 ]
|
||||
if(!FindTagInSet(mBodyContext->Last(),gTableElements,
|
||||
sizeof(gTableElements)/sizeof(eHTMLTag_unknown))) {
|
||||
mFlags |= NS_DTD_FLAG_IS_FORM_CONTAINER;
|
||||
}
|
||||
|
||||
STOP_TIMER();
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenForm(), this=%p\n", this));
|
||||
|
@ -3238,8 +3228,6 @@ nsresult CNavDTD::CloseForm(const nsIParserNode *aNode){
|
|||
|
||||
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseForm(), this=%p\n", this));
|
||||
START_TIMER();
|
||||
|
||||
mFlags &= ~NS_DTD_FLAG_IS_FORM_CONTAINER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,8 @@ public:
|
|||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD WillProcessTokens(void) { return NS_OK; }
|
||||
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
|
||||
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
|
||||
|
|
|
@ -630,6 +630,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,
|
|||
PRBool isUsableAttr = PR_TRUE;
|
||||
const nsAString& key=theToken->GetKey();
|
||||
const nsAString& text=theToken->GetValue();
|
||||
|
||||
// support XML like syntax to fix bugs like 44186
|
||||
if(!key.IsEmpty() && kForwardSlash==key.First() && text.IsEmpty()) {
|
||||
isUsableAttr = PRBool(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE); // Fix bug 103095
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD GetPref(PRInt32 aTag,PRBool& aPref) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
NS_IMETHOD DoFragment(PRBool aFlag);
|
||||
NS_IMETHOD BeginContext(PRInt32 aPosition);
|
||||
NS_IMETHOD EndContext(PRInt32 aPosition);
|
||||
|
@ -119,3 +121,4 @@ protected:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче