Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/WebKit/Source/core/loader/resource/ImageResource.cpp

Issue 2527353002: Phase II Step 3: Reload LoFi/placeholder images via new ImageResource
Patch Set: reloadLoFiImages test Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
7 7
8 This library is free software; you can redistribute it and/or 8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 License as published by the Free Software Foundation; either
(...skipping 17 matching lines...) Expand all
28 #include "core/fetch/ResourceFetcher.h" 28 #include "core/fetch/ResourceFetcher.h"
29 #include "core/fetch/ResourceLoader.h" 29 #include "core/fetch/ResourceLoader.h"
30 #include "core/fetch/ResourceLoadingLog.h" 30 #include "core/fetch/ResourceLoadingLog.h"
31 #include "core/loader/resource/ImageResourceContent.h" 31 #include "core/loader/resource/ImageResourceContent.h"
32 #include "core/loader/resource/ImageResourceInfo.h" 32 #include "core/loader/resource/ImageResourceInfo.h"
33 #include "platform/Histogram.h" 33 #include "platform/Histogram.h"
34 #include "platform/RuntimeEnabledFeatures.h" 34 #include "platform/RuntimeEnabledFeatures.h"
35 #include "platform/SharedBuffer.h" 35 #include "platform/SharedBuffer.h"
36 #include "platform/tracing/TraceEvent.h" 36 #include "platform/tracing/TraceEvent.h"
37 #include "public/platform/Platform.h" 37 #include "public/platform/Platform.h"
38 #include "public/platform/WebCachePolicy.h"
38 #include "wtf/CurrentTime.h" 39 #include "wtf/CurrentTime.h"
39 #include "wtf/StdLibExtras.h" 40 #include "wtf/StdLibExtras.h"
40 #include <memory> 41 #include <memory>
41 #include <v8.h> 42 #include <v8.h>
42 43
43 namespace blink { 44 namespace blink {
44 namespace { 45 namespace {
45 // The amount of time to wait before informing the clients that the image has 46 // The amount of time to wait before informing the clients that the image has
46 // been updated (in seconds). This effectively throttles invalidations that 47 // been updated (in seconds). This effectively throttles invalidations that
47 // result from new data arriving for this image. 48 // result from new data arriving for this image.
48 constexpr double kFlushDelaySeconds = 1.; 49 constexpr double kFlushDelaySeconds = 1.;
49 } // namespace 50 } // namespace
50 51
51 class ImageResource::ImageResourceInfoImpl final 52 class ImageResource::ImageResourceInfoImpl final
52 : public GarbageCollectedFinalized<ImageResourceInfoImpl>, 53 : public GarbageCollectedFinalized<ImageResourceInfoImpl>,
53 public ImageResourceInfo { 54 public ImageResourceInfo {
54 USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl); 55 USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl);
55 56
56 public: 57 public:
57 ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) { 58 ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) {
58 DCHECK(m_resource); 59 DCHECK(m_resource);
59 } 60 }
60 DEFINE_INLINE_VIRTUAL_TRACE() { 61 DEFINE_INLINE_VIRTUAL_TRACE() {
61 visitor->trace(m_resource); 62 visitor->trace(m_resource);
62 ImageResourceInfo::trace(visitor); 63 ImageResourceInfo::trace(visitor);
63 } 64 }
64 65
65 private: 66 private:
66 const KURL& url() const override { return m_resource->url(); } 67 const KURL& url() const override { return m_resource->url(); }
67 bool isSchedulingReload() const override {
68 return m_resource->m_isSchedulingReload;
69 }
70 bool hasDevicePixelRatioHeaderValue() const override { 68 bool hasDevicePixelRatioHeaderValue() const override {
71 return m_resource->m_hasDevicePixelRatioHeaderValue; 69 return m_resource->m_hasDevicePixelRatioHeaderValue;
72 } 70 }
73 float devicePixelRatioHeaderValue() const override { 71 float devicePixelRatioHeaderValue() const override {
74 return m_resource->m_devicePixelRatioHeaderValue; 72 return m_resource->m_devicePixelRatioHeaderValue;
75 } 73 }
76 const ResourceResponse& response() const override { 74 const ResourceResponse& response() const override {
77 return m_resource->response(); 75 return m_resource->response();
78 } 76 }
79 Resource::Status getStatus() const override { 77 Resource::Status getStatus() const override {
80 return m_resource->getStatus(); 78 return m_resource->getStatus();
81 } 79 }
82 bool isPlaceholder() const override { return m_resource->isPlaceholder(); } 80 bool isPlaceholder() const override { return m_resource->isPlaceholder(); }
83 bool isCacheValidator() const override { 81 bool isCacheValidator() const override {
84 return m_resource->isCacheValidator(); 82 return m_resource->isCacheValidator();
85 } 83 }
86 bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override {
87 return m_resource->m_isSchedulingReload ||
88 m_resource->shouldReloadBrokenPlaceholder();
89 }
90 bool isAccessAllowed( 84 bool isAccessAllowed(
91 SecurityOrigin* securityOrigin, 85 SecurityOrigin* securityOrigin,
92 DoesCurrentFrameHaveSingleSecurityOrigin 86 DoesCurrentFrameHaveSingleSecurityOrigin
93 doesCurrentFrameHasSingleSecurityOrigin) const override { 87 doesCurrentFrameHasSingleSecurityOrigin) const override {
94 return m_resource->isAccessAllowed(securityOrigin, 88 return m_resource->isAccessAllowed(securityOrigin,
95 doesCurrentFrameHasSingleSecurityOrigin); 89 doesCurrentFrameHasSingleSecurityOrigin);
96 } 90 }
97 bool hasCacheControlNoStoreHeader() const override { 91 bool hasCacheControlNoStoreHeader() const override {
98 return m_resource->hasCacheControlNoStoreHeader(); 92 return m_resource->hasCacheControlNoStoreHeader();
99 } 93 }
100 const ResourceError& resourceError() const override { 94 const ResourceError& resourceError() const override {
101 return m_resource->resourceError(); 95 return m_resource->resourceError();
102 } 96 }
97 const ImageResource* resourceForTest() const override { return m_resource; }
103 98
104 void decodeError(bool allDataReceived) override { 99 void decodeError(bool allDataReceived) override {
105 m_resource->decodeError(allDataReceived); 100 m_resource->decodeError(allDataReceived);
106 } 101 }
107 void setDecodedSize(size_t size) override { 102 void setDecodedSize(size_t size) override {
108 m_resource->setDecodedSize(size); 103 m_resource->setDecodedSize(size);
109 } 104 }
110 void willAddClientOrObserver() override { 105 void willAddClientOrObserver() override {
111 m_resource->willAddClientOrObserver(Resource::MarkAsReferenced); 106 m_resource->willAddClientOrObserver(Resource::MarkAsReferenced);
112 } 107 }
113 void didRemoveClientOrObserver() override { 108 void didRemoveClientOrObserver() override {
114 m_resource->didRemoveClientOrObserver(); 109 m_resource->didRemoveClientOrObserver();
115 } 110 }
116 void emulateLoadStartedForInspector( 111 void emulateLoadStartedForInspector(
117 ResourceFetcher* fetcher, 112 ResourceFetcher* fetcher,
118 const KURL& url, 113 const KURL& url,
119 const AtomicString& initiatorName) override { 114 const AtomicString& initiatorName) override {
120 fetcher->emulateLoadStartedForInspector(m_resource.get(), url, 115 fetcher->emulateLoadStartedForInspector(m_resource.get(), url,
121 WebURLRequest::RequestContextImage, 116 WebURLRequest::RequestContextImage,
122 initiatorName); 117 initiatorName);
123 } 118 }
119 bool reloadIfLoFiOrPlaceholderIfNeeded(
120 ResourceFetcher* fetcherForReload) override {
121 return m_resource->reloadIfLoFiOrPlaceholderImage(fetcherForReload,
122 kReloadIfNeeded);
123 }
124 124
125 const Member<ImageResource> m_resource; 125 const Member<ImageResource> m_resource;
126 }; 126 };
127 127
128 class ImageResource::ImageResourceFactory : public ResourceFactory { 128 class ImageResource::ImageResourceFactory : public ResourceFactory {
129 STACK_ALLOCATED(); 129 STACK_ALLOCATED();
130 130
131 public: 131 public:
132 ImageResourceFactory(const FetchRequest& fetchRequest) 132 ImageResourceFactory(const FetchRequest& fetchRequest,
133 : ResourceFactory(Resource::Image), m_fetchRequest(&fetchRequest) {} 133 ImageResourceContent* content)
134 : ResourceFactory(Resource::Image),
135 m_fetchRequest(&fetchRequest),
136 m_content(content) {}
134 137
135 Resource* create(const ResourceRequest& request, 138 Resource* create(const ResourceRequest& request,
136 const ResourceLoaderOptions& options, 139 const ResourceLoaderOptions& options,
137 const String&) const override { 140 const String&) const override {
138 return new ImageResource(request, options, ImageResourceContent::create(), 141 return new ImageResource(
139 m_fetchRequest->placeholderImageRequestType() == 142 request, options,
140 FetchRequest::AllowPlaceholder); 143 m_content ? m_content.get() : ImageResourceContent::create(),
144 m_fetchRequest->placeholderImageRequestType() ==
145 FetchRequest::AllowPlaceholder);
141 } 146 }
142 147
143 private: 148 private:
144 // Weak, unowned pointer. Must outlive |this|. 149 // Weak, unowned pointer. Must outlive |this|.
145 const FetchRequest* m_fetchRequest; 150 const FetchRequest* m_fetchRequest;
151 Persistent<ImageResourceContent> m_content;
146 }; 152 };
147 153
148 ImageResource* ImageResource::fetch(FetchRequest& request, 154 ImageResource* ImageResource::fetch(FetchRequest& request,
149 ResourceFetcher* fetcher) { 155 ResourceFetcher* fetcher) {
150 if (request.resourceRequest().requestContext() == 156 if (request.resourceRequest().requestContext() ==
151 WebURLRequest::RequestContextUnspecified) { 157 WebURLRequest::RequestContextUnspecified) {
152 request.mutableResourceRequest().setRequestContext( 158 request.mutableResourceRequest().setRequestContext(
153 WebURLRequest::RequestContextImage); 159 WebURLRequest::RequestContextImage);
154 } 160 }
155 if (fetcher->context().pageDismissalEventBeingDispatched()) { 161 if (fetcher->context().pageDismissalEventBeingDispatched()) {
156 KURL requestURL = request.resourceRequest().url(); 162 KURL requestURL = request.resourceRequest().url();
157 if (requestURL.isValid()) { 163 if (requestURL.isValid()) {
158 ResourceRequestBlockedReason blockReason = fetcher->context().canRequest( 164 ResourceRequestBlockedReason blockReason = fetcher->context().canRequest(
159 Resource::Image, request.resourceRequest(), requestURL, 165 Resource::Image, request.resourceRequest(), requestURL,
160 request.options(), request.forPreload(), 166 request.options(), request.forPreload(),
161 request.getOriginRestriction()); 167 request.getOriginRestriction());
162 if (blockReason == ResourceRequestBlockedReason::None) 168 if (blockReason == ResourceRequestBlockedReason::None)
163 fetcher->context().sendImagePing(requestURL); 169 fetcher->context().sendImagePing(requestURL);
164 } 170 }
165 return nullptr; 171 return nullptr;
166 } 172 }
167 173
168 ImageResource* resource = toImageResource( 174 ImageResource* resource = toImageResource(fetcher->requestResource(
169 fetcher->requestResource(request, ImageResourceFactory(request))); 175 request, ImageResourceFactory(request, nullptr)));
170 if (resource && 176 if (resource &&
171 request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && 177 request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder &&
Nate Chapin 2016/12/28 00:14:57 This also seems like a case where we could have Im
hiroshige 2016/12/28 01:04:21 Sounds good, I created a separate CL: https://code
172 resource->m_isPlaceholder) { 178 resource->m_isPlaceholder) {
173 // If the image is a placeholder, but this fetch doesn't allow a 179 // If the image is a placeholder, but this fetch doesn't allow a
174 // placeholder, then load the original image. Note that the cache is not 180 // placeholder, then load the original image. Note that the cache is not
175 // bypassed here - it should be fine to use a cached copy if possible. 181 // bypassed here - it should be fine to use a cached copy if possible.
176 resource->reloadIfLoFiOrPlaceholderImage( 182 ImageResource* reloadingResource = resource->reloadIfLoFiOrPlaceholderImage(
177 fetcher, kReloadAlwaysWithExistingCachePolicy); 183 fetcher, kReloadAlwaysWithExistingCachePolicy);
184 if (reloadingResource)
185 resource = reloadingResource;
178 } 186 }
179 return resource; 187 return resource;
180 } 188 }
181 189
182 ImageResource* ImageResource::create(const ResourceRequest& request) { 190 ImageResource* ImageResource::create(const ResourceRequest& request) {
183 return new ImageResource(request, ResourceLoaderOptions(), 191 return new ImageResource(request, ResourceLoaderOptions(),
184 ImageResourceContent::create(), false); 192 ImageResourceContent::create(), false);
185 } 193 }
186 194
187 ImageResource::ImageResource(const ResourceRequest& resourceRequest, 195 ImageResource::ImageResource(const ResourceRequest& resourceRequest,
188 const ResourceLoaderOptions& options, 196 const ResourceLoaderOptions& options,
189 ImageResourceContent* content, 197 ImageResourceContent* content,
190 bool isPlaceholder) 198 bool isPlaceholder)
191 : Resource(resourceRequest, Image, options), 199 : Resource(resourceRequest, Image, options),
192 m_content(content), 200 m_content(content),
193 m_devicePixelRatioHeaderValue(1.0), 201 m_devicePixelRatioHeaderValue(1.0),
194 m_hasDevicePixelRatioHeaderValue(false), 202 m_hasDevicePixelRatioHeaderValue(false),
195 m_isSchedulingReload(false),
196 m_isPlaceholder(isPlaceholder), 203 m_isPlaceholder(isPlaceholder),
197 m_flushTimer(this, &ImageResource::flushImageIfNeeded) { 204 m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
198 DCHECK(getContent()); 205 DCHECK(getContent());
199 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; 206 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this;
200 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this)); 207 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this));
201 } 208 }
202 209
203 ImageResource::~ImageResource() { 210 ImageResource::~ImageResource() {
204 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; 211 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this;
205 } 212 }
206 213
207 DEFINE_TRACE(ImageResource) { 214 DEFINE_TRACE(ImageResource) {
208 visitor->trace(m_multipartParser); 215 visitor->trace(m_multipartParser);
209 visitor->trace(m_content); 216 visitor->trace(m_content);
210 Resource::trace(visitor); 217 Resource::trace(visitor);
211 MultipartImageResourceParser::Client::trace(visitor); 218 MultipartImageResourceParser::Client::trace(visitor);
212 } 219 }
213 220
214 void ImageResource::checkNotify() {
215 // Don't notify clients of completion if this ImageResource is
216 // about to be reloaded.
217 if (m_isSchedulingReload || shouldReloadBrokenPlaceholder())
218 return;
219
220 Resource::checkNotify();
221 }
222
223 bool ImageResource::hasClientsOrObservers() const { 221 bool ImageResource::hasClientsOrObservers() const {
224 return Resource::hasClientsOrObservers() || getContent()->hasObservers(); 222 return Resource::hasClientsOrObservers() ||
223 (getContent() && getContent()->hasObservers());
225 } 224 }
226 225
227 void ImageResource::didAddClient(ResourceClient* client) { 226 void ImageResource::didAddClient(ResourceClient* client) {
228 DCHECK((m_multipartParser && isLoading()) || !data() || 227 DCHECK((m_multipartParser && isLoading()) || !data() ||
229 getContent()->hasImage()); 228 (getContent() && getContent()->hasImage()));
230
231 // Don't notify observers and clients of completion if this ImageResource is
232 // about to be reloaded.
233 if (m_isSchedulingReload || shouldReloadBrokenPlaceholder())
234 return;
235
236 Resource::didAddClient(client); 229 Resource::didAddClient(client);
237 } 230 }
238 231
239 void ImageResource::destroyDecodedDataForFailedRevalidation() { 232 void ImageResource::destroyDecodedDataForFailedRevalidation() {
240 // Clears the image, as we must create a new image for the failed 233 // Clears the image, as we must create a new image for the failed
241 // revalidation response. 234 // revalidation response.
242 updateImage(nullptr, ImageResourceContent::ClearAndUpdateImage, false); 235 updateImage(nullptr, ImageResourceContent::ClearAndUpdateImage, false);
243 setDecodedSize(0); 236 setDecodedSize(0);
244 } 237 }
245 238
246 void ImageResource::destroyDecodedDataIfPossible() { 239 void ImageResource::destroyDecodedDataIfPossible() {
240 if (!getContent())
241 return;
247 getContent()->destroyDecodedData(); 242 getContent()->destroyDecodedData();
248 if (getContent()->hasImage() && !isPreloaded() && 243 if (getContent()->hasImage() && !isPreloaded() &&
249 getContent()->isRefetchableDataFromDiskCache()) { 244 getContent()->isRefetchableDataFromDiskCache()) {
250 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize", 245 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize",
251 encodedSize() / 1024); 246 encodedSize() / 1024);
252 } 247 }
253 } 248 }
254 249
255 void ImageResource::allClientsAndObserversRemoved() { 250 void ImageResource::allClientsAndObserversRemoved() {
256 CHECK(!getContent()->hasImage() || !errorOccurred()); 251 CHECK(!getContent() || !getContent()->hasImage() || !errorOccurred());
257 // If possible, delay the resetting until back at the event loop. Doing so 252 // If possible, delay the resetting until back at the event loop. Doing so
258 // after a conservative GC prevents resetAnimation() from upsetting ongoing 253 // after a conservative GC prevents resetAnimation() from upsetting ongoing
259 // animation updates (crbug.com/613709) 254 // animation updates (crbug.com/613709)
260 if (!ThreadHeap::willObjectBeLazilySwept(this)) { 255 if (getContent()) {
261 Platform::current()->currentThread()->getWebTaskRunner()->postTask( 256 if (!ThreadHeap::willObjectBeLazilySwept(this)) {
262 BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, 257 Platform::current()->currentThread()->getWebTaskRunner()->postTask(
263 wrapWeakPersistent(getContent()))); 258 BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation,
264 } else { 259 wrapWeakPersistent(getContent())));
265 getContent()->doResetAnimation(); 260 } else {
261 getContent()->doResetAnimation();
262 }
266 } 263 }
267 if (m_multipartParser) 264 if (m_multipartParser)
268 m_multipartParser->cancel(); 265 m_multipartParser->cancel();
269 Resource::allClientsAndObserversRemoved(); 266 Resource::allClientsAndObserversRemoved();
270 } 267 }
271 268
272 PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { 269 PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const {
273 if (data()) 270 if (data())
274 return data(); 271 return data();
272 if (!getContent())
273 return nullptr;
275 return getContent()->resourceBuffer(); 274 return getContent()->resourceBuffer();
276 } 275 }
277 276
278 void ImageResource::appendData(const char* data, size_t length) { 277 void ImageResource::appendData(const char* data, size_t length) {
279 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); 278 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length);
280 if (m_multipartParser) { 279 if (m_multipartParser) {
281 m_multipartParser->appendData(data, length); 280 m_multipartParser->appendData(data, length);
282 } else { 281 } else {
283 Resource::appendData(data, length); 282 Resource::appendData(data, length);
284 283
284 if (!getContent())
285 return;
286
285 // Update the image immediately if needed. 287 // Update the image immediately if needed.
286 if (getContent()->shouldUpdateImageImmediately()) { 288 if (getContent()->shouldUpdateImageImmediately()) {
287 updateImage(this->data(), ImageResourceContent::UpdateImage, false); 289 updateImage(this->data(), ImageResourceContent::UpdateImage, false);
288 return; 290 return;
289 } 291 }
290 292
291 // For other cases, only update at |kFlushDelaySeconds| intervals. This 293 // For other cases, only update at |kFlushDelaySeconds| intervals. This
292 // throttles how frequently we update |m_image| and how frequently we 294 // throttles how frequently we update |m_image| and how frequently we
293 // inform the clients which causes an invalidation of this image. In other 295 // inform the clients which causes an invalidation of this image. In other
294 // words, we only invalidate this image every |kFlushDelaySeconds| seconds 296 // words, we only invalidate this image every |kFlushDelaySeconds| seconds
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 } 336 }
335 337
336 memoryCache()->remove(this); 338 memoryCache()->remove(this);
337 } 339 }
338 340
339 void ImageResource::updateImageAndClearBuffer() { 341 void ImageResource::updateImageAndClearBuffer() {
340 updateImage(data(), ImageResourceContent::ClearAndUpdateImage, true); 342 updateImage(data(), ImageResourceContent::ClearAndUpdateImage, true);
341 clearData(); 343 clearData();
342 } 344 }
343 345
344 void ImageResource::finish(double loadFinishTime) { 346 void ImageResource::finish(double loadFinishTime,
347 ResourceFetcher* fetcherForReload) {
345 if (m_multipartParser) { 348 if (m_multipartParser) {
346 m_multipartParser->finish(); 349 m_multipartParser->finish();
347 if (data()) 350 if (data())
348 updateImageAndClearBuffer(); 351 updateImageAndClearBuffer();
349 } else { 352 } else {
350 updateImage(data(), ImageResourceContent::UpdateImage, true); 353 updateImage(data(), ImageResourceContent::UpdateImage, true,
354 fetcherForReload);
351 // As encoded image data can be created from m_image (see 355 // As encoded image data can be created from m_image (see
352 // ImageResource::resourceBuffer(), we don't have to keep m_data. Let's 356 // ImageResource::resourceBuffer(), we don't have to keep m_data. Let's
353 // clear this. As for the lifetimes of m_image and m_data, see this 357 // clear this. As for the lifetimes of m_image and m_data, see this
354 // document: 358 // document:
355 // https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1Vsqpxo L7aciY/edit?usp=sharing 359 // https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1Vsqpxo L7aciY/edit?usp=sharing
356 clearData(); 360 clearData();
357 } 361 }
358 Resource::finish(loadFinishTime); 362 Resource::finish(loadFinishTime, fetcherForReload);
359 } 363 }
360 364
361 void ImageResource::error(const ResourceError& error) { 365 void ImageResource::error(const ResourceError& error,
366 ResourceFetcher* fetcherForReload) {
362 if (m_multipartParser) 367 if (m_multipartParser)
363 m_multipartParser->cancel(); 368 m_multipartParser->cancel();
364 // TODO(hiroshige): Move setEncodedSize() call to Resource::error() if it 369 // TODO(hiroshige): Move setEncodedSize() call to Resource::error() if it
365 // is really needed, or remove it otherwise. 370 // is really needed, or remove it otherwise.
366 setEncodedSize(0); 371 setEncodedSize(0);
367 Resource::error(error); 372 Resource::error(error, fetcherForReload);
368 updateImage(nullptr, ImageResourceContent::ClearImageOnly, true); 373 updateImage(nullptr, ImageResourceContent::ClearImageOnly, true,
374 fetcherForReload);
369 } 375 }
370 376
371 void ImageResource::responseReceived( 377 void ImageResource::responseReceived(
372 const ResourceResponse& response, 378 const ResourceResponse& response,
373 std::unique_ptr<WebDataConsumerHandle> handle) { 379 std::unique_ptr<WebDataConsumerHandle> handle) {
374 DCHECK(!handle); 380 DCHECK(!handle);
375 DCHECK(!m_multipartParser); 381 DCHECK(!m_multipartParser);
376 // If there's no boundary, just handle the request normally. 382 // If there's no boundary, just handle the request normally.
377 if (response.isMultipart() && !response.multipartBoundary().isEmpty()) { 383 if (response.isMultipart() && !response.multipartBoundary().isEmpty()) {
378 m_multipartParser = new MultipartImageResourceParser( 384 m_multipartParser = new MultipartImageResourceParser(
379 response, response.multipartBoundary(), this); 385 response, response.multipartBoundary(), this);
380 } 386 }
381 Resource::responseReceived(response, std::move(handle)); 387 Resource::responseReceived(response, std::move(handle));
382 if (RuntimeEnabledFeatures::clientHintsEnabled()) { 388 if (RuntimeEnabledFeatures::clientHintsEnabled()) {
383 m_devicePixelRatioHeaderValue = 389 m_devicePixelRatioHeaderValue =
384 this->response() 390 this->response()
385 .httpHeaderField(HTTPNames::Content_DPR) 391 .httpHeaderField(HTTPNames::Content_DPR)
386 .toFloat(&m_hasDevicePixelRatioHeaderValue); 392 .toFloat(&m_hasDevicePixelRatioHeaderValue);
387 if (!m_hasDevicePixelRatioHeaderValue || 393 if (!m_hasDevicePixelRatioHeaderValue ||
388 m_devicePixelRatioHeaderValue <= 0.0) { 394 m_devicePixelRatioHeaderValue <= 0.0) {
389 m_devicePixelRatioHeaderValue = 1.0; 395 m_devicePixelRatioHeaderValue = 1.0;
390 m_hasDevicePixelRatioHeaderValue = false; 396 m_hasDevicePixelRatioHeaderValue = false;
391 } 397 }
392 } 398 }
393 } 399 }
394 400
401 void ImageResource::detachContent() {
402 bool hasObservers = getContent() && getContent()->hasObservers();
403
404 m_content = nullptr;
405 clearData();
406 memoryCache()->remove(this);
407
408 if (hasObservers)
409 didRemoveClientOrObserver();
410 }
411
395 static bool isLoFiImage(const ImageResource& resource) { 412 static bool isLoFiImage(const ImageResource& resource) {
396 if (resource.resourceRequest().loFiState() != WebURLRequest::LoFiOn) 413 if (resource.resourceRequest().loFiState() != WebURLRequest::LoFiOn)
397 return false; 414 return false;
398 return !resource.isLoaded() || 415 return !resource.isLoaded() ||
399 resource.response() 416 resource.response()
400 .httpHeaderField("chrome-proxy-content-transform") 417 .httpHeaderField("chrome-proxy-content-transform")
401 .contains("empty-image"); 418 .contains("empty-image");
402 } 419 }
403 420
404 void ImageResource::reloadIfLoFiOrPlaceholderImage( 421 ImageResource* ImageResource::reloadIfLoFiOrPlaceholderImage(
405 ResourceFetcher* fetcher, 422 ResourceFetcher* fetcher,
406 ReloadLoFiOrPlaceholderPolicy policy) { 423 ReloadLoFiOrPlaceholderPolicy policy) {
424 if (!fetcher)
425 return nullptr;
407 if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder()) 426 if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder())
408 return; 427 return nullptr;
409 428
410 if (!m_isPlaceholder && !isLoFiImage(*this)) 429 if (!m_isPlaceholder && !isLoFiImage(*this))
411 return; 430 return nullptr;
412 431
413 // Prevent clients and observers from being notified of completion while the 432 ImageResourceContent* content = getContent();
414 // reload is being scheduled, so that e.g. canceling an existing load in 433 if (!content)
415 // progress doesn't cause clients and observers to be notified of completion 434 return nullptr;
416 // prematurely. 435
417 DCHECK(!m_isSchedulingReload); 436 // Creates request/options for new ImageResource for reloading.
418 m_isSchedulingReload = true; 437 ResourceRequest reloadingRequest = resourceRequest();
438 ResourceLoaderOptions reloadingOptions = options();
419 439
420 if (policy != kReloadAlwaysWithExistingCachePolicy) 440 if (policy != kReloadAlwaysWithExistingCachePolicy)
421 setCachePolicyBypassingCache(); 441 reloadingRequest.setCachePolicy(WebCachePolicy::BypassingCache);
422 setLoFiStateOff(); 442 reloadingRequest.setLoFiState(WebURLRequest::LoFiOff);
443 if (m_isPlaceholder)
444 reloadingRequest.clearHTTPHeaderField("range");
423 445
424 if (m_isPlaceholder) { 446 detachContent();
425 m_isPlaceholder = false; 447 // Do not touch |this| after this point.
426 clearRangeRequestHeader();
427 }
428 448
429 if (isLoading()) { 449 FetchRequest fetchRequest(
430 loader()->cancel(); 450 reloadingRequest, reloadingOptions.initiatorInfo.name, reloadingOptions);
431 // Canceling the loader causes error() to be called, which in turn calls 451 DCHECK_EQ(FetchRequest::DisallowPlaceholder,
432 // clear() and notifyObservers(), so there's no need to call these again 452 fetchRequest.placeholderImageRequestType());
433 // here. 453 fetchRequest.setEnforceNewResource();
434 } else {
435 clearData();
436 setEncodedSize(0);
437 updateImage(nullptr, ImageResourceContent::ClearImageOnly, false);
438 }
439 454
440 setStatus(NotStarted); 455 ImageResource* reloadingResource = toImageResource(fetcher->requestResource(
441 456 fetchRequest, ImageResourceFactory(fetchRequest, content)));
442 DCHECK(m_isSchedulingReload); 457 DCHECK(!reloadingResource || content == reloadingResource->getContent());
443 m_isSchedulingReload = false; 458 return reloadingResource;
444
445 fetcher->startLoad(this);
446 } 459 }
447 460
448 void ImageResource::onePartInMultipartReceived( 461 void ImageResource::onePartInMultipartReceived(
449 const ResourceResponse& response) { 462 const ResourceResponse& response) {
450 DCHECK(m_multipartParser); 463 DCHECK(m_multipartParser);
451 464
452 setResponse(response); 465 setResponse(response);
453 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { 466 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) {
454 // We have nothing to do because we don't have any data. 467 // We have nothing to do because we don't have any data.
455 m_multipartParsingState = MultipartParsingState::ParsingFirstPart; 468 m_multipartParsingState = MultipartParsingState::ParsingFirstPart;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 510
498 ImageResourceContent* ImageResource::getContent() { 511 ImageResourceContent* ImageResource::getContent() {
499 return m_content; 512 return m_content;
500 } 513 }
501 514
502 const ImageResourceContent* ImageResource::getContent() const { 515 const ImageResourceContent* ImageResource::getContent() const {
503 return m_content; 516 return m_content;
504 } 517 }
505 518
506 ResourcePriority ImageResource::priorityFromObservers() { 519 ResourcePriority ImageResource::priorityFromObservers() {
520 if (!getContent())
521 return ResourcePriority();
507 return getContent()->priorityFromObservers(); 522 return getContent()->priorityFromObservers();
508 } 523 }
509 524
510 void ImageResource::updateImage( 525 void ImageResource::updateImage(
511 PassRefPtr<SharedBuffer> sharedBuffer, 526 PassRefPtr<SharedBuffer> sharedBuffer,
512 ImageResourceContent::UpdateImageOption updateImageOption, 527 ImageResourceContent::UpdateImageOption updateImageOption,
513 bool allDataReceived) { 528 bool allDataReceived,
529 ResourceFetcher* fetcherForReload) {
530 if (!getContent())
531 return;
514 if (!m_isUpdateImageCalled && 532 if (!m_isUpdateImageCalled &&
515 updateImageOption == ImageResourceContent::UpdateImage) 533 updateImageOption == ImageResourceContent::UpdateImage)
516 updateImageOption = ImageResourceContent::ClearAndUpdateImage; 534 updateImageOption = ImageResourceContent::ClearAndUpdateImage;
517 m_isUpdateImageCalled = true; 535 m_isUpdateImageCalled = true;
518 getContent()->updateImage(std::move(sharedBuffer), updateImageOption, 536 getContent()->updateImage(std::move(sharedBuffer), updateImageOption,
519 allDataReceived); 537 allDataReceived, fetcherForReload);
520 } 538 }
521 539
522 } // namespace blink 540 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698