Chromium Code Reviews| Index: third_party/WebKit/Source/core/loader/resource/ImageResource.cpp |
| diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResource.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResource.cpp |
| index 8e51801e45a6450109f1e143fa3274b004f32be1..21528f0493f29d74d1c4704311d078f3267454e0 100644 |
| --- a/third_party/WebKit/Source/core/loader/resource/ImageResource.cpp |
| +++ b/third_party/WebKit/Source/core/loader/resource/ImageResource.cpp |
| @@ -23,6 +23,9 @@ |
| #include "core/loader/resource/ImageResource.h" |
| +#include <stdint.h> |
| +#include <v8.h> |
| +#include <memory> |
| #include "core/loader/resource/ImageResourceContent.h" |
| #include "core/loader/resource/ImageResourceInfo.h" |
| #include "platform/Histogram.h" |
| @@ -34,11 +37,10 @@ |
| #include "platform/loader/fetch/ResourceFetcher.h" |
| #include "platform/loader/fetch/ResourceLoader.h" |
| #include "platform/loader/fetch/ResourceLoadingLog.h" |
| +#include "platform/network/HTTPParsers.h" |
| #include "public/platform/Platform.h" |
| #include "wtf/CurrentTime.h" |
| #include "wtf/StdLibExtras.h" |
| -#include <memory> |
| -#include <v8.h> |
| namespace blink { |
| namespace { |
| @@ -77,7 +79,9 @@ class ImageResource::ImageResourceInfoImpl final |
| return m_resource->response(); |
| } |
| ResourceStatus getStatus() const override { return m_resource->getStatus(); } |
| - bool isPlaceholder() const override { return m_resource->isPlaceholder(); } |
| + bool shouldShowPlaceholder() const override { |
| + return m_resource->shouldShowPlaceholder(); |
| + } |
| bool isCacheValidator() const override { |
| return m_resource->isCacheValidator(); |
| } |
| @@ -99,9 +103,6 @@ class ImageResource::ImageResourceInfoImpl final |
| return m_resource->resourceError(); |
| } |
| - void setIsPlaceholder(bool isPlaceholder) override { |
| - m_resource->m_isPlaceholder = isPlaceholder; |
| - } |
| void setDecodedSize(size_t size) override { |
| m_resource->setDecodedSize(size); |
| } |
| @@ -172,7 +173,7 @@ ImageResource* ImageResource::fetch(FetchRequest& request, |
| fetcher->requestResource(request, ImageResourceFactory(request))); |
| if (resource && |
| request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && |
| - resource->m_isPlaceholder) { |
| + resource->shouldShowPlaceholder()) { |
| // 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. |
| @@ -196,7 +197,8 @@ ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
| m_devicePixelRatioHeaderValue(1.0), |
| m_hasDevicePixelRatioHeaderValue(false), |
| m_isSchedulingReload(false), |
| - m_isPlaceholder(isPlaceholder), |
| + m_placeholderOption(isPlaceholder ? ShowAndReloadPlaceholderAlways |
| + : DoNotReloadPlaceholder), |
| m_flushTimer(this, &ImageResource::flushImageIfNeeded) { |
| DCHECK(getContent()); |
| RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; |
| @@ -319,10 +321,6 @@ void ImageResource::flushImageIfNeeded(TimerBase*) { |
| } |
| } |
| -bool ImageResource::willPaintBrokenImage() const { |
| - return errorOccurred(); |
| -} |
| - |
| void ImageResource::decodeError(bool allDataReceived) { |
| size_t size = encodedSize(); |
| @@ -379,6 +377,21 @@ void ImageResource::error(const ResourceError& error) { |
| true); |
| } |
| +// Determines if |response| likely contains the entire resource for the purposes |
| +// of determining whether or not to show a placeholder, e.g. if the server |
| +// responded with a full 200 response or if the full image is smaller than the |
| +// requested range. |
| +static bool isEntireResource(const ResourceResponse& response) { |
| + if (response.httpStatusCode() != 206) |
| + return true; |
| + |
| + int64_t firstBytePosition = -1, lastBytePosition = -1, instanceLength = -1; |
| + return parseContentRangeHeaderFor206( |
| + response.httpHeaderField("Content-Range"), &firstBytePosition, |
| + &lastBytePosition, &instanceLength) && |
| + firstBytePosition == 0 && lastBytePosition + 1 == instanceLength; |
| +} |
| + |
| void ImageResource::responseReceived( |
| const ResourceResponse& response, |
| std::unique_ptr<WebDataConsumerHandle> handle) { |
| @@ -401,6 +414,45 @@ void ImageResource::responseReceived( |
| m_hasDevicePixelRatioHeaderValue = false; |
| } |
| } |
| + |
| + if (isEntireResource(this->response())) { |
| + if (this->response().httpStatusCode() < 400 || |
| + this->response().httpStatusCode() >= 600) { |
| + // Don't treat a complete and broken image as a placeholder if the |
| + // response code is something other than a 4xx or 5xx error. |
| + // This is done to prevent reissuing the request in cases like |
| + // "204 No Content" responses to tracking requests triggered by <img> |
| + // tags, and <img> tags used to preload non-image resources. |
| + m_placeholderOption = DoNotReloadPlaceholder; |
| + } else { |
| + m_placeholderOption = ReloadPlaceholderOnDecodeError; |
|
yhirano
2017/02/13 11:36:57
Is DoNotReloadPlaceholder => ReloadPlaceholderOnDe
hiroshige
2017/02/23 20:52:38
Oh, looks invalid. Fixed.
|
| + } |
| + } |
| +} |
| + |
| +bool ImageResource::shouldShowPlaceholder() const { |
| + switch (m_placeholderOption) { |
| + case ShowAndReloadPlaceholderAlways: |
| + return true; |
| + case ReloadPlaceholderOnDecodeError: |
| + case DoNotReloadPlaceholder: |
| + return false; |
| + } |
| + NOTREACHED(); |
| + return false; |
| +} |
| + |
| +bool ImageResource::shouldReloadBrokenPlaceholder() const { |
| + switch (m_placeholderOption) { |
| + case ShowAndReloadPlaceholderAlways: |
| + return errorOccurred(); |
| + case ReloadPlaceholderOnDecodeError: |
| + return getStatus() == ResourceStatus::DecodeError; |
| + case DoNotReloadPlaceholder: |
| + return false; |
| + } |
| + NOTREACHED(); |
| + return false; |
| } |
| static bool isLoFiImage(const ImageResource& resource) { |
| @@ -420,7 +472,7 @@ void ImageResource::reloadIfLoFiOrPlaceholderImage( |
| if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder()) |
| return; |
| - if (!m_isPlaceholder && !isLoFiImage(*this)) |
| + if (m_placeholderOption == DoNotReloadPlaceholder && !isLoFiImage(*this)) |
| return; |
| // Prevent clients and observers from being notified of completion while the |
| @@ -435,10 +487,9 @@ void ImageResource::reloadIfLoFiOrPlaceholderImage( |
| setPreviewsStateNoTransform(); |
| - if (m_isPlaceholder) { |
| - m_isPlaceholder = false; |
| + if (m_placeholderOption != DoNotReloadPlaceholder) |
| clearRangeRequestHeader(); |
| - } |
| + m_placeholderOption = DoNotReloadPlaceholder; |
| if (isLoading()) { |
| loader()->cancel(); |