summaryrefslogtreecommitdiffstats
path: root/WebCore/loader/cache
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-05 14:36:32 +0100
committerBen Murdoch <benm@google.com>2011-05-10 15:38:30 +0100
commitf05b935882198ccf7d81675736e3aeb089c5113a (patch)
tree4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /WebCore/loader/cache
parent60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff)
downloadexternal_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.cpp1
-rw-r--r--WebCore/loader/cache/CachedFont.cpp8
-rw-r--r--WebCore/loader/cache/CachedImage.cpp1
-rw-r--r--WebCore/loader/cache/CachedResource.cpp32
-rw-r--r--WebCore/loader/cache/CachedResource.h11
-rw-r--r--WebCore/loader/cache/CachedResourceLoader.cpp73
-rw-r--r--WebCore/loader/cache/CachedResourceLoader.h20
-rw-r--r--WebCore/loader/cache/CachedResourceRequest.cpp280
-rw-r--r--WebCore/loader/cache/CachedResourceRequest.h65
-rw-r--r--WebCore/loader/cache/MemoryCache.cpp59
-rw-r--r--WebCore/loader/cache/MemoryCache.h13
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;