/*
 * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
 * Copyright (C) 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "FrameLoaderClientImpl.h"

#include "BackForwardListChromium.h"
#include "Chrome.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "FormState.h"
#include "FrameLoadRequest.h"
#include "FrameLoader.h"
#include "FrameNetworkingContextImpl.h"
#include "FrameView.h"
#include "HTMLAppletElement.h"
#include "HTMLFormElement.h"  // needed by FormState.h
#include "HTMLNames.h"
#include "HTTPParsers.h"
#include "HistoryItem.h"
#include "HitTestResult.h"
#include "IntentRequest.h"
#include "MIMETypeRegistry.h"
#include "MessageEvent.h"
#include "MouseEvent.h"
#include "Page.h"
#include "PluginData.h"
#include "PluginDataChromium.h"
#include "ProgressTracker.h"
#include "ResourceHandleInternal.h"
#include "ResourceLoader.h"
#if ENABLE(MEDIA_STREAM)
#include "RTCPeerConnectionHandlerChromium.h"
#endif
#include "Settings.h"
#include "SocketStreamHandleInternal.h"
#include "WebDOMEvent.h"
#include "WebDataSourceImpl.h"
#include "WebDevToolsAgentPrivate.h"
#include "WebDocument.h"
#include "WebFormElement.h"
#include "WebFrameClient.h"
#include "WebFrameImpl.h"
#include "WebIntentRequest.h"
#include "WebIntentServiceInfo.h"
#include "WebNode.h"
#include "WebPermissionClient.h"
#include "WebPlugin.h"
#include "WebPluginContainerImpl.h"
#include "WebPluginLoadObserver.h"
#include "WebPluginParams.h"
#include "WebSecurityOrigin.h"
#include "platform/WebSocketStreamHandle.h"
#include "WebViewClient.h"
#include "WebViewImpl.h"
#include "WindowFeatures.h"
#include "WrappedResourceRequest.h"
#include "WrappedResourceResponse.h"
#include "platform/WebURL.h"
#include "platform/WebURLError.h"
#include <public/Platform.h>
#include <public/WebMimeRegistry.h>
#include <public/WebVector.h>
#include <wtf/StringExtras.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>

#if USE(V8)
#include <v8.h>
#endif

using namespace WebCore;

namespace WebKit {

// Domain for internal error codes.
static const char internalErrorDomain[] = "WebKit";

// An internal error code.  Used to note a policy change error resulting from
// dispatchDecidePolicyForMIMEType not passing the PolicyUse option.
enum {
    PolicyChangeError = -10000,
};

FrameLoaderClientImpl::FrameLoaderClientImpl(WebFrameImpl* frame)
    : m_webFrame(frame)
    , m_sentInitialResponseToPlugin(false)
    , m_nextNavigationPolicy(WebNavigationPolicyIgnore)
{
}

FrameLoaderClientImpl::~FrameLoaderClientImpl()
{
}

void FrameLoaderClientImpl::frameLoaderDestroyed()
{
    // When the WebFrame was created, it had an extra reference given to it on
    // behalf of the Frame.  Since the WebFrame owns us, this extra ref also
    // serves to keep us alive until the FrameLoader is done with us.  The
    // FrameLoader calls this method when it's going away.  Therefore, we balance
    // out that extra reference, which may cause 'this' to be deleted.
    ASSERT(!m_webFrame->frame());
    m_webFrame->deref();
}

void FrameLoaderClientImpl::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*)
{
    if (m_webFrame->client())
        m_webFrame->client()->didClearWindowObject(m_webFrame);
}

void FrameLoaderClientImpl::documentElementAvailable()
{
    if (m_webFrame->client())
        m_webFrame->client()->didCreateDocumentElement(m_webFrame);
}

void FrameLoaderClientImpl::didExhaustMemoryAvailableForScript()
{
    if (m_webFrame->client())
        m_webFrame->client()->didExhaustMemoryAvailableForScript(m_webFrame);
}

#if USE(V8)
void FrameLoaderClientImpl::didCreateScriptContext(v8::Handle<v8::Context> context, int extensionGroup, int worldId)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview->devToolsAgentPrivate())
        webview->devToolsAgentPrivate()->didCreateScriptContext(m_webFrame, worldId);
    if (m_webFrame->client())
        m_webFrame->client()->didCreateScriptContext(m_webFrame, context, extensionGroup, worldId);
}

void FrameLoaderClientImpl::willReleaseScriptContext(v8::Handle<v8::Context> context, int worldId)
{
    if (m_webFrame->client())
        m_webFrame->client()->willReleaseScriptContext(m_webFrame, context, worldId);
}
#endif

bool FrameLoaderClientImpl::allowScriptExtension(const String& extensionName,
                                                 int extensionGroup,
                                                 int worldId)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowScriptExtension(m_webFrame, extensionName, extensionGroup, worldId);

    return true;
}

void FrameLoaderClientImpl::didPerformFirstNavigation() const
{
}

void FrameLoaderClientImpl::registerForIconNotification(bool)
{
}

void FrameLoaderClientImpl::didChangeScrollOffset()
{
    if (m_webFrame->client())
        m_webFrame->client()->didChangeScrollOffset(m_webFrame);
}

bool FrameLoaderClientImpl::allowScript(bool enabledPerSettings)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowScript(m_webFrame, enabledPerSettings);

    return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowScriptFromSource(bool enabledPerSettings, const KURL& scriptURL)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowScriptFromSource(m_webFrame, enabledPerSettings, scriptURL);

    return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowPlugins(bool enabledPerSettings)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowPlugins(m_webFrame, enabledPerSettings);

    return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowImage(bool enabledPerSettings, const KURL& imageURL)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowImage(m_webFrame, enabledPerSettings, imageURL);

    return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowDisplayingInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowDisplayingInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));

    return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowRunningInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        return webview->permissionClient()->allowRunningInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));

    return enabledPerSettings;
}

void FrameLoaderClientImpl::didNotAllowScript()
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        webview->permissionClient()->didNotAllowScript(m_webFrame);
}

void FrameLoaderClientImpl::didNotAllowPlugins()
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->permissionClient())
        webview->permissionClient()->didNotAllowPlugins(m_webFrame);

}

bool FrameLoaderClientImpl::hasWebView() const
{
    return m_webFrame->viewImpl();
}

bool FrameLoaderClientImpl::hasFrameView() const
{
    // The Mac port has this notion of a WebFrameView, which seems to be
    // some wrapper around an NSView.  Since our equivalent is HWND, I guess
    // we have a "frameview" whenever we have the toplevel HWND.
    return m_webFrame->viewImpl();
}

void FrameLoaderClientImpl::makeDocumentView()
{
    m_webFrame->createFrameView();
}

void FrameLoaderClientImpl::forceLayout()
{
    // FIXME
}

void FrameLoaderClientImpl::forceLayoutForNonHTML()
{
    // FIXME
}

void FrameLoaderClientImpl::setCopiesOnScroll()
{
    // FIXME
}

void FrameLoaderClientImpl::detachedFromParent2()
{
    // Nothing to do here.
}

void FrameLoaderClientImpl::detachedFromParent3()
{
    // If we were reading data into a plugin, drop our reference to it. If we
    // don't do this then it may end up out-living the rest of the page, which
    // leads to problems if the plugin's destructor tries to script things.
    m_pluginWidget = 0;

    // Close down the proxy.  The purpose of this change is to make the
    // call to ScriptController::clearWindowShell a no-op when called from
    // Frame::pageDestroyed.  Without this change, this call to clearWindowShell
    // will cause a crash.  If you remove/modify this, just ensure that you can
    // go to a page and then navigate to a new page without getting any asserts
    // or crashes.
    m_webFrame->frame()->script()->clearForClose();

    // Alert the client that the frame is being detached. This is the last
    // chance we have to communicate with the client.
    if (m_webFrame->client())
        m_webFrame->client()->frameDetached(m_webFrame);

    // Stop communicating with the WebFrameClient at this point since we are no
    // longer associated with the Page.
    m_webFrame->setClient(0);
}

// This function is responsible for associating the |identifier| with a given
// subresource load.  The following functions that accept an |identifier| are
// called for each subresource, so they should not be dispatched to the
// WebFrame.
void FrameLoaderClientImpl::assignIdentifierToInitialRequest(
    unsigned long identifier, DocumentLoader* loader,
    const ResourceRequest& request)
{
    if (m_webFrame->client()) {
        WrappedResourceRequest webreq(request);
        m_webFrame->client()->assignIdentifierToRequest(
            m_webFrame, identifier, webreq);
    }
}

// If the request being loaded by |loader| is a frame, update the ResourceType.
// A subresource in this context is anything other than a frame --
// this includes images and xmlhttp requests.  It is important to note that a
// subresource is NOT limited to stuff loaded through the frame's subresource
// loader. Synchronous xmlhttp requests for example, do not go through the
// subresource loader, but we still label them as TargetIsSubresource.
//
// The important edge cases to consider when modifying this function are
// how synchronous resource loads are treated during load/unload threshold.
static void setTargetTypeFromLoader(ResourceRequest& request, DocumentLoader* loader)
{
    if (loader == loader->frameLoader()->provisionalDocumentLoader()) {
        ResourceRequest::TargetType type;
        if (loader->frameLoader()->isLoadingMainFrame())
            type = ResourceRequest::TargetIsMainFrame;
        else
            type = ResourceRequest::TargetIsSubframe;
        request.setTargetType(type);
    }
}

void FrameLoaderClientImpl::dispatchWillSendRequest(
    DocumentLoader* loader, unsigned long identifier, ResourceRequest& request,
    const ResourceResponse& redirectResponse)
{
    if (loader) {
        // We want to distinguish between a request for a document to be loaded into
        // the main frame, a sub-frame, or the sub-objects in that document.
        setTargetTypeFromLoader(request, loader);

        // Avoid repeating a form submission when navigating back or forward.
        if (loader == loader->frameLoader()->provisionalDocumentLoader()
            && request.httpMethod() == "POST"
            && isBackForwardLoadType(loader->frameLoader()->loadType()))
            request.setCachePolicy(ReturnCacheDataDontLoad);
    }

    // FrameLoader::loadEmptyDocumentSynchronously() creates an empty document
    // with no URL.  We don't like that, so we'll rename it to about:blank.
    if (request.url().isEmpty())
        request.setURL(KURL(ParsedURLString, "about:blank"));
    if (request.firstPartyForCookies().isEmpty())
        request.setFirstPartyForCookies(KURL(ParsedURLString, "about:blank"));

    // Give the WebFrameClient a crack at the request.
    if (m_webFrame->client()) {
        WrappedResourceRequest webreq(request);
        WrappedResourceResponse webresp(redirectResponse);
        m_webFrame->client()->willSendRequest(
            m_webFrame, identifier, webreq, webresp);
    }
}

bool FrameLoaderClientImpl::shouldUseCredentialStorage(
    DocumentLoader*, unsigned long identifier)
{
    // FIXME
    // Intended to pass through to a method on the resource load delegate.
    // If implemented, that method controls whether the browser should ask the
    // networking layer for a stored default credential for the page (say from
    // the Mac OS keychain). If the method returns false, the user should be
    // presented with an authentication challenge whether or not the networking
    // layer has a credential stored.
    // This returns true for backward compatibility: the ability to override the
    // system credential store is new. (Actually, not yet fully implemented in
    // WebKit, as of this writing.)
    return true;
}

void FrameLoaderClientImpl::dispatchDidReceiveAuthenticationChallenge(
    DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
{
    // FIXME
}

void FrameLoaderClientImpl::dispatchDidCancelAuthenticationChallenge(
    DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
{
    // FIXME
}

void FrameLoaderClientImpl::dispatchDidReceiveResponse(DocumentLoader* loader,
                                                       unsigned long identifier,
                                                       const ResourceResponse& response)
{
    if (m_webFrame->client()) {
        WrappedResourceResponse webresp(response);
        m_webFrame->client()->didReceiveResponse(m_webFrame, identifier, webresp);
    }
}

void FrameLoaderClientImpl::dispatchDidReceiveContentLength(
    DocumentLoader* loader,
    unsigned long identifier,
    int dataLength)
{
}

// Called when a particular resource load completes
void FrameLoaderClientImpl::dispatchDidFinishLoading(DocumentLoader* loader,
                                                    unsigned long identifier)
{
    if (m_webFrame->client())
        m_webFrame->client()->didFinishResourceLoad(m_webFrame, identifier);
}

void FrameLoaderClientImpl::dispatchDidFailLoading(DocumentLoader* loader,
                                                  unsigned long identifier,
                                                  const ResourceError& error)
{
    if (m_webFrame->client())
        m_webFrame->client()->didFailResourceLoad(m_webFrame, identifier, error);
}

void FrameLoaderClientImpl::dispatchDidFinishDocumentLoad()
{
    if (m_webFrame->client())
        m_webFrame->client()->didFinishDocumentLoad(m_webFrame);
}

bool FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
    DocumentLoader* loader,
    const ResourceRequest& request,
    const ResourceResponse& response,
    int length)
{
    if (m_webFrame->client()) {
        WrappedResourceRequest webreq(request);
        WrappedResourceResponse webresp(response);
        m_webFrame->client()->didLoadResourceFromMemoryCache(
            m_webFrame, webreq, webresp);
    }
    return false;  // Do not suppress remaining notifications
}

void FrameLoaderClientImpl::dispatchDidHandleOnloadEvents()
{
    if (m_webFrame->client())
        m_webFrame->client()->didHandleOnloadEvents(m_webFrame);
}

// Redirect Tracking
// =================
// We want to keep track of the chain of redirects that occur during page
// loading. There are two types of redirects, server redirects which are HTTP
// response codes, and client redirects which are document.location= and meta
// refreshes.
//
// This outlines the callbacks that we get in different redirect situations,
// and how each call modifies the redirect chain.
//
// Normal page load
// ----------------
//   dispatchDidStartProvisionalLoad() -> adds URL to the redirect list
//   dispatchDidCommitLoad()           -> DISPATCHES & clears list
//
// Server redirect (success)
// -------------------------
//   dispatchDidStartProvisionalLoad()                    -> adds source URL
//   dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL
//   dispatchDidCommitLoad()                              -> DISPATCHES
//
// Client redirect (success)
// -------------------------
//   (on page)
//   dispatchWillPerformClientRedirect() -> saves expected redirect
//   dispatchDidStartProvisionalLoad()   -> appends redirect source (since
//                                          it matches the expected redirect)
//                                          and the current page as the dest)
//   dispatchDidCancelClientRedirect()   -> clears expected redirect
//   dispatchDidCommitLoad()             -> DISPATCHES
//
// Client redirect (cancelled)
// (e.g meta-refresh trumped by manual doc.location change, or just cancelled
// because a link was clicked that requires the meta refresh to be rescheduled
// (the SOURCE URL may have changed).
// ---------------------------
//   dispatchDidCancelClientRedirect()                 -> clears expected redirect
//   dispatchDidStartProvisionalLoad()                 -> adds only URL to redirect list
//   dispatchDidCommitLoad()                           -> DISPATCHES & clears list
//   rescheduled ? dispatchWillPerformClientRedirect() -> saves expected redirect
//               : nothing

// Client redirect (failure)
// -------------------------
//   (on page)
//   dispatchWillPerformClientRedirect() -> saves expected redirect
//   dispatchDidStartProvisionalLoad()   -> appends redirect source (since
//                                          it matches the expected redirect)
//                                          and the current page as the dest)
//   dispatchDidCancelClientRedirect()
//   dispatchDidFailProvisionalLoad()
//
// Load 1 -> Server redirect to 2 -> client redirect to 3 -> server redirect to 4
// ------------------------------------------------------------------------------
//   dispatchDidStartProvisionalLoad()                    -> adds source URL 1
//   dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL 2
//   dispatchDidCommitLoad()                              -> DISPATCHES 1+2
//    -- begin client redirect and NEW DATA SOURCE
//   dispatchWillPerformClientRedirect()                  -> saves expected redirect
//   dispatchDidStartProvisionalLoad()                    -> appends URL 2 and URL 3
//   dispatchDidReceiveServerRedirectForProvisionalLoad() -> appends destination URL 4
//   dispatchDidCancelClientRedirect()                    -> clears expected redirect
//   dispatchDidCommitLoad()                              -> DISPATCHES
//
// Interesting case with multiple location changes involving anchors.
// Load page 1 containing future client-redirect (back to 1, e.g meta refresh) > Click
// on a link back to the same page (i.e an anchor href) >
// client-redirect finally fires (with new source, set to 1#anchor)
// -----------------------------------------------------------------------------
//   dispatchWillPerformClientRedirect(non-zero 'interval' param) -> saves expected redirect
//   -- click on anchor href
//   dispatchDidCancelClientRedirect()                            -> clears expected redirect
//   dispatchDidStartProvisionalLoad()                            -> adds 1#anchor source
//   dispatchDidCommitLoad()                                      -> DISPATCHES 1#anchor
//   dispatchWillPerformClientRedirect()                          -> saves exp. source (1#anchor)
//   -- redirect timer fires
//   dispatchDidStartProvisionalLoad()                            -> appends 1#anchor (src) and 1 (dest)
//   dispatchDidCancelClientRedirect()                            -> clears expected redirect
//   dispatchDidCommitLoad()                                      -> DISPATCHES 1#anchor + 1
//
void FrameLoaderClientImpl::dispatchDidReceiveServerRedirectForProvisionalLoad()
{
    WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
    if (!ds) {
        // Got a server redirect when there is no provisional DS!
        ASSERT_NOT_REACHED();
        return;
    }

    // The server redirect may have been blocked.
    if (ds->request().isNull())
        return;

    // A provisional load should have started already, which should have put an
    // entry in our redirect chain.
    ASSERT(ds->hasRedirectChain());

    // The URL of the destination is on the provisional data source. We also need
    // to update the redirect chain to account for this addition (we do this
    // before the callback so the callback can look at the redirect chain to see
    // what happened).
    ds->appendRedirect(ds->request().url());

    if (m_webFrame->client())
        m_webFrame->client()->didReceiveServerRedirectForProvisionalLoad(m_webFrame);
}

// Called on both success and failure of a client redirect.
void FrameLoaderClientImpl::dispatchDidCancelClientRedirect()
{
    // No longer expecting a client redirect.
    if (m_webFrame->client()) {
        m_expectedClientRedirectSrc = KURL();
        m_expectedClientRedirectDest = KURL();
        m_webFrame->client()->didCancelClientRedirect(m_webFrame);
    }

    // No need to clear the redirect chain, since that data source has already
    // been deleted by the time this function is called.
}

void FrameLoaderClientImpl::dispatchWillPerformClientRedirect(
    const KURL& url,
    double interval,
    double fireDate)
{
    // Tells dispatchDidStartProvisionalLoad that if it sees this item it is a
    // redirect and the source item should be added as the start of the chain.
    m_expectedClientRedirectSrc = m_webFrame->document().url();
    m_expectedClientRedirectDest = url;

    // FIXME: bug 1135512. Webkit does not properly notify us of cancelling
    // http > file client redirects. Since the FrameLoader's policy is to never
    // carry out such a navigation anyway, the best thing we can do for now to
    // not get confused is ignore this notification.
    if (m_expectedClientRedirectDest.isLocalFile()
        && m_expectedClientRedirectSrc.protocolIsInHTTPFamily()) {
        m_expectedClientRedirectSrc = KURL();
        m_expectedClientRedirectDest = KURL();
        return;
    }

    if (m_webFrame->client()) {
        m_webFrame->client()->willPerformClientRedirect(
            m_webFrame,
            m_expectedClientRedirectSrc,
            m_expectedClientRedirectDest,
            static_cast<unsigned int>(interval),
            static_cast<unsigned int>(fireDate));
    }
}

void FrameLoaderClientImpl::dispatchDidNavigateWithinPage()
{
    // Anchor fragment navigations are not normal loads, so we need to synthesize
    // some events for our delegate.
    WebViewImpl* webView = m_webFrame->viewImpl();

    // Flag of whether frame loader is completed. Generate didStartLoading and
    // didStopLoading only when loader is completed so that we don't fire
    // them for fragment redirection that happens in window.onload handler.
    // See https://bugs.webkit.org/show_bug.cgi?id=31838
    //
    // FIXME: Although FrameLoader::loadInSameDocument which invokes this
    // method does not have a provisional document loader, we're seeing crashes
    // where the FrameLoader is in provisional state, and thus
    // activeDocumentLoader returns 0. Lacking any understanding of how this
    // can happen, we do this check here to avoid crashing.
    FrameLoader* loader = webView->page()->mainFrame()->loader();
    bool loaderCompleted = !(loader->activeDocumentLoader() && loader->activeDocumentLoader()->isLoadingInAPISense());

    // Generate didStartLoading if loader is completed.
    if (webView->client() && loaderCompleted)
        webView->client()->didStartLoading();

    // We need to classify some hash changes as client redirects.
    // FIXME: It seems wrong that the currentItem can sometimes be null.
    HistoryItem* currentItem = m_webFrame->frame()->loader()->history()->currentItem();
    bool isHashChange = !currentItem || !currentItem->stateObject();

    WebDataSourceImpl* ds = m_webFrame->dataSourceImpl();
    ASSERT(ds);  // Should not be null when navigating to a reference fragment!
    if (ds) {
        KURL url = ds->request().url();
        KURL chainEnd;
        if (ds->hasRedirectChain()) {
            chainEnd = ds->endOfRedirectChain();
            ds->clearRedirectChain();
        }

        if (isHashChange) {
            // Figure out if this location change is because of a JS-initiated
            // client redirect (e.g onload/setTimeout document.location.href=).
            // FIXME: (b/1085325, b/1046841) We don't get proper redirect
            // performed/cancelled notifications across anchor navigations, so the
            // other redirect-tracking code in this class (see
            // dispatch*ClientRedirect() and dispatchDidStartProvisionalLoad) is
            // insufficient to catch and properly flag these transitions. Once a
            // proper fix for this bug is identified and applied the following
            // block may no longer be required.
            //
            // FIXME: Why do we call isProcessingUserGesture here but none of
            // the other ports do?
            bool wasClientRedirect =
                (url == m_expectedClientRedirectDest && chainEnd == m_expectedClientRedirectSrc)
                || !m_webFrame->isProcessingUserGesture();

            if (wasClientRedirect) {
                if (m_webFrame->client())
                    m_webFrame->client()->didCompleteClientRedirect(m_webFrame, chainEnd);
                ds->appendRedirect(chainEnd);
                // Make sure we clear the expected redirect since we just effectively
                // completed it.
                m_expectedClientRedirectSrc = KURL();
                m_expectedClientRedirectDest = KURL();
            }
        }

        // Regardless of how we got here, we are navigating to a URL so we need to
        // add it to the redirect chain.
        ds->appendRedirect(url);
    }

    bool isNewNavigation;
    webView->didCommitLoad(&isNewNavigation, true);
    if (m_webFrame->client())
        m_webFrame->client()->didNavigateWithinPage(m_webFrame, isNewNavigation);

    // Generate didStopLoading if loader is completed.
    if (webView->client() && loaderCompleted)
        webView->client()->didStopLoading();
}

void FrameLoaderClientImpl::dispatchDidChangeLocationWithinPage()
{
    if (m_webFrame)
        m_webFrame->client()->didChangeLocationWithinPage(m_webFrame);
}

void FrameLoaderClientImpl::dispatchDidPushStateWithinPage()
{
    dispatchDidNavigateWithinPage();
}

void FrameLoaderClientImpl::dispatchDidReplaceStateWithinPage()
{
    dispatchDidNavigateWithinPage();
}

void FrameLoaderClientImpl::dispatchDidPopStateWithinPage()
{
    // Ignored since dispatchDidNavigateWithinPage was already called.
}

void FrameLoaderClientImpl::dispatchWillClose()
{
    if (m_webFrame->client())
        m_webFrame->client()->willClose(m_webFrame);
}

void FrameLoaderClientImpl::dispatchDidReceiveIcon()
{
    // The icon database is disabled, so this should never be called.
    ASSERT_NOT_REACHED();
}

void FrameLoaderClientImpl::dispatchDidStartProvisionalLoad()
{
    // In case a redirect occurs, we need this to be set so that the redirect
    // handling code can tell where the redirect came from. Server redirects
    // will occur on the provisional load, so we need to keep track of the most
    // recent provisional load URL.
    // See dispatchDidReceiveServerRedirectForProvisionalLoad.
    WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
    if (!ds) {
        ASSERT_NOT_REACHED();
        return;
    }
    KURL url = ds->request().url();

    // Since the provisional load just started, we should have not gotten
    // any redirects yet.
    ASSERT(!ds->hasRedirectChain());

    // If this load is what we expected from a client redirect, treat it as a
    // redirect from that original page. The expected redirect urls will be
    // cleared by DidCancelClientRedirect.
    bool completingClientRedirect = false;
    if (m_expectedClientRedirectSrc.isValid()) {
        // m_expectedClientRedirectDest could be something like
        // "javascript:history.go(-1)" thus we need to exclude url starts with
        // "javascript:". See bug: 1080873
        if (m_expectedClientRedirectDest.protocolIs("javascript")
            || m_expectedClientRedirectDest == url) {
            ds->appendRedirect(m_expectedClientRedirectSrc);
            completingClientRedirect = true;
        } else {
            // Any pending redirect is no longer in progress. This can happen
            // if the navigation was canceled with PolicyIgnore, or if the
            // redirect was scheduled on the wrong frame (e.g., due to a form
            // submission targeted to _blank, as in http://webkit.org/b/44079).
            m_expectedClientRedirectSrc = KURL();
            m_expectedClientRedirectDest = KURL();
        }
    }
    ds->appendRedirect(url);

    if (m_webFrame->client()) {
        // Whatever information didCompleteClientRedirect contains should only
        // be considered relevant until the next provisional load has started.
        // So we first tell the client that the load started, and then tell it
        // about the client redirect the load is responsible for completing.
        m_webFrame->client()->didStartProvisionalLoad(m_webFrame);
        if (completingClientRedirect) {
            m_webFrame->client()->didCompleteClientRedirect(
                m_webFrame, m_expectedClientRedirectSrc);
        }
    }
}

void FrameLoaderClientImpl::dispatchDidReceiveTitle(const StringWithDirection& title)
{
    if (m_webFrame->client())
        m_webFrame->client()->didReceiveTitle(m_webFrame, title.string(), title.direction() == LTR ? WebTextDirectionLeftToRight : WebTextDirectionRightToLeft);
}

void FrameLoaderClientImpl::dispatchDidChangeIcons(WebCore::IconType type)
{
    if (m_webFrame->client())
        m_webFrame->client()->didChangeIcon(m_webFrame, static_cast<WebIconURL::Type>(type));
}

void FrameLoaderClientImpl::dispatchDidCommitLoad()
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    bool isNewNavigation;
    webview->didCommitLoad(&isNewNavigation, false);

    if (m_webFrame->client())
        m_webFrame->client()->didCommitProvisionalLoad(m_webFrame, isNewNavigation);
}

void FrameLoaderClientImpl::dispatchDidFailProvisionalLoad(
    const ResourceError& error)
{

    // If a policy change occured, then we do not want to inform the plugin
    // delegate.  See http://b/907789 for details.  FIXME: This means the
    // plugin won't receive NPP_URLNotify, which seems like it could result in
    // a memory leak in the plugin!!
    if (error.domain() == internalErrorDomain
        && error.errorCode() == PolicyChangeError) {
        m_webFrame->didFail(cancelledError(error.failingURL()), true);
        return;
    }

    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
    m_webFrame->didFail(error, true);
    if (observer)
        observer->didFailLoading(error);
}

void FrameLoaderClientImpl::dispatchDidFailLoad(const ResourceError& error)
{
    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
    m_webFrame->didFail(error, false);
    if (observer)
        observer->didFailLoading(error);

    // Don't clear the redirect chain, this will happen in the middle of client
    // redirects, and we need the context. The chain will be cleared when the
    // provisional load succeeds or fails, not the "real" one.
}

void FrameLoaderClientImpl::dispatchDidFinishLoad()
{
    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();

    if (m_webFrame->client())
        m_webFrame->client()->didFinishLoad(m_webFrame);

    if (observer)
        observer->didFinishLoading();

    // Don't clear the redirect chain, this will happen in the middle of client
    // redirects, and we need the context. The chain will be cleared when the
    // provisional load succeeds or fails, not the "real" one.
}

void FrameLoaderClientImpl::dispatchDidLayout(LayoutMilestones milestones)
{
    if (!m_webFrame->client())
        return;

    if (milestones & DidFirstLayout)
        m_webFrame->client()->didFirstLayout(m_webFrame);
    if (milestones & DidFirstVisuallyNonEmptyLayout)
        m_webFrame->client()->didFirstVisuallyNonEmptyLayout(m_webFrame);
}

Frame* FrameLoaderClientImpl::dispatchCreatePage(const NavigationAction& action)
{
    // Make sure that we have a valid disposition.  This should have been set in
    // the preceeding call to dispatchDecidePolicyForNewWindowAction.
    ASSERT(m_nextNavigationPolicy != WebNavigationPolicyIgnore);
    WebNavigationPolicy policy = m_nextNavigationPolicy;
    m_nextNavigationPolicy = WebNavigationPolicyIgnore;

    // Store the disposition on the opener ChromeClientImpl so that we can pass
    // it to WebViewClient::createView.
    ChromeClientImpl* chromeClient = static_cast<ChromeClientImpl*>(m_webFrame->frame()->page()->chrome()->client());
    chromeClient->setNewWindowNavigationPolicy(policy);

    struct WindowFeatures features;
    Page* newPage = m_webFrame->frame()->page()->chrome()->createWindow(
        m_webFrame->frame(), FrameLoadRequest(m_webFrame->frame()->document()->securityOrigin()),
        features, action);

    // createWindow can return null (e.g., popup blocker denies the window).
    if (!newPage)
        return 0;

    // Also give the disposition to the new window.
    WebViewImpl::fromPage(newPage)->setInitialNavigationPolicy(policy);
    return newPage->mainFrame();
}

void FrameLoaderClientImpl::dispatchShow()
{
    WebViewImpl* webView = m_webFrame->viewImpl();
    if (webView && webView->client())
        webView->client()->show(webView->initialNavigationPolicy());
}

void FrameLoaderClientImpl::dispatchDecidePolicyForResponse(
     FramePolicyFunction function,
     const ResourceResponse& response,
     const ResourceRequest&)
{
    PolicyAction action;

    int statusCode = response.httpStatusCode();
    if (statusCode == 204 || statusCode == 205) {
        // The server does not want us to replace the page contents.
        action = PolicyIgnore;
    } else if (WebCore::contentDispositionType(response.httpHeaderField("Content-Disposition")) == WebCore::ContentDispositionAttachment) {
        // The server wants us to download instead of replacing the page contents.
        // Downloading is handled by the embedder, but we still get the initial
        // response so that we can ignore it and clean up properly.
        action = PolicyIgnore;
    } else if (!canShowMIMEType(response.mimeType())) {
        // Make sure that we can actually handle this type internally.
        action = PolicyIgnore;
    } else {
        // OK, we will render this page.
        action = PolicyUse;
    }

    // NOTE: PolicyChangeError will be generated when action is not PolicyUse.
    (m_webFrame->frame()->loader()->policyChecker()->*function)(action);
}

void FrameLoaderClientImpl::dispatchDecidePolicyForNewWindowAction(
    FramePolicyFunction function,
    const NavigationAction& action,
    const ResourceRequest& request,
    PassRefPtr<FormState> formState,
    const String& frameName)
{
    WebNavigationPolicy navigationPolicy;
    if (!actionSpecifiesNavigationPolicy(action, &navigationPolicy))
        navigationPolicy = WebNavigationPolicyNewForegroundTab;

    PolicyAction policyAction;
    if (navigationPolicy == WebNavigationPolicyDownload)
        policyAction = PolicyDownload;
    else {
        policyAction = PolicyUse;

        // Remember the disposition for when dispatchCreatePage is called.  It is
        // unfortunate that WebCore does not provide us with any context when
        // creating or showing the new window that would allow us to avoid having
        // to keep this state.
        m_nextNavigationPolicy = navigationPolicy;

        // Store the disposition on the opener ChromeClientImpl so that we can pass
        // it to WebViewClient::createView.
        ChromeClientImpl* chromeClient = static_cast<ChromeClientImpl*>(m_webFrame->frame()->page()->chrome()->client());
        chromeClient->setNewWindowNavigationPolicy(navigationPolicy);
    }
    (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
}

void FrameLoaderClientImpl::dispatchDecidePolicyForNavigationAction(
    FramePolicyFunction function,
    const NavigationAction& action,
    const ResourceRequest& request,
    PassRefPtr<FormState> formState) {
    PolicyAction policyAction = PolicyIgnore;

    // It is valid for this function to be invoked in code paths where the
    // webview is closed.
    // The null check here is to fix a crash that seems strange
    // (see - https://bugs.webkit.org/show_bug.cgi?id=23554).
    if (m_webFrame->client() && !request.url().isNull()) {
        WebNavigationPolicy navigationPolicy = WebNavigationPolicyCurrentTab;
        actionSpecifiesNavigationPolicy(action, &navigationPolicy);

        // Give the delegate a chance to change the navigation policy.
        const WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
        if (ds) {
            KURL url = ds->request().url();
            ASSERT(!url.protocolIs(backForwardNavigationScheme));

            bool isRedirect = ds->isRedirect();

            WebNavigationType webnavType =
                WebDataSourceImpl::toWebNavigationType(action.type());

            RefPtr<Node> node;
            for (const Event* event = action.event(); event; event = event->underlyingEvent()) {
                if (event->isMouseEvent()) {
                    const MouseEvent* mouseEvent =
                        static_cast<const MouseEvent*>(event);
                    node = m_webFrame->frame()->eventHandler()->hitTestResultAtPoint(
                        mouseEvent->absoluteLocation(), false).innerNonSharedNode();
                    break;
                }
            }
            WebNode originatingNode(node);

            navigationPolicy = m_webFrame->client()->decidePolicyForNavigation(
                m_webFrame, ds->request(), webnavType, originatingNode,
                navigationPolicy, isRedirect);
        }

        if (navigationPolicy == WebNavigationPolicyCurrentTab)
            policyAction = PolicyUse;
        else if (navigationPolicy == WebNavigationPolicyDownload)
            policyAction = PolicyDownload;
        else {
            if (navigationPolicy != WebNavigationPolicyIgnore) {
                WrappedResourceRequest webreq(request);
                m_webFrame->client()->loadURLExternally(m_webFrame, webreq, navigationPolicy);
            }
            policyAction = PolicyIgnore;
        }
    }

    (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
}

void FrameLoaderClientImpl::cancelPolicyCheck()
{
    // FIXME
}

void FrameLoaderClientImpl::dispatchUnableToImplementPolicy(const ResourceError& error)
{
    m_webFrame->client()->unableToImplementPolicyWithError(m_webFrame, error);
}

void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(PassRefPtr<FormState> prpFormState)
{
    if (m_webFrame->client())
        m_webFrame->client()->willSendSubmitEvent(m_webFrame, WebFormElement(prpFormState->form()));
}

void FrameLoaderClientImpl::dispatchWillSubmitForm(FramePolicyFunction function,
    PassRefPtr<FormState> formState)
{
    if (m_webFrame->client())
        m_webFrame->client()->willSubmitForm(m_webFrame, WebFormElement(formState->form()));
    (m_webFrame->frame()->loader()->policyChecker()->*function)(PolicyUse);
}

void FrameLoaderClientImpl::setMainDocumentError(DocumentLoader*,
                                                 const ResourceError& error)
{
    if (m_pluginWidget) {
        if (m_sentInitialResponseToPlugin) {
            m_pluginWidget->didFailLoading(error);
            m_sentInitialResponseToPlugin = false;
        }
        m_pluginWidget = 0;
    }
}

void FrameLoaderClientImpl::postProgressStartedNotification()
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->client())
        webview->client()->didStartLoading();
}

void FrameLoaderClientImpl::postProgressEstimateChangedNotification()
{
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->client()) {
        webview->client()->didChangeLoadProgress(
            m_webFrame, m_webFrame->frame()->page()->progress()->estimatedProgress());
    }

}

void FrameLoaderClientImpl::postProgressFinishedNotification()
{
    // FIXME: why might the webview be null?  http://b/1234461
    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview && webview->client())
        webview->client()->didStopLoading();
}

void FrameLoaderClientImpl::setMainFrameDocumentReady(bool ready)
{
    // FIXME
}

// Creates a new connection and begins downloading from that (contrast this
// with |download|).
void FrameLoaderClientImpl::startDownload(const ResourceRequest& request, const String& suggestedName)
{
    if (m_webFrame->client()) {
        WrappedResourceRequest webreq(request);
        m_webFrame->client()->loadURLExternally(
            m_webFrame, webreq, WebNavigationPolicyDownload, suggestedName);
    }
}

void FrameLoaderClientImpl::willChangeTitle(DocumentLoader*)
{
    // FIXME
}

void FrameLoaderClientImpl::didChangeTitle(DocumentLoader*)
{
    // FIXME
}

// Called whenever data is received.
void FrameLoaderClientImpl::committedLoad(DocumentLoader* loader, const char* data, int length)
{
    if (!m_pluginWidget) {
        if (m_webFrame->client()) {
            bool preventDefault = false;
            m_webFrame->client()->didReceiveDocumentData(m_webFrame, data, length, preventDefault);
            if (!preventDefault)
                m_webFrame->commitDocumentData(data, length);
        }
    }

    // If we are sending data to MediaDocument, we should stop here
    // and cancel the request.
    if (m_webFrame->frame()->document()->isMediaDocument())
        loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));

    // The plugin widget could have been created in the m_webFrame->DidReceiveData
    // function.
    if (m_pluginWidget) {
        if (!m_sentInitialResponseToPlugin) {
            m_sentInitialResponseToPlugin = true;
            m_pluginWidget->didReceiveResponse(
                m_webFrame->frame()->loader()->activeDocumentLoader()->response());
        }

        // It's possible that the above call removed the pointer to the plugin, so
        // check before calling it.
        if (m_pluginWidget)
            m_pluginWidget->didReceiveData(data, length);
    }
}

void FrameLoaderClientImpl::finishedLoading(DocumentLoader*)
{
    if (m_pluginWidget) {
        m_pluginWidget->didFinishLoading();
        m_pluginWidget = 0;
        m_sentInitialResponseToPlugin = false;
    }
}

void FrameLoaderClientImpl::updateGlobalHistory()
{
}

void FrameLoaderClientImpl::updateGlobalHistoryRedirectLinks()
{
}

bool FrameLoaderClientImpl::shouldGoToHistoryItem(HistoryItem* item) const
{
    const KURL& url = item->url();
    if (!url.protocolIs(backForwardNavigationScheme))
        return true;

    // Else, we'll punt this history navigation to the embedder.  It is
    // necessary that we intercept this here, well before the FrameLoader
    // has made any state changes for this history traversal.

    bool ok;
    int offset = url.lastPathComponent().toIntStrict(&ok);
    if (!ok) {
        ASSERT_NOT_REACHED();
        return false;
    }

    WebViewImpl* webview = m_webFrame->viewImpl();
    if (webview->client())
        webview->client()->navigateBackForwardSoon(offset);

    return false;
}

bool FrameLoaderClientImpl::shouldStopLoadingForHistoryItem(HistoryItem* targetItem) const
{
    // Don't stop loading for pseudo-back-forward URLs, since they will get
    // translated and then pass through again.
    const KURL& url = targetItem->url();
    return !url.protocolIs(backForwardNavigationScheme);
}

void FrameLoaderClientImpl::didDisplayInsecureContent()
{
    if (m_webFrame->client())
        m_webFrame->client()->didDisplayInsecureContent(m_webFrame);
}

void FrameLoaderClientImpl::didRunInsecureContent(SecurityOrigin* origin, const KURL& insecureURL)
{
    if (m_webFrame->client())
        m_webFrame->client()->didRunInsecureContent(m_webFrame, WebSecurityOrigin(origin), insecureURL);
}

void FrameLoaderClientImpl::didDetectXSS(const KURL& insecureURL, bool didBlockEntirePage)
{
    if (m_webFrame->client())
        m_webFrame->client()->didDetectXSS(m_webFrame, insecureURL, didBlockEntirePage);
}

ResourceError FrameLoaderClientImpl::blockedError(const ResourceRequest&)
{
    // FIXME
    return ResourceError();
}

ResourceError FrameLoaderClientImpl::cancelledError(const ResourceRequest& request)
{
    if (!m_webFrame->client())
        return ResourceError();

    return m_webFrame->client()->cancelledError(
        m_webFrame, WrappedResourceRequest(request));
}

ResourceError FrameLoaderClientImpl::cannotShowURLError(const ResourceRequest& request)
{
    if (!m_webFrame->client())
        return ResourceError();

    return m_webFrame->client()->cannotHandleRequestError(
        m_webFrame, WrappedResourceRequest(request));
}

ResourceError FrameLoaderClientImpl::interruptedForPolicyChangeError(
    const ResourceRequest& request)
{
    return ResourceError(internalErrorDomain, PolicyChangeError,
                         request.url().string(), String());
}

ResourceError FrameLoaderClientImpl::cannotShowMIMETypeError(const ResourceResponse&)
{
    // FIXME
    return ResourceError();
}

ResourceError FrameLoaderClientImpl::fileDoesNotExistError(const ResourceResponse&)
{
    // FIXME
    return ResourceError();
}

ResourceError FrameLoaderClientImpl::pluginWillHandleLoadError(const ResourceResponse&)
{
    // FIXME
    return ResourceError();
}

bool FrameLoaderClientImpl::shouldFallBack(const ResourceError& error)
{
    // This method is called when we fail to load the URL for an <object> tag
    // that has fallback content (child elements) and is being loaded as a frame.
    // The error parameter indicates the reason for the load failure.
    // We should let the fallback content load only if this wasn't a cancelled
    // request.
    // Note: The mac version also has a case for "WebKitErrorPluginWillHandleLoad"
    ResourceError c = cancelledError(ResourceRequest());
    return error.errorCode() != c.errorCode() || error.domain() != c.domain();
}

bool FrameLoaderClientImpl::canHandleRequest(const ResourceRequest& request) const
{
    return m_webFrame->client()->canHandleRequest(
        m_webFrame, WrappedResourceRequest(request));
}

bool FrameLoaderClientImpl::canShowMIMETypeAsHTML(const String& MIMEType) const
{
    notImplemented();
    return false;
}

bool FrameLoaderClientImpl::canShowMIMEType(const String& mimeType) const
{
    // This method is called to determine if the media type can be shown
    // "internally" (i.e. inside the browser) regardless of whether or not the
    // browser or a plugin is doing the rendering.

    // mimeType strings are supposed to be ASCII, but if they are not for some
    // reason, then it just means that the mime type will fail all of these "is
    // supported" checks and go down the path of an unhandled mime type.
    if (WebKit::Platform::current()->mimeRegistry()->supportsMIMEType(mimeType) == WebMimeRegistry::IsSupported)
        return true;

    // If Chrome is started with the --disable-plugins switch, pluginData is null.
    PluginData* pluginData = m_webFrame->frame()->page()->pluginData();

    // See if the type is handled by an installed plugin, if so, we can show it.
    // FIXME: (http://b/1085524) This is the place to stick a preference to
    //        disable full page plugins (optionally for certain types!)
    return !mimeType.isEmpty() && pluginData && pluginData->supportsMimeType(mimeType);
}

bool FrameLoaderClientImpl::representationExistsForURLScheme(const String&) const
{
    // FIXME
    return false;
}

String FrameLoaderClientImpl::generatedMIMETypeForURLScheme(const String& scheme) const
{
    // This appears to generate MIME types for protocol handlers that are handled
    // internally. The only place I can find in the WebKit code that uses this
    // function is WebView::registerViewClass, where it is used as part of the
    // process by which custom view classes for certain document representations
    // are registered.
    String mimeType("x-apple-web-kit/");
    mimeType.append(scheme.lower());
    return mimeType;
}

void FrameLoaderClientImpl::frameLoadCompleted()
{
    // FIXME: the mac port also conditionally calls setDrawsBackground:YES on
    // it's ScrollView here.

    // This comment from the Mac port:
    // Note: Can be called multiple times.
    // Even if already complete, we might have set a previous item on a frame that
    // didn't do any data loading on the past transaction. Make sure to clear these out.

    // FIXME: setPreviousHistoryItem() no longer exists. http://crbug.com/8566
    // m_webFrame->frame()->loader()->setPreviousHistoryItem(0);
}

void FrameLoaderClientImpl::saveViewStateToItem(HistoryItem*)
{
    // FIXME
}

void FrameLoaderClientImpl::restoreViewState()
{
    // FIXME: probably scrolls to last position when you go back or forward
}

void FrameLoaderClientImpl::provisionalLoadStarted()
{
    // FIXME: On mac, this does various caching stuff
}

void FrameLoaderClientImpl::didFinishLoad()
{
    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
    if (observer)
        observer->didFinishLoading();
}

void FrameLoaderClientImpl::prepareForDataSourceReplacement()
{
    // FIXME
}

PassRefPtr<DocumentLoader> FrameLoaderClientImpl::createDocumentLoader(
    const ResourceRequest& request,
    const SubstituteData& data)
{
    RefPtr<WebDataSourceImpl> ds = WebDataSourceImpl::create(request, data);
    if (m_webFrame->client())
        m_webFrame->client()->didCreateDataSource(m_webFrame, ds.get());
    return ds.release();
}

void FrameLoaderClientImpl::setTitle(const StringWithDirection& title, const KURL& url)
{
    // FIXME: inform consumer of changes to the title.
}

String FrameLoaderClientImpl::userAgent(const KURL& url)
{
    WebString override = m_webFrame->client()->userAgentOverride(m_webFrame, WebURL(url));
    if (!override.isEmpty())
        return override;

    return WebKit::Platform::current()->userAgent(url);
}

void FrameLoaderClientImpl::savePlatformDataToCachedFrame(CachedFrame*)
{
    // The page cache should be disabled.
    ASSERT_NOT_REACHED();
}

void FrameLoaderClientImpl::transitionToCommittedFromCachedFrame(CachedFrame*)
{
    ASSERT_NOT_REACHED();
}

// Called when the FrameLoader goes into a state in which a new page load
// will occur.
void FrameLoaderClientImpl::transitionToCommittedForNewPage()
{
    makeDocumentView();
}

void FrameLoaderClientImpl::didSaveToPageCache()
{
}

void FrameLoaderClientImpl::didRestoreFromPageCache()
{
}

void FrameLoaderClientImpl::dispatchDidBecomeFrameset(bool)
{
}

bool FrameLoaderClientImpl::canCachePage() const
{
    // Since we manage the cache, always report this page as non-cacheable to
    // FrameLoader.
    return false;
}

// Downloading is handled in the browser process, not WebKit. If we get to this
// point, our download detection code in the ResourceDispatcherHost is broken!
void FrameLoaderClientImpl::download(ResourceHandle* handle,
                                     const ResourceRequest& request,
                                     const ResourceResponse& response)
{
    ASSERT_NOT_REACHED();
}

PassRefPtr<Frame> FrameLoaderClientImpl::createFrame(
    const KURL& url,
    const String& name,
    HTMLFrameOwnerElement* ownerElement,
    const String& referrer,
    bool allowsScrolling,
    int marginWidth,
    int marginHeight)
{
    FrameLoadRequest frameRequest(m_webFrame->frame()->document()->securityOrigin(),
        ResourceRequest(url, referrer), name);
    return m_webFrame->createChildFrame(frameRequest, ownerElement);
}

PassRefPtr<Widget> FrameLoaderClientImpl::createPlugin(
    const IntSize& size, // FIXME: how do we use this?
    HTMLPlugInElement* element,
    const KURL& url,
    const Vector<String>& paramNames,
    const Vector<String>& paramValues,
    const String& mimeType,
    bool loadManually)
{
    if (!m_webFrame->client())
        return 0;

    WebPluginParams params;
    params.url = url;
    params.mimeType = mimeType;
    params.attributeNames = paramNames;
    params.attributeValues = paramValues;
    params.loadManually = loadManually;

    WebPlugin* webPlugin = m_webFrame->client()->createPlugin(m_webFrame, params);
    if (!webPlugin)
        return 0;

    // The container takes ownership of the WebPlugin.
    RefPtr<WebPluginContainerImpl> container =
        WebPluginContainerImpl::create(element, webPlugin);

    if (!webPlugin->initialize(container.get()))
        return 0;

    // The element might have been removed during plugin initialization!
    if (!element->renderer())
        return 0;

    return container;
}

// This method gets called when a plugin is put in place of html content
// (e.g., acrobat reader).
void FrameLoaderClientImpl::redirectDataToPlugin(Widget* pluginWidget)
{
    ASSERT(!pluginWidget || pluginWidget->isPluginContainer());
    m_pluginWidget = static_cast<WebPluginContainerImpl*>(pluginWidget);
}

PassRefPtr<Widget> FrameLoaderClientImpl::createJavaAppletWidget(
    const IntSize& size,
    HTMLAppletElement* element,
    const KURL& /* baseURL */,
    const Vector<String>& paramNames,
    const Vector<String>& paramValues)
{
    return createPlugin(size, element, KURL(), paramNames, paramValues,
        "application/x-java-applet", false);
}

