コード例 #1
0
void RedirectScheduler::scheduleHistoryNavigation(int steps)
{
    if (!m_frame->page())
        return;

    // Invalid history navigations (such as history.forward() during a new load) have the side effect of cancelling any scheduled
    // redirects. We also avoid the possibility of cancelling the current load by avoiding the scheduled redirection altogether.
    HistoryItem* specifiedEntry = m_frame->page()->backForwardList()->itemAtIndex(steps);
    if (!specifiedEntry) {
        cancel();
        return;
    }
    
#if !ENABLE(HISTORY_ALWAYS_ASYNC)
    // If the specified entry and the current entry have the same document, this is either a state object traversal or a fragment 
    // traversal (or both) and should be performed synchronously.
    HistoryItem* currentEntry = m_frame->loader()->history()->currentItem();
    if (currentEntry != specifiedEntry && currentEntry->documentSequenceNumber() == specifiedEntry->documentSequenceNumber()) {
        m_frame->loader()->history()->goToItem(specifiedEntry, FrameLoadTypeIndexedBackForward);
        return;
    }
#endif
    
    // In all other cases, schedule the history traversal to occur asynchronously.
    schedule(new ScheduledHistoryNavigation(steps));
}
コード例 #2
0
ファイル: HistoryItem.cpp プロジェクト: rhythmkay/webkit
// We do same-document navigation if going to a different item and if either of the following is true:
// - The other item corresponds to the same document (for history entries created via pushState or fragment changes).
// - The other item corresponds to the same set of documents, including frames (for history entries created via regular navigation)
bool HistoryItem::shouldDoSameDocumentNavigationTo(HistoryItem& otherItem) const
{
    if (this == &otherItem)
        return false;

    if (stateObject() || otherItem.stateObject())
        return documentSequenceNumber() == otherItem.documentSequenceNumber();
    
    if ((url().hasFragmentIdentifier() || otherItem.url().hasFragmentIdentifier()) && equalIgnoringFragmentIdentifier(url(), otherItem.url()))
        return documentSequenceNumber() == otherItem.documentSequenceNumber();
    
    return hasSameDocumentTree(otherItem);
}
コード例 #3
0
ファイル: Page.cpp プロジェクト: achellies/WinCEWebKit
void Page::goToItem(HistoryItem* item, FrameLoadType type)
{
    if (defersLoading())
        return;

    // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
    // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
    RefPtr<HistoryItem> protector(item);
    
    // Abort any current load unless we're navigating the current document to a new state object
    HistoryItem* currentItem = m_mainFrame->loader()->history()->currentItem();
    if (!item->stateObject() || !currentItem || item->documentSequenceNumber() != currentItem->documentSequenceNumber() || item == currentItem) {
        // Define what to do with any open database connections. By default we stop them and terminate the database thread.
        DatabasePolicy databasePolicy = DatabasePolicyStop;

#if ENABLE(DATABASE)
        // If we're navigating the history via a fragment on the same document, then we do not want to stop databases.
        const KURL& currentURL = m_mainFrame->loader()->url();
        const KURL& newURL = item->url();
    
        if (newURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(currentURL, newURL))
            databasePolicy = DatabasePolicyContinue;
#endif

        m_mainFrame->loader()->stopAllLoaders(databasePolicy);
    }
        
    m_mainFrame->loader()->history()->goToItem(item, type);
}
コード例 #4
0
void HistoryController::recursiveGoToEntry(LocalFrame* frame, HistoryFrameLoadSet& sameDocumentLoads, HistoryFrameLoadSet& differentDocumentLoads)
{
    ASSERT(m_provisionalEntry);
    ASSERT(m_currentEntry);
    HistoryItem* newItem = m_provisionalEntry->itemForFrame(frame);
    HistoryItem* oldItem = m_currentEntry->itemForFrame(frame);
    if (!newItem)
        return;

    if (!oldItem || (newItem != oldItem && newItem->itemSequenceNumber() != oldItem->itemSequenceNumber())) {
        if (oldItem && newItem->documentSequenceNumber() == oldItem->documentSequenceNumber())
            sameDocumentLoads.set(frame, newItem);
        else
            differentDocumentLoads.set(frame, newItem);
        return;
    }

    for (LocalFrame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling())
        recursiveGoToEntry(child, sameDocumentLoads, differentDocumentLoads);
}
コード例 #5
0
void HistoryController::createNewBackForwardItem(LocalFrame* targetFrame, HistoryItem* item, bool clipAtTarget)
{
    RefPtr<HistoryItem> newItem = item;
    if (!m_currentEntry) {
        m_currentEntry = HistoryEntry::create(newItem.get(), targetFrame->frameID());
    } else {
        HistoryItem* oldItem = m_currentEntry->itemForFrame(targetFrame);
        if (!clipAtTarget && oldItem)
            newItem->setDocumentSequenceNumber(oldItem->documentSequenceNumber());
        m_previousEntry = m_currentEntry.release();
        m_currentEntry = m_previousEntry->cloneAndReplace(newItem.get(), clipAtTarget, targetFrame, m_page);
    }
}
コード例 #6
0
// Does a recursive check that this item and its descendants have the same
// document sequence numbers as the other item.
bool HistoryItem::hasSameDocumentTree(HistoryItem* otherItem) const
{
    if (documentSequenceNumber() != otherItem->documentSequenceNumber())
        return false;
        
    if (children().size() != otherItem->children().size())
        return false;

    for (size_t i = 0; i < children().size(); i++) {
        HistoryItem* child = children()[i].get();
        HistoryItem* otherChild = otherItem->childItemWithDocumentSequenceNumber(child->documentSequenceNumber());
        if (!otherChild || !child->hasSameDocumentTree(otherChild))
            return false;
    }

    return true;
}
コード例 #7
0
ファイル: HistoryItem.cpp プロジェクト: rhythmkay/webkit
// Does a recursive check that this item and its descendants have the same
// document sequence numbers as the other item.
bool HistoryItem::hasSameDocumentTree(HistoryItem& otherItem) const
{
    if (documentSequenceNumber() != otherItem.documentSequenceNumber())
        return false;
        
    if (children().size() != otherItem.children().size())
        return false;

    for (size_t i = 0; i < children().size(); i++) {
        auto& child = children()[i].get();
        auto* otherChild = otherItem.childItemWithDocumentSequenceNumber(child.documentSequenceNumber());
        if (!otherChild || !child.hasSameDocumentTree(*otherChild))
            return false;
    }

    return true;
}
コード例 #8
0
static FrameState toFrameState(const HistoryItem& historyItem)
{
    FrameState frameState;

    frameState.urlString = historyItem.urlString();
    frameState.originalURLString = historyItem.originalURLString();
    frameState.referrer = historyItem.referrer();
    frameState.target = historyItem.target();

    frameState.documentState = historyItem.documentState();
    if (RefPtr<SerializedScriptValue> stateObject = historyItem.stateObject())
        frameState.stateObjectData = stateObject->data();

    frameState.documentSequenceNumber = historyItem.documentSequenceNumber();
    frameState.itemSequenceNumber = historyItem.itemSequenceNumber();

    frameState.scrollPoint = historyItem.scrollPoint();
    frameState.pageScaleFactor = historyItem.pageScaleFactor();

    if (FormData* formData = const_cast<HistoryItem&>(historyItem).formData()) {
        HTTPBody httpBody = toHTTPBody(*formData);
        httpBody.contentType = historyItem.formContentType();

        frameState.httpBody = WTF::move(httpBody);
    }

#if PLATFORM(IOS)
    frameState.exposedContentRect = historyItem.exposedContentRect();
    frameState.unobscuredContentRect = historyItem.unobscuredContentRect();
    frameState.minimumLayoutSizeInScrollViewCoordinates = historyItem.minimumLayoutSizeInScrollViewCoordinates();
    frameState.contentSize = historyItem.contentSize();
    frameState.scaleIsInitial = historyItem.scaleIsInitial();
#endif

    for (auto& childHistoryItem : historyItem.children()) {
        FrameState childFrameState = toFrameState(childHistoryItem);
        frameState.children.append(WTF::move(childFrameState));
    }

    return frameState;
}
コード例 #9
0
void Page::goToItem(HistoryItem* item, FrameLoadType type)
{
    // Abort any current load unless we're navigating the current document to a new state object
    HistoryItem* currentItem = m_mainFrame->loader()->history()->currentItem();
    if (!item->stateObject() || !currentItem || item->documentSequenceNumber() != currentItem->documentSequenceNumber() || item == currentItem) {
        // Define what to do with any open database connections. By default we stop them and terminate the database thread.
        DatabasePolicy databasePolicy = DatabasePolicyStop;

#if ENABLE(DATABASE)
        // If we're navigating the history via a fragment on the same document, then we do not want to stop databases.
        const KURL& currentURL = m_mainFrame->loader()->url();
        const KURL& newURL = item->url();
    
        if (newURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(currentURL, newURL))
            databasePolicy = DatabasePolicyContinue;
#endif

        m_mainFrame->loader()->stopAllLoaders(databasePolicy);
    }
        
    m_mainFrame->loader()->history()->goToItem(item, type);
}