16b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner/*
26b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
36b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
46b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
56b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
66b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
76b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Copyright (C) 2010 Google Inc. All rights reserved.
86b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
96b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    This library is free software; you can redistribute it and/or
106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    modify it under the terms of the GNU Library General Public
116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    License as published by the Free Software Foundation; either
126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    version 2 of the License, or (at your option) any later version.
136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    This library is distributed in the hope that it will be useful,
156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    but WITHOUT ANY WARRANTY; without even the implied warranty of
166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Library General Public License for more details.
186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    You should have received a copy of the GNU Library General Public License
206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    along with this library; see the file COPYING.LIB.  If not, write to
216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Boston, MA 02110-1301, USA.
236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner */
246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "config.h"
266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "ResourceLoadScheduler.h"
276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "Document.h"
296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "Frame.h"
306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "FrameLoader.h"
316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "InspectorInstrumentation.h"
326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "KURL.h"
336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "Logging.h"
346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "NetscapePlugInStreamLoader.h"
356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "ResourceLoader.h"
366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "ResourceRequest.h"
376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "SubresourceLoader.h"
389f8811ec084be6ba9380c41abf6e2a080b6d9b91Russell Brenner#include <wtf/text/CString.h>
396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#define REQUEST_MANAGEMENT_ENABLED 1
416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennernamespace WebCore {
436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#if REQUEST_MANAGEMENT_ENABLED
456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner// Match the parallel connection count used by the networking layer.
476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic unsigned maxRequestsInFlightPerHost;
486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#else
496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic const unsigned maxRequestsInFlightForNonHTTPProtocols = 10000;
506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic const unsigned maxRequestsInFlightPerHost = 10000;
516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif
526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerResourceLoadScheduler::HostInformation* ResourceLoadScheduler::hostForURL(const KURL& url, CreateHostPolicy createHostPolicy)
546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!url.protocolInHTTPFamily())
566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return m_nonHTTPProtocolHost;
576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_hosts.checkConsistency();
596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    String hostName = url.host();
606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    HostInformation* host = m_hosts.get(hostName);
616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!host && createHostPolicy == CreateIfNotFound) {
626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        host = new HostInformation(hostName, maxRequestsInFlightPerHost);
636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_hosts.add(hostName, host);
646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return host;
666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerResourceLoadScheduler* resourceLoadScheduler()
696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(isMainThread());
716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    DEFINE_STATIC_LOCAL(ResourceLoadScheduler, resourceLoadScheduler, ());
726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return &resourceLoadScheduler;
736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerResourceLoadScheduler::ResourceLoadScheduler()
766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    : m_nonHTTPProtocolHost(new HostInformation(String(), maxRequestsInFlightForNonHTTPProtocols))
776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_requestTimer(this, &ResourceLoadScheduler::requestTimerFired)
786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_isSuspendingPendingRequests(false)
79f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    , m_isSerialLoadingEnabled(false)
806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#if REQUEST_MANAGEMENT_ENABLED
826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    maxRequestsInFlightPerHost = initializeMaximumHTTPConnectionCountPerHost();
836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif
846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
862bde8e466a4451c7319e3a072d118917957d6554Steve BlockPassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, ResourceLoadPriority priority, SecurityCheckPolicy securityCheck,
8754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                                                                             bool sendResourceLoadCallbacks, bool shouldContentSniff, const String& optionalOutgoingReferrer, bool shouldBufferData)
886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
8954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    RefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, client, request, securityCheck, sendResourceLoadCallbacks, shouldContentSniff, optionalOutgoingReferrer, shouldBufferData);
906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (loader)
916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        scheduleLoad(loader.get(), priority);
922bde8e466a4451c7319e3a072d118917957d6554Steve Block    return loader.release();
936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerPassRefPtr<NetscapePlugInStreamLoader> ResourceLoadScheduler::schedulePluginStreamLoad(Frame* frame, NetscapePlugInStreamLoaderClient* client, const ResourceRequest& request)
966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    PassRefPtr<NetscapePlugInStreamLoader> loader = NetscapePlugInStreamLoader::create(frame, client, request);
986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (loader)
99f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        scheduleLoad(loader.get(), ResourceLoadPriorityLow);
1006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return loader;
1016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::addMainResourceLoad(ResourceLoader* resourceLoader)
1046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    hostForURL(resourceLoader->url(), CreateIfNotFound)->addLoadInProgress(resourceLoader);
1066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
108f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, ResourceLoadPriority priority)
1096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(resourceLoader);
111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(priority != ResourceLoadPriorityUnresolved);
1126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#if !REQUEST_MANAGEMENT_ENABLED
113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    priority = ResourceLoadPriorityHighest;
1146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif
1156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    LOG(ResourceLoading, "ResourceLoadScheduler::load resource %p '%s'", resourceLoader, resourceLoader->url().string().latin1().data());
1176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    HostInformation* host = hostForURL(resourceLoader->url(), CreateIfNotFound);
1186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    bool hadRequests = host->hasRequests();
1196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    host->schedule(resourceLoader, priority);
1206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (priority > ResourceLoadPriorityLow || !resourceLoader->url().protocolInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) {
1226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // Try to request important resources immediately.
1236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        servePendingRequests(host, priority);
1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
1256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones.
1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    InspectorInstrumentation::didScheduleResourceRequest(resourceLoader->frameLoader() ? resourceLoader->frameLoader()->frame()->document() : 0, resourceLoader->url());
1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    scheduleServePendingRequests();
1306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::remove(ResourceLoader* resourceLoader)
1336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(resourceLoader);
1356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    HostInformation* host = hostForURL(resourceLoader->url());
1376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (host)
1386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        host->remove(resourceLoader);
1396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    scheduleServePendingRequests();
1406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader* resourceLoader, const KURL& redirectURL)
1436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    HostInformation* oldHost = hostForURL(resourceLoader->url());
1456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(oldHost);
1466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    HostInformation* newHost = hostForURL(redirectURL, CreateIfNotFound);
1476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (oldHost->name() == newHost->name())
1496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    newHost->addLoadInProgress(resourceLoader);
1526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    oldHost->remove(resourceLoader);
1536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid ResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
1566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    LOG(ResourceLoading, "ResourceLoadScheduler::servePendingRequests. m_isSuspendingPendingRequests=%d", m_isSuspendingPendingRequests);
1586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_isSuspendingPendingRequests)
1596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_requestTimer.stop();
1626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    servePendingRequests(m_nonHTTPProtocolHost, minimumPriority);
1646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    Vector<HostInformation*> hostsToServe;
1666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_hosts.checkConsistency();
1676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    HostMap::iterator end = m_hosts.end();
1686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (HostMap::iterator iter = m_hosts.begin(); iter != end; ++iter)
1696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        hostsToServe.append(iter->second);
1706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    int size = hostsToServe.size();
1726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (int i = 0; i < size; ++i) {
1736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        HostInformation* host = hostsToServe[i];
1746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        if (host->hasRequests())
1756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            servePendingRequests(host, minimumPriority);
1766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        else
1776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            delete m_hosts.take(host->name());
1786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
1796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid ResourceLoadScheduler::servePendingRequests(HostInformation* host, ResourceLoadPriority minimumPriority)
1826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    LOG(ResourceLoading, "ResourceLoadScheduler::servePendingRequests HostInformation.m_name='%s'", host->name().latin1().data());
1846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
185f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (int priority = ResourceLoadPriorityHighest; priority >= minimumPriority; --priority) {
1862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        HostInformation::RequestQueue& requestsPending = host->requestsPending(ResourceLoadPriority(priority));
1876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        while (!requestsPending.isEmpty()) {
1896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            RefPtr<ResourceLoader> resourceLoader = requestsPending.first();
1906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // For named hosts - which are only http(s) hosts - we should always enforce the connection limit.
1926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // For non-named hosts - everything but http(s) - we should only enforce the limit if the document isn't done parsing
1936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // and we don't know all stylesheets yet.
1946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            Document* document = resourceLoader->frameLoader() ? resourceLoader->frameLoader()->frame()->document() : 0;
1956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            bool shouldLimitRequests = !host->name().isNull() || (document && (document->parsing() || !document->haveStylesheetsLoaded()));
1962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (shouldLimitRequests && host->limitRequests(ResourceLoadPriority(priority)))
1976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                return;
1986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            requestsPending.removeFirst();
2004576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            host->addLoadInProgress(resourceLoader.get());
2014576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            resourceLoader->start();
2026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        }
2036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::suspendPendingRequests()
2076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(!m_isSuspendingPendingRequests);
2096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_isSuspendingPendingRequests = true;
2106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::resumePendingRequests()
2136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(m_isSuspendingPendingRequests);
2156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_isSuspendingPendingRequests = false;
2166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!m_hosts.isEmpty() || m_nonHTTPProtocolHost->hasRequests())
2176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        scheduleServePendingRequests();
2186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::scheduleServePendingRequests()
2216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    LOG(ResourceLoading, "ResourceLoadScheduler::scheduleServePendingRequests, m_requestTimer.isActive()=%u", m_requestTimer.isActive());
2236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!m_requestTimer.isActive())
2246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_requestTimer.startOneShot(0);
2256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::requestTimerFired(Timer<ResourceLoadScheduler>*)
2286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    LOG(ResourceLoading, "ResourceLoadScheduler::requestTimerFired\n");
2306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    servePendingRequests();
2316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerResourceLoadScheduler::HostInformation::HostInformation(const String& name, unsigned maxRequestsInFlight)
2346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    : m_name(name)
2356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_maxRequestsInFlight(maxRequestsInFlight)
2366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerResourceLoadScheduler::HostInformation::~HostInformation()
2406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(m_requestsLoading.isEmpty());
242f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++)
2436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        ASSERT(m_requestsPending[p].isEmpty());
2446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
246f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid ResourceLoadScheduler::HostInformation::schedule(ResourceLoader* resourceLoader, ResourceLoadPriority priority)
2476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_requestsPending[priority].append(resourceLoader);
2496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::HostInformation::addLoadInProgress(ResourceLoader* resourceLoader)
2526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    LOG(ResourceLoading, "HostInformation '%s' loading '%s'. Current count %d", m_name.latin1().data(), resourceLoader->url().string().latin1().data(), m_requestsLoading.size());
2546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_requestsLoading.add(resourceLoader);
2556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid ResourceLoadScheduler::HostInformation::remove(ResourceLoader* resourceLoader)
2586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_requestsLoading.contains(resourceLoader)) {
2606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_requestsLoading.remove(resourceLoader);
2616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
2626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (int priority = ResourceLoadPriorityHighest; priority >= ResourceLoadPriorityLowest; --priority) {
2656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        RequestQueue::iterator end = m_requestsPending[priority].end();
2666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        for (RequestQueue::iterator it = m_requestsPending[priority].begin(); it != end; ++it) {
2676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            if (*it == resourceLoader) {
2686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                m_requestsPending[priority].remove(it);
2696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                return;
2706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            }
2716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        }
2726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool ResourceLoadScheduler::HostInformation::hasRequests() const
2766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!m_requestsLoading.isEmpty())
2786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return true;
279f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) {
2806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        if (!m_requestsPending[p].isEmpty())
2816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            return true;
2826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return false;
2846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool ResourceLoadScheduler::HostInformation::limitRequests(ResourceLoadPriority priority) const
2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (priority == ResourceLoadPriorityVeryLow && !m_requestsLoading.isEmpty())
2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
290f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_requestsLoading.size() >= (resourceLoadScheduler()->isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight);
291f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
292f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} // namespace WebCore
294