ObjectContentType FrameLoaderClientImpl::objectContentType(
    const KURL& url,
    const String& explicitMimeType,
    bool shouldPreferPlugInsForImages)
{
    // This code is based on Apple's implementation from
    // WebCoreSupport/WebFrameBridge.mm.

    String mimeType = explicitMimeType;
    if (mimeType.isEmpty()) {
        // Try to guess the MIME type based off the extension.
        String filename = url.lastPathComponent();
        int extensionPos = filename.reverseFind('.');
        if (extensionPos >= 0) {
            String extension = filename.substring(extensionPos + 1);
            mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
            if (mimeType.isEmpty()) {
                // If there's no mimetype registered for the extension, check to see
                // if a plugin can handle the extension.
                mimeType = getPluginMimeTypeFromExtension(extension);
            }
        }

        if (mimeType.isEmpty())
            return ObjectContentFrame;
    }

    // If Chrome is started with the --disable-plugins switch, pluginData is 0.
    PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
    bool plugInSupportsMIMEType = pluginData && pluginData->supportsMimeType(mimeType);

    if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
        return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;

    if (plugInSupportsMIMEType)
        return ObjectContentNetscapePlugin;

    if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
        return ObjectContentFrame;

    return ObjectContentNone;
}

String FrameLoaderClientImpl::overrideMediaType() const
{
    // FIXME
    return String();
}

