diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/loader/cache/CachedResourceRequest.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_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.cpp | 280 |
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 |