Bug 277890, disabling BUTTON after form.submit() prevents submission, r+sr=bz, a=1.9+, mochitest by ispiked@gmail.com

This commit is contained in:
Olli.Pettay@helsinki.fi 2007-08-16 14:10:29 -07:00
parent ee8b81eaac
commit 56c1fe60b8
8 changed files with 206 additions and 83 deletions

View File

@ -61,7 +61,8 @@
#include "nsPresState.h"
#include "nsLayoutErrors.h"
#define NS_IN_SUBMIT_CLICK (1 << 0)
#define NS_IN_SUBMIT_CLICK (1 << 0)
#define NS_OUTER_ACTIVATE_EVENT (1 << 1)
class nsHTMLButtonElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLButtonElement,
@ -125,6 +126,7 @@ protected:
PRInt8 mType;
PRPackedBool mHandlingClick;
PRPackedBool mDisabledChanged;
PRPackedBool mInInternalActivate;
private:
// The analogue of defaultValue in the DOM for input and textarea
@ -143,7 +145,8 @@ nsHTMLButtonElement::nsHTMLButtonElement(nsINodeInfo *aNodeInfo)
: nsGenericHTMLFormElement(aNodeInfo),
mType(NS_FORM_BUTTON_SUBMIT), // default
mHandlingClick(PR_FALSE),
mDisabledChanged(PR_FALSE)
mDisabledChanged(PR_FALSE),
mInInternalActivate(PR_FALSE)
{
}
@ -319,18 +322,24 @@ nsHTMLButtonElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
}
}
//FIXME Should this use NS_UI_ACTIVATE, not NS_MOUSE_CLICK?
// https://bugzilla.mozilla.org/show_bug.cgi?id=309348#c16
PRBool bInSubmitClick = mType == NS_FORM_BUTTON_SUBMIT &&
NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
mForm;
// Track whether we're in the outermost Dispatch invocation that will
// cause activation of the input. That is, if we're a click event, or a
// DOMActivate that was dispatched directly, this will be set, but if we're
// a DOMActivate dispatched from click handling, it will not be set.
PRBool outerActivateEvent =
(NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) ||
(aVisitor.mEvent->message == NS_UI_ACTIVATE &&
!mInInternalActivate));
if (bInSubmitClick) {
aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
mForm->OnSubmitClickBegin();
if (outerActivateEvent) {
aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
if (mType == NS_FORM_BUTTON_SUBMIT && mForm) {
aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
mForm->OnSubmitClickBegin();
}
}
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
@ -343,6 +352,25 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (!aVisitor.mPresContext) {
return rv;
}
if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_UI_ACTIVATE, 1);
nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
if (shell) {
nsEventStatus status = nsEventStatus_eIgnore;
mInInternalActivate = PR_TRUE;
shell->HandleDOMEventWithTarget(this, &actEvent, &status);
mInInternalActivate = PR_FALSE;
// If activate is cancelled, we must do the same as when click is
// cancelled (revert the checkbox to its original value).
if (status == nsEventStatus_eConsumeNoDefault)
aVisitor.mEventStatus = status;
}
}
// mForm is null if the event handler removed us from the document (bug 194582).
if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
// tell the form that we are about to exit a click handler
@ -376,50 +404,6 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
}
break;// NS_KEY_PRESS
case NS_MOUSE_CLICK:
{
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
nsCOMPtr<nsIPresShell> presShell =
aVisitor.mPresContext->GetPresShell();
if (presShell) {
// single-click
nsUIEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_UI_ACTIVATE, 1);
nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(this, &event, &status);
aVisitor.mEventStatus = status;
}
}
}
break;
case NS_UI_ACTIVATE:
{
if (mForm && (mType == NS_FORM_BUTTON_SUBMIT ||
mType == NS_FORM_BUTTON_RESET)) {
nsFormEvent event(PR_TRUE,
(mType == NS_FORM_BUTTON_RESET)
? NS_FORM_RESET : NS_FORM_SUBMIT);
event.originator = this;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIPresShell> presShell =
aVisitor.mPresContext->GetPresShell();
// If |nsIPresShell::Destroy| has been called due to
// handling the event, the pres context will return
// a null pres shell. See bug 125624.
//
// Using presShell to dispatch the event. It makes sure that
// event is not handled if the window is being destroyed.
if (presShell) {
nsCOMPtr<nsIContent> form(do_QueryInterface(mForm));
presShell->HandleDOMEventWithTarget(form, &event, &status);
}
}
}
break;// NS_MOUSE_CLICK
case NS_MOUSE_BUTTON_DOWN:
{
if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT) {
@ -478,33 +462,36 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
default:
break;
}
} else {
switch (aVisitor.mEvent->message) {
// Make sure any pending submissions from a call to
// form.submit() in a left click handler or an activate
// handler gets flushed, even if the event handler prevented
// the default action.
case NS_MOUSE_CLICK:
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
if (mForm && mType == NS_FORM_BUTTON_SUBMIT) {
// Tell the form to flush a possible pending submission.
// the reason is that the script returned false (the event was
// not ignored) so if there is a stored submission, it needs to
// be submitted immediatelly.
mForm->FlushPendingSubmission();
}
if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) {
if (mForm && (mType == NS_FORM_BUTTON_SUBMIT ||
mType == NS_FORM_BUTTON_RESET)) {
nsFormEvent event(PR_TRUE,
(mType == NS_FORM_BUTTON_RESET)
? NS_FORM_RESET : NS_FORM_SUBMIT);
event.originator = this;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIPresShell> presShell =
aVisitor.mPresContext->GetPresShell();
// If |nsIPresShell::Destroy| has been called due to
// handling the event, the pres context will return
// a null pres shell. See bug 125624.
//
// Using presShell to dispatch the event. It makes sure that
// event is not handled if the window is being destroyed.
if (presShell) {
nsCOMPtr<nsIContent> form(do_QueryInterface(mForm));
presShell->HandleDOMEventWithTarget(form, &event, &status);
}
break;
case NS_UI_ACTIVATE:
if (mForm && mType == NS_FORM_BUTTON_SUBMIT) {
// Tell the form to flush a possible pending submission.
// the reason is that the script returned false (the event was
// not ignored) so if there is a stored submission, it needs to
// be submitted immediatelly.
mForm->FlushPendingSubmission();
}
break;// NS_UI_ACTIVATE
} //switch
}
}
} else if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
// Tell the form to flush a possible pending submission.
// the reason is that the script returned false (the event was
// not ignored) so if there is a stored submission, it needs to
// be submitted immediatelly.
// Note, NS_IN_SUBMIT_CLICK is set only when we're in outer activate event.
mForm->FlushPendingSubmission();
} //if
return rv;