bool FrameLoaderClientImpl::actionSpecifiesNavigationPolicy(
    const NavigationAction& action,
    WebNavigationPolicy* policy)
{
    const MouseEvent* event = 0;
    if (action.type() == NavigationTypeLinkClicked
        && action.event()->isMouseEvent())
        event = static_cast<const MouseEvent*>(action.event());
    else if (action.type() == NavigationTypeFormSubmitted
             && action.event()
             && action.event()->underlyingEvent()
             && action.event()->underlyingEvent()->isMouseEvent())
        event = static_cast<const MouseEvent*>(action.event()->underlyingEvent());

    if (!event)
        return false;

    return WebViewImpl::navigationPolicyFromMouseEvent(
        event->button(), event->ctrlKey(), event->shiftKey(), event->altKey(),
        event->metaKey(), policy);
}

PassOwnPtr<WebPluginLoadObserver> FrameLoaderClientImpl::pluginLoadObserver()
{
    WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(
        m_webFrame->frame()->loader()->activeDocumentLoader());
    if (!ds) {
        // We can arrive here if a popstate event handler detaches this frame.
        // FIXME: Remove this code once http://webkit.org/b/36202 is fixed.
        ASSERT(!m_webFrame->frame()->page());
        return nullptr;
    }
    return ds->releasePluginLoadObserver();
}

