| 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
|
| deleted file mode 100644
|
| index 7c09e138ebd5b153a77c400d264775c5d0a7d68c..0000000000000000000000000000000000000000
|
| --- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
|
| +++ /dev/null
|
| @@ -1,511 +0,0 @@
|
| -/*
|
| - 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.
|
| -*/
|
| -
|
| -#include "core/fetch/ImageResource.h"
|
| -
|
| -#include "core/fetch/ImageResourceContent.h"
|
| -#include "core/fetch/ImageResourceInfo.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 "platform/Histogram.h"
|
| -#include "platform/RuntimeEnabledFeatures.h"
|
| -#include "platform/SharedBuffer.h"
|
| -#include "platform/tracing/TraceEvent.h"
|
| -#include "public/platform/Platform.h"
|
| -#include "wtf/CurrentTime.h"
|
| -#include "wtf/StdLibExtras.h"
|
| -#include <memory>
|
| -#include <v8.h>
|
| -
|
| -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::ImageResourceInfoImpl final
|
| - : public GarbageCollectedFinalized<ImageResourceInfoImpl>,
|
| - public ImageResourceInfo {
|
| - USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl);
|
| -
|
| - public:
|
| - ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) {
|
| - DCHECK(m_resource);
|
| - }
|
| - DEFINE_INLINE_VIRTUAL_TRACE() {
|
| - visitor->trace(m_resource);
|
| - ImageResourceInfo::trace(visitor);
|
| - }
|
| -
|
| - 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;
|
| - }
|
| - float devicePixelRatioHeaderValue() const override {
|
| - return m_resource->m_devicePixelRatioHeaderValue;
|
| - }
|
| - const ResourceResponse& response() const override {
|
| - return m_resource->response();
|
| - }
|
| - Resource::Status getStatus() const override {
|
| - return m_resource->getStatus();
|
| - }
|
| - bool isPlaceholder() const override { return m_resource->isPlaceholder(); }
|
| - bool isCacheValidator() const override {
|
| - return m_resource->isCacheValidator();
|
| - }
|
| - bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override {
|
| - return m_resource->m_isSchedulingReload ||
|
| - m_resource->shouldReloadBrokenPlaceholder();
|
| - }
|
| - bool isAccessAllowed(
|
| - SecurityOrigin* securityOrigin,
|
| - DoesCurrentFrameHaveSingleSecurityOrigin
|
| - doesCurrentFrameHasSingleSecurityOrigin) const override {
|
| - return m_resource->isAccessAllowed(securityOrigin,
|
| - doesCurrentFrameHasSingleSecurityOrigin);
|
| - }
|
| - bool hasCacheControlNoStoreHeader() const override {
|
| - return m_resource->hasCacheControlNoStoreHeader();
|
| - }
|
| - const ResourceError& resourceError() const override {
|
| - return m_resource->resourceError();
|
| - }
|
| -
|
| - void decodeError(bool allDataReceived) override {
|
| - m_resource->decodeError(allDataReceived);
|
| - }
|
| - void setDecodedSize(size_t size) override {
|
| - m_resource->setDecodedSize(size);
|
| - }
|
| - void willAddClientOrObserver() override {
|
| - m_resource->willAddClientOrObserver(Resource::MarkAsReferenced);
|
| - }
|
| - void didRemoveClientOrObserver() override {
|
| - m_resource->didRemoveClientOrObserver();
|
| - }
|
| - void emulateLoadStartedForInspector(
|
| - ResourceFetcher* fetcher,
|
| - const KURL& url,
|
| - const AtomicString& initiatorName) override {
|
| - fetcher->emulateLoadStartedForInspector(m_resource.get(), url,
|
| - WebURLRequest::RequestContextImage,
|
| - initiatorName);
|
| - }
|
| -
|
| - const Member<ImageResource> m_resource;
|
| -};
|
| -
|
| -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, ImageResourceContent::create(),
|
| - 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() ==
|
| - WebURLRequest::RequestContextUnspecified) {
|
| - request.mutableResourceRequest().setRequestContext(
|
| - WebURLRequest::RequestContextImage);
|
| - }
|
| - if (fetcher->context().pageDismissalEventBeingDispatched()) {
|
| - KURL requestURL = request.resourceRequest().url();
|
| - if (requestURL.isValid()) {
|
| - ResourceRequestBlockedReason blockReason = fetcher->context().canRequest(
|
| - Resource::Image, request.resourceRequest(), requestURL,
|
| - request.options(), request.forPreload(),
|
| - request.getOriginRestriction());
|
| - if (blockReason == ResourceRequestBlockedReason::None)
|
| - fetcher->context().sendImagePing(requestURL);
|
| - }
|
| - return nullptr;
|
| - }
|
| -
|
| - 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->reloadIfLoFiOrPlaceholderImage(
|
| - fetcher, kReloadAlwaysWithExistingCachePolicy);
|
| - }
|
| - return resource;
|
| -}
|
| -
|
| -ImageResource* ImageResource::create(const ResourceRequest& request) {
|
| - return new ImageResource(request, ResourceLoaderOptions(),
|
| - ImageResourceContent::create(), false);
|
| -}
|
| -
|
| -ImageResource::ImageResource(const ResourceRequest& resourceRequest,
|
| - const ResourceLoaderOptions& options,
|
| - ImageResourceContent* content,
|
| - bool isPlaceholder)
|
| - : Resource(resourceRequest, Image, options),
|
| - m_content(content),
|
| - m_devicePixelRatioHeaderValue(1.0),
|
| - m_hasDevicePixelRatioHeaderValue(false),
|
| - m_isSchedulingReload(false),
|
| - m_isPlaceholder(isPlaceholder),
|
| - m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
|
| - DCHECK(getContent());
|
| - RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this;
|
| - getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this));
|
| -}
|
| -
|
| -ImageResource::~ImageResource() {
|
| - RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this;
|
| -}
|
| -
|
| -DEFINE_TRACE(ImageResource) {
|
| - visitor->trace(m_multipartParser);
|
| - visitor->trace(m_content);
|
| - Resource::trace(visitor);
|
| - 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();
|
| -}
|
| -
|
| -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;
|
| -
|
| - Resource::didAddClient(client);
|
| -}
|
| -
|
| -void ImageResource::destroyDecodedDataForFailedRevalidation() {
|
| - getContent()->clearImage();
|
| - setDecodedSize(0);
|
| -}
|
| -
|
| -void ImageResource::destroyDecodedDataIfPossible() {
|
| - getContent()->destroyDecodedData();
|
| - if (getContent()->hasImage() && !isPreloaded() &&
|
| - getContent()->isRefetchableDataFromDiskCache()) {
|
| - UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize",
|
| - encodedSize() / 1024);
|
| - }
|
| -}
|
| -
|
| -void ImageResource::allClientsAndObserversRemoved() {
|
| - CHECK(!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 (m_multipartParser)
|
| - m_multipartParser->cancel();
|
| - Resource::allClientsAndObserversRemoved();
|
| -}
|
| -
|
| -PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const {
|
| - if (data())
|
| - return data();
|
| - return getContent()->resourceBuffer();
|
| -}
|
| -
|
| -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);
|
| -
|
| - // Update the image immediately if needed.
|
| - if (getContent()->shouldUpdateImageImmediately()) {
|
| - getContent()->updateImage(this->data(),
|
| - ImageResourceContent::KeepExistingImage, 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();
|
| - getContent()->updateImage(this->data(),
|
| - ImageResourceContent::KeepExistingImage, false);
|
| - }
|
| -}
|
| -
|
| -bool ImageResource::willPaintBrokenImage() const {
|
| - return errorOccurred();
|
| -}
|
| -
|
| -void ImageResource::decodeError(bool allDataReceived) {
|
| - size_t size = encodedSize();
|
| -
|
| - clearData();
|
| - setEncodedSize(0);
|
| - if (!errorOccurred())
|
| - setStatus(DecodeError);
|
| -
|
| - if (!allDataReceived && loader()) {
|
| - // TODO(hiroshige): Do not call didFinishLoading() directly.
|
| - loader()->didFinishLoading(monotonicallyIncreasingTime(), size, size);
|
| - }
|
| -
|
| - memoryCache()->remove(this);
|
| -}
|
| -
|
| -void ImageResource::updateImageAndClearBuffer() {
|
| - getContent()->updateImage(data(), ImageResourceContent::ClearExistingImage,
|
| - true);
|
| - clearData();
|
| -}
|
| -
|
| -void ImageResource::finish(double loadFinishTime) {
|
| - if (m_multipartParser) {
|
| - m_multipartParser->finish();
|
| - if (data())
|
| - updateImageAndClearBuffer();
|
| - } else {
|
| - getContent()->updateImage(data(), ImageResourceContent::KeepExistingImage,
|
| - 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();
|
| - // TODO(hiroshige): Move setEncodedSize() call to Resource::error() if it
|
| - // is really needed, or remove it otherwise.
|
| - setEncodedSize(0);
|
| - Resource::error(error);
|
| - getContent()->clearImageAndNotifyObservers(
|
| - ImageResourceContent::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;
|
| - }
|
| - }
|
| -}
|
| -
|
| -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 ImageResource::reloadIfLoFiOrPlaceholderImage(
|
| - ResourceFetcher* fetcher,
|
| - ReloadLoFiOrPlaceholderPolicy policy) {
|
| - if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder())
|
| - return;
|
| -
|
| - 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;
|
| -
|
| - if (policy != kReloadAlwaysWithExistingCachePolicy)
|
| - 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);
|
| - getContent()->clearImageAndNotifyObservers(
|
| - ImageResourceContent::DoNotNotifyFinish);
|
| - }
|
| -
|
| - setStatus(NotStarted);
|
| -
|
| - DCHECK(m_isSchedulingReload);
|
| - m_isSchedulingReload = false;
|
| -
|
| - fetcher->startLoad(this);
|
| -}
|
| -
|
| -void ImageResource::onePartInMultipartReceived(
|
| - const ResourceResponse& response) {
|
| - DCHECK(m_multipartParser);
|
| -
|
| - 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();
|
| - }
|
| -}
|
| -
|
| -void ImageResource::multipartDataReceived(const char* bytes, size_t size) {
|
| - DCHECK(m_multipartParser);
|
| - Resource::appendData(bytes, size);
|
| -}
|
| -
|
| -bool ImageResource::isAccessAllowed(
|
| - SecurityOrigin* securityOrigin,
|
| - ImageResourceInfo::DoesCurrentFrameHaveSingleSecurityOrigin
|
| - doesCurrentFrameHasSingleSecurityOrigin) const {
|
| - if (response().wasFetchedViaServiceWorker()) {
|
| - return response().serviceWorkerResponseType() !=
|
| - WebServiceWorkerResponseTypeOpaque;
|
| - }
|
| - if (doesCurrentFrameHasSingleSecurityOrigin !=
|
| - ImageResourceInfo::HasSingleSecurityOrigin)
|
| - return false;
|
| - if (passesAccessControlCheck(securityOrigin))
|
| - return true;
|
| - return !securityOrigin->taintsCanvas(response().url());
|
| -}
|
| -
|
| -ImageResourceContent* ImageResource::getContent() {
|
| - return m_content;
|
| -}
|
| -
|
| -const ImageResourceContent* ImageResource::getContent() const {
|
| - return m_content;
|
| -}
|
| -
|
| -ResourcePriority ImageResource::priorityFromObservers() {
|
| - return getContent()->priorityFromObservers();
|
| -}
|
| -
|
| -} // namespace blink
|
|
|