diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index a75e877c72e2..1d1ebc6bf72f 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -5255,24 +5255,34 @@ nsDocShell::InternalLoad(nsIURI * aURI, // // First: // Check to see if the new URI is an anchor in the existing document. - // Skip this check if we're doing some sort of abnormal load, if - // the new load is a non-history load and has postdata, or if - // we're doing a history load and there are postdata differences - // between what we plan to load and what we have loaded currently. + // Skip this check if we're doing some sort of abnormal load, if the + // new load is a non-history load and has postdata, or if we're doing + // a history load and the page identifiers of mOSHE and aSHEntry + // don't match. // - PRBool samePostData = PR_TRUE; + PRBool allowScroll = PR_TRUE; if (!aSHEntry) { - samePostData = (aPostData == nsnull); + allowScroll = (aPostData == nsnull); } else if (mOSHE) { - nsCOMPtr currentPostData; - mOSHE->GetPostData(getter_AddRefs(currentPostData)); - samePostData = (currentPostData == aPostData); + PRUint32 ourPageIdent; + mOSHE->GetPageIdentifier(&ourPageIdent); + PRUint32 otherPageIdent; + aSHEntry->GetPageIdentifier(&otherPageIdent); + allowScroll = (ourPageIdent == otherPageIdent); +#ifdef DEBUG + if (allowScroll) { + nsCOMPtr currentPostData; + mOSHE->GetPostData(getter_AddRefs(currentPostData)); + NS_ASSERTION(currentPostData == aPostData, + "Different POST data for entries for the same page?"); + } +#endif } if ((aLoadType == LOAD_NORMAL || aLoadType == LOAD_NORMAL_REPLACE || aLoadType == LOAD_HISTORY || - aLoadType == LOAD_LINK) && samePostData) { + aLoadType == LOAD_LINK) && allowScroll) { PRBool wasAnchor = PR_FALSE; nscoord cx, cy; NS_ENSURE_SUCCESS(ScrollIfAnchor(aURI, &wasAnchor, aLoadType, &cx, &cy), NS_ERROR_FAILURE); @@ -5293,14 +5303,17 @@ nsDocShell::InternalLoad(nsIURI * aURI, */ OnNewURI(aURI, nsnull, mLoadType); nsCOMPtr postData; + PRUint32 pageIdent = PR_UINT32_MAX; if (mOSHE) { /* save current position of scroller(s) (bug 59774) */ mOSHE->SetScrollPosition(cx, cy); - // Get the postdata from the current page, if it was - // loaded through normal means. - if (aLoadType == LOAD_NORMAL || aLoadType == LOAD_LINK) + // Get the postdata and page ident from the current page, + // if the new load is being done via normal means. + if (aLoadType == LOAD_NORMAL || aLoadType == LOAD_LINK) { mOSHE->GetPostData(getter_AddRefs(postData)); + mOSHE->GetPageIdentifier(&pageIdent); + } } /* Assign mOSHE to mLSHE. This will either be a new entry created @@ -5314,6 +5327,11 @@ nsDocShell::InternalLoad(nsIURI * aURI, // page will restore the appropriate postData. if (postData) mOSHE->SetPostData(postData); + + // Propagate our page ident to the new mOSHE so that + // we'll know it just differed by a scroll on the page. + if (pageIdent != PR_UINT32_MAX) + mOSHE->SetPageIdentifier(pageIdent); } /* restore previous position of scroller(s), if we're moving diff --git a/xpfe/components/shistory/public/nsISHEntry.idl b/xpfe/components/shistory/public/nsISHEntry.idl index 863181b24a30..9e5d7336489b 100644 --- a/xpfe/components/shistory/public/nsISHEntry.idl +++ b/xpfe/components/shistory/public/nsISHEntry.idl @@ -49,7 +49,7 @@ interface nsILayoutHistoryState; interface nsIDOMDocument; -[scriptable, uuid(65281BA1-988A-11d3-BDC7-0050040A9B44)] +[scriptable, uuid(6b596e1f-a3bd-40f9-a7ee-ab3edc7f9960)] interface nsISHEntry : nsISupports { @@ -86,6 +86,16 @@ attribute unsigned long loadType; */ attribute unsigned long ID; +/** + * pageIdentifier is an integer that should be the same for two entries + * attached to the same docshell only if the two entries are entries for the + * same page in the sense that one could go from the state represented by one + * to the state represented by the other simply by scrolling (so the entries + * are separated by an anchor traversal or a subframe navigation in some other + * frame). + */ +attribute unsigned long pageIdentifier; + /** attribute to set and get the cache key for the entry */ attribute nsISupports cacheKey; diff --git a/xpfe/components/shistory/src/nsSHEntry.cpp b/xpfe/components/shistory/src/nsSHEntry.cpp index bebe564fc1aa..313e507b16b7 100644 --- a/xpfe/components/shistory/src/nsSHEntry.cpp +++ b/xpfe/components/shistory/src/nsSHEntry.cpp @@ -52,6 +52,7 @@ static PRUint32 gEntryID = 0; nsSHEntry::nsSHEntry() : mLoadType(0) , mID(gEntryID++) + , mPageIdentifier(mID) , mScrollPositionX(0) , mScrollPositionY(0) , mIsFrameNavigation(PR_FALSE) @@ -70,6 +71,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other) , mLayoutHistoryState(other.mLayoutHistoryState) , mLoadType(0) // XXX why not copy? , mID(other.mID) + , mPageIdentifier(other.mPageIdentifier) , mScrollPositionX(0) // XXX why not copy? , mScrollPositionY(0) // XXX why not copy? , mIsFrameNavigation(other.mIsFrameNavigation) @@ -215,6 +217,18 @@ NS_IMETHODIMP nsSHEntry::SetID(PRUint32 aID) return NS_OK; } +NS_IMETHODIMP nsSHEntry::GetPageIdentifier(PRUint32 * aResult) +{ + *aResult = mPageIdentifier; + return NS_OK; +} + +NS_IMETHODIMP nsSHEntry::SetPageIdentifier(PRUint32 aPageIdentifier) +{ + mPageIdentifier = aPageIdentifier; + return NS_OK; +} + NS_IMETHODIMP nsSHEntry::GetIsSubFrame(PRBool * aFlag) { *aFlag = mIsFrameNavigation; diff --git a/xpfe/components/shistory/src/nsSHEntry.h b/xpfe/components/shistory/src/nsSHEntry.h index c54f5cf12626..f4fa459a0049 100644 --- a/xpfe/components/shistory/src/nsSHEntry.h +++ b/xpfe/components/shistory/src/nsSHEntry.h @@ -80,6 +80,7 @@ private: nsCOMArray mChildren; PRUint32 mLoadType; PRUint32 mID; + PRUint32 mPageIdentifier; PRInt32 mScrollPositionX; PRInt32 mScrollPositionY; PRPackedBool mIsFrameNavigation;