123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- #include "config.h"
- #include "NetworkResourceLoadScheduler.h"
- #include "HostRecord.h"
- #include "Logging.h"
- #include "NetworkProcess.h"
- #include "NetworkResourceLoadParameters.h"
- #include "NetworkResourceLoader.h"
- #include <wtf/MainThread.h>
- #include <wtf/text/CString.h>
- #if ENABLE(NETWORK_PROCESS)
- using namespace WebCore;
- namespace WebKit {
- static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
- NetworkResourceLoadScheduler::NetworkResourceLoadScheduler()
- : m_nonHTTPProtocolHost(HostRecord::create(String(), maxRequestsInFlightForNonHTTPProtocols))
- , m_requestTimer(this, &NetworkResourceLoadScheduler::requestTimerFired)
- {
- platformInitializeMaximumHTTPConnectionCountPerHost();
- }
- void NetworkResourceLoadScheduler::scheduleServePendingRequests()
- {
- if (!m_requestTimer.isActive())
- m_requestTimer.startOneShot(0);
- }
- void NetworkResourceLoadScheduler::requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*)
- {
- servePendingRequests();
- }
- void NetworkResourceLoadScheduler::scheduleLoader(PassRefPtr<NetworkResourceLoader> loader)
- {
- ResourceLoadPriority priority = loader->priority();
- const ResourceRequest& resourceRequest = loader->request();
-
- LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::scheduleLoader resource '%s'", resourceRequest.url().string().utf8().data());
- HostRecord* host = hostForURL(resourceRequest.url(), CreateIfNotFound);
- bool hadRequests = host->hasRequests();
- host->scheduleResourceLoader(loader);
- if (priority > ResourceLoadPriorityLow || !resourceRequest.url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) {
- // Try to request important resources immediately.
- host->servePendingRequests(priority);
- return;
- }
-
- // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones.
- scheduleServePendingRequests();
- }
- HostRecord* NetworkResourceLoadScheduler::hostForURL(const WebCore::KURL& url, CreateHostPolicy createHostPolicy)
- {
- if (!url.protocolIsInHTTPFamily())
- return m_nonHTTPProtocolHost.get();
- m_hosts.checkConsistency();
- String hostName = url.host();
- HostRecord* host = m_hosts.get(hostName);
- if (!host && createHostPolicy == CreateIfNotFound) {
- RefPtr<HostRecord> newHost = HostRecord::create(hostName, m_maxRequestsInFlightPerHost);
- host = newHost.get();
- m_hosts.add(hostName, newHost.release());
- }
-
- return host;
- }
- void NetworkResourceLoadScheduler::removeLoader(NetworkResourceLoader* loader)
- {
- ASSERT(isMainThread());
- ASSERT(loader);
- LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::removeLoadIdentifier removing loader %s", loader->request().url().string().utf8().data());
- HostRecord* host = loader->hostRecord();
-
- // Due to a race condition the WebProcess might have messaged the NetworkProcess to remove this identifier
- // after the NetworkProcess has already removed it internally.
- // In this situation we might not have a HostRecord to clean up.
- if (host)
- host->removeLoader(loader);
- scheduleServePendingRequests();
- }
- void NetworkResourceLoadScheduler::receivedRedirect(NetworkResourceLoader* loader, const WebCore::KURL& redirectURL)
- {
- ASSERT(isMainThread());
- LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::receivedRedirect loader originally for '%s' redirected to '%s'", loader->request().url().string().utf8().data(), redirectURL.string().utf8().data());
- HostRecord* oldHost = loader->hostRecord();
- // The load may have been cancelled while the message was in flight from network thread to main thread.
- if (!oldHost)
- return;
- HostRecord* newHost = hostForURL(redirectURL, CreateIfNotFound);
-
- if (oldHost->name() == newHost->name())
- return;
- oldHost->removeLoader(loader);
- newHost->addLoaderInProgress(loader);
- }
- void NetworkResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
- {
- LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::servePendingRequests Serving requests for up to %i hosts with minimum priority %i", m_hosts.size(), minimumPriority);
- m_requestTimer.stop();
-
- m_nonHTTPProtocolHost->servePendingRequests(minimumPriority);
- m_hosts.checkConsistency();
- Vector<RefPtr<HostRecord>> hostsToServe;
- copyValuesToVector(m_hosts, hostsToServe);
- size_t size = hostsToServe.size();
- for (size_t i = 0; i < size; ++i) {
- HostRecord* host = hostsToServe[i].get();
- if (host->hasRequests())
- host->servePendingRequests(minimumPriority);
- else
- m_hosts.remove(host->name());
- }
- }
- static bool removeScheduledLoadersCalled = false;
- void NetworkResourceLoadScheduler::removeScheduledLoaders(void* context)
- {
- ASSERT(isMainThread());
- ASSERT(removeScheduledLoadersCalled);
- NetworkResourceLoadScheduler* scheduler = static_cast<NetworkResourceLoadScheduler*>(context);
- scheduler->removeScheduledLoaders();
- }
- void NetworkResourceLoadScheduler::removeScheduledLoaders()
- {
- Vector<RefPtr<NetworkResourceLoader>> loadersToRemove;
- {
- MutexLocker locker(m_loadersToRemoveMutex);
- loadersToRemove = m_loadersToRemove;
- m_loadersToRemove.clear();
- removeScheduledLoadersCalled = false;
- }
-
- for (size_t i = 0; i < loadersToRemove.size(); ++i)
- removeLoader(loadersToRemove[i].get());
- }
- void NetworkResourceLoadScheduler::scheduleRemoveLoader(NetworkResourceLoader* loader)
- {
- MutexLocker locker(m_loadersToRemoveMutex);
-
- m_loadersToRemove.append(loader);
-
- if (!removeScheduledLoadersCalled) {
- removeScheduledLoadersCalled = true;
- callOnMainThread(NetworkResourceLoadScheduler::removeScheduledLoaders, this);
- }
- }
- uint64_t NetworkResourceLoadScheduler::hostsPendingCount() const
- {
- uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount() ? 1 : 0;
- HostMap::const_iterator end = m_hosts.end();
- for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) {
- if (i->value->pendingRequestCount())
- ++count;
- }
- return count;
- }
- uint64_t NetworkResourceLoadScheduler::loadsPendingCount() const
- {
- uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount();
- HostMap::const_iterator end = m_hosts.end();
- for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i)
- count += i->value->pendingRequestCount();
- return count;
- }
- uint64_t NetworkResourceLoadScheduler::hostsActiveCount() const
- {
- uint64_t count = 0;
- if (m_nonHTTPProtocolHost->activeLoadCount())
- count = 1;
- HostMap::const_iterator end = m_hosts.end();
- for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) {
- if (i->value->activeLoadCount())
- ++count;
- }
- return count;
- }
- uint64_t NetworkResourceLoadScheduler::loadsActiveCount() const
- {
- uint64_t count = m_nonHTTPProtocolHost->activeLoadCount();
- HostMap::const_iterator end = m_hosts.end();
- for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i)
- count += i->value->activeLoadCount();
- return count;
- }
- } // namespace WebKit
- #endif // ENABLE(NETWORK_PROCESS)
|