PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget) { RefPtr<HistoryItem> bfItem = createItem(); saveScrollPositionAndViewStateToItem(m_previousItem.get()); if (!clipAtTarget || m_frame != targetFrame) { // save frame state for items that aren't loading (khtml doesn't save those) saveDocumentState(); // clipAtTarget is false for navigations within the same document, so // we should copy the documentSequenceNumber over to the newly create // item. Non-target items are just clones, and they should therefore // preserve the same itemSequenceNumber. if (m_previousItem) { if (m_frame != targetFrame) bfItem->setItemSequenceNumber(m_previousItem->itemSequenceNumber()); bfItem->setDocumentSequenceNumber(m_previousItem->documentSequenceNumber()); } for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { // If the child is a frame corresponding to an <object> element that never loaded, // we don't want to create a history item, because that causes fallback content // to be ignored on reload. FrameLoader* childLoader = child->loader(); if (childLoader->stateMachine()->startedFirstRealLoad() || !child->ownerElement()->isObjectElement()) bfItem->addChildItem(childLoader->history()->createItemTree(targetFrame, clipAtTarget)); } } // FIXME: Eliminate the isTargetItem flag in favor of itemSequenceNumber. if (m_frame == targetFrame) bfItem->setIsTargetItem(true); return bfItem; }
void HistoryController::recursiveUpdateForCommit() { // The frame that navigated will now have a null provisional item. // Ignore it and its children. if (!m_provisionalItem) return; // For each frame that already had the content the item requested (based on // (a matching URL and frame tree snapshot), just restore the scroll position. // Save form state (works from currentItem, since m_frameLoadComplete is true) if (m_currentItem && itemsAreClones(m_currentItem.get(), m_provisionalItem.get())) { ASSERT(m_frameLoadComplete); saveDocumentState(); saveScrollPositionAndViewStateToItem(m_currentItem.get()); if (FrameView* view = m_frame->view()) view->setWasScrolledByUser(false); // Now commit the provisional item m_frameLoadComplete = false; m_previousItem = m_currentItem; m_currentItem = m_provisionalItem; m_provisionalItem = 0; // Restore form state (works from currentItem) restoreDocumentState(); // Restore the scroll position (we choose to do this rather than going back to the anchor point) restoreScrollPositionAndViewState(); } // Iterate over the rest of the tree for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) child->loader()->history()->recursiveUpdateForCommit(); }
void HistoryController::updateForBackForwardNavigation() { #if !LOG_DISABLED if (m_frame->loader()->documentLoader()) LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); #endif // Must grab the current scroll position before disturbing it saveScrollPositionAndViewStateToItem(m_previousItem.get()); }
void HistoryController::updateForBackForwardNavigation() { LOG(History, "HistoryController %p updateForBackForwardNavigation: Updating History for back/forward navigation in frame %p (main frame %d) %s", this, &m_frame, m_frame.isMainFrame(), m_frame.loader().documentLoader() ? m_frame.loader().documentLoader()->url().string().utf8().data() : ""); // Must grab the current scroll position before disturbing it if (!m_frameLoadComplete) saveScrollPositionAndViewStateToItem(m_previousItem.get()); // When traversing history, we may end up redirecting to a different URL // this time (e.g., due to cookies). See http://webkit.org/b/49654. updateCurrentItem(); }
// The general idea here is to traverse the frame tree and the item tree in parallel, // tracking whether each frame already has the content the item requests. If there is // a match (by URL), we just restore scroll position and recurse. Otherwise we must // reload that frame, and all its kids. void HistoryController::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type) { ASSERT(item); ASSERT(fromItem); KURL itemURL = item->url(); KURL currentURL; if (m_frame->loader()->documentLoader()) currentURL = m_frame->loader()->documentLoader()->url(); // Always reload the target frame of the item we're going to. This ensures that we will // do -some- load for the transition, which means a proper notification will be posted // to the app. // The exact URL has to match, including fragment. We want to go through the _load // method, even if to do a within-page navigation. // The current frame tree and the frame tree snapshot in the item have to match. if (!item->isTargetItem() && itemURL == currentURL && ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) && childFramesMatchItem(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); saveDocumentState(); saveScrollPositionAndViewStateToItem(m_currentItem.get()); if (FrameView* view = m_frame->view()) view->setWasScrolledByUser(false); m_currentItem = item; // Restore form state (works from currentItem) restoreDocumentState(); // Restore the scroll position (we choose to do this rather than going back to the anchor point) restoreScrollPositionAndViewState(); 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); ASSERT(fromChildItem || fromItem->isTargetItem()); Frame* childFrame = m_frame->tree()->child(childFrameName); ASSERT(childFrame); childFrame->loader()->history()->recursiveGoToItem(childItems[i].get(), fromChildItem, type); } } else { m_frame->loader()->loadItem(item, type); } }
void HistoryController::updateForBackForwardNavigation() { #if !LOG_DISABLED LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", m_frame->document()->title().utf8().data()); #endif saveScrollPositionAndViewStateToItem(m_previousItem.get()); // When traversing history, we may end up redirecting to a different URL // this time (e.g., due to cookies). See http://webkit.org/b/49654. updateCurrentItem(); }
// The general idea here is to traverse the frame tree and the item tree in parallel, // tracking whether each frame already has the content the item requests. If there is // a match (by URL), we just restore scroll position and recurse. Otherwise we must // reload that frame, and all its kids. void HistoryController::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type) { ASSERT(item); ASSERT(fromItem); // If the item we're going to is a clone of the item we're at, then do // not load it again, and continue history traversal to its children. // The current frame tree and the frame tree snapshot in the item have // to match. // Note: If item and fromItem are the same, then we need to create a new // document. if (item != fromItem && item->itemSequenceNumber() == fromItem->itemSequenceNumber() && currentFramesMatchItem(item) && 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 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) restoreDocumentState(); // Restore the scroll position (we choose to do this rather than going back to the anchor point) restoreScrollPositionAndViewState(); 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); ASSERT(fromChildItem); Frame* childFrame = m_frame->tree()->child(childFrameName); ASSERT(childFrame); childFrame->loader()->history()->recursiveGoToItem(childItems[i].get(), fromChildItem, type); } } else { m_frame->loader()->loadItem(item, type); } }
void HistoryController::updateForBackForwardNavigation() { #if !LOG_DISABLED if (m_frame.loader().documentLoader()) LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", m_frame.loader().documentLoader()->title().string().utf8().data()); #endif // Must grab the current scroll position before disturbing it if (!m_frameLoadComplete) saveScrollPositionAndViewStateToItem(m_previousItem.get()); // When traversing history, we may end up redirecting to a different URL // this time (e.g., due to cookies). See http://webkit.org/b/49654. updateCurrentItem(); }
void HistoryController::updateForReload() { #if !LOG_DISABLED LOG(History, "WebCoreHistory: Updating History for reload in frame %s", m_frame->document()->title().utf8().data()); #endif if (m_currentItem) { if (m_frame->loader()->loadType() == FrameLoadTypeReload || m_frame->loader()->loadType() == FrameLoadTypeReloadFromOrigin) saveScrollPositionAndViewStateToItem(m_currentItem.get()); } // When reloading the page, we may end up redirecting to a different URL // this time (e.g., due to cookies). See http://webkit.org/b/4072. updateCurrentItem(); }
void HistoryController::updateForReload() { #if !LOG_DISABLED if (m_frame->loader()->documentLoader()) LOG(History, "WebCoreHistory: Updating History for reload in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); #endif if (m_currentItem) { pageCache()->remove(m_currentItem.get()); if (m_frame->loader()->loadType() == FrameLoadTypeReload || m_frame->loader()->loadType() == FrameLoadTypeReloadFromOrigin) saveScrollPositionAndViewStateToItem(m_currentItem.get()); // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072 if (m_frame->loader()->documentLoader()->unreachableURL().isEmpty()) m_currentItem->setURL(m_frame->loader()->documentLoader()->requestURL()); } }
void HistoryController::updateForReload() { LOG(History, "HistoryController %p updateForBackForwardNavigation: Updating History for reload in frame %p (main frame %d) %s", this, &m_frame, m_frame.isMainFrame(), m_frame.loader().documentLoader() ? m_frame.loader().documentLoader()->url().string().utf8().data() : ""); if (m_currentItem) { PageCache::singleton().remove(*m_currentItem); if (m_frame.loader().loadType() == FrameLoadType::Reload || m_frame.loader().loadType() == FrameLoadType::ReloadFromOrigin) saveScrollPositionAndViewStateToItem(m_currentItem.get()); // Rebuild the history item tree when reloading as trying to re-associate everything is too error-prone. m_currentItem->clearChildren(); } // When reloading the page, we may end up redirecting to a different URL // this time (e.g., due to cookies). See http://webkit.org/b/4072. updateCurrentItem(); }
void HistoryController::updateForReload() { #if !LOG_DISABLED if (m_frame.loader().documentLoader()) LOG(History, "WebCoreHistory: Updating History for reload in frame %s", m_frame.loader().documentLoader()->title().string().utf8().data()); #endif if (m_currentItem) { PageCache::singleton().remove(*m_currentItem); if (m_frame.loader().loadType() == FrameLoadType::Reload || m_frame.loader().loadType() == FrameLoadType::ReloadFromOrigin) saveScrollPositionAndViewStateToItem(m_currentItem.get()); // Rebuild the history item tree when reloading as trying to re-associate everything is too error-prone. m_currentItem->clearChildren(); } // When reloading the page, we may end up redirecting to a different URL // this time (e.g., due to cookies). See http://webkit.org/b/4072. updateCurrentItem(); }
PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget) { RefPtr<HistoryItem> bfItem = createItem(m_frame->tree()->parent() ? true : false); if (m_previousItem) saveScrollPositionAndViewStateToItem(m_previousItem.get()); if (!(clipAtTarget && m_frame == targetFrame)) { // save frame state for items that aren't loading (khtml doesn't save those) saveDocumentState(); for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { FrameLoader* childLoader = child->loader(); bool hasChildLoaded = childLoader->frameHasLoaded(); // If the child is a frame corresponding to an <object> element that never loaded, // we don't want to create a history item, because that causes fallback content // to be ignored on reload. if (!(!hasChildLoaded && childLoader->isHostedByObjectElement())) bfItem->addChildItem(childLoader->history()->createItemTree(targetFrame, clipAtTarget)); } } if (m_frame == targetFrame) bfItem->setIsTargetItem(true); return bfItem; }