/*
    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
    Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
    Copyright (C) 2004-2008, 2015 Apple Inc. All rights reserved.
    Copyright (C) 2010 Google Inc. All rights reserved.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
 */

#include "WebResourceLoadScheduler.h"

#include <WebCore/Document.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/NetscapePlugInStreamLoader.h>
#include <WebCore/PingHandle.h>
#include <WebCore/PlatformStrategies.h>
#include <WebCore/ResourceHandle.h>
#include <WebCore/ResourceRequest.h>
#include <WebCore/SubresourceLoader.h>
#include <WebCore/URL.h>
#include <wtf/MainThread.h>
#include <wtf/TemporaryChange.h>
#include <wtf/text/CString.h>

#if PLATFORM(IOS)
#include <WebCore/RuntimeApplicationChecks.h>
#endif

#if USE(QUICK_LOOK)
#include <WebCore/QuickLook.h>
#endif

// Match the parallel connection count used by the networking layer.
static unsigned maxRequestsInFlightPerHost;
#if !PLATFORM(IOS)
static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
#else
// Limiting this seems to regress performance in some local cases so let's just make it large.
static const unsigned maxRequestsInFlightForNonHTTPProtocols = 10000;
#endif

using namespace WebCore;

WebResourceLoadScheduler& webResourceLoadScheduler()
{
    return static_cast<WebResourceLoadScheduler&>(*platformStrategies()->loaderStrategy());
}

WebResourceLoadScheduler::HostInformation* WebResourceLoadScheduler::hostForURL(const URL& url, CreateHostPolicy createHostPolicy)
{
    if (!url.protocolIsInHTTPFamily())
        return m_nonHTTPProtocolHost;

    m_hosts.checkConsistency();
    String hostName = url.host();
    HostInformation* host = m_hosts.get(hostName);
    if (!host && createHostPolicy == CreateIfNotFound) {
        host = new HostInformation(hostName, maxRequestsInFlightPerHost);
        m_hosts.add(hostName, host);
    }
    return host;
}

WebResourceLoadScheduler::WebResourceLoadScheduler()
    : m_nonHTTPProtocolHost(new HostInformation(String(), maxRequestsInFlightForNonHTTPProtocols))
    , m_requestTimer(*this, &WebResourceLoadScheduler::requestTimerFired)
    , m_suspendPendingRequestsCount(0)
    , m_isSerialLoadingEnabled(false)
{
    maxRequestsInFlightPerHost = initializeMaximumHTTPConnectionCountPerHost();
}

WebResourceLoadScheduler::~WebResourceLoadScheduler()
{
}

RefPtr<SubresourceLoader> WebResourceLoadScheduler::loadResource(Frame& frame, CachedResource& resource, const ResourceRequest& request, const ResourceLoaderOptions& options)
{
    RefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, resource, request, options);
    if (loader)
        scheduleLoad(loader.get());
#if PLATFORM(IOS)
    // Since we defer loader initialization until scheduling on iOS, the frame
    // load delegate that would be called in SubresourceLoader::create() on
    // other ports might be called in scheduleLoad() instead. Our contract to
    // callers of this method is that a null loader is returned if the load was
    // cancelled by a frame load delegate.
    if (!loader || loader->reachedTerminalState())
        return nullptr;
#endif
    return loader;
}

void WebResourceLoadScheduler::loadResourceSynchronously(NetworkingContext* context, unsigned long, const ResourceRequest& request, StoredCredentials storedCredentials, ClientCredentialPolicy, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
    ResourceHandle::loadResourceSynchronously(context, request, storedCredentials, error, response, data);
}

RefPtr<NetscapePlugInStreamLoader> WebResourceLoadScheduler::schedulePluginStreamLoad(Frame& frame, NetscapePlugInStreamLoaderClient& client, const ResourceRequest& request)
{
    RefPtr<NetscapePlugInStreamLoader> loader = NetscapePlugInStreamLoader::create(frame, client, request);
    if (loader)
        scheduleLoad(loader.get());
    return loader;
}

void WebResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader)
{
    ASSERT(resourceLoader);

#if PLATFORM(IOS)
    // If there's a web archive resource for this URL, we don't need to schedule the load since it will never touch the network.
    if (!isSuspendingPendingRequests() && resourceLoader->documentLoader()->archiveResourceForURL(resourceLoader->iOSOriginalRequest().url())) {
        resourceLoader->startLoading();
        return;
    }
#else
    if (resourceLoader->documentLoader()->archiveResourceForURL(resourceLoader->request().url())) {
        resourceLoader->start();
        return;
    }
#endif

#if PLATFORM(IOS)
    HostInformation* host = hostForURL(resourceLoader->iOSOriginalRequest().url(), CreateIfNotFound);
#else
    HostInformation* host = hostForURL(resourceLoader->url(), CreateIfNotFound);
#endif

    ResourceLoadPriority priority = resourceLoader->request().priority();

    bool hadRequests = host->hasRequests();
    host->schedule(resourceLoader, priority);

#if PLATFORM(COCOA) || USE(CFNETWORK)
    if (ResourceRequest::resourcePrioritiesEnabled() && !isSuspendingPendingRequests()) {
        // Serve all requests at once to keep the pipeline full at the network layer.
        // FIXME: Does this code do anything useful, given that we also set maxRequestsInFlightPerHost to effectively unlimited on these platforms?
        servePendingRequests(host, ResourceLoadPriority::VeryLow);
        return;
    }
#endif

#if PLATFORM(IOS)
    if ((priority > ResourceLoadPriority::Low || !resourceLoader->iOSOriginalRequest().url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriority::Low && !hadRequests)) && !isSuspendingPendingRequests()) {
        // Try to request important resources immediately.
        servePendingRequests(host, priority);
        return;
    }
#else
    if (priority > ResourceLoadPriority::Low || !resourceLoader->url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriority::Low && !hadRequests)) {
        // Try to request important resources immediately.
        servePendingRequests(host, priority);
        return;
    }
#endif

    // Handle asynchronously so early low priority requests don't
    // get scheduled before later high priority ones.
    scheduleServePendingRequests();
}

void WebResourceLoadScheduler::remove(ResourceLoader* resourceLoader)
{
    ASSERT(resourceLoader);

    HostInformation* host = hostForURL(resourceLoader->url());
    if (host)
        host->remove(resourceLoader);
#if PLATFORM(IOS)
    // ResourceLoader::url() doesn't start returning the correct value until the load starts. If we get canceled before that, we need to look for originalRequest url instead.
    // FIXME: ResourceLoader::url() should be made to return a sensible value at all times.
    if (!resourceLoader->iOSOriginalRequest().isNull()) {
        HostInformation* originalHost = hostForURL(resourceLoader->iOSOriginalRequest().url());
        if (originalHost && originalHost != host)
            originalHost->remove(resourceLoader);
    }
#endif
    scheduleServePendingRequests();
}

void WebResourceLoadScheduler::setDefersLoading(ResourceLoader*, bool)
{
}

void WebResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader* resourceLoader, const URL& redirectURL)
{
    HostInformation* oldHost = hostForURL(resourceLoader->url());
    ASSERT(oldHost);
    if (!oldHost)
        return;

    HostInformation* newHost = hostForURL(redirectURL, CreateIfNotFound);

    if (oldHost->name() == newHost->name())
        return;

    newHost->addLoadInProgress(resourceLoader);
    oldHost->remove(resourceLoader);
}

void WebResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
{
    if (isSuspendingPendingRequests())
        return;

    m_requestTimer.stop();
    
    servePendingRequests(m_nonHTTPProtocolHost, minimumPriority);

    Vector<HostInformation*> hostsToServe;
    copyValuesToVector(m_hosts, hostsToServe);

    for (auto* host : hostsToServe) {
        if (host->hasRequests())
            servePendingRequests(host, minimumPriority);
        else
            delete m_hosts.take(host->name());
    }
}

