Backed out changeset ff043f7356f7
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 11 Sep 2008 14:54:40 -0700
changeset 19166 77c1ffd2f89039a1201a8add669399ea3591632e
parent 19027 ff043f7356f7d920403ac353db111325564570f6
child 19167 068e5618d7f47ad9e022ec26c74c368db2335a98
push idunknown
push userunknown
push dateunknown
milestone1.9.1b1pre
backs outff043f7356f7d920403ac353db111325564570f6
Backed out changeset ff043f7356f7
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
docshell/base/nsWebShell.cpp
docshell/shistory/public/nsISHEntry.idl
docshell/shistory/public/nsISHistoryInternal.idl
docshell/shistory/src/nsSHEntry.cpp
docshell/shistory/src/nsSHEntry.h
docshell/shistory/src/nsSHistory.cpp
layout/base/nsDocumentViewer.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -302,16 +302,18 @@ nsDocShell::nsDocShell():
     mSavingOldViewer(PR_FALSE),
     mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
     mChildOffset(0),
     mBusyFlags(BUSY_FLAGS_NONE),
     mMarginWidth(0),
     mMarginHeight(0),
     mItemType(typeContent),
     mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto),
+    mPreviousTransIndex(-1),
+    mLoadedTransIndex(-1),
     mTreeOwner(nsnull),
     mChromeEventHandler(nsnull)
 #ifdef DEBUG
     , mInEnsureScriptEnv(PR_FALSE)
 #endif
 {
     if (gDocShellCount++ == 0) {
         NS_ASSERTION(sURIFixup == nsnull,
@@ -1626,16 +1628,52 @@ nsDocShell::SetUseErrorPages(PRBool aUse
             mObserveErrorPages = PR_FALSE;
         }
     }
     mUseErrorPages = aUseErrorPages;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocShell::GetPreviousTransIndex(PRInt32 *aPreviousTransIndex)
+{
+    *aPreviousTransIndex = mPreviousTransIndex;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetLoadedTransIndex(PRInt32 *aLoadedTransIndex)
+{
+    *aLoadedTransIndex = mLoadedTransIndex;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::HistoryPurged(PRInt32 aNumEntries)
+{
+    // These indices are used for fastback cache eviction, to determine
+    // which session history entries are candidates for content viewer
+    // eviction.  We need to adjust by the number of entries that we
+    // just purged from history, so that we look at the right session history
+    // entries during eviction.
+    mPreviousTransIndex = PR_MAX(-1, mPreviousTransIndex - aNumEntries);
+    mLoadedTransIndex = PR_MAX(0, mLoadedTransIndex - aNumEntries);
+
+    PRInt32 count = mChildList.Count();
+    for (PRInt32 i = 0; i < count; ++i) {
+        nsCOMPtr<nsIDocShell> shell = do_QueryInterface(ChildAt(i));
+        if (shell) {
+            shell->HistoryPurged(aNumEntries);
+        }
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
                                     nsIDOMStorage** aStorage)
 {
     NS_ENSURE_ARG_POINTER(aStorage);
 
     *aStorage = nsnull;
 
     nsCOMPtr<nsIDocShellTreeItem> topItem;
@@ -2670,23 +2708,40 @@ nsDocShell::DoAddChildSHEntry(nsISHEntry
 {
     /* You will get here when you are in a subframe and
      * a new url has been loaded on you. 
      * The mOSHE in this subframe will be the previous url's
      * mOSHE. This mOSHE will be used as the identification
      * for this subframe in the  CloneAndReplace function.
      */
 
+    // In this case, we will end up calling AddEntry, which increases the
+    // current index by 1
+    nsCOMPtr<nsISHistory> rootSH;
+    GetRootSessionHistory(getter_AddRefs(rootSH));
+    if (rootSH) {
+        rootSH->GetIndex(&mPreviousTransIndex);
+    }
+
     nsresult rv;
     nsCOMPtr<nsIDocShellHistory> parent =
         do_QueryInterface(GetAsSupports(mParent), &rv);
     if (parent) {
         rv = parent->AddChildSHEntry(mOSHE, aNewEntry, aChildOffset);
     }
 
+
+    if (rootSH) {
+        rootSH->GetIndex(&mLoadedTransIndex);
+#ifdef DEBUG_PAGE_CACHE
+        printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex,
+               mLoadedTransIndex);
+#endif
+    }
+
     return rv;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetUseGlobalHistory(PRBool aUseGlobalHistory)
 {
     nsresult rv;
 
@@ -5381,27 +5436,22 @@ nsDocShell::DetachEditorFromWindow()
 nsresult
 nsDocShell::CaptureState()
 {
     if (!mOSHE || mOSHE == mLSHE) {
         // No entry to save into, or we're replacing the existing entry.
         return NS_ERROR_FAILURE;
     }
 
-    PRBool shouldSaveContentViewer = PR_FALSE;
-    nsresult rv = mOSHE->GetSaveContentViewerFlag(&shouldSaveContentViewer);
-    if (NS_FAILED(rv) || !shouldSaveContentViewer)
-        return NS_ERROR_FAILURE;
-
     nsCOMPtr<nsPIDOMWindow> privWin = do_QueryInterface(mScriptGlobal);
     if (!privWin)
         return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsISupports> windowState;
-    rv = privWin->SaveWindowState(getter_AddRefs(windowState));
+    nsresult rv = privWin->SaveWindowState(getter_AddRefs(windowState));
     NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef DEBUG_PAGE_CACHE
     nsCOMPtr<nsIURI> uri;
     mOSHE->GetURI(getter_AddRefs(uri));
     nsCAutoString spec;
     if (uri)
         uri->GetSpec(spec);
@@ -5702,17 +5752,23 @@ nsDocShell::RestoreFromHistory()
     // *new* document will fire.
     mFiredUnloadEvent = PR_FALSE;
 
     mURIResultedInDocument = PR_TRUE;
     nsCOMPtr<nsISHistory> rootSH;
     GetRootSessionHistory(getter_AddRefs(rootSH));
     if (rootSH) {
         nsCOMPtr<nsISHistoryInternal> hist = do_QueryInterface(rootSH);
+        rootSH->GetIndex(&mPreviousTransIndex);
         hist->UpdateIndex();
+        rootSH->GetIndex(&mLoadedTransIndex);
+#ifdef DEBUG_PAGE_CACHE
+        printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex,
+                   mLoadedTransIndex);
+#endif
     }
 
     // Rather than call Embed(), we will retrieve the viewer from the session
     // history entry and swap it in.
     // XXX can we refactor this so that we can just call Embed()?
     PersistLayoutHistoryState();
     nsresult rv;
     if (mContentViewer) {
@@ -8020,17 +8076,23 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIC
         }
     }
 
     // If this was a history load, update the index in 
     // SH. 
     if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) {
         nsCOMPtr<nsISHistoryInternal> shInternal(do_QueryInterface(rootSH));
         if (shInternal) {
+            rootSH->GetIndex(&mPreviousTransIndex);
             shInternal->UpdateIndex();
+            rootSH->GetIndex(&mLoadedTransIndex);
+#ifdef DEBUG_PAGE_CACHE
+            printf("Previous index: %d, Loaded index: %d\n\n",
+                   mPreviousTransIndex, mLoadedTransIndex);
+#endif
         }
     }
     PRBool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel,
                                                   aFireOnLocationChange);
     // Make sure to store the referrer from the channel, if any
     SetupReferrerFromChannel(aChannel);
     return onLocationChangeNeeded;
 }
@@ -8227,17 +8289,23 @@ nsDocShell::AddToSessionHistory(nsIURI *
             if (shPrivate)
                 rv = shPrivate->ReplaceEntry(index, entry);          
         }
         else {
             // Add to session history
             nsCOMPtr<nsISHistoryInternal>
                 shPrivate(do_QueryInterface(mSessionHistory));
             NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
+            mSessionHistory->GetIndex(&mPreviousTransIndex);
             rv = shPrivate->AddEntry(entry, shouldPersist);
+            mSessionHistory->GetIndex(&mLoadedTransIndex);
+#ifdef DEBUG_PAGE_CACHE
+            printf("Previous index: %d, Loaded index: %d\n\n",
+                   mPreviousTransIndex, mLoadedTransIndex);
+#endif
         }
     }
     else {  
         // This is a subframe.
         if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType,
                                            LOAD_FLAGS_REPLACE_HISTORY))
             rv = DoAddChildSHEntry(entry, mChildOffset);
     }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -643,16 +643,21 @@ protected:
     // Holds a weak pointer to a RestorePresentationEvent object if any that
     // holds a weak pointer back to us.  We use this pointer to possibly revoke
     // the event whenever necessary.
     nsRevocableEventPtr<RestorePresentationEvent> mRestorePresentationEvent;
 
     // hash of session storages, keyed by domain
     nsInterfaceHashtable<nsCStringHashKey, nsIDOMStorage> mStorages;
 
+    // Index into the SHTransaction list, indicating the previous and current
+    // transaction at the time that this DocShell begins to load
+    PRInt32                    mPreviousTransIndex;
+    PRInt32                    mLoadedTransIndex;
+
     // Editor data, if this document is designMode or contentEditable.
     nsAutoPtr<nsDocShellEditorData> mEditorData;
 
     // Transferable hooks/callbacks
     nsCOMPtr<nsIClipboardDragDropHookList>  mTransferableHookData;
 
     // Secure browser UI object
     nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -63,17 +63,17 @@ interface nsIWebNavigation;
 interface nsISimpleEnumerator;
 interface nsIInputStream;
 interface nsIRequest;
 interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 
-[scriptable, uuid(cf974f45-d2f1-4bd5-aecd-568a1c4da454)]
+[scriptable, uuid(7d1cf6b9-daa3-476d-8f9f-9eb2a971a95c)]
 interface nsIDocShell : nsISupports
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -395,16 +395,32 @@ interface nsIDocShell : nsISupports
   void finishRestore();
 
   /* Track whether we're currently restoring a document presentation. */
   readonly attribute boolean restoringDocument;
 
   /* attribute to access whether error pages are enabled */
   attribute boolean useErrorPages;
 
+  /**
+   * Keeps track of the previous SHTransaction index and the current
+   * SHTransaction index at the time that the doc shell begins to load.
+   * Used for ContentViewer eviction.
+   */
+  readonly attribute long previousTransIndex;
+  readonly attribute long loadedTransIndex;
+
+  /**
+   * Notification that entries have been removed from the beginning of a
+   * nsSHistory which has this as its rootDocShell.
+   *
+   * @param numEntries - The number of entries removed
+   */
+  void historyPurged(in long numEntries);
+
   /*
    * Retrieves the WebApps session storage object for the supplied domain.
    * If it doesn't already exist, a new one will be created.
    *
    * @param domain the domain of the storage object to retrieve
    */
   nsIDOMStorage getSessionStorageForURI(in nsIURI uri);
 
--- a/docshell/base/nsWebShell.cpp
+++ b/docshell/base/nsWebShell.cpp
@@ -1234,17 +1234,23 @@ nsresult nsWebShell::EndPageLoad(nsIWebP
             rootAsWebnav->GetSessionHistory(getter_AddRefs(rootSH));
             }
           }
         }  // mSessionHistory
 
         if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) {
           nsCOMPtr<nsISHistoryInternal> shInternal(do_QueryInterface(rootSH));
           if (shInternal) {
+            rootSH->GetIndex(&mPreviousTransIndex);
             shInternal->UpdateIndex();
+            rootSH->GetIndex(&mLoadedTransIndex);
+#ifdef DEBUG_PAGE_CACHE
+            printf("Previous index: %d, Loaded index: %d\n\n",
+                  mPreviousTransIndex, mLoadedTransIndex);
+#endif
           }
         }
 
         // Make it look like we really did honestly finish loading the
         // history page we were loading, since the "reload" load we're
         // about to kick off will reload our current history entry.  This
         // is a bit of a hack, and if the force-load fails I think we'll
         // end up being confused about what page we're on... but we would
--- a/docshell/shistory/public/nsISHEntry.idl
+++ b/docshell/shistory/public/nsISHEntry.idl
@@ -53,17 +53,17 @@ interface nsISupportsArray;
 %{C++
 struct nsRect;
 class nsDocShellEditorData;
 %}
 [ref] native nsRect(nsRect);
 [ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
 
 
-[scriptable, uuid(622412da-be41-407e-b57e-9aba2a282b00)]
+[scriptable, uuid(c16fde76-3108-450e-8c8c-ae8286f286ed)]
 interface nsISHEntry : nsIHistoryEntry
 {
     /** URI for the document */
     void setURI(in nsIURI aURI);
 
     /** Referrer URI */
     attribute nsIURI referrerURI;
 
@@ -147,19 +147,16 @@ interface nsISHEntry : nsIHistoryEntry
      * 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;
 
-    /** attribute to indicate whether the contentViewer should be saved */
-    attribute boolean saveContentViewerFlag;
-
     /** attribute to indicate whether layoutHistoryState should be saved */
     attribute boolean saveLayoutStateFlag;
 
     /** attribute to indicate whether the page is already expired in cache */
     attribute boolean expirationStatus;
 
     /**
      * attribute to indicate the content-type of the document that this
--- a/docshell/shistory/public/nsISHistoryInternal.idl
+++ b/docshell/shistory/public/nsISHistoryInternal.idl
@@ -47,17 +47,17 @@ interface nsIDocShell;
 %{C++
 #define NS_SHISTORY_INTERNAL_CID \
 { 0x9c47c121, 0x1c6e, 0x4d8f, \
   { 0xb9, 0x04, 0x3a, 0xc9, 0x68, 0x11, 0x6e, 0x88 } }
 
 #define NS_SHISTORY_INTERNAL_CONTRACTID "@mozilla.org/browser/shistory-internal;1"
 %}
 
-[scriptable, uuid(0e91697a-4ba0-4ede-b08a-0bae9ee1a701)]
+[scriptable, uuid(9c47c121-1c6e-4d8f-b904-3ac968116e88)]
 interface nsISHistoryInternal: nsISupports
 {
   /**
    * Add a new Entry to the History List
    * @param aEntry - The entry to add
    * @param aPersist - If true this specifies that the entry should persist
    * in the list.  If false, this means that when new entries are added
    * this element will not appear in the session history list.
@@ -87,20 +87,22 @@ interface nsISHistoryInternal: nsISuppor
    void replaceEntry(in long aIndex, in nsISHEntry aReplaceEntry);
 
   /** 
    * Get handle to the history listener
    */
    readonly attribute nsISHistoryListener listener;
 
   /**
-   * Count total number of content viewers globally and evict one if we are over
-   * our total max.  This is always called in Show(), after we destroy the
-   * previous viewer.
+   * Evict content viewers until the number of content viewers per tab
+   * is no more than gHistoryMaxViewers.  Also, count
+   * total number of content viewers globally and evict one if we are over
+   * our total max.  This is always called in Show(), after we destroy
+   * the previous viewer.
    */
-   void evictContentViewers();
+   void evictContentViewers(in long previousIndex, in long index);
    
    /**
     * Evict the content viewer associated with a session history entry
     * that has timed out.
     */
    void evictExpiredContentViewerForEntry(in nsISHEntry aEntry);
 };
--- a/docshell/shistory/src/nsSHEntry.cpp
+++ b/docshell/shistory/src/nsSHEntry.cpp
@@ -101,17 +101,16 @@ static void StopTrackingEntry(nsSHEntry 
 
 
 nsSHEntry::nsSHEntry() 
   : mLoadType(0)
   , mID(gEntryID++)
   , mPageIdentifier(mID)
   , mScrollPositionX(0)
   , mScrollPositionY(0)
-  , mSaveContentViewer(PR_TRUE)
   , mIsFrameNavigation(PR_FALSE)
   , mSaveLayoutState(PR_TRUE)
   , mExpired(PR_FALSE)
   , mSticky(PR_TRUE)
   , mParent(nsnull)
   , mViewerBounds(0, 0, 0, 0)
 {
 }
@@ -123,17 +122,16 @@ nsSHEntry::nsSHEntry(const nsSHEntry &ot
   , mTitle(other.mTitle)
   , mPostData(other.mPostData)
   , 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?
-  , mSaveContentViewer(other.mSaveContentViewer)
   , mIsFrameNavigation(other.mIsFrameNavigation)
   , mSaveLayoutState(other.mSaveLayoutState)
   , mExpired(other.mExpired)
   , mSticky(PR_TRUE)
   // XXX why not copy mContentType?
   , mCacheKey(other.mCacheKey)
   , mParent(other.mParent)
   , mViewerBounds(0, 0, 0, 0)
@@ -413,28 +411,16 @@ NS_IMETHODIMP nsSHEntry::GetCacheKey(nsI
 }
 
 NS_IMETHODIMP nsSHEntry::SetCacheKey(nsISupports* aCacheKey)
 {
   mCacheKey = aCacheKey;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsSHEntry::GetSaveContentViewerFlag(PRBool * aFlag)
-{
-  *aFlag = mSaveContentViewer;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsSHEntry::SetSaveContentViewerFlag(PRBool  aFlag)
-{
-  mSaveContentViewer = aFlag;
-  return NS_OK;
-}
-
 NS_IMETHODIMP nsSHEntry::GetSaveLayoutStateFlag(PRBool * aFlag)
 {
   *aFlag = mSaveLayoutState;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsSHEntry::SetSaveLayoutStateFlag(PRBool  aFlag)
 {
--- a/docshell/shistory/src/nsSHEntry.h
+++ b/docshell/shistory/src/nsSHEntry.h
@@ -97,17 +97,16 @@ private:
   nsCOMPtr<nsIInputStream>        mPostData;
   nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
   nsCOMArray<nsISHEntry>          mChildren;
   PRUint32                        mLoadType;  
   PRUint32                        mID;
   PRUint32                        mPageIdentifier;
   PRInt32                         mScrollPositionX;
   PRInt32                         mScrollPositionY;
-  PRPackedBool                    mSaveContentViewer;
   PRPackedBool                    mIsFrameNavigation;
   PRPackedBool                    mSaveLayoutState;
   PRPackedBool                    mExpired;
   PRPackedBool                    mSticky;
   nsCString                       mContentType;
   nsCOMPtr<nsISupports>           mCacheKey;
   nsISHEntry *                    mParent;  // weak reference
   nsCOMPtr<nsISupports>           mWindowState;
--- a/docshell/shistory/src/nsSHistory.cpp
+++ b/docshell/shistory/src/nsSHistory.cpp
@@ -325,29 +325,26 @@ nsSHistory::AddEntry(nsISHEntry * aSHEnt
   // Set the ShEntry and parent for the transaction. setting the 
   // parent will properly set the parent child relationship
   txn->SetPersist(aPersist);
   NS_ENSURE_SUCCESS(txn->Create(aSHEntry, currentTxn), NS_ERROR_FAILURE);
    
   // A little tricky math here...  Basically when adding an object regardless of
   // what the length was before, it should always be set back to the current and
   // lop off the forward.
-  PRInt32 oldIndex = mIndex;
   mLength = (++mIndex + 1);
 
   // If this is the very first transaction, initialize the list
   if(!mListRoot)
     mListRoot = txn;
 
   // Purge History list if it is too long
   if ((gHistoryMaxSize >= 0) && (mLength > gHistoryMaxSize))
     PurgeHistory(mLength-gHistoryMaxSize);
   
-  // Evict a content viewer if we might have too many behind us
-  EvictWindowContentViewers(oldIndex, mIndex);
   return NS_OK;
 }
 
 /* Get size of the history list */
 NS_IMETHODIMP
 nsSHistory::GetCount(PRInt32 * aResult)
 {
   NS_ENSURE_ARG_POINTER(aResult);
@@ -581,16 +578,19 @@ nsSHistory::PurgeHistory(PRInt32 aEntrie
   mIndex -= cnt;
 
   // Now if we were not at the end of the history, mIndex could have
   // become far too negative.  If so, just set it to -1.
   if (mIndex < -1) {
     mIndex = -1;
   }
 
+  if (mRootDocShell)
+    mRootDocShell->HistoryPurged(cnt);
+
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsSHistory::AddSHistoryListener(nsISHistoryListener * aListener)
 {
   NS_ENSURE_ARG_POINTER(aListener);
@@ -650,18 +650,20 @@ nsSHistory::GetListener(nsISHistoryListe
   NS_ENSURE_ARG_POINTER(aListener);
   if (mListener) 
     CallQueryReferent(mListener.get(),  aListener);
   // Don't addref aListener. It is a weak pointer.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSHistory::EvictContentViewers()
+nsSHistory::EvictContentViewers(PRInt32 aPreviousIndex, PRInt32 aIndex)
 {
+  // Check our per SHistory object limit in the currently navigated SHistory
+  EvictWindowContentViewers(aPreviousIndex, aIndex);
   // Check our total limit across all SHistory objects
   EvictGlobalContentViewer();
   return NS_OK;
 }
 
 //*****************************************************************************
 //    nsSHistory: nsIWebNavigation
 //*****************************************************************************
@@ -1119,25 +1121,16 @@ nsSHistory::LoadURI(const PRUnichar* aUR
                     nsIInputStream* aExtraHeaderStream)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSHistory::GotoIndex(PRInt32 aIndex)
 {
- 
-  if (mIndex > -1 && PR_ABS(aIndex - mIndex) > gHistoryMaxViewers) {
-    // The current entry is too far from the new index, so mark it so its
-    // content viewer doesn't get saved.
-    nsCOMPtr<nsISHEntry> currentEntry;
-    nsresult rv = GetEntryAtIndex(mIndex, PR_FALSE, getter_AddRefs(currentEntry));
-    if (NS_SUCCEEDED(rv) && currentEntry)
-      currentEntry->SetSaveContentViewerFlag(PR_FALSE);
-  }
   return LoadEntry(aIndex, nsIDocShellLoadInfo::loadHistory, HIST_CMD_GOTOINDEX);
 }
 
 NS_IMETHODIMP
 nsSHistory::LoadEntry(PRInt32 aIndex, long aLoadType, PRUint32 aHistCmd)
 {
   nsCOMPtr<nsIDocShell> docShell;
   nsCOMPtr<nsISHEntry> shEntry;
@@ -1223,27 +1216,17 @@ nsSHistory::LoadEntry(PRInt32 aIndex, lo
   if (!docShell) {
     // we did not successfully go to the proper index.
     // return error.
     mRequestedIndex = -1;
     return NS_ERROR_FAILURE;
   }
 
   // Start the load on the appropriate docshell
-  nsresult rv = InitiateLoad(nextEntry, docShell, aLoadType);
-
-  if (NS_SUCCEEDED(rv)) {
-    // mark the entry as being able to save its content viewer
-    nextEntry->SetSaveContentViewerFlag(PR_TRUE);
-    // evict any content viewers that are now gHistoryMaxViewers
-    // or more away from the new index
-    EvictWindowContentViewers(mIndex, mRequestedIndex);
-  }
-
-  return rv;
+  return InitiateLoad(nextEntry, docShell, aLoadType);
 }
 
 
 
 nsresult
 nsSHistory::CompareFrames(nsISHEntry * aPrevEntry, nsISHEntry * aNextEntry, nsIDocShell * aParent, long aLoadType, PRBool * aIsFrameFound)
 {
   if (!aPrevEntry || !aNextEntry || !aParent)
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1856,20 +1856,25 @@ DocumentViewerImpl::Show(void)
       // SHistory and we need the SHistory to evict content viewers
       nsCOMPtr<nsIDocShellTreeItem> root;
       treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
       nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
       nsCOMPtr<nsISHistory> history;
       webNav->GetSessionHistory(getter_AddRefs(history));
       nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history);
       if (historyInt) {
+        PRInt32 prevIndex,loadedIndex;
+        nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
+        docShell->GetPreviousTransIndex(&prevIndex);
+        docShell->GetLoadedTransIndex(&loadedIndex);
 #ifdef DEBUG_PAGE_CACHE
-        printf("About to evict content viewers\n");
+        printf("About to evict content viewers: prev=%d, loaded=%d\n",
+               prevIndex, loadedIndex);
 #endif
-        historyInt->EvictContentViewers();
+        historyInt->EvictContentViewers(prevIndex, loadedIndex);
       }
     }
   }
 
   if (mWindow) {
     mWindow->Show(PR_TRUE);
   }