2010-11-22 Charlie Reis <creis@chromium.org>
[WebKit-https.git] / WebCore / loader / HistoryController.cpp
index 07bece7..ff733a9 100644 (file)
@@ -66,6 +66,7 @@ static inline void addVisitedLink(Page* page, const KURL& url)
 
 HistoryController::HistoryController(Frame* frame)
     : m_frame(frame)
+    , m_frameLoadComplete(true)
 {
 }
 
@@ -138,10 +139,10 @@ void HistoryController::saveDocumentState()
     // target of the current navigation (if we even decide to save with that granularity).
 
     // Because of previousItem's "masking" of currentItem for this purpose, it's important
-    // that previousItem be cleared at the end of a page transition.  We leverage the
-    // checkLoadComplete recursion to achieve this goal.
+    // that we keep track of the end of a page transition with m_frameLoadComplete.  We
+    // leverage the checkLoadComplete recursion to achieve this goal.
 
-    HistoryItem* item = m_previousItem ? m_previousItem.get() : m_currentItem.get();
+    HistoryItem* item = m_frameLoadComplete ? m_currentItem.get() : m_previousItem.get();
     if (!item)
         return;
 
@@ -245,7 +246,8 @@ void HistoryController::updateForBackForwardNavigation()
 #endif
 
     // Must grab the current scroll position before disturbing it
-    saveScrollPositionAndViewStateToItem(m_previousItem.get());
+    if (!m_frameLoadComplete)
+        saveScrollPositionAndViewStateToItem(m_previousItem.get());
 }
 
 void HistoryController::updateForReload()
@@ -392,6 +394,7 @@ void HistoryController::updateForCommit()
         // the provisional item for restoring state.
         // Note previousItem must be set before we close the URL, which will
         // happen when the data source is made non-provisional below
+        m_frameLoadComplete = false;
         m_previousItem = m_currentItem;
         ASSERT(m_provisionalItem);
         m_currentItem = m_provisionalItem;
@@ -418,12 +421,15 @@ void HistoryController::updateForSameDocumentNavigation()
 void HistoryController::updateForFrameLoadCompleted()
 {
     // Even if already complete, we might have set a previous item on a frame that
-    // didn't do any data loading on the past transaction. Make sure to clear these out.
-    m_previousItem = 0;
+    // didn't do any data loading on the past transaction. Make sure to track that
+    // the load is complete so that we use the current item instead.
+    m_frameLoadComplete = true;
 }
 
 void HistoryController::setCurrentItem(HistoryItem* item)
 {
+    m_frameLoadComplete = false;
+    m_previousItem = m_currentItem;
     m_currentItem = item;
 }
 
@@ -498,6 +504,7 @@ PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal)
     }
     
     // Set the item for which we will save document state
+    m_frameLoadComplete = false;
     m_previousItem = m_currentItem;
     m_currentItem = item;
     
@@ -507,7 +514,7 @@ PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal)
 PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget)
 {
     RefPtr<HistoryItem> bfItem = createItem(m_frame->tree()->parent() ? true : false);
-    if (m_previousItem)
+    if (!m_frameLoadComplete)
         saveScrollPositionAndViewStateToItem(m_previousItem.get());
 
     if (!clipAtTarget || m_frame != targetFrame) {
@@ -563,14 +570,15 @@ void HistoryController::recursiveGoToItem(HistoryItem* item, HistoryItem* fromIt
         && fromItem->hasSameFrames(item))
     {
         // This content is good, so leave it alone and look for children that need reloading
-        // Save form state (works from currentItem, since prevItem is nil)
-        ASSERT(!m_previousItem);
+        // Save form state (works from currentItem, since m_frameLoadComplete is true)
+        ASSERT(m_frameLoadComplete);
         saveDocumentState();
         saveScrollPositionAndViewStateToItem(m_currentItem.get());
 
         if (FrameView* view = m_frame->view())
             view->setWasScrolledByUser(false);
 
+        m_previousItem = m_currentItem;
         m_currentItem = item;
                 
         // Restore form state (works from currentItem)