View File

@ -60,9 +60,15 @@ _TEST_FILES = test_bug589.html \
bug100533_iframe.html \
test_bug100533.html \
test_bug237071.html \
bug242709_iframe.html \
bug242709_load.html \
test_bug242709.html \
bug277724_iframe1.html \
bug277724_iframe2.xhtml \
test_bug277724.html \
bug277890_iframe.html \
bug277890_load.html \
test_bug277890.html \
test_bug300691-1.html \
test_bug300691-2.html \
test_bug300691-3.xhtml \

View File

@ -0,0 +1,20 @@
<html>
<head>
<title></title>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript">
function submitIframeForm () {
document.getElementById('b').submit();
document.getElementById('thebutton').disabled = true;
}
</script>
</head>
<body onload="sendMouseEvent({type:'click'}, 'thebutton')">
<form method="get" action="bug242709_load.html" id="b">
<input type="submit" onclick="submitIframeForm()" id="thebutton">
</form>
</body>
</html>

View File

@ -0,0 +1,11 @@
<html>
<head>
<title></title>
</head>
<body onload="parent.submitted();">
<span id="foo"></span>
</body>
</html>

View File

@ -0,0 +1,20 @@
<html>
<head>
<title></title>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript">
function submitIframeForm () {
document.getElementById('b').submit();
document.getElementById('thebutton').disabled = true;
}
</script>
</head>
<body onload="sendMouseEvent({type:'click'}, 'thebutton')">
<form method="get" action="bug277890_load.html" id="b">
<button onclick="submitIframeForm()" id="thebutton">Submit</button>
</form>
</body>
</html>

View File

@ -0,0 +1,11 @@
<html>
<head>
<title></title>
</head>
<body onload="parent.submitted();">
<span id="foo"></span>
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=242709
-->
<head>
<title>Test for Bug 242709</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=242709">Mozilla Bug 242709</a>
<p id="display"></p>
<div id="content">
<iframe src="bug242709_iframe.html" id="a"></iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 242709 **/
SimpleTest.waitForExplicitFinish();
var submitted = function() {
ok(true, "Disabling button after form submission doesn't prevent submitting");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=277890
-->
<head>
<title>Test for Bug 277890</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=277890">Mozilla Bug 277890</a>
<p id="display"></p>
<div id="content">
<iframe src="bug277890_iframe.html" id="a"></iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 277890 **/
SimpleTest.waitForExplicitFinish();
var submitted = function() {
ok(true, "Disabling button after form submission doesn't prevent submitting");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>