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 fb554447b44ecd9020267d7dc38acf96e78a8f87..9029a454746656aba5192e4d459f54a8f1333219 100644 |
--- a/third_party/WebKit/Source/core/loader/resource/ImageResource.cpp |
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResource.cpp |
@@ -23,6 +23,8 @@ |
#include "core/loader/resource/ImageResource.h" |
+#include <stdint.h> |
+#include <v8.h> |
#include <memory> |
#include "core/loader/resource/ImageResourceContent.h" |
@@ -36,6 +38,7 @@ |
#include "platform/loader/fetch/ResourceFetcher.h" |
#include "platform/loader/fetch/ResourceLoader.h" |
#include "platform/loader/fetch/ResourceLoadingLog.h" |
+#include "platform/network/HTTPParsers.h" |
#include "platform/weborigin/SecurityViolationReportingPolicy.h" |
#include "public/platform/Platform.h" |
#include "v8/include/v8.h" |
@@ -79,7 +82,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(); |
} |
@@ -101,9 +106,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); |
} |
@@ -173,7 +175,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. |
@@ -197,7 +199,9 @@ ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
m_devicePixelRatioHeaderValue(1.0), |
m_hasDevicePixelRatioHeaderValue(false), |
m_isSchedulingReload(false), |
- m_isPlaceholder(isPlaceholder), |
+ m_placeholderOption( |
+ isPlaceholder ? PlaceholderOption::ShowAndReloadPlaceholderAlways |
+ : PlaceholderOption::DoNotReloadPlaceholder), |
m_flushTimer(this, &ImageResource::flushImageIfNeeded) { |
DCHECK(getContent()); |
RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; |
@@ -320,10 +324,6 @@ void ImageResource::flushImageIfNeeded(TimerBase*) { |
} |
} |
-bool ImageResource::willPaintBrokenImage() const { |
- return errorOccurred(); |
-} |
- |
void ImageResource::decodeError(bool allDataReceived) { |
size_t size = encodedSize(); |
@@ -380,6 +380,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) { |
@@ -402,6 +417,47 @@ void ImageResource::responseReceived( |
m_hasDevicePixelRatioHeaderValue = false; |
} |
} |
+ |
+ if (m_placeholderOption == |
+ PlaceholderOption::ShowAndReloadPlaceholderAlways && |
+ 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 = PlaceholderOption::DoNotReloadPlaceholder; |
+ } else { |
+ m_placeholderOption = PlaceholderOption::ReloadPlaceholderOnDecodeError; |
+ } |
+ } |
+} |
+ |
+bool ImageResource::shouldShowPlaceholder() const { |
+ switch (m_placeholderOption) { |
+ case PlaceholderOption::ShowAndReloadPlaceholderAlways: |
+ return true; |
+ case PlaceholderOption::ReloadPlaceholderOnDecodeError: |
+ case PlaceholderOption::DoNotReloadPlaceholder: |
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+bool ImageResource::shouldReloadBrokenPlaceholder() const { |
+ switch (m_placeholderOption) { |
+ case PlaceholderOption::ShowAndReloadPlaceholderAlways: |
+ return errorOccurred(); |
+ case PlaceholderOption::ReloadPlaceholderOnDecodeError: |
+ return getStatus() == ResourceStatus::DecodeError; |
+ case PlaceholderOption::DoNotReloadPlaceholder: |
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
} |
static bool isLoFiImage(const ImageResource& resource) { |
@@ -421,7 +477,8 @@ void ImageResource::reloadIfLoFiOrPlaceholderImage( |
if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder()) |
return; |
- if (!m_isPlaceholder && !isLoFiImage(*this)) |
+ if (m_placeholderOption == PlaceholderOption::DoNotReloadPlaceholder && |
+ !isLoFiImage(*this)) |
return; |
// Prevent clients and observers from being notified of completion while the |
@@ -436,10 +493,9 @@ void ImageResource::reloadIfLoFiOrPlaceholderImage( |
setPreviewsStateNoTransform(); |
- if (m_isPlaceholder) { |
- m_isPlaceholder = false; |
+ if (m_placeholderOption != PlaceholderOption::DoNotReloadPlaceholder) |
clearRangeRequestHeader(); |
- } |
+ m_placeholderOption = PlaceholderOption::DoNotReloadPlaceholder; |
if (isLoading()) { |
loader()->cancel(); |