Index: third_party/WebKit/Source/core/fetch/ImageResource.cpp |
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp |
index 861ca24e5593d5c717342eeda851d9ba20e75a74..3fa3f1263a5c0a0794e43644714ca0df76b6df2c 100644 |
--- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp |
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp |
@@ -36,6 +36,7 @@ |
#include "platform/SharedBuffer.h" |
#include "platform/tracing/TraceEvent.h" |
#include "public/platform/Platform.h" |
+#include "public/platform/WebCachePolicy.h" |
#include "wtf/CurrentTime.h" |
#include "wtf/HashCountedSet.h" |
#include "wtf/StdLibExtras.h" |
@@ -67,9 +68,6 @@ class ImageResource::ImageResourceInfoImpl final |
private: |
const KURL& url() const override { return m_resource->url(); } |
- bool isSchedulingReload() const override { |
- return m_resource->m_isSchedulingReload; |
- } |
bool hasDevicePixelRatioHeaderValue() const override { |
return m_resource->m_hasDevicePixelRatioHeaderValue; |
} |
@@ -86,9 +84,8 @@ class ImageResource::ImageResourceInfoImpl final |
bool isCacheValidator() const override { |
return m_resource->isCacheValidator(); |
} |
- bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override { |
- return m_resource->m_isSchedulingReload || |
- m_resource->shouldReloadBrokenPlaceholder(); |
+ bool shouldReloadBrokenPlaceholder() const override { |
+ return m_resource->shouldReloadBrokenPlaceholder(); |
} |
bool isAccessAllowed( |
SecurityOrigin* securityOrigin, |
@@ -102,6 +99,7 @@ class ImageResource::ImageResourceInfoImpl final |
const ResourceError& resourceError() const override { |
return m_resource->resourceError(); |
} |
+ ImageResource* resourceForTest() const override { return m_resource; } |
void decodeError(bool allDataReceived) override { |
m_resource->decodeError(allDataReceived); |
@@ -123,6 +121,9 @@ class ImageResource::ImageResourceInfoImpl final |
WebURLRequest::RequestContextImage, |
initiatorName); |
} |
+ bool reloadIfLoFiOrPlaceholder(ResourceFetcher* fetcherForReload) override { |
+ return m_resource->reloadIfLoFiOrPlaceholder(fetcherForReload); |
+ } |
Member<ImageResource> m_resource; |
}; |
@@ -173,8 +174,10 @@ ImageResource* ImageResource::fetch(FetchRequest& request, |
// If the image is a placeholder, but this fetch doesn't allow a |
// placeholder, then load the original image. Note that the cache is not |
// bypassed here - it should be fine to use a cached copy if possible. |
- resource->reloadIfLoFiOrPlaceholder(fetcher, |
- ReloadCachePolicy::UseExistingPolicy); |
+ ImageResource* reloadingResource = resource->reloadIfLoFiOrPlaceholder( |
+ fetcher, ReloadCachePolicy::UseExistingPolicy); |
+ if (reloadingResource) |
+ resource = reloadingResource; |
} |
return resource; |
} |
@@ -192,7 +195,6 @@ ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
m_content(content), |
m_devicePixelRatioHeaderValue(1.0), |
m_hasDevicePixelRatioHeaderValue(false), |
- m_isSchedulingReload(false), |
m_isPlaceholder(isPlaceholder), |
m_flushTimer(this, &ImageResource::flushImageIfNeeded) { |
DCHECK(getContent()); |
@@ -211,28 +213,14 @@ DEFINE_TRACE(ImageResource) { |
MultipartImageResourceParser::Client::trace(visitor); |
} |
-void ImageResource::checkNotify() { |
- // Don't notify clients of completion if this ImageResource is |
- // about to be reloaded. |
- if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) |
- return; |
- |
- Resource::checkNotify(); |
-} |
- |
bool ImageResource::hasClientsOrObservers() const { |
- return Resource::hasClientsOrObservers() || getContent()->hasObservers(); |
+ return Resource::hasClientsOrObservers() || |
+ (getContent() && getContent()->hasObservers()); |
} |
void ImageResource::didAddClient(ResourceClient* client) { |
DCHECK((m_multipartParser && isLoading()) || !data() || |
- getContent()->hasImage()); |
- |
- // Don't notify observers and clients of completion if this ImageResource is |
- // about to be reloaded. |
- if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) |
- return; |
- |
+ (getContent() && getContent()->hasImage())); |
Resource::didAddClient(client); |
} |
@@ -242,6 +230,8 @@ void ImageResource::destroyDecodedDataForFailedRevalidation() { |
} |
void ImageResource::destroyDecodedDataIfPossible() { |
+ if (!getContent()) |
+ return; |
getContent()->destroyDecodedData(); |
if (getContent()->hasImage() && !isPreloaded() && |
getContent()->isRefetchableDataFromDiskCache()) { |
@@ -251,16 +241,18 @@ void ImageResource::destroyDecodedDataIfPossible() { |
} |
void ImageResource::allClientsAndObserversRemoved() { |
- CHECK(!getContent()->hasImage() || !errorOccurred()); |
+ CHECK(!getContent() || !getContent()->hasImage() || !errorOccurred()); |
// If possible, delay the resetting until back at the event loop. Doing so |
// after a conservative GC prevents resetAnimation() from upsetting ongoing |
// animation updates (crbug.com/613709) |
- if (!ThreadHeap::willObjectBeLazilySwept(this)) { |
- Platform::current()->currentThread()->getWebTaskRunner()->postTask( |
- BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, |
- wrapWeakPersistent(getContent()))); |
- } else { |
- getContent()->doResetAnimation(); |
+ if (getContent()) { |
+ if (!ThreadHeap::willObjectBeLazilySwept(this)) { |
+ Platform::current()->currentThread()->getWebTaskRunner()->postTask( |
+ BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, |
+ wrapWeakPersistent(getContent()))); |
+ } else { |
+ getContent()->doResetAnimation(); |
+ } |
} |
if (m_multipartParser) |
m_multipartParser->cancel(); |
@@ -270,7 +262,7 @@ void ImageResource::allClientsAndObserversRemoved() { |
PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { |
if (data()) |
return data(); |
- if (getContent()->hasImage()) |
+ if (getContent() && getContent()->hasImage()) |
return getContent()->getImage()->data(); |
return nullptr; |
} |
@@ -282,6 +274,9 @@ void ImageResource::appendData(const char* data, size_t length) { |
} else { |
Resource::appendData(data, length); |
+ if (!getContent()) |
+ return; |
+ |
// If we don't have the size available yet, then update immediately since |
// we need to know the image size as soon as possible. Likewise for |
// animated images, update right away since we shouldn't throttle animated |
@@ -346,13 +341,15 @@ void ImageResource::updateImageAndClearBuffer() { |
clearData(); |
} |
-void ImageResource::finish(double loadFinishTime) { |
+void ImageResource::finish(double loadFinishTime, |
+ ResourceFetcher* fetcherForReload) { |
if (m_multipartParser) { |
m_multipartParser->finish(); |
if (data()) |
updateImageAndClearBuffer(); |
} else { |
- updateImage(data(), ImageResourceContent::KeepExistingImage, true); |
+ updateImage(data(), ImageResourceContent::KeepExistingImage, true, |
+ fetcherForReload); |
// As encoded image data can be created from m_image (see |
// ImageResource::resourceBuffer(), we don't have to keep m_data. Let's |
// clear this. As for the lifetimes of m_image and m_data, see this |
@@ -360,15 +357,17 @@ void ImageResource::finish(double loadFinishTime) { |
// https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1VsqpxoL7aciY/edit?usp=sharing |
clearData(); |
} |
- Resource::finish(loadFinishTime); |
+ Resource::finish(loadFinishTime, fetcherForReload); |
} |
-void ImageResource::error(const ResourceError& error) { |
+void ImageResource::error(const ResourceError& error, |
+ ResourceFetcher* fetcherForReload) { |
if (m_multipartParser) |
m_multipartParser->cancel(); |
clearData(); |
- Resource::error(error); |
- updateImage(nullptr, ImageResourceContent::ClearExistingImage, true); |
+ Resource::error(error, fetcherForReload); |
+ updateImage(nullptr, ImageResourceContent::ClearExistingImage, true, |
+ fetcherForReload); |
} |
void ImageResource::responseReceived( |
@@ -404,45 +403,43 @@ static bool isLoFiImage(const ImageResource& resource) { |
.contains("empty-image"); |
} |
-void ImageResource::reloadIfLoFiOrPlaceholder( |
+void ImageResource::detachContent() { |
+ bool hasObservers = getContent() && getContent()->hasObservers(); |
+ |
+ clearData(); |
+ memoryCache()->remove(this); |
+ |
+ if (hasObservers) |
+ didRemoveClientOrObserver(); |
+} |
+ |
+ImageResource* ImageResource::reloadIfLoFiOrPlaceholder( |
ResourceFetcher* fetcher, |
ReloadCachePolicy reloadCachePolicy) { |
+ if (!fetcher) |
+ return nullptr; |
if (!m_isPlaceholder && !isLoFiImage(*this)) |
- return; |
- |
- // Prevent clients and observers from being notified of completion while the |
- // reload is being scheduled, so that e.g. canceling an existing load in |
- // progress doesn't cause clients and observers to be notified of completion |
- // prematurely. |
- DCHECK(!m_isSchedulingReload); |
- m_isSchedulingReload = true; |
+ return nullptr; |
+ ImageResourceContent* content = getContent(); |
+ if (!content) |
+ return nullptr; |
+ // Creates request/options for new ImageResource for reloading. |
+ ResourceRequest reloadingRequest = resourceRequest(); |
+ ResourceLoaderOptions reloadingOptions = options(); |
if (reloadCachePolicy == ReloadCachePolicy::BypassCache) |
- setCachePolicyBypassingCache(); |
- setLoFiStateOff(); |
- |
- if (m_isPlaceholder) { |
- m_isPlaceholder = false; |
- clearRangeRequestHeader(); |
- } |
- |
- if (isLoading()) { |
- loader()->cancel(); |
- // Canceling the loader causes error() to be called, which in turn calls |
- // clear() and notifyObservers(), so there's no need to call these again |
- // here. |
- } else { |
- clearData(); |
- setEncodedSize(0); |
- updateImage(nullptr, ImageResourceContent::ClearExistingImage, false); |
- } |
- |
- setStatus(NotStarted); |
- |
- DCHECK(m_isSchedulingReload); |
- m_isSchedulingReload = false; |
- |
- fetcher->startLoad(this); |
+ reloadingRequest.setCachePolicy(WebCachePolicy::BypassingCache); |
+ reloadingRequest.setLoFiState(WebURLRequest::LoFiOff); |
+ if (m_isPlaceholder) |
+ reloadingRequest.clearHTTPHeaderField("range"); |
+ |
+ detachContent(); |
+ // Do not touch |this| after this point. |
+ |
+ ImageResource* reloadingResource = |
+ new ImageResource(reloadingRequest, reloadingOptions, content, false); |
+ fetcher->startLoad(reloadingResource); |
+ return reloadingResource; |
} |
void ImageResource::onePartInMultipartReceived( |
@@ -496,18 +493,24 @@ ImageResourceContent* ImageResource::getContent() const { |
} |
ResourcePriority ImageResource::priorityFromObservers() { |
+ if (!getContent()) |
+ return ResourcePriority(); |
+ |
return getContent()->priorityFromObservers(); |
} |
void ImageResource::updateImage( |
PassRefPtr<SharedBuffer> sharedBuffer, |
ImageResourceContent::ClearImageOption clearImageOption, |
- bool allDataReceived) { |
+ bool allDataReceived, |
+ ResourceFetcher* fetcherForReload) { |
if (!m_isUpdateImageCalled) |
clearImageOption = ImageResourceContent::ClearExistingImage; |
m_isUpdateImageCalled = true; |
- getContent()->updateImage(std::move(sharedBuffer), clearImageOption, |
- allDataReceived); |
+ if (getContent()) { |
+ getContent()->updateImage(std::move(sharedBuffer), clearImageOption, |
+ allDataReceived, fetcherForReload); |
+ } |
} |
} // namespace blink |