📄 loader.cpp
字号:
/* 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, 2005, 2006, 2007, 2008 Apple 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 "config.h"#include "loader.h"#include "Cache.h"#include "CachedImage.h"#include "CachedResource.h"#include "CString.h"#include "DocLoader.h"#include "Frame.h"#include "FrameLoader.h"#include "HTMLDocument.h"#include "Request.h"#include "ResourceHandle.h"#include "ResourceRequest.h"#include "ResourceResponse.h"#include "SecurityOrigin.h"#include "SubresourceLoader.h"#include <wtf/Assertions.h>#include <wtf/Vector.h>#define REQUEST_MANAGEMENT_ENABLED 1#define REQUEST_DEBUG 0namespace WebCore {#if REQUEST_MANAGEMENT_ENABLED// Match the parallel connection count used by the networking layer// FIXME should not hardcode something like thisstatic const unsigned maxRequestsInFlightPerHost = 4;// Having a limit might still help getting more important resources firststatic const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;#elsestatic const unsigned maxRequestsInFlightPerHost = 10000;static const unsigned maxRequestsInFlightForNonHTTPProtocols = 10000;#endif Loader::Loader() : m_nonHTTPProtocolHost(AtomicString(), maxRequestsInFlightForNonHTTPProtocols) , m_requestTimer(this, &Loader::requestTimerFired){}Loader::~Loader(){ ASSERT_NOT_REACHED();} Loader::Priority Loader::determinePriority(const CachedResource* resource) const{#if REQUEST_MANAGEMENT_ENABLED switch (resource->type()) { case CachedResource::CSSStyleSheet:#if ENABLE(XSLT) case CachedResource::XSLStyleSheet:#endif#if ENABLE(XBL) case CachedResource::XBL:#endif return High; case CachedResource::Script: case CachedResource::FontResource: return Medium; case CachedResource::ImageResource: return Low; } ASSERT_NOT_REACHED(); return Low;#else return High;#endif}void Loader::load(DocLoader* docLoader, CachedResource* resource, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks){ ASSERT(docLoader); Request* request = new Request(docLoader, resource, incremental, skipCanLoadCheck, sendResourceLoadCallbacks); Host* host; KURL url(resource->url()); bool isHTTP = url.protocolIs("http") || url.protocolIs("https"); if (isHTTP) { AtomicString hostName = url.host(); host = m_hosts.get(hostName.impl()); if (!host) { host = new Host(hostName, maxRequestsInFlightPerHost); m_hosts.add(hostName.impl(), host); } } else host = &m_nonHTTPProtocolHost; bool hadRequests = host->hasRequests(); Priority priority = determinePriority(resource); host->addRequest(request, priority); docLoader->incrementRequestCount(); if (priority > Low || !isHTTP || !hadRequests) { // Try to request important resources immediately host->servePendingRequests(priority); } else { // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones scheduleServePendingRequests(); }} void Loader::scheduleServePendingRequests(){ if (!m_requestTimer.isActive()) m_requestTimer.startOneShot(0);}void Loader::requestTimerFired(Timer<Loader>*) { servePendingRequests();}void Loader::servePendingRequests(Priority minimumPriority){ m_requestTimer.stop(); m_nonHTTPProtocolHost.servePendingRequests(minimumPriority); Vector<Host*> hostsToServe; copyValuesToVector(m_hosts, hostsToServe); for (unsigned n = 0; n < hostsToServe.size(); ++n) { Host* host = hostsToServe[n]; if (host->hasRequests()) host->servePendingRequests(minimumPriority); else if (!host->processingResource()){ AtomicString name = host->name(); delete host; m_hosts.remove(name.impl()); } }} void Loader::cancelRequests(DocLoader* docLoader){ docLoader->clearPendingPreloads(); if (m_nonHTTPProtocolHost.hasRequests()) m_nonHTTPProtocolHost.cancelRequests(docLoader); Vector<Host*> hostsToCancel; copyValuesToVector(m_hosts, hostsToCancel); for (unsigned n = 0; n < hostsToCancel.size(); ++n) { Host* host = hostsToCancel[n]; if (host->hasRequests()) host->cancelRequests(docLoader); } scheduleServePendingRequests(); ASSERT(docLoader->requestCount() == (docLoader->loadInProgress() ? 1 : 0));} Loader::Host::Host(const AtomicString& name, unsigned maxRequestsInFlight) : m_name(name) , m_maxRequestsInFlight(maxRequestsInFlight) , m_numResourcesProcessing(0){}Loader::Host::~Host(){ ASSERT(m_requestsLoading.isEmpty()); for (unsigned p = 0; p <= High; p++) ASSERT(m_requestsPending[p].isEmpty());} void Loader::Host::addRequest(Request* request, Priority priority){ m_requestsPending[priority].append(request);} bool Loader::Host::hasRequests() const{ if (!m_requestsLoading.isEmpty()) return true; for (unsigned p = 0; p <= High; p++) { if (!m_requestsPending[p].isEmpty()) return true; } return false;}void Loader::Host::servePendingRequests(Loader::Priority minimumPriority){ bool serveMore = true; for (int priority = High; priority >= minimumPriority && serveMore; --priority) servePendingRequests(m_requestsPending[priority], serveMore);}void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority){ while (!requestsPending.isEmpty()) { Request* request = requestsPending.first(); DocLoader* docLoader = request->docLoader(); bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator(); // If the document is fully parsed and there are no pending stylesheets there won't be any more // resources that we would want to push to the front of the queue. Just hand off the remaining resources // to the networking layer. bool parsedAndStylesheetsKnown = !docLoader->doc()->parsing() && docLoader->doc()->haveStylesheetsLoaded(); if (!parsedAndStylesheetsKnown && !resourceIsCacheValidator && m_requestsLoading.size() >= m_maxRequestsInFlight) { serveLowerPriority = false; return; } requestsPending.removeFirst(); ResourceRequest resourceRequest(request->cachedResource()->url()); if (!request->cachedResource()->accept().isEmpty()) resourceRequest.setHTTPAccept(request->cachedResource()->accept()); KURL referrer = docLoader->doc()->url(); if ((referrer.protocolIs("http") || referrer.protocolIs("https")) && referrer.path().isEmpty()) referrer.setPath("/"); resourceRequest.setHTTPReferrer(referrer.string()); FrameLoader::addHTTPOriginIfNeeded(resourceRequest, docLoader->doc()->securityOrigin()->toString()); if (resourceIsCacheValidator) { CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate(); ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -