Index: Source/WebCore/loader/HistoryController.cpp |
=================================================================== |
--- Source/WebCore/loader/HistoryController.cpp (revision 77734) |
+++ Source/WebCore/loader/HistoryController.cpp (working copy) |
@@ -236,7 +236,7 @@ |
// Set the BF cursor before commit, which lets the user quickly click back/forward again. |
// - plus, it only makes sense for the top level of the operation through the frametree, |
// as opposed to happening for some/one of the page commits that might happen soon |
- HistoryItem* currentItem = page->backForward()->currentItem(); |
+ RefPtr<HistoryItem> currentItem = page->backForward()->currentItem(); |
page->backForward()->setCurrentItem(targetItem); |
Settings* settings = m_frame->settings(); |
page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : targetItem); |
@@ -245,9 +245,9 @@ |
// This must be done before trying to navigate the desired frame, because some |
// navigations can commit immediately (such as about:blank). We must be sure that |
// all frames have provisional items set before the commit. |
- recursiveSetProvisionalItem(targetItem, currentItem, type); |
+ recursiveSetProvisionalItem(targetItem, currentItem.get(), type); |
// Now that all other frames have provisional items, do the actual navigation. |
- recursiveGoToItem(targetItem, currentItem, type); |
+ recursiveGoToItem(targetItem, currentItem.get(), type); |
} |
void HistoryController::updateForBackForwardNavigation() |
@@ -402,8 +402,9 @@ |
LOG(History, "WebCoreHistory: Updating History for commit in frame %s", frameLoader->documentLoader()->title().utf8().data()); |
#endif |
FrameLoadType type = frameLoader->loadType(); |
- if (isBackForwardLoadType(type) || |
- ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin) && !frameLoader->provisionalDocumentLoader()->unreachableURL().isEmpty())) { |
+ if (isBackForwardLoadType(type) |
+ || isReplaceLoadTypeWithProvisionalItem(type) |
+ || ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin) && !frameLoader->provisionalDocumentLoader()->unreachableURL().isEmpty())) { |
// Once committed, we want to use current item for saving DocState, and |
// the provisional item for restoring state. |
// Note previousItem must be set before we close the URL, which will |
@@ -423,6 +424,13 @@ |
} |
} |
+bool HistoryController::isReplaceLoadTypeWithProvisionalItem(FrameLoadType type) |
+{ |
+ // Going back to an error page in a subframe can trigger a FrameLoadTypeReplace |
+ // while m_provisionalItem is set, so we need to commit it. |
+ return type == FrameLoadTypeReplace && m_provisionalItem; |
+} |
+ |
void HistoryController::recursiveUpdateForCommit() |
{ |
// The frame that navigated will now have a null provisional item. |
@@ -471,8 +479,27 @@ |
return; |
addVisitedLink(page, m_frame->loader()->url()); |
+ page->mainFrame()->loader()->history()->recursiveUpdateForSameDocumentNavigation(); |
} |
+void HistoryController::recursiveUpdateForSameDocumentNavigation() |
+{ |
+ // The frame that navigated will now have a null provisional item. |
+ // Ignore it and its children. |
+ if (!m_provisionalItem) |
+ return; |
+ |
+ // Commit the provisional item. |
+ m_frameLoadComplete = false; |
+ m_previousItem = m_currentItem; |
+ m_currentItem = m_provisionalItem; |
+ m_provisionalItem = 0; |
+ |
+ // Iterate over the rest of the tree. |
+ for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) |
+ child->loader()->history()->recursiveUpdateForSameDocumentNavigation(); |
+} |
+ |
void HistoryController::updateForFrameLoadCompleted() |
{ |
// Even if already complete, we might have set a previous item on a frame that |
@@ -620,6 +647,7 @@ |
const HistoryItemVector& childItems = item->children(); |
int size = childItems.size(); |
+ |
for (int i = 0; i < size; ++i) { |
String childFrameName = childItems[i]->target(); |
HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFrameName); |
@@ -658,14 +686,6 @@ |
bool HistoryController::itemsAreClones(HistoryItem* item1, HistoryItem* item2) const |
{ |
- // It appears that one of the items can be null in release builds, leading |
- // to the crashes seen in http://webkit.org/b/52819. For now, try to |
- // narrow it down with a more specific crash. |
- if (!item1) |
- CRASH(); |
- if (!item2) |
- CRASH(); |
- |
// If the item we're going to is a clone of the item we're at, then we do |
// not need to load it again. The current frame tree and the frame tree |
// snapshot in the item have to match. |