void NavigationScheduler::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList) { if (!m_frame->page()) return; if (url.isEmpty()) return; lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame); FrameLoader* loader = m_frame->loader(); // If the URL we're going to navigate to is the same as the current one, except for the // fragment part, we don't need to schedule the location change. KURL parsedURL(ParsedURLString, url); if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(loader->url(), parsedURL)) { loader->changeLocation(loader->completeURL(url), referrer, lockHistory, lockBackForwardList); return; } // Handle a location change of a page with no document as a special case. // This may happen when a frame changes the location of another frame. bool duringLoad = !loader->stateMachine()->committedFirstRealDocumentLoad(); schedule(adoptPtr(new ScheduledLocationChange(url, referrer, lockHistory, lockBackForwardList, duringLoad))); }
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; }