Chromium Code Reviews| 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 e4c93592c8e0ac2361f84aab18df2f68f2c03fd8..ba7f64cc44aeba8a0a99695935d449f86ed77d18 100644 |
| --- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp |
| +++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp |
| @@ -32,7 +32,9 @@ |
| #include "core/svg/graphics/SVGImage.h" |
| #include "platform/RuntimeEnabledFeatures.h" |
| #include "platform/SharedBuffer.h" |
| +#include "platform/geometry/IntSize.h" |
| #include "platform/graphics/BitmapImage.h" |
| +#include "platform/graphics/PlaceholderImage.h" |
| #include "platform/tracing/TraceEvent.h" |
| #include "public/platform/Platform.h" |
| #include "public/platform/WebCachePolicy.h" |
| @@ -45,6 +47,26 @@ |
| namespace blink { |
| +class ImageResource::ImageResourceFactory : public ResourceFactory { |
| + STACK_ALLOCATED(); |
| + |
| + public: |
| + ImageResourceFactory(const FetchRequest& fetchRequest) |
| + : ResourceFactory(Resource::Image), m_fetchRequest(&fetchRequest) {} |
| + |
| + Resource* create(const ResourceRequest& request, |
| + const ResourceLoaderOptions& options, |
| + const String&) const override { |
| + return new ImageResource(request, options, |
| + m_fetchRequest->placeholderImageRequestType() == |
| + FetchRequest::AllowPlaceholder); |
| + } |
| + |
| + private: |
| + // Weak, unowned pointer. Must outlive |this|. |
| + const FetchRequest* m_fetchRequest; |
| +}; |
| + |
| ImageResource* ImageResource::fetch(FetchRequest& request, |
| ResourceFetcher* fetcher) { |
| if (request.resourceRequest().requestContext() == |
| @@ -63,17 +85,27 @@ ImageResource* ImageResource::fetch(FetchRequest& request, |
| return nullptr; |
| } |
| - return toImageResource( |
| - fetcher->requestResource(request, ImageResourceFactory())); |
| + ImageResource* resource = toImageResource( |
| + fetcher->requestResource(request, ImageResourceFactory(request))); |
| + if (request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && |
| + resource->m_isPlaceholder) { |
| + // 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->reloadIfLoFi(fetcher, false); |
| + } |
| + return resource; |
| } |
| ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
| - const ResourceLoaderOptions& options) |
| + const ResourceLoaderOptions& options, |
| + bool isPlaceholder) |
| : Resource(resourceRequest, Image, options), |
| m_devicePixelRatioHeaderValue(1.0), |
| m_image(nullptr), |
| m_hasDevicePixelRatioHeaderValue(false), |
| - m_isSchedulingReload(false) { |
| + m_isSchedulingReload(false), |
| + m_isPlaceholder(isPlaceholder) { |
| RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; |
| } |
| @@ -83,7 +115,8 @@ ImageResource::ImageResource(blink::Image* image, |
| m_devicePixelRatioHeaderValue(1.0), |
| m_image(image), |
| m_hasDevicePixelRatioHeaderValue(false), |
| - m_isSchedulingReload(false) { |
| + m_isSchedulingReload(false), |
| + m_isPlaceholder(false) { |
| RESOURCE_LOADING_DVLOG(1) << "new ImageResource(Image) " << this; |
| setStatus(Cached); |
| } |
| @@ -103,7 +136,7 @@ DEFINE_TRACE(ImageResource) { |
| void ImageResource::checkNotify() { |
| // Don't notify observers and clients of completion if this ImageResource is |
| // about to be reloaded. |
| - if (m_isSchedulingReload) |
| + if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) |
| return; |
| notifyObserversInternal(MarkFinishedOption::ShouldMarkFinished); |
| @@ -136,7 +169,7 @@ void ImageResource::didAddClient(ResourceClient* client) { |
| // Don't notify observers and clients of completion if this ImageResource is |
| // about to be reloaded. |
| - if (m_isSchedulingReload) |
| + if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) |
| return; |
| Resource::didAddClient(client); |
| @@ -164,7 +197,7 @@ void ImageResource::addObserver(ImageResourceObserver* observer) { |
| observer->imageChanged(this); |
| } |
| - if (isLoaded() && !m_isSchedulingReload) { |
| + if (isLoaded() && !m_isSchedulingReload && !shouldReloadBrokenPlaceholder()) { |
| markObserverFinished(observer); |
| observer->imageNotifyFinished(this); |
| } |
| @@ -402,6 +435,22 @@ void ImageResource::updateImage(bool allDataReceived) { |
| // observers to repaint, which will force that chunk to decode. |
| if (sizeAvailable == Image::SizeUnavailable && !allDataReceived) |
| return; |
| + |
| + if (m_isPlaceholder && allDataReceived && m_image && !m_image->isNull()) { |
| + if (sizeAvailable == Image::SizeAvailable) { |
| + // TODO(sclittle): Show the original image if the response consists of the |
| + // entire image, such as if the entire image response body is smaller than |
| + // the requested range. |
| + IntSize dimensions = m_image->size(); |
| + clearImage(); |
| + m_image = PlaceholderImage::create(this, dimensions); |
| + } else { |
| + // Clear the image so that it gets treated like a decoding error, since |
| + // the attempt to build a placeholder image failed. |
| + clearImage(); |
| + } |
| + } |
| + |
| if (!m_image || m_image->isNull()) { |
| size_t size = encodedSize(); |
| clear(); |
| @@ -535,12 +584,13 @@ void ImageResource::updateImageAnimationPolicy() { |
| } |
| } |
| -void ImageResource::reloadIfLoFi(ResourceFetcher* fetcher) { |
| - if (resourceRequest().loFiState() != WebURLRequest::LoFiOn) |
| - return; |
| - if (isLoaded() && |
| - !response().httpHeaderField("chrome-proxy").contains("q=low")) |
| +void ImageResource::reloadIfLoFi(ResourceFetcher* fetcher, bool bypassCache) { |
| + if (!m_isPlaceholder && |
| + (resourceRequest().loFiState() != WebURLRequest::LoFiOn || |
| + (isLoaded() && |
| + !response().httpHeaderField("chrome-proxy").contains("q=low")))) { |
| 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 |
| @@ -549,8 +599,15 @@ void ImageResource::reloadIfLoFi(ResourceFetcher* fetcher) { |
| DCHECK(!m_isSchedulingReload); |
| m_isSchedulingReload = true; |
| - setCachePolicyBypassingCache(); |
| + if (bypassCache) |
| + setCachePolicyBypassingCache(); |
| setLoFiStateOff(); |
|
Stephen Chennney
2016/10/17 18:09:17
It concerns me a little that if you reload the pla
sclittle
2016/10/18 00:54:11
We don't want to load a Lo-Fi image if a placehold
|
| + |
| + if (m_isPlaceholder) { |
| + m_isPlaceholder = false; |
| + clearRangeRequestHeader(); |
| + } |
| + |
| if (isLoading()) { |
| loader()->cancel(); |
| // Canceling the loader causes error() to be called, which in turn calls |