void RedirectScheduler::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
{
    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, wasUserGesture);
        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->committedFirstRealDocumentLoad();

    schedule(new ScheduledLocationChange(url, referrer, lockHistory, lockBackForwardList, wasUserGesture, duringLoad));
}
void RedirectScheduler::timerFired(Timer<RedirectScheduler>*)
{
    if (!m_frame->page())
        return;

    if (m_frame->page()->defersLoading())
        return;

    OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
    FrameLoader* loader = m_frame->loader();

    switch (redirection->type) {
        case ScheduledRedirection::redirection:
        case ScheduledRedirection::locationChange:
            loader->changeLocation(KURL(ParsedURLString, redirection->url), redirection->referrer,
                redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
            return;
        case ScheduledRedirection::historyNavigation:
            if (redirection->historySteps == 0) {
                // Special case for go(0) from a frame -> reload only the frame
                loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, SendReferrer);
                return;
            }
            // go(i!=0) from a frame navigates into the history of the frame only,
            // in both IE and NS (but not in Mozilla). We can't easily do that.
            m_frame->page()->goBackOrForward(redirection->historySteps);
            return;
        case ScheduledRedirection::formSubmission:
            // The submitForm function will find a target frame before using the redirection timer.
            // Now that the timer has fired, we need to repeat the security check which normally is done when
            // selecting a target, in case conditions have changed. Other code paths avoid this by targeting
            // without leaving a time window. If we fail the check just silently drop the form submission.
            if (!redirection->formState->sourceFrame()->loader()->shouldAllowNavigation(m_frame))
                return;
            loader->loadFrameRequest(redirection->frameRequest, redirection->lockHistory, redirection->lockBackForwardList,
                redirection->event, redirection->formState, SendReferrer);
            return;
    }

    ASSERT_NOT_REACHED();
}