Chromium Code Reviews| Index: third_party/WebKit/Source/core/fetch/ImageResourceContent.cpp |
| diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResourceContent.cpp |
| similarity index 31% |
| copy from third_party/WebKit/Source/core/fetch/ImageResource.cpp |
| copy to third_party/WebKit/Source/core/fetch/ImageResourceContent.cpp |
| index 0a454391815e5909ea81d4e931931a92341c7884..8cb95b9879ee7b273cca57321a1729c36b0085a5 100644 |
| --- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp |
| +++ b/third_party/WebKit/Source/core/fetch/ImageResourceContent.cpp |
| @@ -1,34 +1,12 @@ |
| -/* |
| - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
| - Copyright (C) 2001 Dirk Mueller (mueller@kde.org) |
| - Copyright (C) 2002 Waldo Bastian (bastian@kde.org) |
| - Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
| - Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| - |
| - This library is free software; you can redistribute it and/or |
| - modify it under the terms of the GNU Library General Public |
| - License as published by the Free Software Foundation; either |
| - version 2 of the License, or (at your option) any later version. |
| - |
| - This library is distributed in the hope that it will be useful, |
| - but WITHOUT ANY WARRANTY; without even the implied warranty of |
| - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| - Library General Public License for more details. |
| - |
| - You should have received a copy of the GNU Library General Public License |
| - along with this library; see the file COPYING.LIB. If not, write to |
| - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| - Boston, MA 02110-1301, USA. |
| -*/ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| -#include "core/fetch/ImageResource.h" |
| +#include "core/fetch/ImageResourceContent.h" |
| +#include "core/fetch/ImageResource.h" |
| +#include "core/fetch/ImageResourceInfo.h" |
| #include "core/fetch/ImageResourceObserver.h" |
| -#include "core/fetch/MemoryCache.h" |
| -#include "core/fetch/ResourceClient.h" |
| -#include "core/fetch/ResourceFetcher.h" |
| -#include "core/fetch/ResourceLoader.h" |
| -#include "core/fetch/ResourceLoadingLog.h" |
| #include "core/svg/graphics/SVGImage.h" |
| #include "platform/Histogram.h" |
| #include "platform/RuntimeEnabledFeatures.h" |
| @@ -37,10 +15,6 @@ |
| #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" |
| -#include "wtf/CurrentTime.h" |
| -#include "wtf/HashCountedSet.h" |
| #include "wtf/StdLibExtras.h" |
| #include "wtf/Vector.h" |
| #include <memory> |
| @@ -48,161 +22,104 @@ |
| namespace blink { |
| namespace { |
| -// The amount of time to wait before informing the clients that the image has |
| -// been updated (in seconds). This effectively throttles invalidations that |
| -// result from new data arriving for this image. |
| -constexpr double kFlushDelaySeconds = 1.; |
| -} // namespace |
| - |
| -class ImageResource::ImageResourceFactory : public ResourceFactory { |
| - STACK_ALLOCATED(); |
| +class NullImageResourceInfo final |
| + : public GarbageCollectedFinalized<NullImageResourceInfo>, |
| + public ImageResourceInfo { |
| + USING_GARBAGE_COLLECTED_MIXIN(NullImageResourceInfo); |
| 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); |
| - } |
| + NullImageResourceInfo() {} |
| - private: |
| - // Weak, unowned pointer. Must outlive |this|. |
| - const FetchRequest* m_fetchRequest; |
| -}; |
| + DEFINE_INLINE_VIRTUAL_TRACE() { ImageResourceInfo::trace(visitor); } |
| -ImageResource* ImageResource::fetch(FetchRequest& request, |
| - ResourceFetcher* fetcher) { |
| - if (request.resourceRequest().requestContext() == |
| - WebURLRequest::RequestContextUnspecified) { |
| - request.mutableResourceRequest().setRequestContext( |
| - WebURLRequest::RequestContextImage); |
| + private: |
| + const KURL& url() const override { return m_url; } |
| + bool isSchedulingReload() const override { return false; } |
| + bool hasDevicePixelRatioHeaderValue() const override { return false; } |
| + float devicePixelRatioHeaderValue() const override { return 1.0; } |
| + const ResourceResponse& response() const override { return m_response; } |
| + ResourceStatus getStatus() const override { return ResourceStatus::Cached; } |
| + bool isPlaceholder() const override { return false; } |
| + bool isCacheValidator() const override { return false; } |
| + bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override { |
| + return false; |
| } |
| - if (fetcher->context().pageDismissalEventBeingDispatched()) { |
| - KURL requestURL = request.resourceRequest().url(); |
| - if (requestURL.isValid() && |
| - fetcher->context().canRequest(Resource::Image, |
| - request.resourceRequest(), requestURL, |
| - request.options(), request.forPreload(), |
| - request.getOriginRestriction())) |
| - fetcher->context().sendImagePing(requestURL); |
| - return nullptr; |
| + bool isAccessAllowed( |
| + SecurityOrigin*, |
| + DoesCurrentFrameHaveSingleSecurityOrigin) const override { |
| + return true; |
| } |
| + bool hasCacheControlNoStoreHeader() const override { return false; } |
| + const ResourceError& resourceError() const override { return m_error; } |
| + |
| + void decodeError(bool allDataReceived) override {} |
| + void setDecodedSize(size_t) override {} |
| + void willAddClientOrObserver() override {} |
| + void didRemoveClientOrObserver() override {} |
| + void emulateLoadStartedForInspector( |
| + ResourceFetcher*, |
| + const KURL&, |
| + const AtomicString& initiatorName) override {} |
| + |
| + const KURL m_url; |
| + const ResourceResponse m_response; |
| + const ResourceError m_error; |
| +}; |
| - ImageResource* resource = toImageResource( |
| - fetcher->requestResource(request, ImageResourceFactory(request))); |
| - if (resource && |
| - 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->reloadIfLoFiOrPlaceholder(fetcher, |
| - ReloadCachePolicy::UseExistingPolicy); |
| - } |
| - return resource; |
| -} |
| - |
| -ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
| - const ResourceLoaderOptions& options, |
| - bool isPlaceholder) |
| - : Resource(resourceRequest, Image, options), |
| - m_devicePixelRatioHeaderValue(1.0), |
| - m_image(nullptr), |
| - m_hasDevicePixelRatioHeaderValue(false), |
| - m_isSchedulingReload(false), |
| - m_isPlaceholder(isPlaceholder), |
| - m_flushTimer(this, &ImageResource::flushImageIfNeeded), |
| - m_isRefetchableDataFromDiskCache(true) { |
| - RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; |
| -} |
| - |
| -ImageResource::ImageResource(blink::Image* image, |
| - const ResourceLoaderOptions& options) |
| - : Resource(ResourceRequest(""), Image, options), |
| - m_devicePixelRatioHeaderValue(1.0), |
| - m_image(image), |
| - m_hasDevicePixelRatioHeaderValue(false), |
| - m_isSchedulingReload(false), |
| - m_isPlaceholder(false), |
| - m_flushTimer(this, &ImageResource::flushImageIfNeeded), |
| - m_isRefetchableDataFromDiskCache(true) { |
| - RESOURCE_LOADING_DVLOG(1) << "new ImageResource(Image) " << this; |
| - setStatus(Cached); |
| -} |
| - |
| -ImageResource::~ImageResource() { |
| - RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; |
| - clearImage(); |
| +} // namespace |
| + |
| +ImageResourceContent::ImageResourceContent(PassRefPtr<blink::Image> image) |
| + : m_image(image), m_isRefetchableDataFromDiskCache(true) { |
| + DEFINE_STATIC_LOCAL(NullImageResourceInfo, nullInfo, |
| + (new NullImageResourceInfo())); |
| + m_info = &nullInfo; |
| } |
| -DEFINE_TRACE(ImageResource) { |
| - visitor->trace(m_multipartParser); |
| - Resource::trace(visitor); |
| - ImageObserver::trace(visitor); |
| - MultipartImageResourceParser::Client::trace(visitor); |
| +ImageResourceContent* ImageResourceContent::fetch(FetchRequest& request, |
| + ResourceFetcher* fetcher) { |
| + ImageResource* resource = ImageResource::fetch(request, fetcher); |
|
Nate Chapin
2016/12/07 20:27:28
This feels like a layering violation, and is (I th
hiroshige
2016/12/09 22:50:39
Done.
|
| + if (!resource) |
| + return nullptr; |
| + return resource->getContent(); |
| } |
| -void ImageResource::checkNotify() { |
| - // Don't notify clients of completion if this ImageResource is |
| - // about to be reloaded. |
| - if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) |
| - return; |
| +void ImageResourceContent::setImageResourceInfo(ImageResourceInfo* info) { |
| + m_info = info; |
| +} |
| - Resource::checkNotify(); |
| +DEFINE_TRACE(ImageResourceContent) { |
| + visitor->trace(m_info); |
| + ImageObserver::trace(visitor); |
| } |
| -void ImageResource::markObserverFinished(ImageResourceObserver* observer) { |
| +void ImageResourceContent::markObserverFinished( |
| + ImageResourceObserver* observer) { |
| if (m_observers.contains(observer)) { |
| m_finishedObservers.add(observer); |
| m_observers.remove(observer); |
| } |
| } |
| -void ImageResource::didAddClient(ResourceClient* client) { |
| - DCHECK((m_multipartParser && isLoading()) || !data() || m_image); |
| - |
| - // Don't notify observers and clients of completion if this ImageResource is |
| - // about to be reloaded. |
| - if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) |
| - return; |
| - |
| - Resource::didAddClient(client); |
| -} |
| - |
| -void ImageResource::addObserver(ImageResourceObserver* observer) { |
| - willAddClientOrObserver(MarkAsReferenced); |
| +void ImageResourceContent::addObserver(ImageResourceObserver* observer) { |
| + m_info->willAddClientOrObserver(); |
| m_observers.add(observer); |
| - if (isCacheValidator()) |
| + if (m_info->isCacheValidator()) |
| return; |
| - // When the response is not multipart, if |data()| exists, |m_image| must be |
| - // created. This is assured that |updateImage()| is called when |appendData()| |
| - // is called. |
| - // |
| - // On the other hand, when the response is multipart, |updateImage()| is not |
| - // called in |appendData()|, which means |m_image| might not be created even |
| - // when |data()| exists. This is intentional since creating a |m_image| on |
| - // receiving data might destroy an existing image in a previous part. |
| - DCHECK((m_multipartParser && isLoading()) || !data() || m_image); |
| - |
| if (m_image && !m_image->isNull()) { |
| observer->imageChanged(this); |
| } |
| - if (isLoaded() && m_observers.contains(observer) && !m_isSchedulingReload && |
| - !shouldReloadBrokenPlaceholder()) { |
| + if (isLoaded() && m_observers.contains(observer) && |
| + !m_info->schedulingReloadOrShouldReloadBrokenPlaceholder()) { |
| markObserverFinished(observer); |
| observer->imageNotifyFinished(this); |
| } |
| } |
| -void ImageResource::removeObserver(ImageResourceObserver* observer) { |
| +void ImageResourceContent::removeObserver(ImageResourceObserver* observer) { |
| DCHECK(observer); |
| if (m_observers.contains(observer)) |
| @@ -212,7 +129,7 @@ void ImageResource::removeObserver(ImageResourceObserver* observer) { |
| else |
| NOTREACHED(); |
| - didRemoveClientOrObserver(); |
| + m_info->didRemoveClientOrObserver(); |
| } |
| static void priorityFromObserver(const ImageResourceObserver* observer, |
| @@ -224,7 +141,7 @@ static void priorityFromObserver(const ImageResourceObserver* observer, |
| priority.intraPriorityValue += nextPriority.intraPriorityValue; |
| } |
| -ResourcePriority ImageResource::priorityFromObservers() { |
| +ResourcePriority ImageResourceContent::priorityFromObservers() const { |
| ResourcePriority priority; |
| for (auto* observer : m_finishedObservers.asVector()) { |
| @@ -239,100 +156,19 @@ ResourcePriority ImageResource::priorityFromObservers() { |
| return priority; |
| } |
| -void ImageResource::destroyDecodedDataForFailedRevalidation() { |
| - clearImage(); |
| - setDecodedSize(0); |
| -} |
| - |
| -void ImageResource::destroyDecodedDataIfPossible() { |
| +void ImageResourceContent::destroyDecodedData() { |
| if (!m_image) |
| return; |
| CHECK(!errorOccurred()); |
| m_image->destroyDecodedData(); |
| - if (!isPreloaded() && m_isRefetchableDataFromDiskCache) { |
| - UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize", |
| - encodedSize() / 1024); |
| - } |
| } |
| -void ImageResource::doResetAnimation() { |
| +void ImageResourceContent::doResetAnimation() { |
| if (m_image) |
| m_image->resetAnimation(); |
| } |
| -void ImageResource::allClientsAndObserversRemoved() { |
| - if (m_image) { |
| - CHECK(!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(&ImageResource::doResetAnimation, |
| - wrapWeakPersistent(this))); |
| - } else { |
| - m_image->resetAnimation(); |
| - } |
| - } |
| - if (m_multipartParser) |
| - m_multipartParser->cancel(); |
| - Resource::allClientsAndObserversRemoved(); |
| -} |
| - |
| -PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { |
| - if (data()) |
| - return data(); |
| - if (m_image) |
| - return m_image->data(); |
| - return nullptr; |
| -} |
| - |
| -void ImageResource::appendData(const char* data, size_t length) { |
| - v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); |
| - if (m_multipartParser) { |
| - m_multipartParser->appendData(data, length); |
| - } else { |
| - Resource::appendData(data, length); |
| - |
| - // 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 |
| - // images. |
| - if (m_sizeAvailable == Image::SizeUnavailable || |
| - (m_image && m_image->maybeAnimated())) { |
| - updateImage(false); |
| - return; |
| - } |
| - |
| - // For other cases, only update at |kFlushDelaySeconds| intervals. This |
| - // throttles how frequently we update |m_image| and how frequently we |
| - // inform the clients which causes an invalidation of this image. In other |
| - // words, we only invalidate this image every |kFlushDelaySeconds| seconds |
| - // while loading. |
| - if (!m_flushTimer.isActive()) { |
| - double now = WTF::monotonicallyIncreasingTime(); |
| - if (!m_lastFlushTime) |
| - m_lastFlushTime = now; |
| - |
| - DCHECK_LE(m_lastFlushTime, now); |
| - double flushDelay = m_lastFlushTime - now + kFlushDelaySeconds; |
| - if (flushDelay < 0.) |
| - flushDelay = 0.; |
| - m_flushTimer.startOneShot(flushDelay, BLINK_FROM_HERE); |
| - } |
| - } |
| -} |
| - |
| -void ImageResource::flushImageIfNeeded(TimerBase*) { |
| - // We might have already loaded the image fully, in which case we don't need |
| - // to call |updateImage()|. |
| - if (isLoading()) { |
| - m_lastFlushTime = WTF::monotonicallyIncreasingTime(); |
| - updateImage(false); |
| - } |
| -} |
| - |
| -std::pair<blink::Image*, float> ImageResource::brokenImage( |
| +std::pair<blink::Image*, float> ImageResourceContent::brokenImage( |
| float deviceScaleFactor) { |
| if (deviceScaleFactor >= 2) { |
| DEFINE_STATIC_REF(blink::Image, brokenImageHiRes, |
| @@ -345,15 +181,11 @@ std::pair<blink::Image*, float> ImageResource::brokenImage( |
| return std::make_pair(brokenImageLoRes, 1); |
| } |
| -bool ImageResource::willPaintBrokenImage() const { |
| - return errorOccurred(); |
| -} |
| - |
| -blink::Image* ImageResource::getImage() { |
| +blink::Image* ImageResourceContent::getImage() const { |
| if (errorOccurred()) { |
| // Returning the 1x broken image is non-ideal, but we cannot reliably access |
| // the appropriate deviceScaleFactor from here. It is critical that callers |
| - // use ImageResource::brokenImage() when they need the real, |
| + // use ImageResourceContent::brokenImage() when they need the real, |
| // deviceScaleFactor-appropriate broken image icon. |
| return brokenImage(1).first; |
| } |
| @@ -364,21 +196,21 @@ blink::Image* ImageResource::getImage() { |
| return blink::Image::nullImage(); |
| } |
| -bool ImageResource::usesImageContainerSize() const { |
| +bool ImageResourceContent::usesImageContainerSize() const { |
| if (m_image) |
| return m_image->usesContainerSize(); |
| return false; |
| } |
| -bool ImageResource::imageHasRelativeSize() const { |
| +bool ImageResourceContent::imageHasRelativeSize() const { |
| if (m_image) |
| return m_image->hasRelativeSize(); |
| return false; |
| } |
| -LayoutSize ImageResource::imageSize( |
| +LayoutSize ImageResourceContent::imageSize( |
| RespectImageOrientationEnum shouldRespectImageOrientation, |
| float multiplier, |
| SizeType sizeType) { |
| @@ -395,9 +227,9 @@ LayoutSize ImageResource::imageSize( |
| size = LayoutSize(m_image->size()); |
| } |
| - if (sizeType == IntrinsicCorrectedToDPR && m_hasDevicePixelRatioHeaderValue && |
| - m_devicePixelRatioHeaderValue > 0) |
| - multiplier = 1 / m_devicePixelRatioHeaderValue; |
| + if (sizeType == IntrinsicCorrectedToDPR && hasDevicePixelRatioHeaderValue() && |
| + devicePixelRatioHeaderValue() > 0) |
| + multiplier = 1 / devicePixelRatioHeaderValue(); |
| if (multiplier == 1 || m_image->hasRelativeSize()) |
| return size; |
| @@ -411,8 +243,9 @@ LayoutSize ImageResource::imageSize( |
| return size; |
| } |
| -void ImageResource::notifyObservers(NotifyFinishOption notifyingFinishOption, |
| - const IntRect* changeRect) { |
| +void ImageResourceContent::notifyObservers( |
| + NotifyFinishOption notifyingFinishOption, |
| + const IntRect* changeRect) { |
| for (auto* observer : m_finishedObservers.asVector()) { |
| if (m_finishedObservers.contains(observer)) |
| observer->imageChanged(this, changeRect); |
| @@ -421,8 +254,8 @@ void ImageResource::notifyObservers(NotifyFinishOption notifyingFinishOption, |
| if (m_observers.contains(observer)) { |
| observer->imageChanged(this, changeRect); |
| if (notifyingFinishOption == ShouldNotifyFinish && |
| - m_observers.contains(observer) && !m_isSchedulingReload && |
| - !shouldReloadBrokenPlaceholder()) { |
| + m_observers.contains(observer) && |
| + !m_info->schedulingReloadOrShouldReloadBrokenPlaceholder()) { |
| markObserverFinished(observer); |
| observer->imageNotifyFinished(this); |
| } |
| @@ -430,25 +263,13 @@ void ImageResource::notifyObservers(NotifyFinishOption notifyingFinishOption, |
| } |
| } |
| -void ImageResource::clear() { |
| - clearImage(); |
| - clearData(); |
| - setEncodedSize(0); |
| +inline PassRefPtr<Image> ImageResourceContent::createImage() { |
|
yhirano
2016/12/08 04:17:58
Is this inline needed? Ditto below.
hiroshige
2016/12/09 22:50:39
Removed.
|
| + if (m_info->response().mimeType() == "image/svg+xml") |
| + return SVGImage::create(this); |
| + return BitmapImage::create(this); |
| } |
| -inline void ImageResource::createImage() { |
| - // Create the image if it doesn't yet exist. |
| - if (m_image) |
| - return; |
| - |
| - if (response().mimeType() == "image/svg+xml") { |
| - m_image = SVGImage::create(this); |
| - } else { |
| - m_image = BitmapImage::create(this); |
| - } |
| -} |
| - |
| -inline void ImageResource::clearImage() { |
| +inline void ImageResourceContent::clearImage() { |
| if (!m_image) |
| return; |
| int64_t length = m_image->data() ? m_image->data()->size() : 0; |
| @@ -461,18 +282,29 @@ inline void ImageResource::clearImage() { |
| m_sizeAvailable = Image::SizeUnavailable; |
| } |
| -void ImageResource::updateImage(bool allDataReceived) { |
| - TRACE_EVENT0("blink", "ImageResource::updateImage"); |
| +void ImageResourceContent::clearImageAndNotifyObservers( |
| + NotifyFinishOption notifyingFinishOption) { |
| + clearImage(); |
| + notifyObservers(notifyingFinishOption); |
| +} |
| + |
| +void ImageResourceContent::updateImage(PassRefPtr<SharedBuffer> data, |
| + ClearImageOption clearImageOption, |
| + bool allDataReceived) { |
| + TRACE_EVENT0("blink", "ImageResourceContent::updateImage"); |
| - if (data()) |
| - createImage(); |
| + if (clearImageOption == ImageResourceContent::ClearExistingImage) { |
| + clearImage(); |
| + } |
| // 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). |
| - if (data()) { |
| + if (data) { |
| + if (!m_image) |
| + m_image = createImage(); |
| DCHECK(m_image); |
| - m_sizeAvailable = m_image->setData(data(), allDataReceived); |
| + m_sizeAvailable = m_image->setData(std::move(data), allDataReceived); |
| } |
| // Go ahead and tell our observers to try to draw if we have either received |
| @@ -481,12 +313,14 @@ void ImageResource::updateImage(bool allDataReceived) { |
| if (m_sizeAvailable == Image::SizeUnavailable && !allDataReceived) |
| return; |
| - if (m_isPlaceholder && allDataReceived && m_image && !m_image->isNull()) { |
| + if (m_info->isPlaceholder() && allDataReceived && m_image && |
| + !m_image->isNull()) { |
| if (m_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 { |
| @@ -497,14 +331,8 @@ void ImageResource::updateImage(bool allDataReceived) { |
| } |
| if (!m_image || m_image->isNull()) { |
| - size_t size = encodedSize(); |
| - clear(); |
| - if (!errorOccurred()) |
| - setStatus(DecodeError); |
| - if (!allDataReceived && loader()) { |
| - loader()->didFinishLoading(monotonicallyIncreasingTime(), size, size); |
| - } |
| - memoryCache()->remove(this); |
| + clearImage(); |
| + m_info->decodeError(allDataReceived); |
| } |
| // It would be nice to only redraw the decoded band of the image, but with the |
| @@ -512,70 +340,14 @@ void ImageResource::updateImage(bool allDataReceived) { |
| notifyObservers(allDataReceived ? ShouldNotifyFinish : DoNotNotifyFinish); |
| } |
| -void ImageResource::updateImageAndClearBuffer() { |
| - clearImage(); |
| - updateImage(true); |
| - clearData(); |
| -} |
| - |
| -void ImageResource::finish(double loadFinishTime) { |
| - if (m_multipartParser) { |
| - m_multipartParser->finish(); |
| - if (data()) |
| - updateImageAndClearBuffer(); |
| - } else { |
| - updateImage(true); |
| - // 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 |
| - // document: |
| - // https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1VsqpxoL7aciY/edit?usp=sharing |
| - clearData(); |
| - } |
| - Resource::finish(loadFinishTime); |
| -} |
| - |
| -void ImageResource::error(const ResourceError& error) { |
| - if (m_multipartParser) |
| - m_multipartParser->cancel(); |
| - clear(); |
| - Resource::error(error); |
| - notifyObservers(ShouldNotifyFinish); |
| -} |
| - |
| -void ImageResource::responseReceived( |
| - const ResourceResponse& response, |
| - std::unique_ptr<WebDataConsumerHandle> handle) { |
| - DCHECK(!handle); |
| - DCHECK(!m_multipartParser); |
| - // If there's no boundary, just handle the request normally. |
| - if (response.isMultipart() && !response.multipartBoundary().isEmpty()) { |
| - m_multipartParser = new MultipartImageResourceParser( |
| - response, response.multipartBoundary(), this); |
| - } |
| - Resource::responseReceived(response, std::move(handle)); |
| - if (RuntimeEnabledFeatures::clientHintsEnabled()) { |
| - m_devicePixelRatioHeaderValue = |
| - this->response() |
| - .httpHeaderField(HTTPNames::Content_DPR) |
| - .toFloat(&m_hasDevicePixelRatioHeaderValue); |
| - if (!m_hasDevicePixelRatioHeaderValue || |
| - m_devicePixelRatioHeaderValue <= 0.0) { |
| - m_devicePixelRatioHeaderValue = 1.0; |
| - m_hasDevicePixelRatioHeaderValue = false; |
| - } |
| - } |
| -} |
| - |
| -void ImageResource::decodedSizeChangedTo(const blink::Image* image, |
| - size_t newSize) { |
| +void ImageResourceContent::decodedSizeChangedTo(const blink::Image* image, |
| + size_t newSize) { |
| if (!image || image != m_image) |
| return; |
| - |
| - setDecodedSize(newSize); |
| + m_info->setDecodedSize(newSize); |
| } |
| -bool ImageResource::shouldPauseAnimation(const blink::Image* image) { |
| +bool ImageResourceContent::shouldPauseAnimation(const blink::Image* image) { |
| if (!image || image != m_image) |
| return false; |
| @@ -592,13 +364,13 @@ bool ImageResource::shouldPauseAnimation(const blink::Image* image) { |
| return true; |
| } |
| -void ImageResource::animationAdvanced(const blink::Image* image) { |
| +void ImageResourceContent::animationAdvanced(const blink::Image* image) { |
| if (!image || image != m_image) |
| return; |
| notifyObservers(DoNotNotifyFinish); |
| } |
| -void ImageResource::updateImageAnimationPolicy() { |
| +void ImageResourceContent::updateImageAnimationPolicy() { |
| if (!m_image) |
| return; |
| @@ -620,103 +392,73 @@ void ImageResource::updateImageAnimationPolicy() { |
| } |
| } |
| -static bool isLoFiImage(const ImageResource& resource) { |
| - if (resource.resourceRequest().loFiState() != WebURLRequest::LoFiOn) |
| - return false; |
| - return !resource.isLoaded() || |
| - resource.response() |
| - .httpHeaderField("chrome-proxy-content-transform") |
| - .contains("empty-image"); |
| +void ImageResourceContent::changedInRect(const blink::Image* image, |
| + const IntRect& rect) { |
| + if (!image || image != m_image) |
| + return; |
| + notifyObservers(DoNotNotifyFinish, &rect); |
| } |
| -void ImageResource::reloadIfLoFiOrPlaceholder( |
| - ResourceFetcher* fetcher, |
| - ReloadCachePolicy reloadCachePolicy) { |
| - if (!m_isPlaceholder && !isLoFiImage(*this)) |
| - return; |
| +bool ImageResourceContent::isAccessAllowed( |
| + SecurityOrigin* securityOrigin) const { |
| + return m_info->isAccessAllowed( |
| + securityOrigin, getImage()->currentFrameHasSingleSecurityOrigin() |
| + ? ImageResourceInfo::HasSingleSecurityOrigin |
| + : ImageResourceInfo::HasMultipleSecurityOrigin); |
| +} |
| - // 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; |
| +void ImageResourceContent::emulateLoadStartedForInspector( |
| + ResourceFetcher* fetcher, |
| + const KURL& url, |
| + const AtomicString& initiatorName) { |
| + m_info->emulateLoadStartedForInspector(fetcher, url, initiatorName); |
| +} |
| - if (reloadCachePolicy == ReloadCachePolicy::BypassCache) |
| - setCachePolicyBypassingCache(); |
| - setLoFiStateOff(); |
| +// TODO(hiroshige): Consider removing the following methods, or stoping |
| +// redirecting to ImageResource. |
| +bool ImageResourceContent::isLoaded() const { |
| + return getStatus() > ResourceStatus::Pending; |
| +} |
| - if (m_isPlaceholder) { |
| - m_isPlaceholder = false; |
| - clearRangeRequestHeader(); |
| - } |
| +bool ImageResourceContent::isLoading() const { |
| + return getStatus() == ResourceStatus::Pending; |
| +} |
| - 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 { |
| - clear(); |
| - notifyObservers(DoNotNotifyFinish); |
| - } |
| +bool ImageResourceContent::errorOccurred() const { |
| + return getStatus() == ResourceStatus::LoadError || |
| + getStatus() == ResourceStatus::DecodeError; |
| +} |
| - setStatus(NotStarted); |
| +bool ImageResourceContent::loadFailedOrCanceled() const { |
| + return getStatus() == ResourceStatus::LoadError; |
| +} |
| - DCHECK(m_isSchedulingReload); |
| - m_isSchedulingReload = false; |
| +ResourceStatus ImageResourceContent::getStatus() const { |
| + return m_info->getStatus(); |
| +} |
| - fetcher->startLoad(this); |
| +const KURL& ImageResourceContent::url() const { |
| + return m_info->url(); |
| } |
| -void ImageResource::changedInRect(const blink::Image* image, |
| - const IntRect& rect) { |
| - if (!image || image != m_image) |
| - return; |
| - notifyObservers(DoNotNotifyFinish, &rect); |
| +bool ImageResourceContent::hasCacheControlNoStoreHeader() const { |
| + return m_info->hasCacheControlNoStoreHeader(); |
| } |
| -void ImageResource::onePartInMultipartReceived( |
| - const ResourceResponse& response) { |
| - DCHECK(m_multipartParser); |
| +float ImageResourceContent::devicePixelRatioHeaderValue() const { |
| + return m_info->devicePixelRatioHeaderValue(); |
| +} |
| - setResponse(response); |
| - if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { |
| - // We have nothing to do because we don't have any data. |
| - m_multipartParsingState = MultipartParsingState::ParsingFirstPart; |
| - return; |
| - } |
| - updateImageAndClearBuffer(); |
| - |
| - if (m_multipartParsingState == MultipartParsingState::ParsingFirstPart) { |
| - m_multipartParsingState = MultipartParsingState::FinishedParsingFirstPart; |
| - // Notify finished when the first part ends. |
| - if (!errorOccurred()) |
| - setStatus(Cached); |
| - // We notify clients and observers of finish in checkNotify() and |
| - // updateImageAndClearBuffer(), respectively, and they will not be |
| - // notified again in Resource::finish()/error(). |
| - checkNotify(); |
| - if (loader()) |
| - loader()->didFinishLoadingFirstPartInMultipart(); |
| - } |
| +bool ImageResourceContent::hasDevicePixelRatioHeaderValue() const { |
| + return m_info->hasDevicePixelRatioHeaderValue(); |
| } |
| -void ImageResource::multipartDataReceived(const char* bytes, size_t size) { |
| - DCHECK(m_multipartParser); |
| - Resource::appendData(bytes, size); |
| +const ResourceResponse& ImageResourceContent::response() const { |
| + return m_info->response(); |
| } |
| -bool ImageResource::isAccessAllowed(SecurityOrigin* securityOrigin) { |
| - if (response().wasFetchedViaServiceWorker()) { |
| - return response().serviceWorkerResponseType() != |
| - WebServiceWorkerResponseTypeOpaque; |
| - } |
| - if (!getImage()->currentFrameHasSingleSecurityOrigin()) |
| - return false; |
| - if (passesAccessControlCheck(securityOrigin)) |
| - return true; |
| - return !securityOrigin->taintsCanvas(response().url()); |
| +const ResourceError& ImageResourceContent::resourceError() const { |
| + return m_info->resourceError(); |
| } |
| } // namespace blink |