diff options
| author | Ben Murdoch <benm@google.com> | 2011-05-05 14:36:32 +0100 |
|---|---|---|
| committer | Ben Murdoch <benm@google.com> | 2011-05-10 15:38:30 +0100 |
| commit | f05b935882198ccf7d81675736e3aeb089c5113a (patch) | |
| tree | 4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /WebCore/loader/cache | |
| parent | 60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff) | |
| download | external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.zip external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.gz external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.bz2 | |
Merge WebKit at r74534: Initial merge by git.
Change-Id: I6ccd1154fa1b19c2ec2a66878eb675738735f1eb
Diffstat (limited to 'WebCore/loader/cache')
| -rw-r--r-- | WebCore/loader/cache/CachedCSSStyleSheet.cpp | 1 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedFont.cpp | 8 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedImage.cpp | 1 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedResource.cpp | 32 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedResource.h | 11 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedResourceLoader.cpp | 73 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedResourceLoader.h | 20 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedResourceRequest.cpp | 280 | ||||
| -rw-r--r-- | WebCore/loader/cache/CachedResourceRequest.h | 65 | ||||
| -rw-r--r-- | WebCore/loader/cache/MemoryCache.cpp | 59 | ||||
| -rw-r--r-- | WebCore/loader/cache/MemoryCache.h | 13 |
11 files changed, 504 insertions, 59 deletions
diff --git a/WebCore/loader/cache/CachedCSSStyleSheet.cpp b/WebCore/loader/cache/CachedCSSStyleSheet.cpp index 9ec979b..ae7a03c 100644 --- a/WebCore/loader/cache/CachedCSSStyleSheet.cpp +++ b/WebCore/loader/cache/CachedCSSStyleSheet.cpp @@ -33,7 +33,6 @@ #include "HTTPParsers.h" #include "TextResourceDecoder.h" #include "SharedBuffer.h" -#include "loader.h" #include <wtf/Vector.h> namespace WebCore { diff --git a/WebCore/loader/cache/CachedFont.cpp b/WebCore/loader/cache/CachedFont.cpp index 96654a5..d6967bf 100644 --- a/WebCore/loader/cache/CachedFont.cpp +++ b/WebCore/loader/cache/CachedFont.cpp @@ -31,13 +31,13 @@ #define STORE_FONT_CUSTOM_PLATFORM_DATA #endif -#include "MemoryCache.h" #include "CachedResourceClient.h" #include "CachedResourceClientWalker.h" +#include "CachedResourceLoader.h" #include "FontPlatformData.h" +#include "MemoryCache.h" #include "SharedBuffer.h" #include "TextResourceDecoder.h" -#include "loader.h" #include <wtf/Vector.h> #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA @@ -45,11 +45,11 @@ #endif #if ENABLE(SVG_FONTS) -#include "HTMLNames.h" #include "NodeList.h" #include "SVGElement.h" #include "SVGFontElement.h" #include "SVGGElement.h" +#include "SVGNames.h" #endif namespace WebCore { @@ -98,7 +98,7 @@ void CachedFont::beginLoadIfNeeded(CachedResourceLoader* dl) { if (!m_loadInitiated) { m_loadInitiated = true; - cache()->loader()->load(dl, this, false); + dl->load(this, false); } } diff --git a/WebCore/loader/cache/CachedImage.cpp b/WebCore/loader/cache/CachedImage.cpp index eb5fb1c..ccc34c1 100644 --- a/WebCore/loader/cache/CachedImage.cpp +++ b/WebCore/loader/cache/CachedImage.cpp @@ -32,7 +32,6 @@ #include "Frame.h" #include "FrameLoaderTypes.h" #include "FrameView.h" -#include "Request.h" #include "Settings.h" #include "SharedBuffer.h" #include <wtf/CurrentTime.h> diff --git a/WebCore/loader/cache/CachedResource.cpp b/WebCore/loader/cache/CachedResource.cpp index 844065d..19e535f 100644 --- a/WebCore/loader/cache/CachedResource.cpp +++ b/WebCore/loader/cache/CachedResource.cpp @@ -30,12 +30,12 @@ #include "CachedResourceClientWalker.h" #include "CachedResourceHandle.h" #include "CachedResourceLoader.h" +#include "CachedResourceRequest.h" #include "Frame.h" #include "FrameLoaderClient.h" #include "KURL.h" #include "Logging.h" #include "PurgeableBuffer.h" -#include "Request.h" #include "ResourceHandle.h" #include "SharedBuffer.h" #include <wtf/CurrentTime.h> @@ -47,6 +47,28 @@ using namespace WTF; namespace WebCore { + +static ResourceLoadPriority defaultPriorityForResourceType(CachedResource::Type type) +{ + switch (type) { + case CachedResource::CSSStyleSheet: +#if ENABLE(XSLT) + case CachedResource::XSLStyleSheet: +#endif + return ResourceLoadPriorityHigh; + case CachedResource::Script: + case CachedResource::FontResource: + return ResourceLoadPriorityMedium; + case CachedResource::ImageResource: + return ResourceLoadPriorityLow; +#if ENABLE(LINK_PREFETCH) + case CachedResource::LinkPrefetch: + return ResourceLoadPriorityVeryLow; +#endif + } + ASSERT_NOT_REACHED(); + return ResourceLoadPriorityLow; +} #ifndef NDEBUG static RefCountedLeakCounter cachedResourceLeakCounter("CachedResource"); @@ -55,6 +77,7 @@ static RefCountedLeakCounter cachedResourceLeakCounter("CachedResource"); CachedResource::CachedResource(const String& url, Type type) : m_url(url) , m_request(0) + , m_loadPriority(defaultPriorityForResourceType(type)) , m_responseTimestamp(currentTime()) , m_lastDecodedAccessTime(0) , m_encodedSize(0) @@ -93,7 +116,7 @@ CachedResource::~CachedResource() ASSERT(canDelete()); ASSERT(!inCache()); ASSERT(!m_deleted); - ASSERT(url().isNull() || cache()->resourceForURL(url()) != this); + ASSERT(url().isNull() || cache()->resourceForURL(KURL(ParsedURLString, url())) != this); #ifndef NDEBUG m_deleted = true; cachedResourceLeakCounter.decrement(); @@ -106,7 +129,7 @@ CachedResource::~CachedResource() void CachedResource::load(CachedResourceLoader* cachedResourceLoader, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) { m_sendResourceLoadCallbacks = sendResourceLoadCallbacks; - cache()->loader()->load(cachedResourceLoader, this, incremental, securityCheck, sendResourceLoadCallbacks); + cachedResourceLoader->load(this, incremental, securityCheck, sendResourceLoadCallbacks); m_loading = true; } @@ -115,6 +138,7 @@ void CachedResource::data(PassRefPtr<SharedBuffer>, bool allDataReceived) if (!allDataReceived) return; + setLoading(false); CachedResourceClientWalker w(m_clients); while (CachedResourceClient* c = w.next()) c->notifyFinished(this); @@ -201,7 +225,7 @@ CachedMetadata* CachedResource::cachedMetadata(unsigned dataTypeID) const return m_cachedMetadata.get(); } -void CachedResource::setRequest(Request* request) +void CachedResource::setRequest(CachedResourceRequest* request) { if (request && !m_request) m_status = Pending; diff --git a/WebCore/loader/cache/CachedResource.h b/WebCore/loader/cache/CachedResource.h index 9a54c53..9defc16 100644 --- a/WebCore/loader/cache/CachedResource.h +++ b/WebCore/loader/cache/CachedResource.h @@ -27,6 +27,7 @@ #include "FrameLoaderTypes.h" #include "PlatformString.h" #include "PurgePriority.h" +#include "ResourceLoadPriority.h" #include "ResourceResponse.h" #include <wtf/HashCountedSet.h> #include <wtf/HashSet.h> @@ -41,10 +42,10 @@ class CachedMetadata; class CachedResourceClient; class CachedResourceHandleBase; class CachedResourceLoader; +class CachedResourceRequest; class Frame; class InspectorResource; class PurgeableBuffer; -class Request; // A resource that is held in the cache. Classes who want to use this object should derive // from CachedResourceClient, to get the function calls in case the requested data has arrived. @@ -90,6 +91,8 @@ public: const String &url() const { return m_url; } Type type() const { return static_cast<Type>(m_type); } + + ResourceLoadPriority loadPriority() const { return m_loadPriority; } void addClient(CachedResourceClient*); void removeClient(CachedResourceClient*); @@ -150,7 +153,7 @@ public: void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; } bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } - void setRequest(Request*); + void setRequest(CachedResourceRequest*); SharedBuffer* data() const { ASSERT(!m_purgeableData); return m_data.get(); } @@ -216,7 +219,8 @@ protected: String m_url; String m_accept; - Request* m_request; + CachedResourceRequest* m_request; + ResourceLoadPriority m_loadPriority; ResourceResponse m_response; double m_responseTimestamp; @@ -233,6 +237,7 @@ private: void clearResourceToRevalidate(); void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse); virtual PurgePriority purgePriority() const { return PurgeDefault; } + void setLoadPriority(ResourceLoadPriority loadPriority) { m_loadPriority = loadPriority; } double currentAge() const; double freshnessLifetime() const; diff --git a/WebCore/loader/cache/CachedResourceLoader.cpp b/WebCore/loader/cache/CachedResourceLoader.cpp index 992e1b5..903c633 100644 --- a/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/WebCore/loader/cache/CachedResourceLoader.cpp @@ -43,7 +43,6 @@ #include "PingLoader.h" #include "SecurityOrigin.h" #include "Settings.h" -#include "loader.h" #include <wtf/text/StringConcatenate.h> #define PRELOAD_DEBUG 0 @@ -58,7 +57,7 @@ CachedResourceLoader::CachedResourceLoader(Document* document) , m_blockNetworkImage(false) #endif , m_autoLoadImages(true) - , m_loadInProgress(false) + , m_loadFinishing(false) , m_allowStaleResources(false) { m_cache->addCachedResourceLoader(this); @@ -66,9 +65,7 @@ CachedResourceLoader::CachedResourceLoader(Document* document) CachedResourceLoader::~CachedResourceLoader() { - if (m_requestCount) - m_cache->loader()->cancelRequests(this); - + cancelRequests(); clearPreloads(); DocumentResourceMap::iterator end = m_documentResources.end(); for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) @@ -79,6 +76,18 @@ CachedResourceLoader::~CachedResourceLoader() ASSERT(m_requestCount == 0); } +CachedResource* CachedResourceLoader::cachedResource(const String& resourceURL) const +{ + KURL url = m_document->completeURL(resourceURL); + return cachedResource(url); +} + +CachedResource* CachedResourceLoader::cachedResource(const KURL& resourceURL) const +{ + KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL); + return m_documentResources.get(url).get(); +} + Frame* CachedResourceLoader::frame() const { return m_document->frame(); @@ -95,7 +104,7 @@ void CachedResourceLoader::checkForReload(const KURL& fullURL) if (m_reloadedURLs.contains(fullURL.string())) return; - CachedResource* existing = cache()->resourceForURL(fullURL.string()); + CachedResource* existing = cache()->resourceForURL(fullURL); if (!existing || existing->isPreloaded()) return; @@ -145,7 +154,7 @@ CachedImage* CachedResourceLoader::requestImage(const String& url) } #endif resource->setLoading(true); - cache()->loader()->load(this, resource, true); + load(resource, true); } return resource; } @@ -155,14 +164,14 @@ CachedFont* CachedResourceLoader::requestFont(const String& url) return static_cast<CachedFont*>(requestResource(CachedResource::FontResource, url, String())); } -CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(const String& url, const String& charset) +CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(const String& url, const String& charset, ResourceLoadPriority priority) { - return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, charset)); + return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, charset, priority)); } CachedCSSStyleSheet* CachedResourceLoader::requestUserCSSStyleSheet(const String& url, const String& charset) { - return cache()->requestUserCSSStyleSheet(this, url, charset); + return cache()->requestUserCSSStyleSheet(this, KURL(KURL(), url), charset); } CachedScript* CachedResourceLoader::requestScript(const String& url, const String& charset) @@ -253,9 +262,12 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url return true; } -CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, bool isPreload) +CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, ResourceLoadPriority priority, bool isPreload) { KURL fullURL = m_document->completeURL(url); + + // If only the fragment identifiers differ, it is the same resource. + fullURL = MemoryCache::removeFragmentIdentifierIfNeeded(fullURL); if (!fullURL.isValid() || !canRequest(type, fullURL)) return 0; @@ -272,7 +284,7 @@ CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, checkForReload(fullURL); bool allowForHistoryOnlyResources = cachePolicy() == CachePolicyHistoryBuffer; - CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, isPreload, allowForHistoryOnlyResources); + CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, priority, isPreload, allowForHistoryOnlyResources); if (resource) { // Check final URL of resource to catch redirects. // See <https://bugs.webkit.org/show_bug.cgi?id=21963>. @@ -326,7 +338,7 @@ void CachedResourceLoader::setAutoLoadImages(bool enable) #endif if (image->stillNeedsLoad()) - cache()->loader()->load(this, image, true); + load(image, true); } } } @@ -381,11 +393,36 @@ void CachedResourceLoader::removeCachedResource(CachedResource* resource) const m_documentResources.remove(resource->url()); } -void CachedResourceLoader::setLoadInProgress(bool load) +void CachedResourceLoader::load(CachedResource* resource, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) +{ + incrementRequestCount(resource); + + RefPtr<CachedResourceRequest> request = CachedResourceRequest::load(this, resource, incremental, securityCheck, sendResourceLoadCallbacks); + if (request) + m_requests.add(request); +} + +void CachedResourceLoader::loadDone(CachedResourceRequest* request) { - m_loadInProgress = load; - if (!load && frame()) + m_loadFinishing = false; + RefPtr<CachedResourceRequest> protect(request); + if (request) + m_requests.remove(request); + if (frame()) frame()->loader()->loadDone(); + checkForPendingPreloads(); +} + +void CachedResourceLoader::cancelRequests() +{ + clearPendingPreloads(); + Vector<CachedResourceRequest*, 256> requestsToCancel; + RequestSet::iterator end = m_requests.end(); + for (RequestSet::iterator i = m_requests.begin(); i != end; ++i) + requestsToCancel.append((*i).get()); + + for (unsigned i = 0; i < requestsToCancel.size(); ++i) + requestsToCancel[i]->didFail(true); } void CachedResourceLoader::checkCacheObjectStatus(CachedResource* resource) @@ -417,7 +454,7 @@ void CachedResourceLoader::decrementRequestCount(const CachedResource* res) int CachedResourceLoader::requestCount() { - if (loadInProgress()) + if (m_loadFinishing) return m_requestCount + 1; return m_requestCount; } @@ -455,7 +492,7 @@ void CachedResourceLoader::requestPreload(CachedResource::Type type, const Strin if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) encoding = charset.isEmpty() ? m_document->frame()->loader()->writer()->encoding() : charset; - CachedResource* resource = requestResource(type, url, encoding, true); + CachedResource* resource = requestResource(type, url, encoding, ResourceLoadPriorityUnresolved, true); if (!resource || (m_preloads && m_preloads->contains(resource))) return; resource->increasePreloadCount(); diff --git a/WebCore/loader/cache/CachedResourceLoader.h b/WebCore/loader/cache/CachedResourceLoader.h index eaed52e..a03e999 100644 --- a/WebCore/loader/cache/CachedResourceLoader.h +++ b/WebCore/loader/cache/CachedResourceLoader.h @@ -28,7 +28,9 @@ #include "CachedResource.h" #include "CachedResourceHandle.h" +#include "CachedResourceRequest.h" #include "CachePolicy.h" +#include "ResourceLoadPriority.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/ListHashSet.h> @@ -56,7 +58,7 @@ public: ~CachedResourceLoader(); CachedImage* requestImage(const String& url); - CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset); + CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset, ResourceLoadPriority priority = ResourceLoadPriorityUnresolved); CachedCSSStyleSheet* requestUserCSSStyleSheet(const String& url, const String& charset); CachedScript* requestScript(const String& url, const String& charset); CachedFont* requestFont(const String& url); @@ -71,7 +73,8 @@ public: // Logs an access denied message to the console for the specified URL. void printAccessDeniedMessage(const KURL& url) const; - CachedResource* cachedResource(const String& url) const { return m_documentResources.get(url).get(); } + CachedResource* cachedResource(const String& url) const; + CachedResource* cachedResource(const KURL& url) const; typedef HashMap<String, CachedResourceHandle<CachedResource> > DocumentResourceMap; const DocumentResourceMap& allCachedResources() const { return m_documentResources; } @@ -92,8 +95,10 @@ public: void removeCachedResource(CachedResource*) const; - void setLoadInProgress(bool); - bool loadInProgress() const { return m_loadInProgress; } + void load(CachedResource*, bool incremental = false, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true); + void loadFinishing() { m_loadFinishing = true; } + void loadDone(CachedResourceRequest*); + void cancelRequests(); void setAllowStaleResources(bool allowStaleResources) { m_allowStaleResources = allowStaleResources; } @@ -108,7 +113,7 @@ public: void printPreloadStats(); private: - CachedResource* requestResource(CachedResource::Type, const String& url, const String& charset, bool isPreload = false); + CachedResource* requestResource(CachedResource::Type, const String& url, const String& charset, ResourceLoadPriority priority = ResourceLoadPriorityUnresolved, bool isPreload = false); void requestPreload(CachedResource::Type, const String& url, const String& charset); void checkForReload(const KURL&); @@ -119,6 +124,9 @@ private: HashSet<String> m_reloadedURLs; mutable DocumentResourceMap m_documentResources; Document* m_document; + + typedef HashSet<RefPtr<CachedResourceRequest> > RequestSet; + RequestSet m_requests; int m_requestCount; @@ -135,7 +143,7 @@ private: bool m_blockNetworkImage : 1; #endif bool m_autoLoadImages : 1; - bool m_loadInProgress : 1; + bool m_loadFinishing : 1; bool m_allowStaleResources : 1; }; diff --git a/WebCore/loader/cache/CachedResourceRequest.cpp b/WebCore/loader/cache/CachedResourceRequest.cpp new file mode 100644 index 0000000..827bb8e --- /dev/null +++ b/WebCore/loader/cache/CachedResourceRequest.cpp @@ -0,0 +1,280 @@ +/* + 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 "CachedResourceRequest.h" + +#include "MemoryCache.h" +#include "CachedImage.h" +#include "CachedResource.h" +#include "CachedResourceLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "Logging.h" +#include "ResourceHandle.h" +#include "ResourceLoadScheduler.h" +#include "ResourceRequest.h" +#include "ResourceResponse.h" +#include "SharedBuffer.h" +#include <wtf/Assertions.h> +#include <wtf/Vector.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +static ResourceRequest::TargetType cachedResourceTypeToTargetType(CachedResource::Type type) +{ + switch (type) { + case CachedResource::CSSStyleSheet: +#if ENABLE(XSLT) + case CachedResource::XSLStyleSheet: +#endif + return ResourceRequest::TargetIsStyleSheet; + case CachedResource::Script: + return ResourceRequest::TargetIsScript; + case CachedResource::FontResource: + return ResourceRequest::TargetIsFontResource; + case CachedResource::ImageResource: + return ResourceRequest::TargetIsImage; +#if ENABLE(LINK_PREFETCH) + case CachedResource::LinkPrefetch: + return ResourceRequest::TargetIsPrefetch; +#endif + } + ASSERT_NOT_REACHED(); + return ResourceRequest::TargetIsSubresource; +} + +CachedResourceRequest::CachedResourceRequest(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, bool incremental) + : m_cachedResourceLoader(cachedResourceLoader) + , m_resource(resource) + , m_incremental(incremental) + , m_multipart(false) + , m_finishing(false) +{ + m_resource->setRequest(this); +} + +CachedResourceRequest::~CachedResourceRequest() +{ + m_resource->setRequest(0); +} + +PassRefPtr<CachedResourceRequest> CachedResourceRequest::load(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) +{ + RefPtr<CachedResourceRequest> request = adoptRef(new CachedResourceRequest(cachedResourceLoader, resource, incremental)); + + ResourceRequest resourceRequest(resource->url()); + resourceRequest.setTargetType(cachedResourceTypeToTargetType(resource->type())); + + if (!resource->accept().isEmpty()) + resourceRequest.setHTTPAccept(resource->accept()); + + if (resource->isCacheValidator()) { + CachedResource* resourceToRevalidate = resource->resourceToRevalidate(); + ASSERT(resourceToRevalidate->canUseCacheValidator()); + ASSERT(resourceToRevalidate->isLoaded()); + const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); + const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); + if (!lastModified.isEmpty() || !eTag.isEmpty()) { + ASSERT(cachedResourceLoader->cachePolicy() != CachePolicyReload); + if (cachedResourceLoader->cachePolicy() == CachePolicyRevalidate) + resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); + if (!lastModified.isEmpty()) + resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); + if (!eTag.isEmpty()) + resourceRequest.setHTTPHeaderField("If-None-Match", eTag); + } + } + +#if ENABLE(LINK_PREFETCH) + if (resource->type() == CachedResource::LinkPrefetch) + resourceRequest.setHTTPHeaderField("Purpose", "prefetch"); +#endif + + ResourceLoadPriority priority = resource->loadPriority(); + + RefPtr<SubresourceLoader> loader = resourceLoadScheduler()->scheduleSubresourceLoad(cachedResourceLoader->document()->frame(), + request.get(), resourceRequest, priority, securityCheck, sendResourceLoadCallbacks); + if (!loader || loader->reachedTerminalState()) { + // FIXME: What if resources in other frames were waiting for this revalidation? + LOG(ResourceLoading, "Cannot start loading '%s'", resource->url().latin1().data()); + cachedResourceLoader->decrementRequestCount(resource); + cachedResourceLoader->loadFinishing(); + if (resource->resourceToRevalidate()) + cache()->revalidationFailed(resource); + resource->error(CachedResource::LoadError); + cachedResourceLoader->loadDone(0); + return 0; + } + request->m_loader = loader; + return request.release(); +} + +void CachedResourceRequest::willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse&) +{ + m_resource->setRequestedFromNetworkingLayer(); +} + +void CachedResourceRequest::didFinishLoading(SubresourceLoader* loader) +{ + if (m_finishing) + return; + + ASSERT(loader == m_loader.get()); + ASSERT(!m_resource->resourceToRevalidate()); + LOG(ResourceLoading, "Received '%s'.", m_resource->url().latin1().data()); + + // Prevent the document from being destroyed before we are done with + // the cachedResourceLoader that it will delete when the document gets deleted. + RefPtr<Document> protector(m_cachedResourceLoader->document()); + if (!m_multipart) + m_cachedResourceLoader->decrementRequestCount(m_resource); + m_finishing = true; + + // If we got a 4xx response, we're pretending to have received a network + // error, so we can't send the successful data() and finish() callbacks. + if (!m_resource->errorOccurred()) { + m_cachedResourceLoader->loadFinishing(); + m_resource->data(loader->resourceData(), true); + if (!m_resource->errorOccurred()) + m_resource->finish(); + } + m_cachedResourceLoader->loadDone(this); +} + +void CachedResourceRequest::didFail(SubresourceLoader*, const ResourceError&) +{ + if (!m_loader) + return; + didFail(); +} + +void CachedResourceRequest::didFail(bool cancelled) +{ + if (m_finishing) + return; + + LOG(ResourceLoading, "Failed to load '%s' (cancelled=%d).\n", m_resource->url().latin1().data(), cancelled); + + // Prevent the document from being destroyed before we are done with + // the cachedResourceLoader that it will delete when the document gets deleted. + RefPtr<Document> protector(m_cachedResourceLoader->document()); + if (!m_multipart) + m_cachedResourceLoader->decrementRequestCount(m_resource); + m_finishing = true; + m_loader->clearClient(); + + if (m_resource->resourceToRevalidate()) + cache()->revalidationFailed(m_resource); + + if (!cancelled) { + m_cachedResourceLoader->loadFinishing(); + m_resource->error(CachedResource::LoadError); + } + + if (cancelled || !m_resource->isPreloaded()) + cache()->remove(m_resource); + + m_cachedResourceLoader->loadDone(this); +} + +void CachedResourceRequest::didReceiveResponse(SubresourceLoader* loader, const ResourceResponse& response) +{ + ASSERT(loader == m_loader.get()); + if (m_resource->isCacheValidator()) { + if (response.httpStatusCode() == 304) { + // 304 Not modified / Use local copy + loader->clearClient(); + RefPtr<Document> protector(m_cachedResourceLoader->document()); + m_cachedResourceLoader->decrementRequestCount(m_resource); + m_finishing = true; + + // Existing resource is ok, just use it updating the expiration time. + cache()->revalidationSucceeded(m_resource, response); + + if (m_cachedResourceLoader->frame()) + m_cachedResourceLoader->frame()->loader()->checkCompleted(); + + m_cachedResourceLoader->loadDone(this); + return; + } + // Did not get 304 response, continue as a regular resource load. + cache()->revalidationFailed(m_resource); + } + + m_resource->setResponse(response); + + String encoding = response.textEncodingName(); + if (!encoding.isNull()) + m_resource->setEncoding(encoding); + + if (m_multipart) { + ASSERT(m_resource->isImage()); + static_cast<CachedImage*>(m_resource)->clear(); + if (m_cachedResourceLoader->frame()) + m_cachedResourceLoader->frame()->loader()->checkCompleted(); + } else if (response.isMultipart()) { + m_multipart = true; + + // We don't count multiParts in a CachedResourceLoader's request count + m_cachedResourceLoader->decrementRequestCount(m_resource); + + // If we get a multipart response, we must have a handle + ASSERT(loader->handle()); + if (!m_resource->isImage()) + loader->handle()->cancel(); + } +} + +void CachedResourceRequest::didReceiveData(SubresourceLoader* loader, const char* data, int size) +{ + ASSERT(loader == m_loader.get()); + ASSERT(!m_resource->isCacheValidator()); + + if (m_resource->errorOccurred()) + return; + + if (m_resource->response().httpStatusCode() >= 400) { + if (!m_resource->shouldIgnoreHTTPStatusCodeErrors()) + m_resource->error(CachedResource::LoadError); + return; + } + + // Set the data. + if (m_multipart) { + // The loader delivers the data in a multipart section all at once, send eof. + // The resource data will change as the next part is loaded, so we need to make a copy. + RefPtr<SharedBuffer> copiedData = SharedBuffer::create(data, size); + m_resource->data(copiedData.release(), true); + } else if (m_incremental) + m_resource->data(loader->resourceData(), false); +} + +void CachedResourceRequest::didReceiveCachedMetadata(SubresourceLoader*, const char* data, int size) +{ + ASSERT(!m_resource->isCacheValidator()); + m_resource->setSerializedCachedMetadata(data, size); +} + +} //namespace WebCore diff --git a/WebCore/loader/cache/CachedResourceRequest.h b/WebCore/loader/cache/CachedResourceRequest.h new file mode 100644 index 0000000..389b9ce --- /dev/null +++ b/WebCore/loader/cache/CachedResourceRequest.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2001 Dirk Mueller <mueller@kde.org> + Copyright (C) 2004, 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. +*/ + +#ifndef CachedResourceRequest_h +#define CachedResourceRequest_h + +#include "FrameLoaderTypes.h" +#include "SubresourceLoader.h" +#include "SubresourceLoaderClient.h" +#include <wtf/HashMap.h> +#include <wtf/Noncopyable.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + + class CachedResource; + class CachedResourceLoader; + class Request; + + class CachedResourceRequest : public RefCounted<CachedResourceRequest>, private SubresourceLoaderClient { + public: + static PassRefPtr<CachedResourceRequest> load(CachedResourceLoader*, CachedResource*, bool incremental, SecurityCheckPolicy, bool sendResourceLoadCallbacks); + ~CachedResourceRequest(); + void didFail(bool cancelled = false); + + CachedResourceLoader* cachedResourceLoader() const { return m_cachedResourceLoader; } + + private: + CachedResourceRequest(CachedResourceLoader*, CachedResource*, bool incremental); + virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse&); + virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&); + virtual void didReceiveData(SubresourceLoader*, const char*, int); + virtual void didReceiveCachedMetadata(SubresourceLoader*, const char*, int); + virtual void didFinishLoading(SubresourceLoader*); + virtual void didFail(SubresourceLoader*, const ResourceError&); + + RefPtr<SubresourceLoader> m_loader; + CachedResourceLoader* m_cachedResourceLoader; + CachedResource* m_resource; + bool m_incremental; + bool m_multipart; + bool m_finishing; + }; + +} + +#endif diff --git a/WebCore/loader/cache/MemoryCache.cpp b/WebCore/loader/cache/MemoryCache.cpp index fc6682a..8826cec 100644 --- a/WebCore/loader/cache/MemoryCache.cpp +++ b/WebCore/loader/cache/MemoryCache.cpp @@ -95,17 +95,20 @@ static CachedResource* createResource(CachedResource::Type type, const KURL& url return 0; } -CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourceLoader, CachedResource::Type type, const KURL& url, const String& charset, bool requestIsPreload, bool forHistory) +CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourceLoader, CachedResource::Type type, const KURL& requestURL, const String& charset, ResourceLoadPriority priority, bool requestIsPreload, bool forHistory) { - LOG(ResourceLoading, "MemoryCache::requestResource '%s', charset '%s', preload=%u, forHistory=%u", url.string().latin1().data(), charset.latin1().data(), requestIsPreload, forHistory); - + LOG(ResourceLoading, "MemoryCache::requestResource '%s', charset '%s', priority=%d, preload=%u, forHistory=%u", requestURL.string().latin1().data(), charset.latin1().data(), priority, requestIsPreload, forHistory); + // FIXME: Do we really need to special-case an empty URL? // Would it be better to just go on with the cache code and let it fail later? - if (url.isEmpty()) + if (requestURL.isEmpty()) return 0; + + // Ensure this is the pure primary resource URL. + KURL url = removeFragmentIdentifierIfNeeded(requestURL); // Look up the resource in our map. - CachedResource* resource = resourceForURL(url.string()); + CachedResource* resource = resourceForURL(url); // Non https "no-store" resources are left in the cache to be used for back/forward navigation only. // If this is not a request forHistory and the resource was served with "no-store" we should evict @@ -127,7 +130,13 @@ CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourc FrameLoader::reportLocalLoadFailed(cachedResourceLoader->document()->frame(), url.string()); return 0; } - + + if (resource && resource->type() != type) { + LOG(ResourceLoading, "Cache::requestResource found a cache resource with matching url but different type, evicting and loading with new type."); + evict(resource); + resource = 0; + } + if (!resource) { LOG(ResourceLoading, "CachedResource for '%s' wasn't found in cache. Creating it", url.string().latin1().data()); // The resource does not exist. Create it. @@ -138,6 +147,10 @@ CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourc // FIXME: CachedResource should just use normal refcounting instead. resource->setInCache(true); + // Default priority based on resource type is used if the request did not specify one. + if (priority != ResourceLoadPriorityUnresolved) + resource->setLoadPriority(priority); + resource->load(cachedResourceLoader); if (resource->errorOccurred()) { @@ -156,11 +169,12 @@ CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourc resource->setInCache(false); resource->setCachedResourceLoader(cachedResourceLoader); } - } - - if (resource->type() != type) { - LOG(ResourceLoading, "MemoryCache::requestResource cannot use cached resource for '%s' due to type mismatch", url.string().latin1().data()); - return 0; + } else { + // FIXME: Upgrading the priority doesn't really do much since the ResourceLoadScheduler does not currently + // allow changing priorities. This might become important if we make scheduling priorities + // more dynamic. + if (priority != ResourceLoadPriorityUnresolved && resource->loadPriority() < priority) + resource->setLoadPriority(priority); } if (!disabled()) { @@ -173,8 +187,11 @@ CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourc return resource; } -CachedCSSStyleSheet* MemoryCache::requestUserCSSStyleSheet(CachedResourceLoader* cachedResourceLoader, const String& url, const String& charset) +CachedCSSStyleSheet* MemoryCache::requestUserCSSStyleSheet(CachedResourceLoader* cachedResourceLoader, const KURL& requestURL, const String& charset) { + // Ensure this is the pure primary resource URL. + KURL url = removeFragmentIdentifierIfNeeded(requestURL); + CachedCSSStyleSheet* userSheet; if (CachedResource* existing = resourceForURL(url)) { if (existing->type() != CachedResource::CSSStyleSheet) @@ -201,7 +218,20 @@ CachedCSSStyleSheet* MemoryCache::requestUserCSSStyleSheet(CachedResourceLoader* return userSheet; } - + +KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL) +{ + if (!originalURL.hasFragmentIdentifier()) + return originalURL; + // Strip away fragment identifier from HTTP and file urls. + // Data urls must be unmodified and it is also safer to keep them for custom protocols. + if (!(originalURL.protocolInHTTPFamily() || originalURL.isLocalFile())) + return originalURL; + KURL url = originalURL; + url.removeFragmentIdentifier(); + return url; +} + void MemoryCache::revalidateResource(CachedResource* resource, CachedResourceLoader* cachedResourceLoader) { ASSERT(resource); @@ -258,8 +288,9 @@ void MemoryCache::revalidationFailed(CachedResource* revalidatingResource) revalidatingResource->clearResourceToRevalidate(); } -CachedResource* MemoryCache::resourceForURL(const String& url) +CachedResource* MemoryCache::resourceForURL(const KURL& resourceURL) { + KURL url = removeFragmentIdentifierIfNeeded(resourceURL); CachedResource* resource = m_resources.get(url); bool wasPurgeable = MemoryCache::shouldMakeResourcePurgeableOnEviction() && resource && resource->isPurgeable(); if (resource && !resource->makePurgeable(false)) { diff --git a/WebCore/loader/cache/MemoryCache.h b/WebCore/loader/cache/MemoryCache.h index 6b94eda..57fec04 100644 --- a/WebCore/loader/cache/MemoryCache.h +++ b/WebCore/loader/cache/MemoryCache.h @@ -28,7 +28,6 @@ #include "CachePolicy.h" #include "CachedResource.h" #include "PlatformString.h" -#include "loader.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> @@ -104,14 +103,13 @@ public: TypeStatistic fonts; }; - // The loader that fetches resources. - Loader* loader() { return &m_loader; } - // Request resources from the cache. A load will be initiated and a cache object created if the object is not // found in the cache. - CachedResource* requestResource(CachedResourceLoader*, CachedResource::Type, const KURL& url, const String& charset, bool isPreload = false, bool forHistory = false); + CachedResource* requestResource(CachedResourceLoader*, CachedResource::Type, const KURL& url, const String& charset, ResourceLoadPriority, bool isPreload = false, bool forHistory = false); - CachedCSSStyleSheet* requestUserCSSStyleSheet(CachedResourceLoader*, const String& url, const String& charset); + CachedCSSStyleSheet* requestUserCSSStyleSheet(CachedResourceLoader*, const KURL& url, const String& charset); + + static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); void revalidateResource(CachedResource*, CachedResourceLoader*); void revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse&); @@ -148,7 +146,7 @@ public: void addCachedResourceLoader(CachedResourceLoader*); void removeCachedResourceLoader(CachedResourceLoader*); - CachedResource* resourceForURL(const String&); + CachedResource* resourceForURL(const KURL&); // Calls to put the cached resource into and out of LRU lists. void insertInLRUList(CachedResource*); @@ -196,7 +194,6 @@ private: // Member variables. HashSet<CachedResourceLoader*> m_cachedResourceLoaders; - Loader m_loader; bool m_disabled; // Whether or not the cache is enabled. bool m_pruneEnabled; |
