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 +

+
+
+
+ + + + + +