OLD | NEW |
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 23 matching lines...) Expand all Loading... |
34 #include "platform/SharedBuffer.h" | 34 #include "platform/SharedBuffer.h" |
35 #include "platform/instrumentation/tracing/TraceEvent.h" | 35 #include "platform/instrumentation/tracing/TraceEvent.h" |
36 #include "platform/loader/fetch/MemoryCache.h" | 36 #include "platform/loader/fetch/MemoryCache.h" |
37 #include "platform/loader/fetch/ResourceClient.h" | 37 #include "platform/loader/fetch/ResourceClient.h" |
38 #include "platform/loader/fetch/ResourceFetcher.h" | 38 #include "platform/loader/fetch/ResourceFetcher.h" |
39 #include "platform/loader/fetch/ResourceLoader.h" | 39 #include "platform/loader/fetch/ResourceLoader.h" |
40 #include "platform/loader/fetch/ResourceLoadingLog.h" | 40 #include "platform/loader/fetch/ResourceLoadingLog.h" |
41 #include "platform/network/HTTPParsers.h" | 41 #include "platform/network/HTTPParsers.h" |
42 #include "platform/weborigin/SecurityViolationReportingPolicy.h" | 42 #include "platform/weborigin/SecurityViolationReportingPolicy.h" |
43 #include "public/platform/Platform.h" | 43 #include "public/platform/Platform.h" |
| 44 #include "public/platform/WebCachePolicy.h" |
44 #include "v8/include/v8.h" | 45 #include "v8/include/v8.h" |
45 #include "wtf/CurrentTime.h" | 46 #include "wtf/CurrentTime.h" |
46 #include "wtf/StdLibExtras.h" | 47 #include "wtf/StdLibExtras.h" |
47 | 48 |
48 namespace blink { | 49 namespace blink { |
49 namespace { | 50 namespace { |
50 // The amount of time to wait before informing the clients that the image has | 51 // The amount of time to wait before informing the clients that the image has |
51 // been updated (in seconds). This effectively throttles invalidations that | 52 // been updated (in seconds). This effectively throttles invalidations that |
52 // result from new data arriving for this image. | 53 // result from new data arriving for this image. |
53 constexpr double kFlushDelaySeconds = 1.; | 54 constexpr double kFlushDelaySeconds = 1.; |
54 } // namespace | 55 } // namespace |
55 | 56 |
56 class ImageResource::ImageResourceInfoImpl final | 57 class ImageResource::ImageResourceInfoImpl final |
57 : public GarbageCollectedFinalized<ImageResourceInfoImpl>, | 58 : public GarbageCollectedFinalized<ImageResourceInfoImpl>, |
58 public ImageResourceInfo { | 59 public ImageResourceInfo { |
59 USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl); | 60 USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl); |
60 | 61 |
61 public: | 62 public: |
62 ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) { | 63 ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) { |
63 DCHECK(m_resource); | 64 DCHECK(m_resource); |
64 } | 65 } |
65 DEFINE_INLINE_VIRTUAL_TRACE() { | 66 DEFINE_INLINE_VIRTUAL_TRACE() { |
66 visitor->trace(m_resource); | 67 visitor->trace(m_resource); |
67 ImageResourceInfo::trace(visitor); | 68 ImageResourceInfo::trace(visitor); |
68 } | 69 } |
69 | 70 |
70 private: | 71 private: |
71 const KURL& url() const override { return m_resource->url(); } | 72 const KURL& url() const override { return m_resource->url(); } |
72 bool isSchedulingReload() const override { | |
73 return m_resource->m_isSchedulingReload; | |
74 } | |
75 bool hasDevicePixelRatioHeaderValue() const override { | 73 bool hasDevicePixelRatioHeaderValue() const override { |
76 return m_resource->m_hasDevicePixelRatioHeaderValue; | 74 return m_resource->m_hasDevicePixelRatioHeaderValue; |
77 } | 75 } |
78 float devicePixelRatioHeaderValue() const override { | 76 float devicePixelRatioHeaderValue() const override { |
79 return m_resource->m_devicePixelRatioHeaderValue; | 77 return m_resource->m_devicePixelRatioHeaderValue; |
80 } | 78 } |
81 const ResourceResponse& response() const override { | 79 const ResourceResponse& response() const override { |
82 return m_resource->response(); | 80 return m_resource->response(); |
83 } | 81 } |
84 ResourceStatus getStatus() const override { return m_resource->getStatus(); } | 82 ResourceStatus getStatus() const override { return m_resource->getStatus(); } |
85 bool shouldShowPlaceholder() const override { | 83 bool shouldShowPlaceholder() const override { |
86 return m_resource->shouldShowPlaceholder(); | 84 return m_resource->shouldShowPlaceholder(); |
87 } | 85 } |
88 bool isCacheValidator() const override { | 86 bool isCacheValidator() const override { |
89 return m_resource->isCacheValidator(); | 87 return m_resource->isCacheValidator(); |
90 } | 88 } |
91 bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override { | |
92 return m_resource->m_isSchedulingReload || | |
93 m_resource->shouldReloadBrokenPlaceholder(); | |
94 } | |
95 bool isAccessAllowed( | 89 bool isAccessAllowed( |
96 SecurityOrigin* securityOrigin, | 90 SecurityOrigin* securityOrigin, |
97 DoesCurrentFrameHaveSingleSecurityOrigin | 91 DoesCurrentFrameHaveSingleSecurityOrigin |
98 doesCurrentFrameHasSingleSecurityOrigin) const override { | 92 doesCurrentFrameHasSingleSecurityOrigin) const override { |
99 return m_resource->isAccessAllowed(securityOrigin, | 93 return m_resource->isAccessAllowed(securityOrigin, |
100 doesCurrentFrameHasSingleSecurityOrigin); | 94 doesCurrentFrameHasSingleSecurityOrigin); |
101 } | 95 } |
102 bool hasCacheControlNoStoreHeader() const override { | 96 bool hasCacheControlNoStoreHeader() const override { |
103 return m_resource->hasCacheControlNoStoreHeader(); | 97 return m_resource->hasCacheControlNoStoreHeader(); |
104 } | 98 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 fetcher->context().sendImagePing(requestURL); | 162 fetcher->context().sendImagePing(requestURL); |
169 } | 163 } |
170 return nullptr; | 164 return nullptr; |
171 } | 165 } |
172 | 166 |
173 return toImageResource( | 167 return toImageResource( |
174 fetcher->requestResource(request, ImageResourceFactory(request))); | 168 fetcher->requestResource(request, ImageResourceFactory(request))); |
175 } | 169 } |
176 | 170 |
177 bool ImageResource::canReuse(const FetchRequest& request) const { | 171 bool ImageResource::canReuse(const FetchRequest& request) const { |
| 172 if (!getContent()) |
| 173 return false; |
| 174 |
178 // If the image is a placeholder, but this fetch doesn't allow a | 175 // If the image is a placeholder, but this fetch doesn't allow a |
179 // placeholder, then do not reuse this resource. | 176 // placeholder, then do not reuse this resource. |
180 if (request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && | 177 if (request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && |
181 m_placeholderOption != PlaceholderOption::DoNotReloadPlaceholder) | 178 m_placeholderOption != PlaceholderOption::DoNotReloadPlaceholder) |
182 return false; | 179 return false; |
| 180 |
183 return true; | 181 return true; |
184 } | 182 } |
185 | 183 |
186 ImageResource* ImageResource::create(const ResourceRequest& request) { | 184 ImageResource* ImageResource::create(const ResourceRequest& request) { |
187 return new ImageResource(request, ResourceLoaderOptions(), | 185 return new ImageResource(request, ResourceLoaderOptions(), |
188 ImageResourceContent::create(), false); | 186 ImageResourceContent::create(), false); |
189 } | 187 } |
190 | 188 |
191 ImageResource::ImageResource(const ResourceRequest& resourceRequest, | 189 ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
192 const ResourceLoaderOptions& options, | 190 const ResourceLoaderOptions& options, |
193 ImageResourceContent* content, | 191 ImageResourceContent* content, |
194 bool isPlaceholder) | 192 bool isPlaceholder) |
195 : Resource(resourceRequest, Image, options), | 193 : Resource(resourceRequest, Image, options), |
196 m_content(content), | 194 m_content(content), |
197 m_devicePixelRatioHeaderValue(1.0), | 195 m_devicePixelRatioHeaderValue(1.0), |
198 m_hasDevicePixelRatioHeaderValue(false), | 196 m_hasDevicePixelRatioHeaderValue(false), |
199 m_isSchedulingReload(false), | |
200 m_placeholderOption( | 197 m_placeholderOption( |
201 isPlaceholder ? PlaceholderOption::ShowAndReloadPlaceholderAlways | 198 isPlaceholder ? PlaceholderOption::ShowAndReloadPlaceholderAlways |
202 : PlaceholderOption::DoNotReloadPlaceholder), | 199 : PlaceholderOption::DoNotReloadPlaceholder), |
203 m_flushTimer(this, &ImageResource::flushImageIfNeeded) { | 200 m_flushTimer(this, &ImageResource::flushImageIfNeeded) { |
204 DCHECK(getContent()); | 201 DCHECK(getContent()); |
205 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; | 202 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; |
206 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this)); | 203 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this)); |
207 } | 204 } |
208 | 205 |
209 ImageResource::~ImageResource() { | 206 ImageResource::~ImageResource() { |
210 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; | 207 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; |
211 } | 208 } |
212 | 209 |
213 DEFINE_TRACE(ImageResource) { | 210 DEFINE_TRACE(ImageResource) { |
214 visitor->trace(m_multipartParser); | 211 visitor->trace(m_multipartParser); |
215 visitor->trace(m_content); | 212 visitor->trace(m_content); |
216 Resource::trace(visitor); | 213 Resource::trace(visitor); |
217 MultipartImageResourceParser::Client::trace(visitor); | 214 MultipartImageResourceParser::Client::trace(visitor); |
218 } | 215 } |
219 | 216 |
220 void ImageResource::checkNotify() { | |
221 // Don't notify clients of completion if this ImageResource is | |
222 // about to be reloaded. | |
223 if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) | |
224 return; | |
225 | |
226 Resource::checkNotify(); | |
227 } | |
228 | |
229 bool ImageResource::hasClientsOrObservers() const { | 217 bool ImageResource::hasClientsOrObservers() const { |
230 return Resource::hasClientsOrObservers() || getContent()->hasObservers(); | 218 return Resource::hasClientsOrObservers() || |
| 219 (getContent() && getContent()->hasObservers()); |
231 } | 220 } |
232 | 221 |
233 void ImageResource::didAddClient(ResourceClient* client) { | 222 void ImageResource::didAddClient(ResourceClient* client) { |
234 DCHECK((m_multipartParser && isLoading()) || !data() || | 223 DCHECK((m_multipartParser && isLoading()) || !data() || |
235 getContent()->hasImage()); | 224 (getContent() && getContent()->hasImage())); |
236 | |
237 // Don't notify observers and clients of completion if this ImageResource is | |
238 // about to be reloaded. | |
239 if (m_isSchedulingReload || shouldReloadBrokenPlaceholder()) | |
240 return; | |
241 | |
242 Resource::didAddClient(client); | 225 Resource::didAddClient(client); |
243 } | 226 } |
244 | 227 |
245 void ImageResource::destroyDecodedDataForFailedRevalidation() { | 228 void ImageResource::destroyDecodedDataForFailedRevalidation() { |
246 // Clears the image, as we must create a new image for the failed | 229 // Clears the image, as we must create a new image for the failed |
247 // revalidation response. | 230 // revalidation response. |
248 updateImage(nullptr, ImageResourceContent::ClearAndUpdateImage, false); | 231 updateImage(nullptr, ImageResourceContent::ClearAndUpdateImage, false); |
249 setDecodedSize(0); | 232 setDecodedSize(0); |
250 } | 233 } |
251 | 234 |
252 void ImageResource::destroyDecodedDataIfPossible() { | 235 void ImageResource::destroyDecodedDataIfPossible() { |
| 236 if (!getContent()) |
| 237 return; |
253 getContent()->destroyDecodedData(); | 238 getContent()->destroyDecodedData(); |
254 if (getContent()->hasImage() && !isPreloaded() && | 239 if (getContent()->hasImage() && !isPreloaded() && |
255 getContent()->isRefetchableDataFromDiskCache()) { | 240 getContent()->isRefetchableDataFromDiskCache()) { |
256 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize", | 241 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize", |
257 encodedSize() / 1024); | 242 encodedSize() / 1024); |
258 } | 243 } |
259 } | 244 } |
260 | 245 |
261 void ImageResource::allClientsAndObserversRemoved() { | 246 void ImageResource::allClientsAndObserversRemoved() { |
262 CHECK(!getContent()->hasImage() || !errorOccurred()); | 247 CHECK(!getContent() || !getContent()->hasImage() || !errorOccurred()); |
263 // If possible, delay the resetting until back at the event loop. Doing so | 248 if (getContent()) { |
264 // after a conservative GC prevents resetAnimation() from upsetting ongoing | 249 // If possible, delay the resetting until back at the event loop. Doing so |
265 // animation updates (crbug.com/613709) | 250 // after a conservative GC prevents resetAnimation() from upsetting ongoing |
266 if (!ThreadHeap::willObjectBeLazilySwept(this)) { | 251 // animation updates (crbug.com/613709) |
267 Platform::current()->currentThread()->getWebTaskRunner()->postTask( | 252 if (!ThreadHeap::willObjectBeLazilySwept(this)) { |
268 BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, | 253 Platform::current()->currentThread()->getWebTaskRunner()->postTask( |
269 wrapWeakPersistent(getContent()))); | 254 BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, |
270 } else { | 255 wrapWeakPersistent(getContent()))); |
271 getContent()->doResetAnimation(); | 256 } else { |
| 257 getContent()->doResetAnimation(); |
| 258 } |
272 } | 259 } |
273 if (m_multipartParser) | 260 if (m_multipartParser) |
274 m_multipartParser->cancel(); | 261 m_multipartParser->cancel(); |
275 Resource::allClientsAndObserversRemoved(); | 262 Resource::allClientsAndObserversRemoved(); |
276 } | 263 } |
277 | 264 |
278 PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { | 265 PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { |
| 266 if (!getContent()) { |
| 267 DCHECK(!data()); |
| 268 return nullptr; |
| 269 } |
| 270 |
279 if (data()) | 271 if (data()) |
280 return data(); | 272 return data(); |
281 return getContent()->resourceBuffer(); | 273 return getContent()->resourceBuffer(); |
282 } | 274 } |
283 | 275 |
284 void ImageResource::appendData(const char* data, size_t length) { | 276 void ImageResource::appendData(const char* data, size_t length) { |
285 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); | 277 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); |
286 if (m_multipartParser) { | 278 if (m_multipartParser) { |
287 m_multipartParser->appendData(data, length); | 279 m_multipartParser->appendData(data, length); |
288 } else { | 280 } else { |
289 Resource::appendData(data, length); | 281 Resource::appendData(data, length); |
290 | 282 |
| 283 if (!getContent()) |
| 284 return; |
| 285 |
291 // Update the image immediately if needed. | 286 // Update the image immediately if needed. |
292 if (getContent()->shouldUpdateImageImmediately()) { | 287 if (getContent()->shouldUpdateImageImmediately()) { |
293 updateImage(this->data(), ImageResourceContent::UpdateImage, false); | 288 updateImage(this->data(), ImageResourceContent::UpdateImage, false); |
294 return; | 289 return; |
295 } | 290 } |
296 | 291 |
297 // For other cases, only update at |kFlushDelaySeconds| intervals. This | 292 // For other cases, only update at |kFlushDelaySeconds| intervals. This |
298 // throttles how frequently we update |m_image| and how frequently we | 293 // throttles how frequently we update |m_image| and how frequently we |
299 // inform the clients which causes an invalidation of this image. In other | 294 // inform the clients which causes an invalidation of this image. In other |
300 // words, we only invalidate this image every |kFlushDelaySeconds| seconds | 295 // words, we only invalidate this image every |kFlushDelaySeconds| seconds |
(...skipping 22 matching lines...) Expand all Loading... |
323 } | 318 } |
324 | 319 |
325 void ImageResource::decodeError(bool allDataReceived) { | 320 void ImageResource::decodeError(bool allDataReceived) { |
326 size_t size = encodedSize(); | 321 size_t size = encodedSize(); |
327 | 322 |
328 clearData(); | 323 clearData(); |
329 setEncodedSize(0); | 324 setEncodedSize(0); |
330 if (!errorOccurred()) | 325 if (!errorOccurred()) |
331 setStatus(ResourceStatus::DecodeError); | 326 setStatus(ResourceStatus::DecodeError); |
332 | 327 |
| 328 // Tries to reload here to avoid imageNotifyFinished() |
| 329 // notification in the case of decode error. |
| 330 if (loader()) |
| 331 loader()->reloadIfLoFiOrPlaceholderImage(this); |
| 332 |
333 // Finishes loading if needed, and notifies observers. | 333 // Finishes loading if needed, and notifies observers. |
334 if (!allDataReceived && loader()) { | 334 if (!allDataReceived && loader()) { |
335 // Observers are notified via ImageResource::finish(). | 335 // Observers are notified via ImageResource::finish(). |
336 // TODO(hiroshige): Do not call didFinishLoading() directly. | 336 // TODO(hiroshige): Do not call didFinishLoading() directly. |
337 loader()->didFinishLoading(monotonicallyIncreasingTime(), size, size); | 337 loader()->didFinishLoading(monotonicallyIncreasingTime(), size, size); |
338 } else { | 338 } else if (getContent()) { |
339 auto result = getContent()->updateImage( | 339 auto result = getContent()->updateImage( |
340 nullptr, ImageResourceContent::ClearImageAndNotifyObservers, | 340 nullptr, ImageResourceContent::ClearImageAndNotifyObservers, |
341 allDataReceived); | 341 allDataReceived); |
342 DCHECK_EQ(result, ImageResourceContent::UpdateImageResult::NoDecodeError); | 342 DCHECK_EQ(result, ImageResourceContent::UpdateImageResult::NoDecodeError); |
343 } | 343 } |
344 | 344 |
345 memoryCache()->remove(this); | 345 memoryCache()->remove(this); |
346 } | 346 } |
347 | 347 |
348 void ImageResource::updateImageAndClearBuffer() { | 348 void ImageResource::updateImageAndClearBuffer() { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 return errorOccurred(); | 451 return errorOccurred(); |
452 case PlaceholderOption::ReloadPlaceholderOnDecodeError: | 452 case PlaceholderOption::ReloadPlaceholderOnDecodeError: |
453 return getStatus() == ResourceStatus::DecodeError; | 453 return getStatus() == ResourceStatus::DecodeError; |
454 case PlaceholderOption::DoNotReloadPlaceholder: | 454 case PlaceholderOption::DoNotReloadPlaceholder: |
455 return false; | 455 return false; |
456 } | 456 } |
457 NOTREACHED(); | 457 NOTREACHED(); |
458 return false; | 458 return false; |
459 } | 459 } |
460 | 460 |
| 461 void ImageResource::detachContent() { |
| 462 bool contentHadObservers = getContent() && getContent()->hasObservers(); |
| 463 |
| 464 m_content = nullptr; |
| 465 clearData(); |
| 466 memoryCache()->remove(this); |
| 467 |
| 468 if (contentHadObservers) |
| 469 didRemoveClientOrObserver(); |
| 470 } |
| 471 |
461 static bool isLoFiImage(const ImageResource& resource) { | 472 static bool isLoFiImage(const ImageResource& resource) { |
462 if (!(resource.resourceRequest().previewsState() & | 473 if (!(resource.resourceRequest().previewsState() & |
463 WebURLRequest::ServerLoFiOn)) { | 474 WebURLRequest::ServerLoFiOn)) { |
464 return false; | 475 return false; |
465 } | 476 } |
466 return !resource.isLoaded() || | 477 return !resource.isLoaded() || |
467 resource.response() | 478 resource.response() |
468 .httpHeaderField("chrome-proxy-content-transform") | 479 .httpHeaderField("chrome-proxy-content-transform") |
469 .contains("empty-image"); | 480 .contains("empty-image"); |
470 } | 481 } |
471 | 482 |
472 void ImageResource::reloadIfLoFiOrPlaceholderImage( | 483 ImageResource* ImageResource::reloadIfLoFiOrPlaceholderImage( |
473 ResourceFetcher* fetcher, | 484 ResourceFetcher* fetcher, |
474 ReloadLoFiOrPlaceholderPolicy policy) { | 485 ReloadLoFiOrPlaceholderPolicy policy) { |
| 486 DCHECK(fetcher); |
| 487 |
475 if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder()) | 488 if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder()) |
476 return; | 489 return nullptr; |
477 | 490 |
478 if (m_placeholderOption == PlaceholderOption::DoNotReloadPlaceholder && | 491 if (m_placeholderOption == PlaceholderOption::DoNotReloadPlaceholder && |
479 !isLoFiImage(*this)) | 492 !isLoFiImage(*this)) |
480 return; | 493 return nullptr; |
481 | 494 |
482 // Prevent clients and observers from being notified of completion while the | 495 ImageResourceContent* content = getContent(); |
483 // reload is being scheduled, so that e.g. canceling an existing load in | 496 if (!content) |
484 // progress doesn't cause clients and observers to be notified of completion | 497 return nullptr; |
485 // prematurely. | |
486 DCHECK(!m_isSchedulingReload); | |
487 m_isSchedulingReload = true; | |
488 | 498 |
489 setCachePolicyBypassingCache(); | 499 // Creates request/options for new ImageResource for reloading. |
| 500 ResourceLoaderOptions reloadingOptions = options(); |
| 501 ResourceRequest reloadingRequest = resourceRequest(); |
| 502 reloadingRequest.setCachePolicy(WebCachePolicy::BypassingCache); |
| 503 reloadingRequest.setPreviewsState(WebURLRequest::PreviewsNoTransform); |
| 504 if (m_placeholderOption != PlaceholderOption::DoNotReloadPlaceholder) |
| 505 reloadingRequest.clearHTTPHeaderField("range"); |
490 | 506 |
491 setPreviewsStateNoTransform(); | 507 // Clear the image before reloading starts to avoid mixing the image from |
| 508 // previous response with the response from the new reloading response. |
| 509 updateImage(nullptr, ImageResourceContent::ClearImageAndNotifyObservers, |
| 510 false); |
492 | 511 |
493 if (m_placeholderOption != PlaceholderOption::DoNotReloadPlaceholder) | 512 detachContent(); |
494 clearRangeRequestHeader(); | 513 // |this->getContent()| is nullptr after this point. |
495 m_placeholderOption = PlaceholderOption::DoNotReloadPlaceholder; | |
496 | 514 |
497 if (isLoading()) { | 515 // TODO(hiroshige): Use ResourceFetcher::requestResource() to unify the |
498 loader()->cancel(); | 516 // starting points of resource loading into requestResource(). |
499 // Canceling the loader causes error() to be called, which in turn calls | 517 // Currently we call ResourceFetcher::startLoad() instead, in order to avoid |
500 // clear() and notifyObservers(), so there's no need to call these again | 518 // re-applying modifications to ResourceRequest in requestResource(). |
501 // here. | 519 ImageResource* reloadingResource = |
502 } else { | 520 new ImageResource(reloadingRequest, reloadingOptions, content, false); |
503 clearData(); | 521 DCHECK(!reloadingResource || content == reloadingResource->getContent()); |
504 setEncodedSize(0); | 522 memoryCache()->add(reloadingResource); |
505 updateImage(nullptr, ImageResourceContent::ClearImageAndNotifyObservers, | 523 fetcher->addToDocumentResources(reloadingResource); |
506 false); | 524 fetcher->startLoad(reloadingResource); |
507 } | |
508 | 525 |
509 setStatus(ResourceStatus::NotStarted); | 526 return reloadingResource; |
510 | |
511 DCHECK(m_isSchedulingReload); | |
512 m_isSchedulingReload = false; | |
513 | |
514 fetcher->startLoad(this); | |
515 } | 527 } |
516 | 528 |
517 void ImageResource::onePartInMultipartReceived( | 529 void ImageResource::onePartInMultipartReceived( |
518 const ResourceResponse& response) { | 530 const ResourceResponse& response) { |
519 DCHECK(m_multipartParser); | 531 DCHECK(m_multipartParser); |
520 | 532 |
521 setResponse(response); | 533 setResponse(response); |
522 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { | 534 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { |
523 // We have nothing to do because we don't have any data. | 535 // We have nothing to do because we don't have any data. |
524 m_multipartParsingState = MultipartParsingState::ParsingFirstPart; | 536 m_multipartParsingState = MultipartParsingState::ParsingFirstPart; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 | 575 |
564 ImageResourceContent* ImageResource::getContent() { | 576 ImageResourceContent* ImageResource::getContent() { |
565 return m_content; | 577 return m_content; |
566 } | 578 } |
567 | 579 |
568 const ImageResourceContent* ImageResource::getContent() const { | 580 const ImageResourceContent* ImageResource::getContent() const { |
569 return m_content; | 581 return m_content; |
570 } | 582 } |
571 | 583 |
572 ResourcePriority ImageResource::priorityFromObservers() { | 584 ResourcePriority ImageResource::priorityFromObservers() { |
| 585 if (!getContent()) |
| 586 return ResourcePriority(); |
573 return getContent()->priorityFromObservers(); | 587 return getContent()->priorityFromObservers(); |
574 } | 588 } |
575 | 589 |
576 void ImageResource::updateImage( | 590 void ImageResource::updateImage( |
577 PassRefPtr<SharedBuffer> sharedBuffer, | 591 PassRefPtr<SharedBuffer> sharedBuffer, |
578 ImageResourceContent::UpdateImageOption updateImageOption, | 592 ImageResourceContent::UpdateImageOption updateImageOption, |
579 bool allDataReceived) { | 593 bool allDataReceived) { |
| 594 if (!getContent()) |
| 595 return; |
580 auto result = getContent()->updateImage(std::move(sharedBuffer), | 596 auto result = getContent()->updateImage(std::move(sharedBuffer), |
581 updateImageOption, allDataReceived); | 597 updateImageOption, allDataReceived); |
582 if (result == ImageResourceContent::UpdateImageResult::ShouldDecodeError) { | 598 if (result == ImageResourceContent::UpdateImageResult::ShouldDecodeError) { |
| 599 // TODO before commit (hiroshige): Update the comment. |
583 // In case of decode error, we call imageNotifyFinished() iff we don't | 600 // In case of decode error, we call imageNotifyFinished() iff we don't |
584 // initiate reloading: | 601 // initiate reloading: |
585 // [(a): when this is in the middle of loading, or (b): otherwise] | 602 // [(a): when this is in the middle of loading, or (b): otherwise] |
586 // 1. The updateImage() call above doesn't call notifyObservers(). | 603 // 1. The updateImage() call above doesn't call notifyObservers(). |
587 // 2. notifyObservers(ShouldNotifyFinish) is called | 604 // 2. notifyObservers(ShouldNotifyFinish) is called |
588 // (a) via updateImage() called in ImageResource::finish() | 605 // (a) via updateImage() called in ImageResource::finish() |
589 // called via didFinishLoading() called in decodeError(), or | 606 // called via didFinishLoading() called in decodeError(), or |
590 // (b) via updateImage() called in decodeError(). | 607 // (b) via updateImage() called in decodeError(). |
591 // imageNotifyFinished() is called here iff we will not initiate | 608 // imageNotifyFinished() is called here iff we will not initiate |
592 // reloading in Step 3 due to notifyObservers()'s | 609 // reloading in Step 3 due to notifyObservers()'s |
593 // schedulingReloadOrShouldReloadBrokenPlaceholder() check. | 610 // schedulingReloadOrShouldReloadBrokenPlaceholder() check. |
594 // 3. reloadIfLoFiOrPlaceholderImage() is called via ResourceFetcher | 611 // 3. reloadIfLoFiOrPlaceholderImage() is called via ResourceFetcher |
595 // (a) via didFinishLoading() called in decodeError(), or | 612 // (a) via didFinishLoading() called in decodeError(), or |
596 // (b) after returning ImageResource::updateImage(). | 613 // (b) after returning ImageResource::updateImage(). |
597 decodeError(allDataReceived); | 614 decodeError(allDataReceived); |
598 } | 615 } |
599 } | 616 } |
600 | 617 |
601 } // namespace blink | 618 } // namespace blink |
OLD | NEW |