From 161f586d2244b737d4ecff7c3830eff297dff8f6 Mon Sep 17 00:00:00 2001 From: "pollmann%netscape.com" Date: Wed, 30 May 2001 11:26:21 +0000 Subject: [PATCH] Bug 77834: Fix problem where form control state is being restored to the wrong form control or not restored at all when going back and forth through session history. The problem was that the hash key we used was the content ID, which was not consistent from page load to page load. The fix was to key instead by index of form in document / index of control in form, with logic to fall back to content ID if we are unable to do this. r=nisheeth@netscape.com, sr=jst@netscape.com, a=drivers@mozilla.org (blizzard@mozilla.org) git-svn-id: svn://10.0.0.236/trunk@96057 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/MANIFEST | 1 + mozilla/content/base/public/Makefile.in | 1 + mozilla/content/base/public/makefile.win | 1 + mozilla/content/base/src/nsContentList.cpp | 47 ++- mozilla/content/base/src/nsContentList.h | 13 +- mozilla/content/html/content/public/nsIForm.h | 3 +- .../html/content/src/nsGenericHTMLElement.cpp | 54 ++-- .../html/content/src/nsGenericHTMLElement.h | 1 - .../html/content/src/nsHTMLFormElement.cpp | 23 +- .../html/content/src/nsHTMLInputElement.cpp | 44 +-- .../html/content/src/nsHTMLIsIndexElement.cpp | 6 + .../html/content/src/nsHTMLSelectElement.cpp | 8 +- .../html/document/src/nsHTMLContentSink.cpp | 13 + .../html/document/src/nsHTMLDocument.cpp | 33 +- .../html/document/src/nsHTMLDocument.h | 3 + .../html/document/src/nsIHTMLDocument.h | 3 + mozilla/layout/base/nsFrameManager.cpp | 301 ++++++++++++++---- mozilla/layout/base/nsILayoutHistoryState.h | 7 +- mozilla/layout/base/nsLayoutHistoryState.cpp | 68 ++-- mozilla/layout/base/public/nsIFrameManager.h | 5 + .../base/public/nsILayoutHistoryState.h | 7 +- mozilla/layout/base/public/nsIStatefulFrame.h | 7 - .../layout/base/src/nsLayoutHistoryState.cpp | 68 ++-- .../layout/forms/nsComboboxControlFrame.cpp | 8 - mozilla/layout/forms/nsComboboxControlFrame.h | 3 +- mozilla/layout/forms/nsFileControlFrame.cpp | 7 - mozilla/layout/forms/nsFileControlFrame.h | 1 - .../layout/forms/nsGfxButtonControlFrame.cpp | 17 +- .../layout/forms/nsGfxButtonControlFrame.h | 3 +- .../forms/nsGfxCheckboxControlFrame.cpp | 7 - .../layout/forms/nsGfxCheckboxControlFrame.h | 1 - .../layout/forms/nsGfxRadioControlFrame.cpp | 8 - mozilla/layout/forms/nsGfxRadioControlFrame.h | 1 - mozilla/layout/forms/nsIsIndexFrame.cpp | 7 - mozilla/layout/forms/nsIsIndexFrame.h | 1 - mozilla/layout/forms/nsListControlFrame.cpp | 9 - mozilla/layout/forms/nsListControlFrame.h | 1 - mozilla/layout/generic/nsIStatefulFrame.h | 7 - .../layout/html/base/src/nsFrameManager.cpp | 301 ++++++++++++++---- .../layout/html/base/src/nsScrollFrame.cpp | 11 +- mozilla/layout/html/base/src/nsScrollFrame.h | 1 - .../html/forms/src/nsComboboxControlFrame.cpp | 8 - .../html/forms/src/nsComboboxControlFrame.h | 3 +- .../html/forms/src/nsFileControlFrame.cpp | 7 - .../html/forms/src/nsFileControlFrame.h | 1 - .../forms/src/nsGfxButtonControlFrame.cpp | 17 +- .../html/forms/src/nsGfxButtonControlFrame.h | 3 +- .../forms/src/nsGfxCheckboxControlFrame.cpp | 7 - .../forms/src/nsGfxCheckboxControlFrame.h | 1 - .../html/forms/src/nsGfxRadioControlFrame.cpp | 8 - .../html/forms/src/nsGfxRadioControlFrame.h | 1 - .../html/forms/src/nsGfxTextControlFrame2.cpp | 36 +-- .../html/forms/src/nsGfxTextControlFrame2.h | 3 +- .../layout/html/forms/src/nsIsIndexFrame.cpp | 7 - .../layout/html/forms/src/nsIsIndexFrame.h | 1 - .../html/forms/src/nsListControlFrame.cpp | 9 - .../html/forms/src/nsListControlFrame.h | 1 - .../layout/xul/base/src/nsScrollBoxFrame.cpp | 11 +- .../layout/xul/base/src/nsScrollBoxFrame.h | 1 - 59 files changed, 729 insertions(+), 507 deletions(-) diff --git a/mozilla/content/base/public/MANIFEST b/mozilla/content/base/public/MANIFEST index 56a3dd9f2e8..805b3c61427 100644 --- a/mozilla/content/base/public/MANIFEST +++ b/mozilla/content/base/public/MANIFEST @@ -26,3 +26,4 @@ nsIStyleRuleSupplier.h nsIStyleSheet.h nsIStyleSheetLinkingElement.h nsITextContent.h +nsIContentList.h diff --git a/mozilla/content/base/public/Makefile.in b/mozilla/content/base/public/Makefile.in index cd121d7eb13..ff680c77ccf 100644 --- a/mozilla/content/base/public/Makefile.in +++ b/mozilla/content/base/public/Makefile.in @@ -55,6 +55,7 @@ nsITextContent.h \ nsIPrivateDOMImplementation.h \ nsIContentSerializer.h \ nsIHTMLToTextSink.h \ +nsIContentList.h \ $(NULL) XPIDLSRCS = \ diff --git a/mozilla/content/base/public/makefile.win b/mozilla/content/base/public/makefile.win index 2d76798520d..a448af3d69d 100644 --- a/mozilla/content/base/public/makefile.win +++ b/mozilla/content/base/public/makefile.win @@ -47,6 +47,7 @@ EXPORTS = \ nsIPrivateDOMImplementation.h \ nsIContentSerializer.h \ nsIHTMLToTextSink.h \ + nsIContentList.h \ $(NULL) MODULE=content_base diff --git a/mozilla/content/base/src/nsContentList.cpp b/mozilla/content/base/src/nsContentList.cpp index ae9b7378565..14962d26f13 100644 --- a/mozilla/content/base/src/nsContentList.cpp +++ b/mozilla/content/base/src/nsContentList.cpp @@ -34,6 +34,7 @@ // Form related includes #include "nsIDOMHTMLFormElement.h" +#include "nsIContentList.h" nsBaseContentList::nsBaseContentList() { @@ -371,6 +372,7 @@ NS_CLASSINFO_MAP_END // QueryInterface implementation for nsContentList NS_INTERFACE_MAP_BEGIN(nsContentList) NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLCollection) + NS_INTERFACE_MAP_ENTRY(nsIContentList) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLCollection) NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList) @@ -380,11 +382,11 @@ NS_IMPL_RELEASE_INHERITED(nsContentList, nsBaseContentList) NS_IMETHODIMP -nsContentList::GetLength(PRUint32* aLength) +nsContentList::GetLength(PRUint32* aLength, PRBool aDoFlush) { nsresult result = CheckDocumentExistence(); if (NS_SUCCEEDED(result)) { - if (mDocument) { + if (mDocument && aDoFlush) { mDocument->FlushPendingNotifications(PR_FALSE); } @@ -395,11 +397,11 @@ nsContentList::GetLength(PRUint32* aLength) } NS_IMETHODIMP -nsContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +nsContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn, PRBool aDoFlush) { nsresult result = CheckDocumentExistence(); if (NS_SUCCEEDED(result)) { - if (mDocument) { + if (mDocument && aDoFlush) { // Flush pending content changes Bug 4891 mDocument->FlushPendingNotifications(PR_FALSE); } @@ -419,12 +421,12 @@ nsContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) } NS_IMETHODIMP -nsContentList::NamedItem(const nsAReadableString& aName, nsIDOMNode** aReturn) +nsContentList::NamedItem(const nsAReadableString& aName, nsIDOMNode** aReturn, PRBool aDoFlush) { nsresult result = CheckDocumentExistence(); if (NS_SUCCEEDED(result)) { - if (mDocument) { + if (mDocument && aDoFlush) { mDocument->FlushPendingNotifications(PR_FALSE); // Flush pending content changes Bug 4891 } @@ -450,6 +452,39 @@ nsContentList::NamedItem(const nsAReadableString& aName, nsIDOMNode** aReturn) return result; } +NS_IMETHODIMP +nsContentList::IndexOf(nsIContent *aContent, PRInt32& aIndex, PRBool aDoFlush) +{ + nsresult result = CheckDocumentExistence(); + if (NS_SUCCEEDED(result)) { + if (mDocument && aDoFlush) { + mDocument->FlushPendingNotifications(PR_FALSE); + } + + aIndex = mElements.IndexOf(aContent); + } + + return result; +} + +NS_IMETHODIMP +nsContentList::GetLength(PRUint32* aLength) +{ + return GetLength(aLength, PR_TRUE); +} + +NS_IMETHODIMP +nsContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + return Item(aIndex, aReturn, PR_TRUE); +} + +NS_IMETHODIMP +nsContentList::NamedItem(const nsAReadableString& aName, nsIDOMNode** aReturn) +{ + return NamedItem(aName, aReturn, PR_TRUE); +} + NS_IMETHODIMP nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer, PRInt32 aNewIndexInContainer) diff --git a/mozilla/content/base/src/nsContentList.h b/mozilla/content/base/src/nsContentList.h index f8493b94286..404dc724b6a 100644 --- a/mozilla/content/base/src/nsContentList.h +++ b/mozilla/content/base/src/nsContentList.h @@ -28,6 +28,7 @@ #include "nsIDOMHTMLCollection.h" #include "nsIDOMNodeList.h" #include "nsIDocumentObserver.h" +#include "nsIContentList.h" typedef PRBool (*nsContentListMatchFunc)(nsIContent* aContent, nsString* aData); @@ -75,7 +76,8 @@ public: class nsContentList : public nsBaseContentList, public nsIDOMHTMLCollection, - public nsIDocumentObserver + public nsIDocumentObserver, + public nsIContentList { public: NS_DECL_ISUPPORTS_INHERITED @@ -97,6 +99,15 @@ public: NS_IMETHOD Item(PRUint32 aIndex, nsIDOMNode** aReturn); NS_IMETHOD NamedItem(const nsAReadableString& aName, nsIDOMNode** aReturn); + /// nsIContentList + NS_IMETHOD GetLength(PRUint32* aLength, PRBool aDoFlush); + NS_IMETHOD Item(PRUint32 aIndex, nsIDOMNode** aReturn, + PRBool aDoFlush); + NS_IMETHOD NamedItem(const nsAReadableString& aName, nsIDOMNode** aReturn, + PRBool aDoFlush); + NS_IMETHOD IndexOf(nsIContent *aContent, PRInt32& aIndex, + PRBool aDoFlush); + // nsIDocumentObserver NS_IMETHOD BeginUpdate(nsIDocument *aDocument) { return NS_OK; } NS_IMETHOD EndUpdate(nsIDocument *aDocument) { return NS_OK; } diff --git a/mozilla/content/html/content/public/nsIForm.h b/mozilla/content/html/content/public/nsIForm.h index 5e772fcfe4c..1cead6bf207 100644 --- a/mozilla/content/html/content/public/nsIForm.h +++ b/mozilla/content/html/content/public/nsIForm.h @@ -115,7 +115,8 @@ public: * @return NS_OK if the element was successfully removed. */ NS_IMETHOD ResolveName(const nsAReadableString& aName, nsISupports **aResult) = 0; - + + NS_IMETHOD IndexOfControl(nsIFormControl* aControl, PRInt32* aIndex) = 0; NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const = 0; }; diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index 2a8b1f7b303..47f88dee24f 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -62,9 +62,9 @@ #include "nsINameSpaceManager.h" #include "nsDOMError.h" -#include "nsIStatefulFrame.h" #include "nsIPresState.h" #include "nsILayoutHistoryState.h" +#include "nsIFrameManager.h" #include "nsIHTMLContentContainer.h" #include "nsHTMLParts.h" @@ -2567,7 +2567,6 @@ nsGenericHTMLElement::GetPrimaryFrame(nsIHTMLContent* aContent, nsresult nsGenericHTMLElement::GetPrimaryPresState(nsIHTMLContent* aContent, - nsIStatefulFrame::StateType aStateType, nsIPresState** aPresState) { NS_ENSURE_ARG_POINTER(aPresState); @@ -2575,28 +2574,39 @@ nsGenericHTMLElement::GetPrimaryPresState(nsIHTMLContent* aContent, nsresult result = NS_OK; - // Get the document + // Generate the state key nsCOMPtr doc; result = aContent->GetDocument(*getter_AddRefs(doc)); - if (doc) { - // Get presentation shell 0 - nsCOMPtr presShell = getter_AddRefs(doc->GetShellAt(0)); - if (presShell) { - nsCOMPtr history; - result = presShell->GetHistoryState(getter_AddRefs(history)); - if (NS_SUCCEEDED(result) && history) { - PRUint32 ID; - aContent->GetContentID(&ID); - result = history->GetState(ID, aPresState, aStateType); - if (!*aPresState) { - result = nsComponentManager::CreateInstance(kPresStateCID, nsnull, - NS_GET_IID(nsIPresState), - (void**)aPresState); - if (NS_SUCCEEDED(result)) { - result = history->AddState(ID, *aPresState, aStateType); - } - } - } + if (!doc) { + return result; + } + + nsCOMPtr presShell = getter_AddRefs(doc->GetShellAt(0)); + NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); + + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + NS_ENSURE_TRUE(frameManager, NS_ERROR_FAILURE); + + nsCAutoString stateKey; + result = frameManager->GenerateStateKey(aContent, nsIStatefulFrame::eNoID, stateKey); + NS_ENSURE_TRUE((NS_SUCCEEDED(result) && !stateKey.IsEmpty()), result); + + // Get the pres state for this key, if it doesn't exist, create one + // + // Return early if we can't get history - we don't want to create a + // new history state that is free-floating, not in history. + nsCOMPtr history; + result = presShell->GetHistoryState(getter_AddRefs(history)); + NS_ENSURE_TRUE(NS_SUCCEEDED(result) && history, result); + + history->GetState(stateKey, aPresState); + if (!*aPresState) { + result = nsComponentManager::CreateInstance(kPresStateCID, nsnull, + NS_GET_IID(nsIPresState), + (void**)aPresState); + if (NS_SUCCEEDED(result)) { + result = history->AddState(stateKey, *aPresState); } } diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.h b/mozilla/content/html/content/src/nsGenericHTMLElement.h index 2f866da6b82..32fb9d72675 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.h +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.h @@ -320,7 +320,6 @@ public: nsIFormControlFrame *&aFormControlFrame, PRBool aFlushNotifications=PR_TRUE); static nsresult GetPrimaryPresState(nsIHTMLContent* aContent, - nsIStatefulFrame::StateType aStateType, nsIPresState** aPresState); static nsresult GetPresContext(nsIHTMLContent* aContent, nsIPresContext** aPresContext); diff --git a/mozilla/content/html/content/src/nsHTMLFormElement.cpp b/mozilla/content/html/content/src/nsHTMLFormElement.cpp index d83598e0241..4323d21fff2 100644 --- a/mozilla/content/html/content/src/nsHTMLFormElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLFormElement.cpp @@ -91,6 +91,7 @@ public: const nsAReadableString& aName); NS_IMETHOD ResolveName(const nsAReadableString& aName, nsISupports **aReturn); + NS_IMETHOD IndexOfControl(nsIFormControl* aControl, PRInt32* aIndex); NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; // nsIContent @@ -140,6 +141,8 @@ public: const nsAReadableString& aName); nsresult RemoveElementFromTable(nsIFormControl* aChild, const nsAReadableString& aName); + nsresult IndexOfControl(nsIFormControl* aControl, + PRInt32* aIndex); #ifdef DEBUG nsresult SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; @@ -631,6 +634,13 @@ nsHTMLFormElement::GetLength(PRInt32* aLength) return NS_OK; } +NS_IMETHODIMP +nsHTMLFormElement::IndexOfControl(nsIFormControl* aControl, PRInt32* aIndex) +{ + NS_ENSURE_TRUE(mControls, NS_ERROR_FAILURE); + return mControls->IndexOfControl(aControl, aIndex); +} + //---------------------------------------------------------------------- // nsFormControlList implementation, this could go away if there were @@ -876,7 +886,7 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild, (nsIDOMNodeList *)nodeList.get()); PRInt32 oldIndex = -1; - list->IndexOf(newChild, oldIndex); + list->IndexOf(newChild, oldIndex, PR_TRUE); // Add the new child only if it's not in our list already if (oldIndex < 0) { @@ -888,6 +898,17 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild, return NS_OK; } +nsresult +nsFormControlList::IndexOfControl(nsIFormControl* aControl, + PRInt32* aIndex) +{ + NS_ENSURE_ARG_POINTER(aIndex); + + *aIndex = mElements.IndexOf(aControl); + + return NS_OK; +} + nsresult nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild, const nsAReadableString& aName) diff --git a/mozilla/content/html/content/src/nsHTMLInputElement.cpp b/mozilla/content/html/content/src/nsHTMLInputElement.cpp index b2a2a67e5c8..45d0e798089 100644 --- a/mozilla/content/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLInputElement.cpp @@ -205,7 +205,6 @@ public: protected: // Helper method void SetPresStateChecked(nsIHTMLContent * aHTMLContent, - nsIStatefulFrame::StateType aStateType, PRBool aValue); nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd); @@ -437,8 +436,7 @@ nsHTMLInputElement::GetValue(nsAWritableString& aValue) else { // Retrieve the presentation state instead. nsCOMPtr presState; - GetPrimaryPresState(this, nsIStatefulFrame::eTextType, - getter_AddRefs(presState)); + GetPrimaryPresState(this, getter_AddRefs(presState)); // Obtain the value property from the presentation state. if (presState) { @@ -507,8 +505,7 @@ nsHTMLInputElement::SetValue(const nsAReadableString& aValue) else { // Retrieve the presentation state instead. nsCOMPtr presState; - GetPrimaryPresState(this, nsIStatefulFrame::eTextType, - getter_AddRefs(presState)); + GetPrimaryPresState(this, getter_AddRefs(presState)); // Obtain the value property from the presentation state. if (presState) { @@ -537,18 +534,7 @@ nsHTMLInputElement::GetChecked(PRBool* aValue) else { // Retrieve the presentation state instead. nsCOMPtr presState; - PRInt32 type; - GetType(&type); - nsIStatefulFrame::StateType stateType; - - if (type == NS_FORM_INPUT_CHECKBOX) { - stateType = nsIStatefulFrame::eCheckboxType; - } - else { - stateType = nsIStatefulFrame::eRadioType; - } - - GetPrimaryPresState(this, stateType, getter_AddRefs(presState)); + GetPrimaryPresState(this, getter_AddRefs(presState)); // Obtain the value property from the presentation state. if (presState) { @@ -567,11 +553,10 @@ nsHTMLInputElement::GetChecked(PRBool* aValue) void nsHTMLInputElement::SetPresStateChecked(nsIHTMLContent * aHTMLContent, - nsIStatefulFrame::StateType aStateType, PRBool aValue) { nsCOMPtr presState; - GetPrimaryPresState(aHTMLContent, aStateType, getter_AddRefs(presState)); + GetPrimaryPresState(aHTMLContent, getter_AddRefs(presState)); // Obtain the value property from the presentation state. if (presState) { @@ -603,22 +588,11 @@ nsHTMLInputElement::SetChecked(PRBool aValue) formControlFrame->SetProperty(presContext, nsHTMLAtoms::checked, val); } else { - // Retrieve the presentation state instead. - nsCOMPtr presState; + SetPresStateChecked(this, aValue); + PRInt32 type; GetType(&type); - - nsIStatefulFrame::StateType stateType; - - if (type == NS_FORM_INPUT_CHECKBOX) { - stateType = nsIStatefulFrame::eCheckboxType; - } else { - stateType = nsIStatefulFrame::eRadioType; - } - - SetPresStateChecked(this, stateType, aValue); - - if (stateType == nsIStatefulFrame::eRadioType) { + if (type == NS_FORM_INPUT_RADIO) { nsAutoString name; GetName(name); @@ -653,9 +627,7 @@ nsHTMLInputElement::SetChecked(PRBool aValue) nsCOMPtr htmlContent(do_QueryInterface(inputElement)); - SetPresStateChecked(htmlContent, - nsIStatefulFrame::eRadioType, - PR_FALSE); + SetPresStateChecked(htmlContent, PR_FALSE); } } } diff --git a/mozilla/content/html/content/src/nsHTMLIsIndexElement.cpp b/mozilla/content/html/content/src/nsHTMLIsIndexElement.cpp index fe0a44777c4..f992c371423 100644 --- a/mozilla/content/html/content/src/nsHTMLIsIndexElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLIsIndexElement.cpp @@ -53,6 +53,7 @@ public: // nsIDOMHTMLIsIndexElement NS_DECL_NSIDOMHTMLISINDEXELEMENT + NS_IMETHOD_(PRBool) IsContentOfType(PRUint32 aFlags); NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; }; @@ -149,6 +150,11 @@ nsHTMLIsIndexElement::GetForm(nsIDOMHTMLFormElement** aForm) NS_IMPL_STRING_ATTR(nsHTMLIsIndexElement, Prompt, prompt) +NS_IMETHODIMP_(PRBool) +nsHTMLIsIndexElement::IsContentOfType(PRUint32 aFlags) +{ + return !(aFlags & ~(eELEMENT | eHTML | eHTML_FORM_CONTROL)); +} NS_IMETHODIMP nsHTMLIsIndexElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const diff --git a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp index 0927d1dde45..280a30073ec 100644 --- a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp @@ -1173,11 +1173,8 @@ nsHTMLSelectElement::GetPresState(nsIPresState** aPresState, *aPresState = nsnull; // Retrieve the presentation state instead. - nsIPresState* presState; - PRInt32 type; - GetType(&type); - nsresult rv = GetPrimaryPresState(this, nsIStatefulFrame::eSelectType, - &presState); + nsCOMPtr presState; + nsresult rv = GetPrimaryPresState(this, getter_AddRefs(presState)); // Obtain the value property from the presentation state. if (NS_FAILED(rv) || !presState) { @@ -1198,6 +1195,7 @@ nsHTMLSelectElement::GetPresState(nsIPresState** aPresState, } *aPresState = presState; + NS_ADDREF(*aPresState); return rv; } diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 5badb204888..56735632afe 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -2791,6 +2791,19 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode) SINK_TRACE_NODE(SINK_TRACE_CALLS, "HTMLContentSink::OpenHead", aNode, 0, this); nsresult rv = NS_OK; + + // Flush everything in the current context so that we don't have + // to worry about insertions resulting in inconsistent frame creation. + // + // Try to do this only if needed (costly), i.e., only if we are sure + // we are changing contexts from some other context to the head. + // + // PERF: This call causes approximately a 2% slowdown in page load time + // according to jrgm's page load tests, but seems to be a necessary evil + if (mCurrentContext && (mCurrentContext != mHeadContext)) { + mCurrentContext->FlushTags(PR_TRUE); + } + if (nsnull == mHeadContext) { mHeadContext = new SinkContext(this); if (nsnull == mHeadContext) { diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp index e75331d0143..f205855b350 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp @@ -1289,13 +1289,15 @@ nsHTMLDocument::FlushPendingNotifications(PRBool aFlushReflows) // Determine if it is safe to flush the sink // by determining if it safe to flush all the presshells. PRBool isSafeToFlush = PR_TRUE; - PRInt32 i = 0, n = mPresShells.Count(); - while ((i < n) && (isSafeToFlush)) { - nsIPresShell* shell = NS_STATIC_CAST(nsIPresShell*, mPresShells[i]); - if (shell) { - shell->IsSafeToFlush(isSafeToFlush); + if (aFlushReflows) { + PRInt32 i = 0, n = mPresShells.Count(); + while ((i < n) && (isSafeToFlush)) { + nsIPresShell* shell = NS_STATIC_CAST(nsIPresShell*, mPresShells[i]); + if (shell) { + shell->IsSafeToFlush(isSafeToFlush); + } + ++i; } - i++; } nsresult result = NS_OK; @@ -2579,6 +2581,25 @@ nsHTMLDocument::GetElementsByName(const nsAReadableString& aElementName, return NS_OK; } +PRBool +nsHTMLDocument::MatchFormControls(nsIContent* aContent, nsString* aData) +{ + return aContent->IsContentOfType(nsIContent::eHTML_FORM_CONTROL); +} + +NS_IMETHODIMP +nsHTMLDocument::GetFormControlElements(nsIDOMNodeList** aReturn) +{ + nsContentList* elements = nsnull; + elements = new nsContentList(this, MatchFormControls, nsString()); + NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY); + + *aReturn = elements; + NS_ADDREF(*aReturn); + + return NS_OK; +} + nsresult nsHTMLDocument::GetPixelDimensions(nsIPresShell* aShell, PRInt32* aWidth, diff --git a/mozilla/content/html/document/src/nsHTMLDocument.h b/mozilla/content/html/document/src/nsHTMLDocument.h index 4c8ff767363..4937f96faab 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.h +++ b/mozilla/content/html/document/src/nsHTMLDocument.h @@ -151,6 +151,8 @@ public: nsIDOMHTMLFormElement *aForm, nsISupports **aResult); + NS_IMETHOD GetFormControlElements(nsIDOMNodeList** aReturn); + protected: nsresult GetPixelDimensions(nsIPresShell* aShell, PRInt32* aWidth, @@ -180,6 +182,7 @@ protected: static PRBool MatchAnchors(nsIContent *aContent, nsString* aData); static PRBool MatchLayers(nsIContent *aContent, nsString* aData); static PRBool MatchNameAttribute(nsIContent* aContent, nsString* aData); + static PRBool MatchFormControls(nsIContent* aContent, nsString* aData); nsresult GetSourceDocumentURL(JSContext* cx, nsIURI** sourceURL); diff --git a/mozilla/content/html/document/src/nsIHTMLDocument.h b/mozilla/content/html/document/src/nsIHTMLDocument.h index 37b5f5e2850..b59f35f0fdb 100644 --- a/mozilla/content/html/document/src/nsIHTMLDocument.h +++ b/mozilla/content/html/document/src/nsIHTMLDocument.h @@ -71,6 +71,9 @@ public: NS_IMETHOD ResolveName(const nsAReadableString& aName, nsIDOMHTMLFormElement *aForm, nsISupports **aResult) = 0; + + NS_IMETHOD GetFormControlElements(nsIDOMNodeList** aReturn) = 0; + }; #endif /* nsIHTMLDocument_h___ */ diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index 53ddc65f8d9..ce542477cc9 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -57,6 +57,16 @@ #include "nsIBindingManager.h" #include "nsIScrollableFrame.h" +#include "nsIHTMLDocument.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMNodeList.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIFormControl.h" +#include "nsIDOMElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIForm.h" +#include "nsIContentList.h" + #define NEW_CONTEXT_PARENTAGE_INVARIANT #ifdef NEW_CONTEXT_PARENTAGE_INVARIANT @@ -288,6 +298,9 @@ public: nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID); + NS_IMETHOD GenerateStateKey(nsIContent* aContent, + nsIStatefulFrame::SpecialStateID aID, + nsCString& aString); // Gets and sets properties on a given frame NS_IMETHOD GetFrameProperty(nsIFrame* aFrame, @@ -336,6 +349,8 @@ private: UndisplayedMap* mUndisplayedMap; CantRenderReplacedElementEvent* mPostedEvents; PropertyList* mPropertyList; + nsCOMPtr mHTMLForms; + nsCOMPtr mHTMLFormControls; void ReResolveStyleContext(nsIPresContext* aPresContext, nsIFrame* aFrame, @@ -403,6 +418,23 @@ FrameManager::Init(nsIPresShell* aPresShell, return NS_ERROR_OUT_OF_MEMORY; } + // Force the forms and form control content lists to be added as + // document observers *before* us (pres shell) so they will be + // up to date when we try to use them. + nsCOMPtr document; + mPresShell->GetDocument(getter_AddRefs(document)); + nsCOMPtr htmlDocument(do_QueryInterface(document)); + nsCOMPtr domHtmlDocument(do_QueryInterface(htmlDocument)); + if (domHtmlDocument) { + nsCOMPtr forms; + domHtmlDocument->GetForms(getter_AddRefs(forms)); + mHTMLForms = do_QueryInterface(forms); + + nsCOMPtr formControls; + htmlDocument->GetFormControlElements(getter_AddRefs(formControls)); + mHTMLFormControls = do_QueryInterface(formControls); + } + return NS_OK; } @@ -2064,52 +2096,47 @@ FrameManager::AttributeAffectsStyle(nsIAtom *aAttribute, nsIContent *aContent, // Capture state for a given frame. // Accept a content id here, in some cases we may not have content (scroll position) NS_IMETHODIMP -FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID) +FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsILayoutHistoryState* aState, + nsIStatefulFrame::SpecialStateID aID) { - nsresult rv = NS_OK; - NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); - NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in"); + NS_ENSURE_TRUE(mPresShell && aFrame && aState, NS_ERROR_FAILURE); - // See if the frame is stateful. - // Frames are not ref-counted so no addref/release is required on statefulFrame. + // Only capture state for stateful frames nsIStatefulFrame* statefulFrame = nsnull; aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame); - if (nsnull != statefulFrame) { - - // If not given one, get the content ID - PRUint32 ID = aID; - if (nsIStatefulFrame::eNoID == ID) { - nsCOMPtr content; - rv = aFrame->GetContent(getter_AddRefs(content)); - if (NS_SUCCEEDED(rv) && content) { - rv = content->GetContentID(&ID); - } - } - if (NS_SUCCEEDED(rv) && ID) { // Must have ID (don't do anonymous content) - - // Get the state type - nsIStatefulFrame::StateType type = nsIStatefulFrame::eNoType; - rv = statefulFrame->GetStateType(aPresContext, &type); - if (NS_SUCCEEDED(rv)) { - - // Get the state - nsCOMPtr frameState; - rv = statefulFrame->SaveState(aPresContext, getter_AddRefs(frameState)); - if (NS_SUCCEEDED(rv) && frameState) { - - // add an association between (ID, type) and (state) to the - // history state storage object, aState. - rv = aState->AddState(ID, frameState, type); - } - } - } + if (!statefulFrame) { + return NS_OK; } - return rv; + // Capture the state, exit early if we get null (nothing to save) + nsCOMPtr frameState; + nsresult rv = NS_OK; + rv = statefulFrame->SaveState(aPresContext, getter_AddRefs(frameState)); + if (!frameState) { + return NS_OK; + } + + // Generate the hash key to store the state under + // Exit early if we get empty key + nsCOMPtr content; + rv = aFrame->GetContent(getter_AddRefs(content)); + + nsCAutoString stateKey; + rv = GenerateStateKey(content, aID, stateKey); + if(NS_FAILED(rv) || stateKey.IsEmpty()) { + return rv; + } + + // Store the state + return aState->AddState(stateKey, frameState); } NS_IMETHODIMP -FrameManager::CaptureFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState) +FrameManager::CaptureFrameState(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsILayoutHistoryState* aState) { nsresult rv = NS_OK; NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); @@ -2140,45 +2167,40 @@ FrameManager::CaptureFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, NS_IMETHODIMP FrameManager::RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID) { - nsresult rv = NS_OK; - NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); - NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in"); + NS_ENSURE_TRUE(mPresShell && aFrame && aState, NS_ERROR_FAILURE); - // See if the frame is stateful. - // Frames are not ref-counted so no addref/release is required on statefulFrame. + // Only capture state for stateful frames nsIStatefulFrame* statefulFrame = nsnull; aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame); - if (nsnull != statefulFrame) { - // If not given one, get the content ID - PRUint32 ID = aID; - if (nsIStatefulFrame::eNoID == ID) { - nsCOMPtr content; - rv = aFrame->GetContent(getter_AddRefs(content)); - if (NS_SUCCEEDED(rv) && content) { - rv = content->GetContentID(&ID); - } - } - if (NS_SUCCEEDED(rv) && ID) { // Must have ID (don't do anonymous content) + if (!statefulFrame) { + return NS_OK; + } - nsIStatefulFrame::StateType type = nsIStatefulFrame::eNoType; - rv = statefulFrame->GetStateType(aPresContext, &type); - if (NS_SUCCEEDED(rv)) { + // Generate the hash key the state was stored under + // Exit early if we get empty key + nsresult rv = NS_OK; + nsCOMPtr content; + rv = aFrame->GetContent(getter_AddRefs(content)); - nsCOMPtr frameState; - rv = aState->GetState(ID, getter_AddRefs(frameState), type); - if (NS_SUCCEEDED(rv) && frameState) { + nsCAutoString stateKey; + rv = GenerateStateKey(content, aID, stateKey); + if(NS_FAILED(rv) || stateKey.IsEmpty()) { + return rv; + } - // First restore the state. - rv = statefulFrame->RestoreState(aPresContext, frameState); + // Get the state from the hash + nsCOMPtr frameState; + rv = aState->GetState(stateKey, getter_AddRefs(frameState)); + if (!frameState) { + return NS_OK; + } - // Now remove the state from the state table. - aState->RemoveState(ID, type); - } - } - } - } + // Restore it + rv = statefulFrame->RestoreState(aPresContext, frameState); + NS_ENSURE_SUCCESS(rv, rv); - return rv; + // If we restore ok, remove the state from the state table + return aState->RemoveState(stateKey); } NS_IMETHODIMP @@ -2196,7 +2218,7 @@ FrameManager::RestoreFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, do { nsIFrame* childFrame; aFrame->FirstChild(aPresContext, childListName, &childFrame); - while (childFrame) { + while (childFrame) { rv = RestoreFrameState(aPresContext, childFrame, aState); // Get the next sibling child frame childFrame->GetNextSibling(&childFrame); @@ -2208,6 +2230,147 @@ FrameManager::RestoreFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, return rv; } + +static inline void KeyAppendSep(nsCString& aKey) +{ + if (!aKey.IsEmpty()) { + aKey.Append(">"); + } +} + +static inline void KeyAppendString(nsAReadableString& aString, nsCString& aKey) +{ + KeyAppendSep(aKey); + + // Could escape separator here if collisions happen. > is not a legal char + // for a name or type attribute, so we should be safe avoiding that extra work. + + aKey.Append(NS_ConvertUCS2toUTF8(aString)); +} + +static inline void KeyAppendInt(PRInt32 aInt, nsCString& aKey) +{ + KeyAppendSep(aKey); + + aKey.AppendInt(aInt); +} + +static inline void KeyAppendAtom(nsIAtom* aAtom, nsCString& aKey) +{ + NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n"); + + const PRUnichar* atomString = nsnull; + aAtom->GetUnicode(&atomString); + + KeyAppendString(nsDependentString(atomString), aKey); +} + +NS_IMETHODIMP +FrameManager::GenerateStateKey(nsIContent* aContent, + nsIStatefulFrame::SpecialStateID aID, + nsCString& aKey) +{ + aKey.Truncate(); + + // SpecialStateID case - e.g. scrollbars around the content window + // The key in this case is the special state id (always < min(contentID)) + if (nsIStatefulFrame::eNoID != aID) { + KeyAppendInt(aID, aKey); + return NS_OK; + } + + // We must have content if we're not using a special state id + NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE); + + // Don't capture state for anonymous content + PRUint32 contentID; + aContent->GetContentID(&contentID); + if (!contentID) { + return NS_OK; + } + + // If we have a dom element, add tag/type/name to hash key + // This is paranoia, but guarantees that we won't restore + // state to the wrong type of control. + nsCOMPtr tag; + if (aContent->IsContentOfType(nsIContent::eHTML_FORM_CONTROL)) { + + aContent->GetTag(*getter_AddRefs(tag)); + KeyAppendAtom(tag, aKey); + + nsAutoString name; + aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name); + KeyAppendString(name, aKey); + } + + // If we have a form control and can calculate form information, use + // that as the key - it is more reliable than contentID. + // Important to have a unique key, and tag/type/name may not be. + nsCOMPtr control(do_QueryInterface(aContent)); + PRBool generatedUniqueKey = PR_FALSE; + if (control && mHTMLFormControls && mHTMLForms) { + + if (tag == nsHTMLAtoms::input) { + PRInt32 type; + control->GetType(&type); + KeyAppendInt(type, aKey); + } + + // If in a form, add form name / index of form / index in form + PRInt32 index = -1; + nsCOMPtr formElement; + control->GetForm(getter_AddRefs(formElement)); + if (formElement) { + + nsAutoString formName; + formElement->GetName(formName); + KeyAppendString(formName, aKey); + + nsCOMPtr formContent(do_QueryInterface(formElement)); + mHTMLForms->IndexOf(formContent, index, PR_FALSE); + NS_ASSERTION(index > -1, + "nsFrameManager::GenerateStateKey didn't find form index!"); + if (index > -1) { + KeyAppendInt(index, aKey); + + nsCOMPtr form(do_QueryInterface(formElement)); + form->IndexOfControl(control, &index); + NS_ASSERTION(index > -1, + "nsFrameManager::GenerateStateKey didn't find form control index!"); + + if (index > -1) { + KeyAppendInt(index, aKey); + generatedUniqueKey = PR_TRUE; + } + } + + } else { + + // If not in a form, add index of control in document + // Less desirable than indexing by form info. + + // Hash by index of control in doc (we are not in a form) + // These are important as they are unique, and type/name may not be. + mHTMLFormControls->IndexOf(aContent, index, PR_FALSE); + NS_ASSERTION(index > -1, + "nsFrameManager::GenerateStateKey didn't find content by type!"); + if (index > -1) { + KeyAppendInt(index, aKey); + generatedUniqueKey = PR_TRUE; + } + } + } + + if (!generatedUniqueKey) { + + // Either we didn't have a form control or we aren't in an HTML document + // so we can't figure out form info, hash by content ID instead :( + KeyAppendInt(contentID, aKey); + } + + return NS_OK; +} + //---------------------------------------------------------------------- static PLHashNumber diff --git a/mozilla/layout/base/nsILayoutHistoryState.h b/mozilla/layout/base/nsILayoutHistoryState.h index 5a8e3a473c4..2f6e541b2a3 100644 --- a/mozilla/layout/base/nsILayoutHistoryState.h +++ b/mozilla/layout/base/nsILayoutHistoryState.h @@ -2,7 +2,6 @@ #define _nsILayoutHistoryState_h #include "nsISupports.h" -#include "nsIStatefulFrame.h" // Get StateType enum #include "nsIPresState.h" #define NS_ILAYOUTHISTORYSTATE_IID_STR "306c8ca0-5f0c-11d3-a9fb-000064657374" @@ -15,9 +14,9 @@ class nsILayoutHistoryState : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILAYOUTHISTORYSTATE_IID) - NS_IMETHOD AddState(PRUint32 aContentID, nsIPresState* aState, nsIStatefulFrame::StateType aStateType) = 0; - NS_IMETHOD GetState(PRUint32 aContentID, nsIPresState** aState, nsIStatefulFrame::StateType aStateType) = 0; - NS_IMETHOD RemoveState(PRUint32 aContentID, nsIStatefulFrame::StateType aStateType) = 0; + NS_IMETHOD AddState(const nsCString& aKey, nsIPresState* aState) = 0; + NS_IMETHOD GetState(const nsCString& aKey, nsIPresState** aState) = 0; + NS_IMETHOD RemoveState(const nsCString& aKey) = 0; }; nsresult diff --git a/mozilla/layout/base/nsLayoutHistoryState.cpp b/mozilla/layout/base/nsLayoutHistoryState.cpp index d131cca79c4..6d0f3922294 100644 --- a/mozilla/layout/base/nsLayoutHistoryState.cpp +++ b/mozilla/layout/base/nsLayoutHistoryState.cpp @@ -24,20 +24,6 @@ #include "nsILayoutHistoryState.h" #include "nsWeakReference.h" #include "nsHashtable.h" -#include "nsIStatefulFrame.h" // Get StateType enum - -MOZ_DECL_CTOR_COUNTER(HistoryKey) - -class HistoryKey: public nsVoidKey { - public: - HistoryKey(PRUint32 aContentID, nsIStatefulFrame::StateType aStateType) - : nsVoidKey((void*)(aContentID * nsIStatefulFrame::eNumStateTypes + aStateType)) { - } - - HistoryKey(PRUint32 aKey) - : nsVoidKey((void*)aKey) { - } -}; class nsLayoutHistoryState : public nsILayoutHistoryState, public nsSupportsWeakReference @@ -49,14 +35,9 @@ public: NS_DECL_ISUPPORTS // nsILayoutHistoryState - NS_IMETHOD AddState(PRUint32 aContentID, - nsIPresState* aState, - nsIStatefulFrame::StateType aStateType = nsIStatefulFrame::eNoType); - NS_IMETHOD GetState(PRUint32 aContentID, - nsIPresState** aState, - nsIStatefulFrame::StateType aStateType = nsIStatefulFrame::eNoType); - NS_IMETHOD RemoveState(PRUint32 aContentID, - nsIStatefulFrame::StateType aStateType = nsIStatefulFrame::eNoType); + NS_IMETHOD AddState(const nsCString& aKey, nsIPresState* aState); + NS_IMETHOD GetState(const nsCString& aKey, nsIPresState** aState); + NS_IMETHOD RemoveState(const nsCString& aKey); private: @@ -67,7 +48,7 @@ private: nsresult NS_NewLayoutHistoryState(nsILayoutHistoryState** aState) { - NS_PRECONDITION(aState != nsnull, "null ptr"); + NS_ENSURE_ARG_POINTER(aState); if (! aState) return NS_ERROR_NULL_POINTER; @@ -95,35 +76,35 @@ NS_IMPL_ISUPPORTS2(nsLayoutHistoryState, nsISupportsWeakReference); NS_IMETHODIMP -nsLayoutHistoryState::AddState(PRUint32 aContentID, - nsIPresState* aState, - nsIStatefulFrame::StateType aStateType) +nsLayoutHistoryState::AddState(const nsCString& aStateKey, + nsIPresState* aState) { - HistoryKey key(aContentID, aStateType); + nsCStringKey key(aStateKey); + /* - * nsSupportsHashtable::Put() returns false when no object has been - * replaced when inserting the new one, true if it some one was. - * + * nsSupportsHashtable::Put() returns false when no object was + * replaced when inserting the new one, true if one was. */ - PRBool replaced = mStates.Put (&key, aState); - if (replaced) - { - // done this way by indication of warren@netscape.com [ipg] -#if 0 - printf("nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n"); +#ifdef DEBUG_pollmann + PRBool replaced = +#endif + + mStates.Put (&key, aState); + +#ifdef DEBUG_pollmann + NS_ASSERTION(!replaced, + "nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n"); #endif - } return NS_OK; } NS_IMETHODIMP -nsLayoutHistoryState::GetState(PRUint32 aContentID, - nsIPresState** aState, - nsIStatefulFrame::StateType aStateType) +nsLayoutHistoryState::GetState(const nsCString& aKey, + nsIPresState** aState) { nsresult rv = NS_OK; - HistoryKey key(aContentID, aStateType); + nsCStringKey key(aKey); nsISupports *state = nsnull; state = mStates.Get(&key); if (state) { @@ -140,11 +121,10 @@ nsLayoutHistoryState::GetState(PRUint32 aContentID, } NS_IMETHODIMP -nsLayoutHistoryState::RemoveState(PRUint32 aContentID, - nsIStatefulFrame::StateType aStateType) +nsLayoutHistoryState::RemoveState(const nsCString& aKey) { nsresult rv = NS_OK; - HistoryKey key(aContentID, aStateType); + nsCStringKey key(aKey); mStates.Remove(&key); return rv; } diff --git a/mozilla/layout/base/public/nsIFrameManager.h b/mozilla/layout/base/public/nsIFrameManager.h index 002401840c3..7e7562f48e4 100644 --- a/mozilla/layout/base/public/nsIFrameManager.h +++ b/mozilla/layout/base/public/nsIFrameManager.h @@ -25,6 +25,7 @@ #include "nslayout.h" #include "nsISupports.h" #include "nsIStatefulFrame.h" +#include "nsString.h" class nsIAtom; class nsIContent; @@ -183,6 +184,10 @@ public: nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID) = 0; + NS_IMETHOD GenerateStateKey(nsIContent* aContent, + nsIStatefulFrame::SpecialStateID aID, + nsCString& aString) = 0; + /** * Gets a property value for a given frame. diff --git a/mozilla/layout/base/public/nsILayoutHistoryState.h b/mozilla/layout/base/public/nsILayoutHistoryState.h index 5a8e3a473c4..2f6e541b2a3 100644 --- a/mozilla/layout/base/public/nsILayoutHistoryState.h +++ b/mozilla/layout/base/public/nsILayoutHistoryState.h @@ -2,7 +2,6 @@ #define _nsILayoutHistoryState_h #include "nsISupports.h" -#include "nsIStatefulFrame.h" // Get StateType enum #include "nsIPresState.h" #define NS_ILAYOUTHISTORYSTATE_IID_STR "306c8ca0-5f0c-11d3-a9fb-000064657374" @@ -15,9 +14,9 @@ class nsILayoutHistoryState : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILAYOUTHISTORYSTATE_IID) - NS_IMETHOD AddState(PRUint32 aContentID, nsIPresState* aState, nsIStatefulFrame::StateType aStateType) = 0; - NS_IMETHOD GetState(PRUint32 aContentID, nsIPresState** aState, nsIStatefulFrame::StateType aStateType) = 0; - NS_IMETHOD RemoveState(PRUint32 aContentID, nsIStatefulFrame::StateType aStateType) = 0; + NS_IMETHOD AddState(const nsCString& aKey, nsIPresState* aState) = 0; + NS_IMETHOD GetState(const nsCString& aKey, nsIPresState** aState) = 0; + NS_IMETHOD RemoveState(const nsCString& aKey) = 0; }; nsresult diff --git a/mozilla/layout/base/public/nsIStatefulFrame.h b/mozilla/layout/base/public/nsIStatefulFrame.h index ae37fcd11d8..33ed56860c9 100644 --- a/mozilla/layout/base/public/nsIStatefulFrame.h +++ b/mozilla/layout/base/public/nsIStatefulFrame.h @@ -16,11 +16,6 @@ class nsIStatefulFrame : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTATEFULFRAME_IID) - // If you implement nsIStatefulFrame, add an entry to this enum and use it - // in your GetStateType method to prevent collisions. - enum StateType {eNoType=-1, eCheckboxType, eFileType, eRadioType, eSelectType, - eTextType, eScrollType, eNumStateTypes}; - // If you create a special type stateful frame (e.g. scroll) that needs // to be captured outside of the standard pass through the frames, you'll need // a special ID by which to refer to that type. @@ -29,8 +24,6 @@ class nsIStatefulFrame : public nsISupports { // offset NS_CONTENT_ID_COUNTER_BASE enum SpecialStateID {eNoID=0, eDocumentScrollState}; - - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) = 0; NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState) = 0; NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState) = 0; }; diff --git a/mozilla/layout/base/src/nsLayoutHistoryState.cpp b/mozilla/layout/base/src/nsLayoutHistoryState.cpp index d131cca79c4..6d0f3922294 100644 --- a/mozilla/layout/base/src/nsLayoutHistoryState.cpp +++ b/mozilla/layout/base/src/nsLayoutHistoryState.cpp @@ -24,20 +24,6 @@ #include "nsILayoutHistoryState.h" #include "nsWeakReference.h" #include "nsHashtable.h" -#include "nsIStatefulFrame.h" // Get StateType enum - -MOZ_DECL_CTOR_COUNTER(HistoryKey) - -class HistoryKey: public nsVoidKey { - public: - HistoryKey(PRUint32 aContentID, nsIStatefulFrame::StateType aStateType) - : nsVoidKey((void*)(aContentID * nsIStatefulFrame::eNumStateTypes + aStateType)) { - } - - HistoryKey(PRUint32 aKey) - : nsVoidKey((void*)aKey) { - } -}; class nsLayoutHistoryState : public nsILayoutHistoryState, public nsSupportsWeakReference @@ -49,14 +35,9 @@ public: NS_DECL_ISUPPORTS // nsILayoutHistoryState - NS_IMETHOD AddState(PRUint32 aContentID, - nsIPresState* aState, - nsIStatefulFrame::StateType aStateType = nsIStatefulFrame::eNoType); - NS_IMETHOD GetState(PRUint32 aContentID, - nsIPresState** aState, - nsIStatefulFrame::StateType aStateType = nsIStatefulFrame::eNoType); - NS_IMETHOD RemoveState(PRUint32 aContentID, - nsIStatefulFrame::StateType aStateType = nsIStatefulFrame::eNoType); + NS_IMETHOD AddState(const nsCString& aKey, nsIPresState* aState); + NS_IMETHOD GetState(const nsCString& aKey, nsIPresState** aState); + NS_IMETHOD RemoveState(const nsCString& aKey); private: @@ -67,7 +48,7 @@ private: nsresult NS_NewLayoutHistoryState(nsILayoutHistoryState** aState) { - NS_PRECONDITION(aState != nsnull, "null ptr"); + NS_ENSURE_ARG_POINTER(aState); if (! aState) return NS_ERROR_NULL_POINTER; @@ -95,35 +76,35 @@ NS_IMPL_ISUPPORTS2(nsLayoutHistoryState, nsISupportsWeakReference); NS_IMETHODIMP -nsLayoutHistoryState::AddState(PRUint32 aContentID, - nsIPresState* aState, - nsIStatefulFrame::StateType aStateType) +nsLayoutHistoryState::AddState(const nsCString& aStateKey, + nsIPresState* aState) { - HistoryKey key(aContentID, aStateType); + nsCStringKey key(aStateKey); + /* - * nsSupportsHashtable::Put() returns false when no object has been - * replaced when inserting the new one, true if it some one was. - * + * nsSupportsHashtable::Put() returns false when no object was + * replaced when inserting the new one, true if one was. */ - PRBool replaced = mStates.Put (&key, aState); - if (replaced) - { - // done this way by indication of warren@netscape.com [ipg] -#if 0 - printf("nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n"); +#ifdef DEBUG_pollmann + PRBool replaced = +#endif + + mStates.Put (&key, aState); + +#ifdef DEBUG_pollmann + NS_ASSERTION(!replaced, + "nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n"); #endif - } return NS_OK; } NS_IMETHODIMP -nsLayoutHistoryState::GetState(PRUint32 aContentID, - nsIPresState** aState, - nsIStatefulFrame::StateType aStateType) +nsLayoutHistoryState::GetState(const nsCString& aKey, + nsIPresState** aState) { nsresult rv = NS_OK; - HistoryKey key(aContentID, aStateType); + nsCStringKey key(aKey); nsISupports *state = nsnull; state = mStates.Get(&key); if (state) { @@ -140,11 +121,10 @@ nsLayoutHistoryState::GetState(PRUint32 aContentID, } NS_IMETHODIMP -nsLayoutHistoryState::RemoveState(PRUint32 aContentID, - nsIStatefulFrame::StateType aStateType) +nsLayoutHistoryState::RemoveState(const nsCString& aKey) { nsresult rv = NS_OK; - HistoryKey key(aContentID, aStateType); + nsCStringKey key(aKey); mStates.Remove(&key); return rv; } diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index 40a514e34b4..c6a44f3cc63 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -2503,14 +2503,6 @@ nsComboboxControlFrame::Rollup() // XXX Do we need to implement this here? It is already implemented in // the ListControlFrame, our child... //---------------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eSelectType; - return NS_OK; -} - NS_IMETHODIMP nsComboboxControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 4889339694e..0b2414106a6 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -66,7 +66,7 @@ class nsComboboxControlFrame : public nsAreaFrame, public nsIComboboxControlFrame, public nsIAnonymousContentCreator, public nsISelectControlFrame, - public nsIStatefulFrame, + public nsIStatefulFrame, public nsIRollupListener, public nsIScrollableViewProvider { @@ -179,7 +179,6 @@ public: NS_IMETHOD OptionDisabled(nsIContent * aContent); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index 81bdf61bc6f..944ea80ea01 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -690,13 +690,6 @@ nsFileControlFrame::Paint(nsIPresContext* aPresContext, //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- -NS_IMETHODIMP -nsFileControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eFileType; - return NS_OK; -} - NS_IMETHODIMP nsFileControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/forms/nsFileControlFrame.h b/mozilla/layout/forms/nsFileControlFrame.h index 80af3b7e802..19118f51bc7 100644 --- a/mozilla/layout/forms/nsFileControlFrame.h +++ b/mozilla/layout/forms/nsFileControlFrame.h @@ -173,7 +173,6 @@ public: NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; } //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp index 6be2626455a..bb545f61c0c 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp @@ -692,13 +692,9 @@ nsGfxButtonControlFrame::HandleEvent(nsIPresContext* aPresContext, return NS_OK; } -NS_IMETHODIMP -nsGfxButtonControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eTextType; - return NS_OK; -} - +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- NS_IMETHODIMP nsGfxButtonControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { @@ -710,12 +706,11 @@ nsGfxButtonControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** NS_ENSURE_SUCCESS(res, res); // Compare to default value, and only save if needed (Bug 62713) + NS_ENSURE_TRUE(mContent->IsContentOfType(nsIContent::eHTML_FORM_CONTROL), + NS_ERROR_UNEXPECTED); nsAutoString defaultStateString; if (!mDefaultValueWasChanged) { - nsCOMPtr formControl(do_QueryInterface(mContent)); - if (formControl) { - formControl->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, defaultStateString); - } + mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, defaultStateString); } if (mDefaultValueWasChanged || !stateString.Equals(defaultStateString)) { diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.h b/mozilla/layout/forms/nsGfxButtonControlFrame.h index f4445defeef..9ba5e168233 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.h +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.h @@ -99,8 +99,7 @@ protected: virtual PRBool IsSubmit(PRInt32 type); virtual PRBool IsBrowse(PRInt32 type); // Browse button of file input -//nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + //nsIStatefulFrame NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp b/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp index b09b0022f7a..67e6a2f4b9e 100644 --- a/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp @@ -613,13 +613,6 @@ nsGfxCheckboxControlFrame::SwitchModesWithEmergencyBrake ( nsIPresContext* aPres //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- -NS_IMETHODIMP nsGfxCheckboxControlFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType=nsIStatefulFrame::eCheckboxType; - return NS_OK; -} - NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/forms/nsGfxCheckboxControlFrame.h b/mozilla/layout/forms/nsGfxCheckboxControlFrame.h index 512bb40c086..0d9218e68ed 100644 --- a/mozilla/layout/forms/nsGfxCheckboxControlFrame.h +++ b/mozilla/layout/forms/nsGfxCheckboxControlFrame.h @@ -92,7 +92,6 @@ public: // nsIStatefulFrame NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/forms/nsGfxRadioControlFrame.cpp b/mozilla/layout/forms/nsGfxRadioControlFrame.cpp index 2abf03ad3f9..4e4d511dbe3 100644 --- a/mozilla/layout/forms/nsGfxRadioControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxRadioControlFrame.cpp @@ -372,14 +372,6 @@ nsGfxRadioControlFrame::InitializeControl(nsIPresContext* aPresContext) //---------------------------------------------------------------------- // nsIStatefulFrame -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsGfxRadioControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eRadioType; - return NS_OK; -} - //---------------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) diff --git a/mozilla/layout/forms/nsGfxRadioControlFrame.h b/mozilla/layout/forms/nsGfxRadioControlFrame.h index 05823144e4b..907cd9a3d65 100644 --- a/mozilla/layout/forms/nsGfxRadioControlFrame.h +++ b/mozilla/layout/forms/nsGfxRadioControlFrame.h @@ -94,7 +94,6 @@ public: NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/forms/nsIsIndexFrame.cpp b/mozilla/layout/forms/nsIsIndexFrame.cpp index b6d5bfd2efa..fd0c15feac6 100644 --- a/mozilla/layout/forms/nsIsIndexFrame.cpp +++ b/mozilla/layout/forms/nsIsIndexFrame.cpp @@ -568,13 +568,6 @@ nsIsIndexFrame::URLEncode(const nsString& aString, nsIUnicodeEncoder* encoder, n //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- -NS_IMETHODIMP -nsIsIndexFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eFileType; // XXX eIsIndexType - return NS_OK; -} - NS_IMETHODIMP nsIsIndexFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/forms/nsIsIndexFrame.h b/mozilla/layout/forms/nsIsIndexFrame.h index ed38d1f1467..e735d272ac2 100644 --- a/mozilla/layout/forms/nsIsIndexFrame.h +++ b/mozilla/layout/forms/nsIsIndexFrame.h @@ -116,7 +116,6 @@ public: NS_IMETHOD OnSubmit(nsIPresContext* aPresContext); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index d95f62d45b5..e7ddafd1d37 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -3983,15 +3983,6 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) //---------------------------------------------------------------------- // nsIStatefulFrame -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsListControlFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eSelectType; - return NS_OK; -} - //---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::SaveStateInternal(nsIPresContext* aPresContext, nsIPresState** aState) diff --git a/mozilla/layout/forms/nsListControlFrame.h b/mozilla/layout/forms/nsListControlFrame.h index 47b1d9c7183..14048d6718c 100644 --- a/mozilla/layout/forms/nsListControlFrame.h +++ b/mozilla/layout/forms/nsListControlFrame.h @@ -266,7 +266,6 @@ public: NS_IMETHOD OptionDisabled(nsIContent * aContent); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/generic/nsIStatefulFrame.h b/mozilla/layout/generic/nsIStatefulFrame.h index ae37fcd11d8..33ed56860c9 100644 --- a/mozilla/layout/generic/nsIStatefulFrame.h +++ b/mozilla/layout/generic/nsIStatefulFrame.h @@ -16,11 +16,6 @@ class nsIStatefulFrame : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTATEFULFRAME_IID) - // If you implement nsIStatefulFrame, add an entry to this enum and use it - // in your GetStateType method to prevent collisions. - enum StateType {eNoType=-1, eCheckboxType, eFileType, eRadioType, eSelectType, - eTextType, eScrollType, eNumStateTypes}; - // If you create a special type stateful frame (e.g. scroll) that needs // to be captured outside of the standard pass through the frames, you'll need // a special ID by which to refer to that type. @@ -29,8 +24,6 @@ class nsIStatefulFrame : public nsISupports { // offset NS_CONTENT_ID_COUNTER_BASE enum SpecialStateID {eNoID=0, eDocumentScrollState}; - - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) = 0; NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState) = 0; NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState) = 0; }; diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index 53ddc65f8d9..ce542477cc9 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -57,6 +57,16 @@ #include "nsIBindingManager.h" #include "nsIScrollableFrame.h" +#include "nsIHTMLDocument.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMNodeList.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIFormControl.h" +#include "nsIDOMElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIForm.h" +#include "nsIContentList.h" + #define NEW_CONTEXT_PARENTAGE_INVARIANT #ifdef NEW_CONTEXT_PARENTAGE_INVARIANT @@ -288,6 +298,9 @@ public: nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID); + NS_IMETHOD GenerateStateKey(nsIContent* aContent, + nsIStatefulFrame::SpecialStateID aID, + nsCString& aString); // Gets and sets properties on a given frame NS_IMETHOD GetFrameProperty(nsIFrame* aFrame, @@ -336,6 +349,8 @@ private: UndisplayedMap* mUndisplayedMap; CantRenderReplacedElementEvent* mPostedEvents; PropertyList* mPropertyList; + nsCOMPtr mHTMLForms; + nsCOMPtr mHTMLFormControls; void ReResolveStyleContext(nsIPresContext* aPresContext, nsIFrame* aFrame, @@ -403,6 +418,23 @@ FrameManager::Init(nsIPresShell* aPresShell, return NS_ERROR_OUT_OF_MEMORY; } + // Force the forms and form control content lists to be added as + // document observers *before* us (pres shell) so they will be + // up to date when we try to use them. + nsCOMPtr document; + mPresShell->GetDocument(getter_AddRefs(document)); + nsCOMPtr htmlDocument(do_QueryInterface(document)); + nsCOMPtr domHtmlDocument(do_QueryInterface(htmlDocument)); + if (domHtmlDocument) { + nsCOMPtr forms; + domHtmlDocument->GetForms(getter_AddRefs(forms)); + mHTMLForms = do_QueryInterface(forms); + + nsCOMPtr formControls; + htmlDocument->GetFormControlElements(getter_AddRefs(formControls)); + mHTMLFormControls = do_QueryInterface(formControls); + } + return NS_OK; } @@ -2064,52 +2096,47 @@ FrameManager::AttributeAffectsStyle(nsIAtom *aAttribute, nsIContent *aContent, // Capture state for a given frame. // Accept a content id here, in some cases we may not have content (scroll position) NS_IMETHODIMP -FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID) +FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsILayoutHistoryState* aState, + nsIStatefulFrame::SpecialStateID aID) { - nsresult rv = NS_OK; - NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); - NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in"); + NS_ENSURE_TRUE(mPresShell && aFrame && aState, NS_ERROR_FAILURE); - // See if the frame is stateful. - // Frames are not ref-counted so no addref/release is required on statefulFrame. + // Only capture state for stateful frames nsIStatefulFrame* statefulFrame = nsnull; aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame); - if (nsnull != statefulFrame) { - - // If not given one, get the content ID - PRUint32 ID = aID; - if (nsIStatefulFrame::eNoID == ID) { - nsCOMPtr content; - rv = aFrame->GetContent(getter_AddRefs(content)); - if (NS_SUCCEEDED(rv) && content) { - rv = content->GetContentID(&ID); - } - } - if (NS_SUCCEEDED(rv) && ID) { // Must have ID (don't do anonymous content) - - // Get the state type - nsIStatefulFrame::StateType type = nsIStatefulFrame::eNoType; - rv = statefulFrame->GetStateType(aPresContext, &type); - if (NS_SUCCEEDED(rv)) { - - // Get the state - nsCOMPtr frameState; - rv = statefulFrame->SaveState(aPresContext, getter_AddRefs(frameState)); - if (NS_SUCCEEDED(rv) && frameState) { - - // add an association between (ID, type) and (state) to the - // history state storage object, aState. - rv = aState->AddState(ID, frameState, type); - } - } - } + if (!statefulFrame) { + return NS_OK; } - return rv; + // Capture the state, exit early if we get null (nothing to save) + nsCOMPtr frameState; + nsresult rv = NS_OK; + rv = statefulFrame->SaveState(aPresContext, getter_AddRefs(frameState)); + if (!frameState) { + return NS_OK; + } + + // Generate the hash key to store the state under + // Exit early if we get empty key + nsCOMPtr content; + rv = aFrame->GetContent(getter_AddRefs(content)); + + nsCAutoString stateKey; + rv = GenerateStateKey(content, aID, stateKey); + if(NS_FAILED(rv) || stateKey.IsEmpty()) { + return rv; + } + + // Store the state + return aState->AddState(stateKey, frameState); } NS_IMETHODIMP -FrameManager::CaptureFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState) +FrameManager::CaptureFrameState(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsILayoutHistoryState* aState) { nsresult rv = NS_OK; NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); @@ -2140,45 +2167,40 @@ FrameManager::CaptureFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, NS_IMETHODIMP FrameManager::RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFrame, nsILayoutHistoryState* aState, nsIStatefulFrame::SpecialStateID aID) { - nsresult rv = NS_OK; - NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); - NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in"); + NS_ENSURE_TRUE(mPresShell && aFrame && aState, NS_ERROR_FAILURE); - // See if the frame is stateful. - // Frames are not ref-counted so no addref/release is required on statefulFrame. + // Only capture state for stateful frames nsIStatefulFrame* statefulFrame = nsnull; aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame); - if (nsnull != statefulFrame) { - // If not given one, get the content ID - PRUint32 ID = aID; - if (nsIStatefulFrame::eNoID == ID) { - nsCOMPtr content; - rv = aFrame->GetContent(getter_AddRefs(content)); - if (NS_SUCCEEDED(rv) && content) { - rv = content->GetContentID(&ID); - } - } - if (NS_SUCCEEDED(rv) && ID) { // Must have ID (don't do anonymous content) + if (!statefulFrame) { + return NS_OK; + } - nsIStatefulFrame::StateType type = nsIStatefulFrame::eNoType; - rv = statefulFrame->GetStateType(aPresContext, &type); - if (NS_SUCCEEDED(rv)) { + // Generate the hash key the state was stored under + // Exit early if we get empty key + nsresult rv = NS_OK; + nsCOMPtr content; + rv = aFrame->GetContent(getter_AddRefs(content)); - nsCOMPtr frameState; - rv = aState->GetState(ID, getter_AddRefs(frameState), type); - if (NS_SUCCEEDED(rv) && frameState) { + nsCAutoString stateKey; + rv = GenerateStateKey(content, aID, stateKey); + if(NS_FAILED(rv) || stateKey.IsEmpty()) { + return rv; + } - // First restore the state. - rv = statefulFrame->RestoreState(aPresContext, frameState); + // Get the state from the hash + nsCOMPtr frameState; + rv = aState->GetState(stateKey, getter_AddRefs(frameState)); + if (!frameState) { + return NS_OK; + } - // Now remove the state from the state table. - aState->RemoveState(ID, type); - } - } - } - } + // Restore it + rv = statefulFrame->RestoreState(aPresContext, frameState); + NS_ENSURE_SUCCESS(rv, rv); - return rv; + // If we restore ok, remove the state from the state table + return aState->RemoveState(stateKey); } NS_IMETHODIMP @@ -2196,7 +2218,7 @@ FrameManager::RestoreFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, do { nsIFrame* childFrame; aFrame->FirstChild(aPresContext, childListName, &childFrame); - while (childFrame) { + while (childFrame) { rv = RestoreFrameState(aPresContext, childFrame, aState); // Get the next sibling child frame childFrame->GetNextSibling(&childFrame); @@ -2208,6 +2230,147 @@ FrameManager::RestoreFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame, return rv; } + +static inline void KeyAppendSep(nsCString& aKey) +{ + if (!aKey.IsEmpty()) { + aKey.Append(">"); + } +} + +static inline void KeyAppendString(nsAReadableString& aString, nsCString& aKey) +{ + KeyAppendSep(aKey); + + // Could escape separator here if collisions happen. > is not a legal char + // for a name or type attribute, so we should be safe avoiding that extra work. + + aKey.Append(NS_ConvertUCS2toUTF8(aString)); +} + +static inline void KeyAppendInt(PRInt32 aInt, nsCString& aKey) +{ + KeyAppendSep(aKey); + + aKey.AppendInt(aInt); +} + +static inline void KeyAppendAtom(nsIAtom* aAtom, nsCString& aKey) +{ + NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n"); + + const PRUnichar* atomString = nsnull; + aAtom->GetUnicode(&atomString); + + KeyAppendString(nsDependentString(atomString), aKey); +} + +NS_IMETHODIMP +FrameManager::GenerateStateKey(nsIContent* aContent, + nsIStatefulFrame::SpecialStateID aID, + nsCString& aKey) +{ + aKey.Truncate(); + + // SpecialStateID case - e.g. scrollbars around the content window + // The key in this case is the special state id (always < min(contentID)) + if (nsIStatefulFrame::eNoID != aID) { + KeyAppendInt(aID, aKey); + return NS_OK; + } + + // We must have content if we're not using a special state id + NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE); + + // Don't capture state for anonymous content + PRUint32 contentID; + aContent->GetContentID(&contentID); + if (!contentID) { + return NS_OK; + } + + // If we have a dom element, add tag/type/name to hash key + // This is paranoia, but guarantees that we won't restore + // state to the wrong type of control. + nsCOMPtr tag; + if (aContent->IsContentOfType(nsIContent::eHTML_FORM_CONTROL)) { + + aContent->GetTag(*getter_AddRefs(tag)); + KeyAppendAtom(tag, aKey); + + nsAutoString name; + aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name); + KeyAppendString(name, aKey); + } + + // If we have a form control and can calculate form information, use + // that as the key - it is more reliable than contentID. + // Important to have a unique key, and tag/type/name may not be. + nsCOMPtr control(do_QueryInterface(aContent)); + PRBool generatedUniqueKey = PR_FALSE; + if (control && mHTMLFormControls && mHTMLForms) { + + if (tag == nsHTMLAtoms::input) { + PRInt32 type; + control->GetType(&type); + KeyAppendInt(type, aKey); + } + + // If in a form, add form name / index of form / index in form + PRInt32 index = -1; + nsCOMPtr formElement; + control->GetForm(getter_AddRefs(formElement)); + if (formElement) { + + nsAutoString formName; + formElement->GetName(formName); + KeyAppendString(formName, aKey); + + nsCOMPtr formContent(do_QueryInterface(formElement)); + mHTMLForms->IndexOf(formContent, index, PR_FALSE); + NS_ASSERTION(index > -1, + "nsFrameManager::GenerateStateKey didn't find form index!"); + if (index > -1) { + KeyAppendInt(index, aKey); + + nsCOMPtr form(do_QueryInterface(formElement)); + form->IndexOfControl(control, &index); + NS_ASSERTION(index > -1, + "nsFrameManager::GenerateStateKey didn't find form control index!"); + + if (index > -1) { + KeyAppendInt(index, aKey); + generatedUniqueKey = PR_TRUE; + } + } + + } else { + + // If not in a form, add index of control in document + // Less desirable than indexing by form info. + + // Hash by index of control in doc (we are not in a form) + // These are important as they are unique, and type/name may not be. + mHTMLFormControls->IndexOf(aContent, index, PR_FALSE); + NS_ASSERTION(index > -1, + "nsFrameManager::GenerateStateKey didn't find content by type!"); + if (index > -1) { + KeyAppendInt(index, aKey); + generatedUniqueKey = PR_TRUE; + } + } + } + + if (!generatedUniqueKey) { + + // Either we didn't have a form control or we aren't in an HTML document + // so we can't figure out form info, hash by content ID instead :( + KeyAppendInt(contentID, aKey); + } + + return NS_OK; +} + //---------------------------------------------------------------------- static PLHashNumber diff --git a/mozilla/layout/html/base/src/nsScrollFrame.cpp b/mozilla/layout/html/base/src/nsScrollFrame.cpp index 5eb462b9fdf..efb98158b1e 100644 --- a/mozilla/layout/html/base/src/nsScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollFrame.cpp @@ -1022,19 +1022,10 @@ nsScrollFrame::GetSkipSides() const //---------------------------------------------------------------------- // nsIStatefulFrame -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsScrollFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eScrollType; - return NS_OK; -} - //---------------------------------------------------------------------- NS_IMETHODIMP nsScrollFrame::SaveState(nsIPresContext* aPresContext, - nsIPresState** aState) + nsIPresState** aState) { NS_ENSURE_ARG_POINTER(aState); nsCOMPtr state; diff --git a/mozilla/layout/html/base/src/nsScrollFrame.h b/mozilla/layout/html/base/src/nsScrollFrame.h index 248cb47ff1f..74ea7a796c1 100644 --- a/mozilla/layout/html/base/src/nsScrollFrame.h +++ b/mozilla/layout/html/base/src/nsScrollFrame.h @@ -135,7 +135,6 @@ public: #endif //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index 40a514e34b4..c6a44f3cc63 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -2503,14 +2503,6 @@ nsComboboxControlFrame::Rollup() // XXX Do we need to implement this here? It is already implemented in // the ListControlFrame, our child... //---------------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eSelectType; - return NS_OK; -} - NS_IMETHODIMP nsComboboxControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 4889339694e..0b2414106a6 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -66,7 +66,7 @@ class nsComboboxControlFrame : public nsAreaFrame, public nsIComboboxControlFrame, public nsIAnonymousContentCreator, public nsISelectControlFrame, - public nsIStatefulFrame, + public nsIStatefulFrame, public nsIRollupListener, public nsIScrollableViewProvider { @@ -179,7 +179,6 @@ public: NS_IMETHOD OptionDisabled(nsIContent * aContent); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index 81bdf61bc6f..944ea80ea01 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -690,13 +690,6 @@ nsFileControlFrame::Paint(nsIPresContext* aPresContext, //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- -NS_IMETHODIMP -nsFileControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eFileType; - return NS_OK; -} - NS_IMETHODIMP nsFileControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.h b/mozilla/layout/html/forms/src/nsFileControlFrame.h index 80af3b7e802..19118f51bc7 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.h +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.h @@ -173,7 +173,6 @@ public: NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; } //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp index 6be2626455a..bb545f61c0c 100644 --- a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp @@ -692,13 +692,9 @@ nsGfxButtonControlFrame::HandleEvent(nsIPresContext* aPresContext, return NS_OK; } -NS_IMETHODIMP -nsGfxButtonControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eTextType; - return NS_OK; -} - +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- NS_IMETHODIMP nsGfxButtonControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { @@ -710,12 +706,11 @@ nsGfxButtonControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** NS_ENSURE_SUCCESS(res, res); // Compare to default value, and only save if needed (Bug 62713) + NS_ENSURE_TRUE(mContent->IsContentOfType(nsIContent::eHTML_FORM_CONTROL), + NS_ERROR_UNEXPECTED); nsAutoString defaultStateString; if (!mDefaultValueWasChanged) { - nsCOMPtr formControl(do_QueryInterface(mContent)); - if (formControl) { - formControl->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, defaultStateString); - } + mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, defaultStateString); } if (mDefaultValueWasChanged || !stateString.Equals(defaultStateString)) { diff --git a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h index f4445defeef..9ba5e168233 100644 --- a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h +++ b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h @@ -99,8 +99,7 @@ protected: virtual PRBool IsSubmit(PRInt32 type); virtual PRBool IsBrowse(PRInt32 type); // Browse button of file input -//nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + //nsIStatefulFrame NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp index b09b0022f7a..67e6a2f4b9e 100644 --- a/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp @@ -613,13 +613,6 @@ nsGfxCheckboxControlFrame::SwitchModesWithEmergencyBrake ( nsIPresContext* aPres //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- -NS_IMETHODIMP nsGfxCheckboxControlFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType=nsIStatefulFrame::eCheckboxType; - return NS_OK; -} - NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.h b/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.h index 512bb40c086..0d9218e68ed 100644 --- a/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.h @@ -92,7 +92,6 @@ public: // nsIStatefulFrame NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp index 2abf03ad3f9..4e4d511dbe3 100644 --- a/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp @@ -372,14 +372,6 @@ nsGfxRadioControlFrame::InitializeControl(nsIPresContext* aPresContext) //---------------------------------------------------------------------- // nsIStatefulFrame -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsGfxRadioControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eRadioType; - return NS_OK; -} - //---------------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) diff --git a/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.h b/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.h index 05823144e4b..907cd9a3d65 100644 --- a/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.h +++ b/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.h @@ -94,7 +94,6 @@ public: NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp index 68c35200315..e4b2ff637a5 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp @@ -3433,20 +3433,16 @@ nsGfxTextControlFrame2::GetWidthInCharacters() const return DEFAULT_COLUMN_WIDTH; } -NS_IMETHODIMP -nsGfxTextControlFrame2::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eTextType; - return NS_OK; -} - +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- NS_IMETHODIMP nsGfxTextControlFrame2::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { NS_ENSURE_ARG_POINTER(aState); // Don't save state before we are initialized - if (!mUseEditor) { + if (!mUseEditor && !mCachedState) { return NS_OK; } @@ -3455,26 +3451,18 @@ nsGfxTextControlFrame2::SaveState(nsIPresContext* aPresContext, nsIPresState** a nsresult res = GetProperty(nsHTMLAtoms::value, stateString); NS_ENSURE_SUCCESS(res, res); - // Compare to default value, and only save if needed (Bug 62713) - nsAutoString defaultStateString; - nsCOMPtr formControl(do_QueryInterface(mContent)); - if (formControl) { - formControl->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, defaultStateString); - } - // XXX Removed comparison between current and default state to // XXX temporarily fix bug 69365 (mail reply all looses addresses) - // XXX Should use nsAutoString above but ConvertStringLineBreaks requires mOwnsBuffer! - res = nsLinebreakConverter::ConvertStringLineBreaks(stateString, - nsLinebreakConverter::eLinebreakPlatform, nsLinebreakConverter::eLinebreakContent); - NS_ASSERTION(NS_SUCCEEDED(res), "Converting linebreaks failed!"); - - // Construct a pres state and store value in it. - res = NS_NewPresState(aState); - NS_ENSURE_SUCCESS(res, res); - res = (*aState)->SetStateProperty(NS_LITERAL_STRING("value"), stateString); + // XXX Should use nsAutoString above but ConvertStringLineBreaks requires mOwnsBuffer! + res = nsLinebreakConverter::ConvertStringLineBreaks(stateString, + nsLinebreakConverter::eLinebreakPlatform, nsLinebreakConverter::eLinebreakContent); + NS_ASSERTION(NS_SUCCEEDED(res), "Converting linebreaks failed!"); + // Construct a pres state and store value in it. + res = NS_NewPresState(aState); + NS_ENSURE_SUCCESS(res, res); + res = (*aState)->SetStateProperty(NS_LITERAL_STRING("value"), stateString); return res; } diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h index 3872c68c59a..8c0e8d12205 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h @@ -229,8 +229,7 @@ protected: PRInt32 GetWidthInCharacters() const; -//nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + //nsIStatefulFrame NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp b/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp index b6d5bfd2efa..fd0c15feac6 100644 --- a/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp +++ b/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp @@ -568,13 +568,6 @@ nsIsIndexFrame::URLEncode(const nsString& aString, nsIUnicodeEncoder* encoder, n //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- -NS_IMETHODIMP -nsIsIndexFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eFileType; // XXX eIsIndexType - return NS_OK; -} - NS_IMETHODIMP nsIsIndexFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) { diff --git a/mozilla/layout/html/forms/src/nsIsIndexFrame.h b/mozilla/layout/html/forms/src/nsIsIndexFrame.h index ed38d1f1467..e735d272ac2 100644 --- a/mozilla/layout/html/forms/src/nsIsIndexFrame.h +++ b/mozilla/layout/html/forms/src/nsIsIndexFrame.h @@ -116,7 +116,6 @@ public: NS_IMETHOD OnSubmit(nsIPresContext* aPresContext); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index d95f62d45b5..e7ddafd1d37 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -3983,15 +3983,6 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) //---------------------------------------------------------------------- // nsIStatefulFrame -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsListControlFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eSelectType; - return NS_OK; -} - //---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::SaveStateInternal(nsIPresContext* aPresContext, nsIPresState** aState) diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.h b/mozilla/layout/html/forms/src/nsListControlFrame.h index 47b1d9c7183..14048d6718c 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.h +++ b/mozilla/layout/html/forms/src/nsListControlFrame.h @@ -266,7 +266,6 @@ public: NS_IMETHOD OptionDisabled(nsIContent * aContent); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); diff --git a/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp b/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp index fc1a140203d..1537b85bbc9 100644 --- a/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp @@ -689,19 +689,10 @@ nsScrollBoxFrame::Release(void) //---------------------------------------------------------------------- // nsIStatefulFrame -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsScrollBoxFrame::GetStateType(nsIPresContext* aPresContext, - nsIStatefulFrame::StateType* aStateType) -{ - *aStateType = nsIStatefulFrame::eScrollType; - return NS_OK; -} - //---------------------------------------------------------------------- NS_IMETHODIMP nsScrollBoxFrame::SaveState(nsIPresContext* aPresContext, - nsIPresState** aState) + nsIPresState** aState) { NS_ENSURE_ARG_POINTER(aState); diff --git a/mozilla/layout/xul/base/src/nsScrollBoxFrame.h b/mozilla/layout/xul/base/src/nsScrollBoxFrame.h index b082b07f4b6..07768d87e71 100644 --- a/mozilla/layout/xul/base/src/nsScrollBoxFrame.h +++ b/mozilla/layout/xul/base/src/nsScrollBoxFrame.h @@ -115,7 +115,6 @@ protected: nsIView** aParentView); //nsIStatefulFrame - NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);