diff --git a/mozilla/content/html/content/src/nsHTMLButtonElement.cpp b/mozilla/content/html/content/src/nsHTMLButtonElement.cpp
index 952920ba6d5..d1b62bc8624 100644
--- a/mozilla/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/mozilla/content/html/content/src/nsHTMLButtonElement.cpp
@@ -58,6 +58,8 @@
#include "nsUnicharUtils.h"
#include "nsLayoutUtils.h"
#include "nsEventDispatcher.h"
+#include "nsPresState.h"
+#include "nsLayoutErrors.h"
#define NS_IN_SUBMIT_CLICK (1 << 0)
@@ -92,12 +94,20 @@ public:
NS_IMETHOD Click();
NS_IMETHOD SetType(const nsAString& aType);
- // overrided nsIFormControl method
+ // overriden nsIFormControl methods
NS_IMETHOD_(PRInt32) GetType() const { return mType; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
nsIContent* aSubmitElement);
+ NS_IMETHOD SaveState();
+ PRBool RestoreState(nsPresState* aState);
+ /**
+ * Called when an attribute is about to be changed
+ */
+ virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify);
+
// nsIContent overrides...
virtual void SetFocus(nsPresContext* aPresContext);
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
@@ -109,10 +119,12 @@ public:
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+ virtual void DoneCreatingElement();
protected:
PRInt8 mType;
PRPackedBool mHandlingClick;
+ PRPackedBool mDisabledChanged;
private:
// The analogue of defaultValue in the DOM for input and textarea
@@ -128,10 +140,11 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Button)
nsHTMLButtonElement::nsHTMLButtonElement(nsINodeInfo *aNodeInfo)
- : nsGenericHTMLFormElement(aNodeInfo)
+ : nsGenericHTMLFormElement(aNodeInfo),
+ mType(NS_FORM_BUTTON_SUBMIT), // default
+ mHandlingClick(PR_FALSE),
+ mDisabledChanged(PR_FALSE)
{
- mType = NS_FORM_BUTTON_SUBMIT; // default
- mHandlingClick = PR_FALSE;
}
nsHTMLButtonElement::~nsHTMLButtonElement()
@@ -565,3 +578,62 @@ nsHTMLButtonElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
return rv;
}
+
+void
+nsHTMLButtonElement::DoneCreatingElement()
+{
+ // Restore state as needed.
+ RestoreFormControlState(this, this);
+}
+
+nsresult
+nsHTMLButtonElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify)
+{
+ if (aNotify && aName == nsHTMLAtoms::disabled &&
+ aNameSpaceID == kNameSpaceID_None) {
+ mDisabledChanged = PR_TRUE;
+ }
+
+ return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
+ aValue, aNotify);
+}
+
+NS_IMETHODIMP
+nsHTMLButtonElement::SaveState()
+{
+ if (!mDisabledChanged) {
+ return NS_OK;
+ }
+
+ nsPresState *state = nsnull;
+ nsresult rv = GetPrimaryPresState(this, &state);
+ if (state) {
+ PRBool disabled;
+ GetDisabled(&disabled);
+ if (disabled) {
+ rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
+ NS_LITERAL_STRING("t"));
+ } else {
+ rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
+ NS_LITERAL_STRING("f"));
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "disabled save failed!");
+ }
+
+ return rv;
+}
+
+PRBool
+nsHTMLButtonElement::RestoreState(nsPresState* aState)
+{
+ nsAutoString disabled;
+ nsresult rv =
+ aState->GetStateProperty(NS_LITERAL_STRING("disabled"), disabled);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "disabled restore failed!");
+ if (rv == NS_STATE_PROPERTY_EXISTS) {
+ SetDisabled(disabled.EqualsLiteral("t"));
+ }
+
+ return PR_FALSE;
+}
diff --git a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp
index 84d0e6337c5..606667fe0b2 100644
--- a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp
@@ -73,6 +73,7 @@
#include "nsPresState.h"
#include "nsIComponentManager.h"
#include "nsCheapSets.h"
+#include "nsLayoutErrors.h"
// Notify/query select frame for selectedIndex
#include "nsIDocument.h"
@@ -268,6 +269,11 @@ public:
// nsISelectElement
NS_DECL_NSISELECTELEMENT
+ /**
+ * Called when an attribute is about to be changed
+ */
+ virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify);
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify);
@@ -455,7 +461,9 @@ protected:
/** The options[] array */
nsRefPtr mOptions;
/** false if the parser is in the middle of adding children. */
- PRBool mIsDoneAddingChildren;
+ PRPackedBool mIsDoneAddingChildren;
+ /** true if our disabled state has changed from the default **/
+ PRPackedBool mDisabledChanged;
/** The number of non-options as children of the select */
PRUint32 mNonOptionChildren;
/** The number of optgroups anywhere under the select */
@@ -488,6 +496,7 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsINodeInfo *aNodeInfo,
: nsGenericHTMLFormElement(aNodeInfo),
mOptions(new nsHTMLOptionCollection(this)),
mIsDoneAddingChildren(!aFromParser),
+ mDisabledChanged(PR_FALSE),
mNonOptionChildren(0),
mOptGroupCount(0),
mSelectedIndex(-1)
@@ -1677,6 +1686,19 @@ nsHTMLSelectElement::SelectSomething()
return PR_FALSE;
}
+nsresult
+nsHTMLSelectElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify)
+{
+ if (aNotify && aName == nsHTMLAtoms::disabled &&
+ aNameSpaceID == kNameSpaceID_None) {
+ mDisabledChanged = PR_TRUE;
+ }
+
+ return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
+ aValue, aNotify);
+}
+
nsresult
nsHTMLSelectElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
@@ -1867,6 +1889,19 @@ nsHTMLSelectElement::SaveState()
rv = presState->SetStatePropertyAsSupports(NS_LITERAL_STRING("selecteditems"),
state);
NS_ASSERTION(NS_SUCCEEDED(rv), "selecteditems set failed!");
+
+ if (mDisabledChanged) {
+ PRBool disabled;
+ GetDisabled(&disabled);
+ if (disabled) {
+ rv |= presState->SetStateProperty(NS_LITERAL_STRING("disabled"),
+ NS_LITERAL_STRING("t"));
+ } else {
+ rv |= presState->SetStateProperty(NS_LITERAL_STRING("disabled"),
+ NS_LITERAL_STRING("f"));
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "disabled save failed!");
+ }
}
return rv;
@@ -1887,6 +1922,13 @@ nsHTMLSelectElement::RestoreState(nsPresState* aState)
DispatchContentReset();
}
+ nsAutoString disabled;
+ rv = aState->GetStateProperty(NS_LITERAL_STRING("disabled"), disabled);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "disabled restore failed!");
+ if (rv == NS_STATE_PROPERTY_EXISTS) {
+ SetDisabled(disabled.EqualsLiteral("t"));
+ }
+
return PR_FALSE;
}
diff --git a/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp b/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp
index 3b23823e8a8..c7d20d056e3 100644
--- a/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -72,6 +72,7 @@
#include "nsReadableUtils.h"
#include "nsEventDispatcher.h"
#include "nsLayoutUtils.h"
+#include "nsLayoutErrors.h"
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
@@ -143,6 +144,11 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+ /**
+ * Called when an attribute is about to be changed
+ */
+ virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify);
protected:
nsCOMPtr mControllers;
/** The current value. This is null if the frame owns the value. */
@@ -154,7 +160,9 @@ protected:
/** Whether or not we are done adding children (always PR_TRUE if not
created by a parser */
PRPackedBool mDoneAddingChildren;
-
+ /** Whether our disabled state has changed from the default **/
+ PRPackedBool mDisabledChanged;
+
NS_IMETHOD SelectAll(nsPresContext* aPresContext);
/**
* Get the value, whether it is from the content or the frame.
@@ -180,7 +188,8 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsINodeInfo *aNodeInfo,
mValue(nsnull),
mValueChanged(PR_FALSE),
mHandlingSelect(PR_FALSE),
- mDoneAddingChildren(!aFromParser)
+ mDoneAddingChildren(!aFromParser),
+ mDisabledChanged(PR_FALSE)
{
}
@@ -852,8 +861,8 @@ nsHTMLTextAreaElement::SaveState()
nsresult rv = NS_OK;
// Only save if value != defaultValue (bug 62713)
+ nsPresState *state = nsnull;
if (mValueChanged) {
- nsPresState *state = nsnull;
rv = GetPrimaryPresState(this, &state);
if (state) {
nsAutoString value;
@@ -869,6 +878,23 @@ nsHTMLTextAreaElement::SaveState()
}
}
+ if (mDisabledChanged) {
+ if (!state) {
+ rv = GetPrimaryPresState(this, &state);
+ }
+ if (state) {
+ PRBool disabled;
+ GetDisabled(&disabled);
+ if (disabled) {
+ rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
+ NS_LITERAL_STRING("t"));
+ } else {
+ rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
+ NS_LITERAL_STRING("f"));
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "disabled save failed!");
+ }
+ }
return rv;
}
@@ -876,12 +902,30 @@ PRBool
nsHTMLTextAreaElement::RestoreState(nsPresState* aState)
{
nsAutoString value;
-#ifdef DEBUG
nsresult rv =
-#endif
aState->GetStateProperty(NS_LITERAL_STRING("value"), value);
NS_ASSERTION(NS_SUCCEEDED(rv), "value restore failed!");
SetValue(value);
+ nsAutoString disabled;
+ rv = aState->GetStateProperty(NS_LITERAL_STRING("disabled"), disabled);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "disabled restore failed!");
+ if (rv == NS_STATE_PROPERTY_EXISTS) {
+ SetDisabled(disabled.EqualsLiteral("t"));
+ }
+
return PR_FALSE;
}
+
+nsresult
+nsHTMLTextAreaElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+ const nsAString* aValue, PRBool aNotify)
+{
+ if (aNotify && aName == nsHTMLAtoms::disabled &&
+ aNameSpaceID == kNameSpaceID_None) {
+ mDisabledChanged = PR_TRUE;
+ }
+
+ return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
+ aValue, aNotify);
+}
diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp
index 997d7702ef4..ab039ff141b 100644
--- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp
+++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp
@@ -1126,6 +1126,10 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
}
break;
+ case eHTMLTag_button:
+ content->DoneCreatingElement();
+ break;
+
default:
break;
}
@@ -1349,7 +1353,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
break;
case eHTMLTag_input:
- case eHTMLTag_button:
content->DoneCreatingElement();
break;
diff --git a/mozilla/testing/mochitest/static/bug277724_iframe1.html b/mozilla/testing/mochitest/static/bug277724_iframe1.html
new file mode 100644
index 00000000000..d0d881b7666
--- /dev/null
+++ b/mozilla/testing/mochitest/static/bug277724_iframe1.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mozilla/testing/mochitest/static/bug277724_iframe2.xhtml b/mozilla/testing/mochitest/static/bug277724_iframe2.xhtml
new file mode 100644
index 00000000000..14423aa06ce
--- /dev/null
+++ b/mozilla/testing/mochitest/static/bug277724_iframe2.xhtml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mozilla/testing/mochitest/tests/index.html b/mozilla/testing/mochitest/tests/index.html
index 477de87aae3..bf4ea5767da 100644
--- a/mozilla/testing/mochitest/tests/index.html
+++ b/mozilla/testing/mochitest/tests/index.html
@@ -62,6 +62,7 @@ RunSet.runall = function() {
'test_bug100533.html',
'test_bug218277.html',
'test_bug237071.html',
+ 'test_bug277724.html',
'test_bug302186.html',
'test_bug308856.html',
'test_bug333983.html',
diff --git a/mozilla/testing/mochitest/tests/test_bug277724.html b/mozilla/testing/mochitest/tests/test_bug277724.html
new file mode 100644
index 00000000000..ace086776b5
--- /dev/null
+++ b/mozilla/testing/mochitest/tests/test_bug277724.html
@@ -0,0 +1,138 @@
+
+
+
+
+ Test for Bug 277724
+
+
+
+
+
+Mozilla Bug 277724
+
+
+
+
+
+
+
+
+
+
+
+
+