summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/loader/cache/CachedResourceRequest.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/loader/cache/CachedResourceRequest.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/loader/cache/CachedResourceRequest.cpp')
-rw-r--r--Source/WebCore/loader/cache/CachedResourceRequest.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/Source/WebCore/loader/cache/CachedResourceRequest.cpp b/Source/WebCore/loader/cache/CachedResourceRequest.cpp
new file mode 100644
index 0000000..827bb8e
--- /dev/null
+++ b/Source/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