mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-11 01:57:00 +00:00
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:
parent
ee8b81eaac
commit
56c1fe60b8
@ -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;
|
||||
|
@ -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 \
|
||||
|
20
content/html/content/test/bug242709_iframe.html
Normal file
20
content/html/content/test/bug242709_iframe.html
Normal 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>
|
11
content/html/content/test/bug242709_load.html
Normal file
11
content/html/content/test/bug242709_load.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body onload="parent.submitted();">
|
||||
|
||||
<span id="foo"></span>
|
||||
|
||||
</body>
|
||||
</html>
|
20
content/html/content/test/bug277890_iframe.html
Normal file
20
content/html/content/test/bug277890_iframe.html
Normal 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>
|
11
content/html/content/test/bug277890_load.html
Normal file
11
content/html/content/test/bug277890_load.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body onload="parent.submitted();">
|
||||
|
||||
<span id="foo"></span>
|
||||
|
||||
</body>
|
||||
</html>
|
34
content/html/content/test/test_bug242709.html
Normal file
34
content/html/content/test/test_bug242709.html
Normal 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>
|
||||
|
34
content/html/content/test/test_bug277890.html
Normal file
34
content/html/content/test/test_bug277890.html
Normal 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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user