void WebResourceLoadScheduler::servePendingRequests(HostInformation* host, ResourceLoadPriority minimumPriority)
{
    auto priority = ResourceLoadPriority::Highest;
    while (true) {
        auto& requestsPending = host->requestsPending(priority);
        while (!requestsPending.isEmpty()) {
            RefPtr<ResourceLoader> resourceLoader = requestsPending.first();

            // For named hosts - which are only http(s) hosts - we should always enforce the connection limit.
            // For non-named hosts - everything but http(s) - we should only enforce the limit if the document isn't done parsing 
            // and we don't know all stylesheets yet.
            Document* document = resourceLoader->frameLoader() ? resourceLoader->frameLoader()->frame().document() : 0;
            bool shouldLimitRequests = !host->name().isNull() || (document && (document->parsing() || !document->haveStylesheetsLoaded()));
            if (shouldLimitRequests && host->limitRequests(priority))
                return;

            requestsPending.removeFirst();
            host->addLoadInProgress(resourceLoader.get());
#if PLATFORM(IOS)
            if (!IOSApplication::isWebProcess()) {
                resourceLoader->startLoading();
                return;
            }
#endif
            resourceLoader->start();
        }
        if (priority == minimumPriority)
            return;
        --priority;
    }
}

void WebResourceLoadScheduler::suspendPendingRequests()
{
    ++m_suspendPendingRequestsCount;
}

void WebResourceLoadScheduler::resumePendingRequests()
{
    ASSERT(m_suspendPendingRequestsCount);
    --m_suspendPendingRequestsCount;
    if (m_suspendPendingRequestsCount)
        return;
    if (!m_hosts.isEmpty() || m_nonHTTPProtocolHost->hasRequests())
        scheduleServePendingRequests();
}
    
void WebResourceLoadScheduler::scheduleServePendingRequests()
{
    if (!m_requestTimer.isActive())
        m_requestTimer.startOneShot(0);
}

void WebResourceLoadScheduler::requestTimerFired()
{
    servePendingRequests();
}

WebResourceLoadScheduler::HostInformation::HostInformation(const String& name, unsigned maxRequestsInFlight)
    : m_name(name)
    , m_maxRequestsInFlight(maxRequestsInFlight)
{
}

WebResourceLoadScheduler::HostInformation::~HostInformation()
{
    ASSERT(!hasRequests());
}

unsigned WebResourceLoadScheduler::HostInformation::priorityToIndex(ResourceLoadPriority priority)
{
    switch (priority) {
    case ResourceLoadPriority::VeryLow:
        return 0;
    case ResourceLoadPriority::Low:
        return 1;
    case ResourceLoadPriority::Medium:
        return 2;
    case ResourceLoadPriority::High:
        return 3;
    case ResourceLoadPriority::VeryHigh:
        return 4;
    }
    ASSERT_NOT_REACHED();
    return 0;
}

void WebResourceLoadScheduler::HostInformation::schedule(ResourceLoader* resourceLoader, ResourceLoadPriority priority)
{
    m_requestsPending[priorityToIndex(priority)].append(resourceLoader);
}
    
void WebResourceLoadScheduler::HostInformation::addLoadInProgress(ResourceLoader* resourceLoader)
{
    m_requestsLoading.add(resourceLoader);
}
    
void WebResourceLoadScheduler::HostInformation::remove(ResourceLoader* resourceLoader)
{
    if (m_requestsLoading.remove(resourceLoader))
        return;
    
    for (auto& requestQueue : m_requestsPending) {
        for (auto it = requestQueue.begin(), end = requestQueue.end(); it != end; ++it) {
            if (*it == resourceLoader) {
                requestQueue.remove(it);
                return;
            }
        }
    }
}

bool WebResourceLoadScheduler::HostInformation::hasRequests() const
{
    if (!m_requestsLoading.isEmpty())
        return true;
    for (auto& requestQueue : m_requestsPending) {
        if (!requestQueue.isEmpty())
            return true;
    }
    return false;
}

bool WebResourceLoadScheduler::HostInformation::limitRequests(ResourceLoadPriority priority) const 
{
    if (priority == ResourceLoadPriority::VeryLow && !m_requestsLoading.isEmpty())
        return true;
    return m_requestsLoading.size() >= (webResourceLoadScheduler().isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight);
}

void WebResourceLoadScheduler::createPingHandle(NetworkingContext* networkingContext, ResourceRequest& request, bool shouldUseCredentialStorage)
{
    // PingHandle manages its own lifetime, deleting itself when its purpose has been fulfilled.
    new PingHandle(networkingContext, request, shouldUseCredentialStorage, PingHandle::UsesAsyncCallbacks::No);
}