PassRefPtr<FrameNetworkingContext> FrameLoaderClientImpl::createNetworkingContext()
{
    return FrameNetworkingContextImpl::create(m_webFrame->frame());
}

bool FrameLoaderClientImpl::willCheckAndDispatchMessageEvent(
    SecurityOrigin* target, MessageEvent* event) const
{
    if (!m_webFrame->client())
        return false;

    WebFrame* source = 0;
    if (event && event->source() && event->source()->document())
        source = WebFrameImpl::fromFrame(event->source()->document()->frame());
    return m_webFrame->client()->willCheckAndDispatchMessageEvent(
        source, m_webFrame, WebSecurityOrigin(target), WebDOMMessageEvent(event));
}

#if ENABLE(WEB_INTENTS_TAG)
void FrameLoaderClientImpl::registerIntentService(
        const String& action,
        const String& type,
        const KURL& href,
        const String& title,
        const String& disposition) {
    if (!m_webFrame->client())
        return;

    WebIntentServiceInfo service(action, type, href, title, disposition);
    m_webFrame->client()->registerIntentService(m_webFrame, service);
}
#endif

#if ENABLE(WEB_INTENTS)
void FrameLoaderClientImpl::dispatchIntent(PassRefPtr<WebCore::IntentRequest> intentRequest)
{
    m_webFrame->client()->dispatchIntent(webFrame(), intentRequest);
}
#endif

void FrameLoaderClientImpl::dispatchWillOpenSocketStream(SocketStreamHandle* handle)
{
    m_webFrame->client()->willOpenSocketStream(SocketStreamHandleInternal::toWebSocketStreamHandle(handle));
}

#if ENABLE(MEDIA_STREAM)
void FrameLoaderClientImpl::dispatchWillStartUsingPeerConnectionHandler(RTCPeerConnectionHandler* handler)
{
    m_webFrame->client()->willStartUsingPeerConnectionHandler(webFrame(), RTCPeerConnectionHandlerChromium::toWebRTCPeerConnectionHandler(handler));
}
#endif


} // namespace WebKit
