diff --git a/content/base/public/MANIFEST b/content/base/public/MANIFEST index 56a3dd9f2e8..805b3c61427 100644 --- a/content/base/public/MANIFEST +++ b/content/base/public/MANIFEST @@ -26,3 +26,4 @@ nsIStyleRuleSupplier.h nsIStyleSheet.h nsIStyleSheetLinkingElement.h nsITextContent.h +nsIContentList.h diff --git a/content/base/public/Makefile.in b/content/base/public/Makefile.in index cd121d7eb13..ff680c77ccf 100644 --- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -55,6 +55,7 @@ nsITextContent.h \ nsIPrivateDOMImplementation.h \ nsIContentSerializer.h \ nsIHTMLToTextSink.h \ +nsIContentList.h \ $(NULL) XPIDLSRCS = \ diff --git a/content/base/public/makefile.win b/content/base/public/makefile.win index 2d76798520d..a448af3d69d 100644 --- a/content/base/public/makefile.win +++ b/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/content/base/src/nsContentList.cpp b/content/base/src/nsContentList.cpp index ae9b7378565..14962d26f13 100644 --- a/content/base/src/nsContentList.cpp +++ b/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/content/base/src/nsContentList.h b/content/base/src/nsContentList.h index f8493b94286..404dc724b6a 100644 --- a/content/base/src/nsContentList.h +++ b/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/content/html/content/public/nsIForm.h b/content/html/content/public/nsIForm.h index 5e772fcfe4c..1cead6bf207 100644 --- a/content/html/content/public/nsIForm.h +++ b/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/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 2a8b1f7b303..47f88dee24f 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/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/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 2f866da6b82..32fb9d72675 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/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/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index d83598e0241..4323d21fff2 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/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/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index b2a2a67e5c8..45d0e798089 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/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/content/html/content/src/nsHTMLIsIndexElement.cpp b/content/html/content/src/nsHTMLIsIndexElement.cpp index fe0a44777c4..f992c371423 100644 --- a/content/html/content/src/nsHTMLIsIndexElement.cpp +++ b/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/content/html/content/src/nsHTMLSelectElement.cpp b/content/html/content/src/nsHTMLSelectElement.cpp index 0927d1dde45..280a30073ec 100644 --- a/content/html/content/src/nsHTMLSelectElement.cpp +++ b/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/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 5badb204888..56735632afe 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/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/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index e75331d0143..f205855b350 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/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/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 4c8ff767363..4937f96faab 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/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/content/html/document/src/nsIHTMLDocument.h b/content/html/document/src/nsIHTMLDocument.h index 37b5f5e2850..b59f35f0fdb 100644 --- a/content/html/document/src/nsIHTMLDocument.h +++ b/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/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index 53ddc65f8d9..ce542477cc9 100644 --- a/layout/base/nsFrameManager.cpp +++ b/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/layout/base/nsILayoutHistoryState.h b/layout/base/nsILayoutHistoryState.h index 5a8e3a473c4..2f6e541b2a3 100644 --- a/layout/base/nsILayoutHistoryState.h +++ b/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/layout/base/nsLayoutHistoryState.cpp b/layout/base/nsLayoutHistoryState.cpp index d131cca79c4..6d0f3922294 100644 --- a/layout/base/nsLayoutHistoryState.cpp +++ b/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/layout/base/public/nsIFrameManager.h b/layout/base/public/nsIFrameManager.h index 002401840c3..7e7562f48e4 100644 --- a/layout/base/public/nsIFrameManager.h +++ b/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/layout/base/public/nsILayoutHistoryState.h b/layout/base/public/nsILayoutHistoryState.h index 5a8e3a473c4..e69de29bb2d 100644 --- a/layout/base/public/nsILayoutHistoryState.h +++ b/layout/base/public/nsILayoutHistoryState.h @@ -1,27 +0,0 @@ -#ifndef _nsILayoutHistoryState_h -#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" - -#define NS_ILAYOUTHISTORYSTATE_IID \ -{0x306c8ca0, 0x5f0c, 0x11d3, \ -{0xa9, 0xfb, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}} - -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; -}; - -nsresult -NS_NewLayoutHistoryState(nsILayoutHistoryState** aState); - -#endif /* _nsILayoutHistoryState_h */ - diff --git a/layout/base/public/nsIStatefulFrame.h b/layout/base/public/nsIStatefulFrame.h index ae37fcd11d8..33ed56860c9 100644 --- a/layout/base/public/nsIStatefulFrame.h +++ b/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/layout/base/src/nsLayoutHistoryState.cpp b/layout/base/src/nsLayoutHistoryState.cpp index d131cca79c4..6d0f3922294 100644 --- a/layout/base/src/nsLayoutHistoryState.cpp +++ b/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/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 40a514e34b4..c6a44f3cc63 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/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/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h index 4889339694e..0b2414106a6 100644 --- a/layout/forms/nsComboboxControlFrame.h +++ b/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/layout/forms/nsFileControlFrame.cpp b/layout/forms/nsFileControlFrame.cpp index 81bdf61bc6f..944ea80ea01 100644 --- a/layout/forms/nsFileControlFrame.cpp +++ b/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/layout/forms/nsFileControlFrame.h b/layout/forms/nsFileControlFrame.h index 80af3b7e802..19118f51bc7 100644 --- a/layout/forms/nsFileControlFrame.h +++ b/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/layout/forms/nsGfxButtonControlFrame.cpp b/layout/forms/nsGfxButtonControlFrame.cpp index 6be2626455a..bb545f61c0c 100644 --- a/layout/forms/nsGfxButtonControlFrame.cpp +++ b/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/layout/forms/nsGfxButtonControlFrame.h b/layout/forms/nsGfxButtonControlFrame.h index f4445defeef..9ba5e168233 100644 --- a/layout/forms/nsGfxButtonControlFrame.h +++ b/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/layout/forms/nsGfxCheckboxControlFrame.cpp b/layout/forms/nsGfxCheckboxControlFrame.cpp index b09b0022f7a..67e6a2f4b9e 100644 --- a/layout/forms/nsGfxCheckboxControlFrame.cpp +++ b/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/layout/forms/nsGfxCheckboxControlFrame.h b/layout/forms/nsGfxCheckboxControlFrame.h index 512bb40c086..0d9218e68ed 100644 --- a/layout/forms/nsGfxCheckboxControlFrame.h +++ b/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/layout/forms/nsGfxRadioControlFrame.cpp b/layout/forms/nsGfxRadioControlFrame.cpp index 2abf03ad3f9..4e4d511dbe3 100644 --- a/layout/forms/nsGfxRadioControlFrame.cpp +++ b/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/layout/forms/nsGfxRadioControlFrame.h b/layout/forms/nsGfxRadioControlFrame.h index 05823144e4b..907cd9a3d65 100644 --- a/layout/forms/nsGfxRadioControlFrame.h +++ b/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/layout/forms/nsIsIndexFrame.cpp b/layout/forms/nsIsIndexFrame.cpp index b6d5bfd2efa..fd0c15feac6 100644 --- a/layout/forms/nsIsIndexFrame.cpp +++ b/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/layout/forms/nsIsIndexFrame.h b/layout/forms/nsIsIndexFrame.h index ed38d1f1467..e735d272ac2 100644 --- a/layout/forms/nsIsIndexFrame.h +++ b/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/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index d95f62d45b5..e7ddafd1d37 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/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/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 47b1d9c7183..14048d6718c 100644 --- a/layout/forms/nsListControlFrame.h +++ b/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/layout/generic/nsIStatefulFrame.h b/layout/generic/nsIStatefulFrame.h index ae37fcd11d8..33ed56860c9 100644 --- a/layout/generic/nsIStatefulFrame.h +++ b/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/layout/html/base/src/nsFrameManager.cpp b/layout/html/base/src/nsFrameManager.cpp index 53ddc65f8d9..ce542477cc9 100644 --- a/layout/html/base/src/nsFrameManager.cpp +++ b/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/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index 5eb462b9fdf..efb98158b1e 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/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/layout/html/base/src/nsScrollFrame.h b/layout/html/base/src/nsScrollFrame.h index 248cb47ff1f..74ea7a796c1 100644 --- a/layout/html/base/src/nsScrollFrame.h +++ b/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/layout/html/forms/src/nsComboboxControlFrame.cpp b/layout/html/forms/src/nsComboboxControlFrame.cpp index 40a514e34b4..c6a44f3cc63 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/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/layout/html/forms/src/nsComboboxControlFrame.h b/layout/html/forms/src/nsComboboxControlFrame.h index 4889339694e..0b2414106a6 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.h +++ b/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/layout/html/forms/src/nsFileControlFrame.cpp b/layout/html/forms/src/nsFileControlFrame.cpp index 81bdf61bc6f..944ea80ea01 100644 --- a/layout/html/forms/src/nsFileControlFrame.cpp +++ b/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/layout/html/forms/src/nsFileControlFrame.h b/layout/html/forms/src/nsFileControlFrame.h index 80af3b7e802..19118f51bc7 100644 --- a/layout/html/forms/src/nsFileControlFrame.h +++ b/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/layout/html/forms/src/nsGfxButtonControlFrame.cpp b/layout/html/forms/src/nsGfxButtonControlFrame.cpp index 6be2626455a..bb545f61c0c 100644 --- a/layout/html/forms/src/nsGfxButtonControlFrame.cpp +++ b/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/layout/html/forms/src/nsGfxButtonControlFrame.h b/layout/html/forms/src/nsGfxButtonControlFrame.h index f4445defeef..9ba5e168233 100644 --- a/layout/html/forms/src/nsGfxButtonControlFrame.h +++ b/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/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp b/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp index b09b0022f7a..67e6a2f4b9e 100644 --- a/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp +++ b/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/layout/html/forms/src/nsGfxCheckboxControlFrame.h b/layout/html/forms/src/nsGfxCheckboxControlFrame.h index 512bb40c086..0d9218e68ed 100644 --- a/layout/html/forms/src/nsGfxCheckboxControlFrame.h +++ b/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/layout/html/forms/src/nsGfxRadioControlFrame.cpp b/layout/html/forms/src/nsGfxRadioControlFrame.cpp index 2abf03ad3f9..4e4d511dbe3 100644 --- a/layout/html/forms/src/nsGfxRadioControlFrame.cpp +++ b/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/layout/html/forms/src/nsGfxRadioControlFrame.h b/layout/html/forms/src/nsGfxRadioControlFrame.h index 05823144e4b..907cd9a3d65 100644 --- a/layout/html/forms/src/nsGfxRadioControlFrame.h +++ b/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/layout/html/forms/src/nsGfxTextControlFrame2.cpp b/layout/html/forms/src/nsGfxTextControlFrame2.cpp index 68c35200315..e4b2ff637a5 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame2.cpp +++ b/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/layout/html/forms/src/nsGfxTextControlFrame2.h b/layout/html/forms/src/nsGfxTextControlFrame2.h index 3872c68c59a..8c0e8d12205 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame2.h +++ b/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/layout/html/forms/src/nsIsIndexFrame.cpp b/layout/html/forms/src/nsIsIndexFrame.cpp index b6d5bfd2efa..fd0c15feac6 100644 --- a/layout/html/forms/src/nsIsIndexFrame.cpp +++ b/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/layout/html/forms/src/nsIsIndexFrame.h b/layout/html/forms/src/nsIsIndexFrame.h index ed38d1f1467..e735d272ac2 100644 --- a/layout/html/forms/src/nsIsIndexFrame.h +++ b/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/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index d95f62d45b5..e7ddafd1d37 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/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/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index 47b1d9c7183..14048d6718c 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/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/layout/xul/base/src/nsScrollBoxFrame.cpp b/layout/xul/base/src/nsScrollBoxFrame.cpp index fc1a140203d..1537b85bbc9 100644 --- a/layout/xul/base/src/nsScrollBoxFrame.cpp +++ b/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/layout/xul/base/src/nsScrollBoxFrame.h b/layout/xul/base/src/nsScrollBoxFrame.h index b082b07f4b6..07768d87e71 100644 --- a/layout/xul/base/src/nsScrollBoxFrame.h +++ b/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);