| 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 861ca24e5593d5c717342eeda851d9ba20e75a74..3fa3f1263a5c0a0794e43644714ca0df76b6df2c 100644
|
| --- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
|
| +++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
|
| @@ -36,6 +36,7 @@
|
| #include "platform/SharedBuffer.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"
|
| @@ -67,9 +68,6 @@ class ImageResource::ImageResourceInfoImpl final
|
|
|
| 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;
|
| }
|
| @@ -86,9 +84,8 @@ class ImageResource::ImageResourceInfoImpl final
|
| bool isCacheValidator() const override {
|
| return m_resource->isCacheValidator();
|
| }
|
| - bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override {
|
| - return m_resource->m_isSchedulingReload ||
|
| - m_resource->shouldReloadBrokenPlaceholder();
|
| + bool shouldReloadBrokenPlaceholder() const override {
|
| + return m_resource->shouldReloadBrokenPlaceholder();
|
| }
|
| bool isAccessAllowed(
|
| SecurityOrigin* securityOrigin,
|
| @@ -102,6 +99,7 @@ class ImageResource::ImageResourceInfoImpl final
|
| const ResourceError& resourceError() const override {
|
| return m_resource->resourceError();
|
| }
|
| + ImageResource* resourceForTest() const override { return m_resource; }
|
|
|
| void decodeError(bool allDataReceived) override {
|
| m_resource->decodeError(allDataReceived);
|
| @@ -123,6 +121,9 @@ class ImageResource::ImageResourceInfoImpl final
|
| WebURLRequest::RequestContextImage,
|
| initiatorName);
|
| }
|
| + bool reloadIfLoFiOrPlaceholder(ResourceFetcher* fetcherForReload) override {
|
| + return m_resource->reloadIfLoFiOrPlaceholder(fetcherForReload);
|
| + }
|
|
|
| Member<ImageResource> m_resource;
|
| };
|
| @@ -173,8 +174,10 @@ ImageResource* ImageResource::fetch(FetchRequest& request,
|
| // 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);
|
| + ImageResource* reloadingResource = resource->reloadIfLoFiOrPlaceholder(
|
| + fetcher, ReloadCachePolicy::UseExistingPolicy);
|
| + if (reloadingResource)
|
| + resource = reloadingResource;
|
| }
|
| return resource;
|
| }
|
| @@ -192,7 +195,6 @@ ImageResource::ImageResource(const ResourceRequest& resourceRequest,
|
| m_content(content),
|
| m_devicePixelRatioHeaderValue(1.0),
|
| m_hasDevicePixelRatioHeaderValue(false),
|
| - m_isSchedulingReload(false),
|
| m_isPlaceholder(isPlaceholder),
|
| m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
|
| DCHECK(getContent());
|
| @@ -211,28 +213,14 @@ DEFINE_TRACE(ImageResource) {
|
| 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();
|
| + return Resource::hasClientsOrObservers() ||
|
| + (getContent() && 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;
|
| -
|
| + (getContent() && getContent()->hasImage()));
|
| Resource::didAddClient(client);
|
| }
|
|
|
| @@ -242,6 +230,8 @@ void ImageResource::destroyDecodedDataForFailedRevalidation() {
|
| }
|
|
|
| void ImageResource::destroyDecodedDataIfPossible() {
|
| + if (!getContent())
|
| + return;
|
| getContent()->destroyDecodedData();
|
| if (getContent()->hasImage() && !isPreloaded() &&
|
| getContent()->isRefetchableDataFromDiskCache()) {
|
| @@ -251,16 +241,18 @@ void ImageResource::destroyDecodedDataIfPossible() {
|
| }
|
|
|
| void ImageResource::allClientsAndObserversRemoved() {
|
| - CHECK(!getContent()->hasImage() || !errorOccurred());
|
| + CHECK(!getContent() || !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 (getContent()) {
|
| + 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();
|
| @@ -270,7 +262,7 @@ void ImageResource::allClientsAndObserversRemoved() {
|
| PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const {
|
| if (data())
|
| return data();
|
| - if (getContent()->hasImage())
|
| + if (getContent() && getContent()->hasImage())
|
| return getContent()->getImage()->data();
|
| return nullptr;
|
| }
|
| @@ -282,6 +274,9 @@ void ImageResource::appendData(const char* data, size_t length) {
|
| } else {
|
| Resource::appendData(data, length);
|
|
|
| + if (!getContent())
|
| + return;
|
| +
|
| // 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
|
| @@ -346,13 +341,15 @@ void ImageResource::updateImageAndClearBuffer() {
|
| clearData();
|
| }
|
|
|
| -void ImageResource::finish(double loadFinishTime) {
|
| +void ImageResource::finish(double loadFinishTime,
|
| + ResourceFetcher* fetcherForReload) {
|
| if (m_multipartParser) {
|
| m_multipartParser->finish();
|
| if (data())
|
| updateImageAndClearBuffer();
|
| } else {
|
| - updateImage(data(), ImageResourceContent::KeepExistingImage, true);
|
| + updateImage(data(), ImageResourceContent::KeepExistingImage, true,
|
| + fetcherForReload);
|
| // 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
|
| @@ -360,15 +357,17 @@ void ImageResource::finish(double loadFinishTime) {
|
| // https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1VsqpxoL7aciY/edit?usp=sharing
|
| clearData();
|
| }
|
| - Resource::finish(loadFinishTime);
|
| + Resource::finish(loadFinishTime, fetcherForReload);
|
| }
|
|
|
| -void ImageResource::error(const ResourceError& error) {
|
| +void ImageResource::error(const ResourceError& error,
|
| + ResourceFetcher* fetcherForReload) {
|
| if (m_multipartParser)
|
| m_multipartParser->cancel();
|
| clearData();
|
| - Resource::error(error);
|
| - updateImage(nullptr, ImageResourceContent::ClearExistingImage, true);
|
| + Resource::error(error, fetcherForReload);
|
| + updateImage(nullptr, ImageResourceContent::ClearExistingImage, true,
|
| + fetcherForReload);
|
| }
|
|
|
| void ImageResource::responseReceived(
|
| @@ -404,45 +403,43 @@ static bool isLoFiImage(const ImageResource& resource) {
|
| .contains("empty-image");
|
| }
|
|
|
| -void ImageResource::reloadIfLoFiOrPlaceholder(
|
| +void ImageResource::detachContent() {
|
| + bool hasObservers = getContent() && getContent()->hasObservers();
|
| +
|
| + clearData();
|
| + memoryCache()->remove(this);
|
| +
|
| + if (hasObservers)
|
| + didRemoveClientOrObserver();
|
| +}
|
| +
|
| +ImageResource* ImageResource::reloadIfLoFiOrPlaceholder(
|
| ResourceFetcher* fetcher,
|
| ReloadCachePolicy reloadCachePolicy) {
|
| + if (!fetcher)
|
| + return nullptr;
|
| 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;
|
| + return nullptr;
|
| + ImageResourceContent* content = getContent();
|
| + if (!content)
|
| + return nullptr;
|
|
|
| + // Creates request/options for new ImageResource for reloading.
|
| + ResourceRequest reloadingRequest = resourceRequest();
|
| + ResourceLoaderOptions reloadingOptions = options();
|
| if (reloadCachePolicy == ReloadCachePolicy::BypassCache)
|
| - 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);
|
| - updateImage(nullptr, ImageResourceContent::ClearExistingImage, false);
|
| - }
|
| -
|
| - setStatus(NotStarted);
|
| -
|
| - DCHECK(m_isSchedulingReload);
|
| - m_isSchedulingReload = false;
|
| -
|
| - fetcher->startLoad(this);
|
| + reloadingRequest.setCachePolicy(WebCachePolicy::BypassingCache);
|
| + reloadingRequest.setLoFiState(WebURLRequest::LoFiOff);
|
| + if (m_isPlaceholder)
|
| + reloadingRequest.clearHTTPHeaderField("range");
|
| +
|
| + detachContent();
|
| + // Do not touch |this| after this point.
|
| +
|
| + ImageResource* reloadingResource =
|
| + new ImageResource(reloadingRequest, reloadingOptions, content, false);
|
| + fetcher->startLoad(reloadingResource);
|
| + return reloadingResource;
|
| }
|
|
|
| void ImageResource::onePartInMultipartReceived(
|
| @@ -496,18 +493,24 @@ ImageResourceContent* ImageResource::getContent() const {
|
| }
|
|
|
| ResourcePriority ImageResource::priorityFromObservers() {
|
| + if (!getContent())
|
| + return ResourcePriority();
|
| +
|
| return getContent()->priorityFromObservers();
|
| }
|
|
|
| void ImageResource::updateImage(
|
| PassRefPtr<SharedBuffer> sharedBuffer,
|
| ImageResourceContent::ClearImageOption clearImageOption,
|
| - bool allDataReceived) {
|
| + bool allDataReceived,
|
| + ResourceFetcher* fetcherForReload) {
|
| if (!m_isUpdateImageCalled)
|
| clearImageOption = ImageResourceContent::ClearExistingImage;
|
| m_isUpdateImageCalled = true;
|
| - getContent()->updateImage(std::move(sharedBuffer), clearImageOption,
|
| - allDataReceived);
|
| + if (getContent()) {
|
| + getContent()->updateImage(std::move(sharedBuffer), clearImageOption,
|
| + allDataReceived, fetcherForReload);
|
| + }
|
| }
|
|
|
| } // namespace blink
|
|
|