summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/cache/CachedImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/loader/cache/CachedImage.cpp')
-rw-r--r--Source/WebCore/loader/cache/CachedImage.cpp432
1 files changed, 174 insertions, 258 deletions
diff --git a/Source/WebCore/loader/cache/CachedImage.cpp b/Source/WebCore/loader/cache/CachedImage.cpp
index 5525fb1f3..65f0bf79c 100644
--- a/Source/WebCore/loader/cache/CachedImage.cpp
+++ b/Source/WebCore/loader/cache/CachedImage.cpp
@@ -35,15 +35,15 @@
#include "FrameLoaderTypes.h"
#include "FrameView.h"
#include "MemoryCache.h"
-#include "Page.h"
#include "RenderElement.h"
-#include "ResourceBuffer.h"
+#include "SVGImage.h"
#include "SecurityOrigin.h"
#include "Settings.h"
+#include "SharedBuffer.h"
#include "SubresourceLoader.h"
#include <wtf/CurrentTime.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/StdLibExtras.h>
-#include <wtf/Vector.h>
#if PLATFORM(IOS)
#include "SystemMemory.h"
@@ -53,40 +53,28 @@
#include "PDFDocumentImage.h"
#endif
-#if ENABLE(SVG)
-#include "SVGImage.h"
-#endif
-
-#if ENABLE(DISK_IMAGE_CACHE)
-#include "DiskImageCacheIOS.h"
-#endif
-
namespace WebCore {
-CachedImage::CachedImage(const ResourceRequest& resourceRequest)
- : CachedResource(resourceRequest, ImageResource)
- , m_image(0)
- , m_shouldPaintBrokenImage(true)
+CachedImage::CachedImage(CachedResourceRequest&& request, SessionID sessionID)
+ : CachedResource(WTFMove(request), ImageResource, sessionID)
{
setStatus(Unknown);
}
-CachedImage::CachedImage(Image* image)
- : CachedResource(ResourceRequest(), ImageResource)
+CachedImage::CachedImage(Image* image, SessionID sessionID)
+ : CachedResource(URL(), ImageResource, sessionID)
, m_image(image)
- , m_shouldPaintBrokenImage(true)
{
- setStatus(Cached);
- setLoading(false);
}
-CachedImage::CachedImage(const URL& url, Image* image)
- : CachedResource(ResourceRequest(url), ImageResource)
+CachedImage::CachedImage(const URL& url, Image* image, SessionID sessionID)
+ : CachedResource(url, ImageResource, sessionID)
, m_image(image)
- , m_shouldPaintBrokenImage(true)
+ , m_isManuallyCached(true)
{
- setStatus(Cached);
- setLoading(false);
+ // Use the incoming URL in the response field. This ensures that code using the response directly,
+ // such as origin checks for security, actually see something.
+ m_response.setURL(url);
}
CachedImage::~CachedImage()
@@ -94,56 +82,69 @@ CachedImage::~CachedImage()
clearImage();
}
-void CachedImage::load(CachedResourceLoader* cachedResourceLoader, const ResourceLoaderOptions& options)
+void CachedImage::load(CachedResourceLoader& loader)
{
- if (!cachedResourceLoader || cachedResourceLoader->autoLoadImages())
- CachedResource::load(cachedResourceLoader, options);
+ if (loader.shouldPerformImageLoad(url()))
+ CachedResource::load(loader);
else
setLoading(false);
}
-void CachedImage::didAddClient(CachedResourceClient* c)
+void CachedImage::setBodyDataFrom(const CachedResource& resource)
+{
+ ASSERT(resource.type() == type());
+ const CachedImage& image = static_cast<const CachedImage&>(resource);
+
+ CachedResource::setBodyDataFrom(resource);
+
+ m_image = image.m_image;
+ m_imageObserver = image.m_imageObserver;
+ if (m_imageObserver)
+ m_imageObserver->add(*this);
+
+ if (m_image && is<SVGImage>(*m_image))
+ m_svgImageCache = std::make_unique<SVGImageCache>(&downcast<SVGImage>(*m_image));
+}
+
+void CachedImage::didAddClient(CachedResourceClient& client)
{
if (m_data && !m_image && !errorOccurred()) {
createImage();
- m_image->setData(m_data->sharedBuffer(), true);
+ m_image->setData(m_data.copyRef(), true);
}
-
- ASSERT(c->resourceClientType() == CachedImageClient::expectedType());
+
+ ASSERT(client.resourceClientType() == CachedImageClient::expectedType());
if (m_image && !m_image->isNull())
- static_cast<CachedImageClient*>(c)->imageChanged(this);
+ static_cast<CachedImageClient&>(client).imageChanged(this);
- CachedResource::didAddClient(c);
+ CachedResource::didAddClient(client);
}
-void CachedImage::didRemoveClient(CachedResourceClient* c)
+void CachedImage::didRemoveClient(CachedResourceClient& client)
{
- ASSERT(c);
- ASSERT(c->resourceClientType() == CachedImageClient::expectedType());
+ ASSERT(client.resourceClientType() == CachedImageClient::expectedType());
+
+ m_pendingContainerSizeRequests.remove(&static_cast<CachedImageClient&>(client));
- m_pendingContainerSizeRequests.remove(static_cast<CachedImageClient*>(c));
-#if ENABLE(SVG)
if (m_svgImageCache)
- m_svgImageCache->removeClientFromCache(static_cast<CachedImageClient*>(c));
-#endif
+ m_svgImageCache->removeClientFromCache(&static_cast<CachedImageClient&>(client));
- CachedResource::didRemoveClient(c);
+ CachedResource::didRemoveClient(client);
}
void CachedImage::switchClientsToRevalidatedResource()
{
- ASSERT(resourceToRevalidate());
- ASSERT(resourceToRevalidate()->isImage());
+ ASSERT(is<CachedImage>(resourceToRevalidate()));
// Pending container size requests need to be transferred to the revalidated resource.
if (!m_pendingContainerSizeRequests.isEmpty()) {
// A copy of pending size requests is needed as they are deleted during CachedResource::switchClientsToRevalidateResouce().
ContainerSizeRequests switchContainerSizeRequests;
- for (ContainerSizeRequests::iterator it = m_pendingContainerSizeRequests.begin(); it != m_pendingContainerSizeRequests.end(); ++it)
- switchContainerSizeRequests.set(it->key, it->value);
+ for (auto& request : m_pendingContainerSizeRequests)
+ switchContainerSizeRequests.set(request.key, request.value);
CachedResource::switchClientsToRevalidatedResource();
- CachedImage* revalidatedCachedImage = static_cast<CachedImage*>(resourceToRevalidate());
- for (ContainerSizeRequests::iterator it = switchContainerSizeRequests.begin(); it != switchContainerSizeRequests.end(); ++it)
- revalidatedCachedImage->setContainerSizeForRenderer(it->key, it->value.first, it->value.second);
+ CachedImage& revalidatedCachedImage = downcast<CachedImage>(*resourceToRevalidate());
+ for (auto& request : switchContainerSizeRequests)
+ revalidatedCachedImage.setContainerSizeForRenderer(request.key, request.value.first, request.value.second);
return;
}
@@ -159,12 +160,17 @@ void CachedImage::allClientsRemoved()
std::pair<Image*, float> CachedImage::brokenImage(float deviceScaleFactor) const
{
+ if (deviceScaleFactor >= 3) {
+ static NeverDestroyed<Image*> brokenImageVeryHiRes(Image::loadPlatformResource("missingImage@3x").leakRef());
+ return std::make_pair(brokenImageVeryHiRes, 3);
+ }
+
if (deviceScaleFactor >= 2) {
- DEFINE_STATIC_LOCAL(Image*, brokenImageHiRes, (Image::loadPlatformResource("missingImage@2x").leakRef()));
+ static NeverDestroyed<Image*> brokenImageHiRes(Image::loadPlatformResource("missingImage@2x").leakRef());
return std::make_pair(brokenImageHiRes, 2);
}
- DEFINE_STATIC_LOCAL(Image*, brokenImageLoRes, (Image::loadPlatformResource("missingImage").leakRef()));
+ static NeverDestroyed<Image*> brokenImageLoRes(Image::loadPlatformResource("missingImage").leakRef());
return std::make_pair(brokenImageLoRes, 1);
}
@@ -175,8 +181,6 @@ bool CachedImage::willPaintBrokenImage() const
Image* CachedImage::image()
{
- ASSERT(!isPurgeable());
-
if (errorOccurred() && m_shouldPaintBrokenImage) {
// Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
// deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage()
@@ -192,8 +196,6 @@ Image* CachedImage::image()
Image* CachedImage::imageForRenderer(const RenderObject* renderer)
{
- ASSERT(!isPurgeable());
-
if (errorOccurred() && m_shouldPaintBrokenImage) {
// Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
// deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage()
@@ -204,19 +206,15 @@ Image* CachedImage::imageForRenderer(const RenderObject* renderer)
if (!m_image)
return Image::nullImage();
-#if ENABLE(SVG)
if (m_image->isSVGImage()) {
Image* image = m_svgImageCache->imageForRenderer(renderer);
if (image != Image::nullImage())
return image;
}
-#else
- UNUSED_PARAM(renderer);
-#endif
return m_image.get();
}
-void CachedImage::setContainerSizeForRenderer(const CachedImageClient* renderer, const IntSize& containerSize, float containerZoom)
+void CachedImage::setContainerSizeForRenderer(const CachedImageClient* renderer, const LayoutSize& containerSize, float containerZoom)
{
if (containerSize.isEmpty())
return;
@@ -226,17 +224,13 @@ void CachedImage::setContainerSizeForRenderer(const CachedImageClient* renderer,
m_pendingContainerSizeRequests.set(renderer, SizeAndZoom(containerSize, containerZoom));
return;
}
-#if ENABLE(SVG)
+
if (!m_image->isSVGImage()) {
m_image->setContainerSize(containerSize);
return;
}
m_svgImageCache->setContainerSizeForRenderer(renderer, containerSize, containerZoom);
-#else
- UNUSED_PARAM(containerZoom);
- m_image->setContainerSize(containerSize);
-#endif
}
bool CachedImage::usesImageContainerSize() const
@@ -263,42 +257,19 @@ bool CachedImage::imageHasRelativeHeight() const
return false;
}
-LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float multiplier, SizeType sizeType)
+LayoutSize CachedImage::imageSizeForRenderer(const RenderElement* renderer, float multiplier, SizeType sizeType)
{
- ASSERT(!isPurgeable());
-
if (!m_image)
- return IntSize();
+ return LayoutSize();
- LayoutSize imageSize(m_image->size());
+ LayoutSize imageSize;
-#if ENABLE(CSS_IMAGE_ORIENTATION)
- if (renderer && m_image->isBitmapImage()) {
- ImageOrientationDescription orientationDescription(renderer->shouldRespectImageOrientation(), renderer->style().imageOrientation());
- if (orientationDescription.respectImageOrientation() == RespectImageOrientation)
- imageSize = toBitmapImage(m_image.get())->sizeRespectingOrientation(orientationDescription);
- }
-#else
- if (m_image->isBitmapImage() && (renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation))
-#if !PLATFORM(IOS)
- imageSize = toBitmapImage(m_image.get())->sizeRespectingOrientation();
-#else
- {
- // On iOS, the image may have been subsampled to accommodate our size restrictions. However
- // we should tell the renderer what the original size was.
- imageSize = toBitmapImage(m_image.get())->originalSizeRespectingOrientation();
- } else if (m_image->isBitmapImage())
- imageSize = toBitmapImage(m_image.get())->originalSize();
-#endif // !PLATFORM(IOS)
-#endif // ENABLE(CSS_IMAGE_ORIENTATION)
-
-#if ENABLE(SVG)
- else if (m_image->isSVGImage() && sizeType == UsedSize) {
- imageSize = m_svgImageCache->imageSizeForRenderer(renderer);
- }
-#else
- UNUSED_PARAM(sizeType);
-#endif
+ if (is<BitmapImage>(*m_image) && renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation)
+ imageSize = LayoutSize(downcast<BitmapImage>(*m_image).sizeRespectingOrientation());
+ else if (is<SVGImage>(*m_image) && sizeType == UsedSize)
+ imageSize = LayoutSize(m_svgImageCache->imageSizeForRenderer(renderer));
+ else
+ imageSize = LayoutSize(m_image->size());
if (multiplier == 1.0f)
return imageSize;
@@ -331,7 +302,7 @@ void CachedImage::checkShouldPaintBrokenImage()
if (!m_loader || m_loader->reachedTerminalState())
return;
- m_shouldPaintBrokenImage = m_loader->frameLoader()->client().shouldPaintBrokenImage(m_resourceRequest.url());
+ m_shouldPaintBrokenImage = m_loader->frameLoader()->client().shouldPaintBrokenImage(url());
}
void CachedImage::clear()
@@ -347,77 +318,98 @@ inline void CachedImage::createImage()
// Create the image if it doesn't yet exist.
if (m_image)
return;
+
+ m_imageObserver = CachedImageObserver::create(*this);
+
+ if (m_response.mimeType() == "image/svg+xml") {
+ auto svgImage = SVGImage::create(*m_imageObserver, url());
+ m_svgImageCache = std::make_unique<SVGImageCache>(svgImage.ptr());
+ m_image = WTFMove(svgImage);
#if USE(CG) && !USE(WEBKIT_IMAGE_DECODERS)
- else if (m_response.mimeType() == "application/pdf")
- m_image = PDFDocumentImage::create(this);
+ } else if (m_response.mimeType() == "application/pdf") {
+ m_image = PDFDocumentImage::create(m_imageObserver.get());
#endif
-#if ENABLE(SVG)
- else if (m_response.mimeType() == "image/svg+xml") {
- RefPtr<SVGImage> svgImage = SVGImage::create(this);
- m_svgImageCache = std::make_unique<SVGImageCache>(svgImage.get());
- m_image = svgImage.release();
- }
-#endif
- else
- m_image = BitmapImage::create(this);
+ } else
+ m_image = BitmapImage::create(m_imageObserver.get());
if (m_image) {
// Send queued container size requests.
if (m_image->usesContainerSize()) {
- for (ContainerSizeRequests::iterator it = m_pendingContainerSizeRequests.begin(); it != m_pendingContainerSizeRequests.end(); ++it)
- setContainerSizeForRenderer(it->key, it->value.first, it->value.second);
+ for (auto& request : m_pendingContainerSizeRequests)
+ setContainerSizeForRenderer(request.key, request.value.first, request.value.second);
}
m_pendingContainerSizeRequests.clear();
}
}
-inline void CachedImage::clearImage()
+CachedImage::CachedImageObserver::CachedImageObserver(CachedImage& image)
{
- // If our Image has an observer, it's always us so we need to clear the back pointer
- // before dropping our reference.
- if (m_image)
- m_image->setImageObserver(0);
- m_image.clear();
+ m_cachedImages.reserveInitialCapacity(1);
+ m_cachedImages.append(&image);
+ if (auto* loader = image.loader()) {
+ m_allowSubsampling = loader->frameLoader()->frame().settings().imageSubsamplingEnabled();
+ m_allowLargeImageAsyncDecoding = loader->frameLoader()->frame().settings().largeImageAsyncDecodingEnabled();
+ m_allowAnimatedImageAsyncDecoding = loader->frameLoader()->frame().settings().animatedImageAsyncDecodingEnabled();
+ m_showDebugBackground = loader->frameLoader()->frame().settings().showDebugBorders();
+ }
}
-bool CachedImage::canBeDrawn() const
+void CachedImage::CachedImageObserver::decodedSizeChanged(const Image* image, long long delta)
{
- if (!m_image || m_image->isNull())
- return false;
+ for (auto cachedImage : m_cachedImages)
+ cachedImage->decodedSizeChanged(image, delta);
+}
- if (!m_loader || m_loader->reachedTerminalState())
- return true;
+void CachedImage::CachedImageObserver::didDraw(const Image* image)
+{
+ for (auto cachedImage : m_cachedImages)
+ cachedImage->didDraw(image);
+}
- size_t estimatedDecodedImageSize = m_image->width() * m_image->height() * 4; // no overflow check
- return estimatedDecodedImageSize <= m_loader->frameLoader()->frame().settings().maximumDecodedImageSize();
+void CachedImage::CachedImageObserver::animationAdvanced(const Image* image)
+{
+ for (auto cachedImage : m_cachedImages)
+ cachedImage->animationAdvanced(image);
}
-void CachedImage::addIncrementalDataBuffer(ResourceBuffer* data)
+void CachedImage::CachedImageObserver::changedInRect(const Image* image, const IntRect* rect)
{
- m_data = data;
- if (!data)
- return;
+ for (auto cachedImage : m_cachedImages)
+ cachedImage->changedInRect(image, rect);
+}
+
+inline void CachedImage::clearImage()
+{
+ if (m_imageObserver) {
+ m_imageObserver->remove(*this);
+ m_imageObserver = nullptr;
+ }
+ m_image = nullptr;
+}
+
+void CachedImage::addIncrementalDataBuffer(SharedBuffer& data)
+{
+ m_data = &data;
createImage();
// Have the image update its data from its internal buffer.
// It will not do anything now, but will delay decoding until
// queried for info (like size or specific image frames).
- bool sizeAvailable = m_image->setData(m_data->sharedBuffer(), false);
+ bool sizeAvailable = m_image->setData(&data, false);
if (!sizeAvailable)
return;
- if (!canBeDrawn()) {
- // There's no image to draw or its decoded size is bigger than the maximum allowed.
+ if (m_image->isNull()) {
+ // Image decoding failed. Either we need more image data or the image data is malformed.
error(errorOccurred() ? status() : DecodeError);
if (inCache())
- memoryCache()->remove(this);
+ MemoryCache::singleton().remove(*this);
return;
}
- // Go ahead and tell our observers to try to draw.
- // Each chunk from the network causes observers to repaint, which will
- // force that chunk to decode.
+ // Tell our observers to try to draw.
+ // Each chunk from the network causes observers to repaint, which will force that chunk to decode.
// It would be nice to only redraw the decoded band of the image, but with the current design
// (decoding delayed until painting) that seems hard.
notifyObservers();
@@ -425,32 +417,34 @@ void CachedImage::addIncrementalDataBuffer(ResourceBuffer* data)
setEncodedSize(m_image->data() ? m_image->data()->size() : 0);
}
-void CachedImage::addDataBuffer(ResourceBuffer* data)
+void CachedImage::addDataBuffer(SharedBuffer& data)
{
- ASSERT(m_options.dataBufferingPolicy == BufferData);
+ ASSERT(dataBufferingPolicy() == BufferData);
addIncrementalDataBuffer(data);
+ CachedResource::addDataBuffer(data);
}
void CachedImage::addData(const char* data, unsigned length)
{
- ASSERT(m_options.dataBufferingPolicy == DoNotBufferData);
- addIncrementalDataBuffer(ResourceBuffer::create(data, length).get());
+ ASSERT(dataBufferingPolicy() == DoNotBufferData);
+ addIncrementalDataBuffer(SharedBuffer::create(data, length));
+ CachedResource::addData(data, length);
}
-void CachedImage::finishLoading(ResourceBuffer* data)
+void CachedImage::finishLoading(SharedBuffer* data)
{
m_data = data;
if (!m_image && data)
createImage();
if (m_image)
- m_image->setData(m_data->sharedBuffer(), true);
+ m_image->setData(data, true);
- if (!canBeDrawn()) {
- // There's no image to draw or its decoded size is bigger than the maximum allowed.
+ if (!m_image || m_image->isNull()) {
+ // Image decoding failed; the image data is malformed.
error(errorOccurred() ? status() : DecodeError);
if (inCache())
- memoryCache()->remove(this);
+ MemoryCache::singleton().remove(*this);
return;
}
@@ -460,6 +454,16 @@ void CachedImage::finishLoading(ResourceBuffer* data)
CachedResource::finishLoading(data);
}
+void CachedImage::didReplaceSharedBufferContents()
+{
+ if (m_image) {
+ // Let the Image know that the SharedBuffer has been rejigged, so it can let go of any references to the heap-allocated resource buffer.
+ // FIXME(rdar://problem/24275617): It would be better if we could somehow tell the Image's decoder to swap in the new contents without destroying anything.
+ m_image->destroyDecodedData(true);
+ }
+ CachedResource::didReplaceSharedBufferContents();
+}
+
void CachedImage::error(CachedResource::Status status)
{
checkShouldPaintBrokenImage();
@@ -478,23 +482,20 @@ void CachedImage::responseReceived(const ResourceResponse& response)
void CachedImage::destroyDecodedData()
{
bool canDeleteImage = !m_image || (m_image->hasOneRef() && m_image->isBitmapImage());
- if (isSafeToMakePurgeable() && canDeleteImage && !isLoading()) {
- // Image refs the data buffer so we should not make it purgeable while the image is alive.
- // Invoking addClient() will reconstruct the image object.
- m_image = 0;
+ if (canDeleteImage && !isLoading() && !hasClients()) {
+ m_image = nullptr;
setDecodedSize(0);
- if (!MemoryCache::shouldMakeResourcePurgeableOnEviction())
- makePurgeable(true);
} else if (m_image && !errorOccurred())
m_image->destroyDecodedData();
}
-void CachedImage::decodedSizeChanged(const Image* image, int delta)
+void CachedImage::decodedSizeChanged(const Image* image, long long delta)
{
if (!image || image != m_image)
return;
-
- setDecodedSize(decodedSize() + delta);
+
+ ASSERT(delta >= 0 || decodedSize() + delta >= 0);
+ setDecodedSize(static_cast<unsigned>(decodedSize() + delta));
}
void CachedImage::didDraw(const Image* image)
@@ -509,132 +510,47 @@ void CachedImage::didDraw(const Image* image)
CachedResource::didAccessDecodedData(timeStamp);
}
-bool CachedImage::shouldPauseAnimation(const Image* image)
-{
- if (!image || image != m_image)
- return false;
-
- CachedResourceClientWalker<CachedImageClient> w(m_clients);
- while (CachedImageClient* c = w.next()) {
- if (c->willRenderImage(this))
- return false;
- }
-
- return true;
-}
-
void CachedImage::animationAdvanced(const Image* image)
{
if (!image || image != m_image)
return;
- notifyObservers();
+ CachedResourceClientWalker<CachedImageClient> clientWalker(m_clients);
+ while (CachedImageClient* client = clientWalker.next())
+ client->newImageAnimationFrameAvailable(*this);
}
-void CachedImage::changedInRect(const Image* image, const IntRect& rect)
+void CachedImage::changedInRect(const Image* image, const IntRect* rect)
{
if (!image || image != m_image)
return;
- notifyObservers(&rect);
-}
-
-void CachedImage::resumeAnimatingImagesForLoader(CachedResourceLoader* loader)
-{
- const CachedResourceLoader::DocumentResourceMap& resources = loader->allCachedResources();
-
- for (CachedResourceLoader::DocumentResourceMap::const_iterator it = resources.begin(), end = resources.end(); it != end; ++it) {
- const CachedResourceHandle<CachedResource>& resource = it->value;
- if (!resource || !resource->isImage())
- continue;
- CachedImage* cachedImage = static_cast<CachedImage*>(resource.get());
- if (!cachedImage->hasImage())
- continue;
- Image* image = cachedImage->image();
- if (!image->isBitmapImage())
- continue;
- BitmapImage* bitmapImage = toBitmapImage(image);
- if (!bitmapImage->canAnimate())
- continue;
- cachedImage->animationAdvanced(bitmapImage);
- }
+ notifyObservers(rect);
}
bool CachedImage::currentFrameKnownToBeOpaque(const RenderElement* renderer)
{
Image* image = imageForRenderer(renderer);
- if (image->isBitmapImage())
- image->nativeImageForCurrentFrame(); // force decode
return image->currentFrameKnownToBeOpaque();
}
-#if ENABLE(DISK_IMAGE_CACHE)
-bool CachedImage::canUseDiskImageCache() const
-{
- if (isLoading() || errorOccurred())
- return false;
-
- if (!m_data)
- return false;
-
- if (isPurgeable())
- return false;
-
- if (m_data->size() < diskImageCache().minimumImageSize())
- return false;
-
- // "Cache-Control: no-store" resources may be marked as such because they may
- // contain sensitive information. We should not write these resources to disk.
- if (m_response.cacheControlContainsNoStore())
- return false;
-
- // Testing shows that PDF images did not work when memory mapped.
- // However, SVG images and Bitmap images were fine. See:
- // <rdar://problem/8591834> Disk Image Cache should support PDF Images
- if (m_response.mimeType() == "application/pdf")
- return false;
-
- return true;
-}
-
-void CachedImage::useDiskImageCache()
+bool CachedImage::isOriginClean(SecurityOrigin* origin)
{
- ASSERT(canUseDiskImageCache());
- ASSERT(!isUsingDiskImageCache());
- m_data->sharedBuffer()->allowToBeMemoryMapped();
-}
-#endif
-
-bool CachedImage::isOriginClean(SecurityOrigin* securityOrigin)
-{
- if (!image()->hasSingleSecurityOrigin())
- return false;
- if (passesAccessControlCheck(securityOrigin))
- return true;
- return !securityOrigin->taintsCanvas(response().url());
+ ASSERT_UNUSED(origin, origin);
+ ASSERT(this->origin());
+ ASSERT(origin->toString() == this->origin()->toString());
+ return !loadFailedOrCanceled() && isCORSSameOrigin();
}
-#if USE(CF)
-// FIXME: We should look to incorporate the functionality of CachedImageManual
-// into CachedImage or find a better place for this class.
-// FIXME: Remove the USE(CF) once we make MemoryCache::addImageToCache() platform-independent.
-CachedImageManual::CachedImageManual(const URL& url, Image* image)
- : CachedImage(url, image)
- , m_fakeClient(std::make_unique<CachedImageClient>())
+CachedResource::RevalidationDecision CachedImage::makeRevalidationDecision(CachePolicy cachePolicy) const
{
- // Use the incoming URL in the response field. This ensures that code
- // using the response directly, such as origin checks for security,
- // actually see something.
- m_response.setURL(url);
-}
-
-bool CachedImageManual::mustRevalidateDueToCacheHeaders(CachePolicy) const
-{
- // Do not revalidate manually cached images. This mechanism is used as a
- // way to efficiently share an image from the client to content and
- // the URL for that image may not represent a resource that can be
- // retrieved by standard means. If the manual caching SPI is used, it is
- // incumbent on the client to only use valid resources.
- return false;
+ if (UNLIKELY(isManuallyCached())) {
+ // Do not revalidate manually cached images. This mechanism is used as a
+ // way to efficiently share an image from the client to content and
+ // the URL for that image may not represent a resource that can be
+ // retrieved by standard means. If the manual caching SPI is used, it is
+ // incumbent on the client to only use valid resources.
+ return RevalidationDecision::No;
+ }
+ return CachedResource::makeRevalidationDecision(cachePolicy);
}
-#endif
} // namespace WebCore