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 18 matching lines...) Expand all Loading... |
29 #include "core/fetch/MemoryCache.h" | 29 #include "core/fetch/MemoryCache.h" |
30 #include "core/fetch/ResourceClient.h" | 30 #include "core/fetch/ResourceClient.h" |
31 #include "core/fetch/ResourceFetcher.h" | 31 #include "core/fetch/ResourceFetcher.h" |
32 #include "core/fetch/ResourceLoader.h" | 32 #include "core/fetch/ResourceLoader.h" |
33 #include "core/fetch/ResourceLoadingLog.h" | 33 #include "core/fetch/ResourceLoadingLog.h" |
34 #include "platform/Histogram.h" | 34 #include "platform/Histogram.h" |
35 #include "platform/RuntimeEnabledFeatures.h" | 35 #include "platform/RuntimeEnabledFeatures.h" |
36 #include "platform/SharedBuffer.h" | 36 #include "platform/SharedBuffer.h" |
37 #include "platform/tracing/TraceEvent.h" | 37 #include "platform/tracing/TraceEvent.h" |
38 #include "public/platform/Platform.h" | 38 #include "public/platform/Platform.h" |
| 39 #include "public/platform/WebCachePolicy.h" |
39 #include "wtf/CurrentTime.h" | 40 #include "wtf/CurrentTime.h" |
40 #include "wtf/HashCountedSet.h" | 41 #include "wtf/HashCountedSet.h" |
41 #include "wtf/StdLibExtras.h" | 42 #include "wtf/StdLibExtras.h" |
42 #include "wtf/Vector.h" | 43 #include "wtf/Vector.h" |
43 #include <memory> | 44 #include <memory> |
44 #include <v8.h> | 45 #include <v8.h> |
45 | 46 |
46 namespace blink { | 47 namespace blink { |
47 namespace { | 48 namespace { |
48 // The amount of time to wait before informing the clients that the image has | 49 // The amount of time to wait before informing the clients that the image has |
(...skipping 11 matching lines...) Expand all Loading... |
60 ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) { | 61 ImageResourceInfoImpl(ImageResource* resource) : m_resource(resource) { |
61 DCHECK(m_resource); | 62 DCHECK(m_resource); |
62 } | 63 } |
63 DEFINE_INLINE_VIRTUAL_TRACE() { | 64 DEFINE_INLINE_VIRTUAL_TRACE() { |
64 visitor->trace(m_resource); | 65 visitor->trace(m_resource); |
65 ImageResourceInfo::trace(visitor); | 66 ImageResourceInfo::trace(visitor); |
66 } | 67 } |
67 | 68 |
68 private: | 69 private: |
69 const KURL& url() const override { return m_resource->url(); } | 70 const KURL& url() const override { return m_resource->url(); } |
70 bool isSchedulingReload() const override { | |
71 return m_resource->m_isSchedulingReload; | |
72 } | |
73 bool hasDevicePixelRatioHeaderValue() const override { | 71 bool hasDevicePixelRatioHeaderValue() const override { |
74 return m_resource->m_hasDevicePixelRatioHeaderValue; | 72 return m_resource->m_hasDevicePixelRatioHeaderValue; |
75 } | 73 } |
76 float devicePixelRatioHeaderValue() const override { | 74 float devicePixelRatioHeaderValue() const override { |
77 return m_resource->m_devicePixelRatioHeaderValue; | 75 return m_resource->m_devicePixelRatioHeaderValue; |
78 } | 76 } |
79 const ResourceResponse& response() const override { | 77 const ResourceResponse& response() const override { |
80 return m_resource->response(); | 78 return m_resource->response(); |
81 } | 79 } |
82 Resource::Status getStatus() const override { | 80 Resource::Status getStatus() const override { |
83 return m_resource->getStatus(); | 81 return m_resource->getStatus(); |
84 } | 82 } |
85 bool isPlaceholder() const override { return m_resource->isPlaceholder(); } | 83 bool isPlaceholder() const override { return m_resource->isPlaceholder(); } |
86 bool isCacheValidator() const override { | 84 bool isCacheValidator() const override { |
87 return m_resource->isCacheValidator(); | 85 return m_resource->isCacheValidator(); |
88 } | 86 } |
89 bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override { | 87 bool shouldReloadBrokenPlaceholder() const override { |
90 return m_resource->m_isSchedulingReload || | 88 return m_resource->shouldReloadBrokenPlaceholder(); |
91 m_resource->shouldReloadBrokenPlaceholder(); | |
92 } | 89 } |
93 bool isAccessAllowed( | 90 bool isAccessAllowed( |
94 SecurityOrigin* securityOrigin, | 91 SecurityOrigin* securityOrigin, |
95 bool doesCurrentFrameHasSingleSecurityOrigin) const override { | 92 bool doesCurrentFrameHasSingleSecurityOrigin) const override { |
96 return m_resource->isAccessAllowed(securityOrigin, | 93 return m_resource->isAccessAllowed(securityOrigin, |
97 doesCurrentFrameHasSingleSecurityOrigin); | 94 doesCurrentFrameHasSingleSecurityOrigin); |
98 } | 95 } |
99 bool hasCacheControlNoStoreHeader() const override { | 96 bool hasCacheControlNoStoreHeader() const override { |
100 return m_resource->hasCacheControlNoStoreHeader(); | 97 return m_resource->hasCacheControlNoStoreHeader(); |
101 } | 98 } |
102 const ResourceError& resourceError() const override { | 99 const ResourceError& resourceError() const override { |
103 return m_resource->resourceError(); | 100 return m_resource->resourceError(); |
104 } | 101 } |
| 102 ImageResource* resourceForTest() const override { return m_resource; } |
105 | 103 |
106 void decodeError(bool allDataReceived) override { | 104 void decodeError(bool allDataReceived) override { |
107 m_resource->decodeError(allDataReceived); | 105 m_resource->decodeError(allDataReceived); |
108 } | 106 } |
109 void setDecodedSize(size_t size) override { | 107 void setDecodedSize(size_t size) override { |
110 m_resource->setDecodedSize(size); | 108 m_resource->setDecodedSize(size); |
111 } | 109 } |
112 void willAddClientOrObserver() override { | 110 void willAddClientOrObserver() override { |
113 m_resource->willAddClientOrObserver(Resource::MarkAsReferenced); | 111 m_resource->willAddClientOrObserver(Resource::MarkAsReferenced); |
114 } | 112 } |
115 void didRemoveClientOrObserver() override { | 113 void didRemoveClientOrObserver() override { |
116 m_resource->didRemoveClientOrObserver(); | 114 m_resource->didRemoveClientOrObserver(); |
117 } | 115 } |
118 void emulateLoadStartedForInspector( | 116 void emulateLoadStartedForInspector( |
119 ResourceFetcher* fetcher, | 117 ResourceFetcher* fetcher, |
120 const KURL& url, | 118 const KURL& url, |
121 const AtomicString& initiatorName) override { | 119 const AtomicString& initiatorName) override { |
122 fetcher->emulateLoadStartedForInspector(m_resource.get(), url, | 120 fetcher->emulateLoadStartedForInspector(m_resource.get(), url, |
123 WebURLRequest::RequestContextImage, | 121 WebURLRequest::RequestContextImage, |
124 initiatorName); | 122 initiatorName); |
125 } | 123 } |
| 124 bool reloadIfLoFiOrPlaceholder(ResourceFetcher* fetcherForReload) override { |
| 125 return m_resource->reloadIfLoFiOrPlaceholder(fetcherForReload); |
| 126 } |
126 | 127 |
127 Member<ImageResource> m_resource; | 128 Member<ImageResource> m_resource; |
128 }; | 129 }; |
129 | 130 |
130 class ImageResource::ImageResourceFactory : public ResourceFactory { | 131 class ImageResource::ImageResourceFactory : public ResourceFactory { |
131 STACK_ALLOCATED(); | 132 STACK_ALLOCATED(); |
132 | 133 |
133 public: | 134 public: |
134 ImageResourceFactory(const FetchRequest& fetchRequest) | 135 ImageResourceFactory(const FetchRequest& fetchRequest) |
135 : ResourceFactory(Resource::Image), m_fetchRequest(&fetchRequest) {} | 136 : ResourceFactory(Resource::Image), m_fetchRequest(&fetchRequest) {} |
(...skipping 30 matching lines...) Expand all Loading... |
166 } | 167 } |
167 | 168 |
168 ImageResource* resource = toImageResource( | 169 ImageResource* resource = toImageResource( |
169 fetcher->requestResource(request, ImageResourceFactory(request))); | 170 fetcher->requestResource(request, ImageResourceFactory(request))); |
170 if (resource && | 171 if (resource && |
171 request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && | 172 request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && |
172 resource->m_isPlaceholder) { | 173 resource->m_isPlaceholder) { |
173 // If the image is a placeholder, but this fetch doesn't allow a | 174 // 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 | 175 // 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. | 176 // bypassed here - it should be fine to use a cached copy if possible. |
176 resource->reloadIfLoFiOrPlaceholder(fetcher, | 177 ImageResource* reloadingResource = resource->reloadIfLoFiOrPlaceholder( |
177 ReloadCachePolicy::UseExistingPolicy); | 178 fetcher, ReloadCachePolicy::UseExistingPolicy); |
| 179 if (reloadingResource) |
| 180 resource = reloadingResource; |
178 } | 181 } |
179 return resource; | 182 return resource; |
180 } | 183 } |
181 | 184 |
182 ImageResource* ImageResource::create(const ResourceRequest& request) { | 185 ImageResource* ImageResource::create(const ResourceRequest& request) { |
183 return new ImageResource(request, ResourceLoaderOptions(), | 186 return new ImageResource(request, ResourceLoaderOptions(), |
184 ImageResourceContent::create(), false); | 187 ImageResourceContent::create(), false); |
185 } | 188 } |
186 | 189 |
187 ImageResource::ImageResource(const ResourceRequest& resourceRequest, | 190 ImageResource::ImageResource(const ResourceRequest& resourceRequest, |
188 const ResourceLoaderOptions& options, | 191 const ResourceLoaderOptions& options, |
189 ImageResourceContent* content, | 192 ImageResourceContent* content, |
190 bool isPlaceholder) | 193 bool isPlaceholder) |
191 : Resource(resourceRequest, Image, options), | 194 : Resource(resourceRequest, Image, options), |
192 m_content(content), | 195 m_content(content), |
193 m_devicePixelRatioHeaderValue(1.0), | 196 m_devicePixelRatioHeaderValue(1.0), |
194 m_hasDevicePixelRatioHeaderValue(false), | 197 m_hasDevicePixelRatioHeaderValue(false), |
195 m_isSchedulingReload(false), | |
196 m_isPlaceholder(isPlaceholder), | 198 m_isPlaceholder(isPlaceholder), |
197 m_flushTimer(this, &ImageResource::flushImageIfNeeded) { | 199 m_flushTimer(this, &ImageResource::flushImageIfNeeded) { |
198 DCHECK(getContent()); | 200 DCHECK(getContent()); |
199 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; | 201 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; |
200 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this)); | 202 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this)); |
201 } | 203 } |
202 | 204 |
203 ImageResource::~ImageResource() { | 205 ImageResource::~ImageResource() { |
204 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; | 206 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; |
205 } | 207 } |
206 | 208 |
207 DEFINE_TRACE(ImageResource) { | 209 DEFINE_TRACE(ImageResource) { |
208 visitor->trace(m_multipartParser); | 210 visitor->trace(m_multipartParser); |
209 visitor->trace(m_content); | 211 visitor->trace(m_content); |
210 Resource::trace(visitor); | 212 Resource::trace(visitor); |
211 MultipartImageResourceParser::Client::trace(visitor); | 213 MultipartImageResourceParser::Client::trace(visitor); |
212 } | 214 } |
213 | 215 |
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 { | 216 bool ImageResource::hasClientsOrObservers() const { |
224 return Resource::hasClientsOrObservers() || getContent()->hasObservers(); | 217 return Resource::hasClientsOrObservers() || |
| 218 (getContent() && getContent()->hasObservers()); |
225 } | 219 } |
226 | 220 |
227 void ImageResource::didAddClient(ResourceClient* client) { | 221 void ImageResource::didAddClient(ResourceClient* client) { |
228 DCHECK((m_multipartParser && isLoading()) || !data() || | 222 DCHECK((m_multipartParser && isLoading()) || !data() || |
229 getContent()->hasImage()); | 223 (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); | 224 Resource::didAddClient(client); |
237 } | 225 } |
238 | 226 |
239 void ImageResource::destroyDecodedDataForFailedRevalidation() { | 227 void ImageResource::destroyDecodedDataForFailedRevalidation() { |
240 updateImage(nullptr, ImageResourceContent::ClearExistingImage, false); | 228 updateImage(nullptr, ImageResourceContent::ClearExistingImage, false); |
241 setDecodedSize(0); | 229 setDecodedSize(0); |
242 } | 230 } |
243 | 231 |
244 void ImageResource::destroyDecodedDataIfPossible() { | 232 void ImageResource::destroyDecodedDataIfPossible() { |
| 233 if (!getContent()) |
| 234 return; |
245 getContent()->destroyDecodedData(); | 235 getContent()->destroyDecodedData(); |
246 if (getContent()->hasImage() && !isPreloaded() && | 236 if (getContent()->hasImage() && !isPreloaded() && |
247 getContent()->isRefetchableDataFromDiskCache()) { | 237 getContent()->isRefetchableDataFromDiskCache()) { |
248 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize", | 238 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer.EstimatedDroppableEncodedSize", |
249 encodedSize() / 1024); | 239 encodedSize() / 1024); |
250 } | 240 } |
251 } | 241 } |
252 | 242 |
253 void ImageResource::allClientsAndObserversRemoved() { | 243 void ImageResource::allClientsAndObserversRemoved() { |
254 CHECK(!getContent()->hasImage() || !errorOccurred()); | 244 CHECK(!getContent() || !getContent()->hasImage() || !errorOccurred()); |
255 // If possible, delay the resetting until back at the event loop. Doing so | 245 // If possible, delay the resetting until back at the event loop. Doing so |
256 // after a conservative GC prevents resetAnimation() from upsetting ongoing | 246 // after a conservative GC prevents resetAnimation() from upsetting ongoing |
257 // animation updates (crbug.com/613709) | 247 // animation updates (crbug.com/613709) |
258 if (!ThreadHeap::willObjectBeLazilySwept(this)) { | 248 if (getContent()) { |
259 Platform::current()->currentThread()->getWebTaskRunner()->postTask( | 249 if (!ThreadHeap::willObjectBeLazilySwept(this)) { |
260 BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, | 250 Platform::current()->currentThread()->getWebTaskRunner()->postTask( |
261 wrapWeakPersistent(getContent()))); | 251 BLINK_FROM_HERE, WTF::bind(&ImageResourceContent::doResetAnimation, |
262 } else { | 252 wrapWeakPersistent(getContent()))); |
263 getContent()->doResetAnimation(); | 253 } else { |
| 254 getContent()->doResetAnimation(); |
| 255 } |
264 } | 256 } |
265 if (m_multipartParser) | 257 if (m_multipartParser) |
266 m_multipartParser->cancel(); | 258 m_multipartParser->cancel(); |
267 Resource::allClientsAndObserversRemoved(); | 259 Resource::allClientsAndObserversRemoved(); |
268 } | 260 } |
269 | 261 |
270 PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { | 262 PassRefPtr<const SharedBuffer> ImageResource::resourceBuffer() const { |
271 if (data()) | 263 if (data()) |
272 return data(); | 264 return data(); |
273 if (getContent()->hasImage()) | 265 if (getContent() && getContent()->hasImage()) |
274 return getContent()->getImage()->data(); | 266 return getContent()->getImage()->data(); |
275 return nullptr; | 267 return nullptr; |
276 } | 268 } |
277 | 269 |
278 void ImageResource::appendData(const char* data, size_t length) { | 270 void ImageResource::appendData(const char* data, size_t length) { |
279 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); | 271 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); |
280 if (m_multipartParser) { | 272 if (m_multipartParser) { |
281 m_multipartParser->appendData(data, length); | 273 m_multipartParser->appendData(data, length); |
282 } else { | 274 } else { |
283 Resource::appendData(data, length); | 275 Resource::appendData(data, length); |
284 | 276 |
| 277 if (!getContent()) |
| 278 return; |
| 279 |
285 // If we don't have the size available yet, then update immediately since | 280 // If we don't have the size available yet, then update immediately since |
286 // we need to know the image size as soon as possible. Likewise for | 281 // we need to know the image size as soon as possible. Likewise for |
287 // animated images, update right away since we shouldn't throttle animated | 282 // animated images, update right away since we shouldn't throttle animated |
288 // images. | 283 // images. |
289 if (!getContent()->isSizeAvailable() || | 284 if (!getContent()->isSizeAvailable() || |
290 (getContent()->hasImage() && | 285 (getContent()->hasImage() && |
291 getContent()->getImage()->maybeAnimated())) { | 286 getContent()->getImage()->maybeAnimated())) { |
292 updateImage(this->data(), ImageResourceContent::KeepExistingImage, false); | 287 updateImage(this->data(), ImageResourceContent::KeepExistingImage, false); |
293 return; | 288 return; |
294 } | 289 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 } | 334 } |
340 | 335 |
341 memoryCache()->remove(this); | 336 memoryCache()->remove(this); |
342 } | 337 } |
343 | 338 |
344 void ImageResource::updateImageAndClearBuffer() { | 339 void ImageResource::updateImageAndClearBuffer() { |
345 updateImage(data(), ImageResourceContent::ClearExistingImage, true); | 340 updateImage(data(), ImageResourceContent::ClearExistingImage, true); |
346 clearData(); | 341 clearData(); |
347 } | 342 } |
348 | 343 |
349 void ImageResource::finish(double loadFinishTime) { | 344 void ImageResource::finish(double loadFinishTime, |
| 345 ResourceFetcher* fetcherForReload) { |
350 if (m_multipartParser) { | 346 if (m_multipartParser) { |
351 m_multipartParser->finish(); | 347 m_multipartParser->finish(); |
352 if (data()) | 348 if (data()) |
353 updateImageAndClearBuffer(); | 349 updateImageAndClearBuffer(); |
354 } else { | 350 } else { |
355 updateImage(data(), ImageResourceContent::KeepExistingImage, true); | 351 updateImage(data(), ImageResourceContent::KeepExistingImage, true, |
| 352 fetcherForReload); |
356 // As encoded image data can be created from m_image (see | 353 // As encoded image data can be created from m_image (see |
357 // ImageResource::resourceBuffer(), we don't have to keep m_data. Let's | 354 // ImageResource::resourceBuffer(), we don't have to keep m_data. Let's |
358 // clear this. As for the lifetimes of m_image and m_data, see this | 355 // clear this. As for the lifetimes of m_image and m_data, see this |
359 // document: | 356 // document: |
360 // https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1Vsqpxo
L7aciY/edit?usp=sharing | 357 // https://docs.google.com/document/d/1v0yTAZ6wkqX2U_M6BNIGUJpM1s0TIw1Vsqpxo
L7aciY/edit?usp=sharing |
361 clearData(); | 358 clearData(); |
362 } | 359 } |
363 Resource::finish(loadFinishTime); | 360 Resource::finish(loadFinishTime, fetcherForReload); |
364 } | 361 } |
365 | 362 |
366 void ImageResource::error(const ResourceError& error) { | 363 void ImageResource::error(const ResourceError& error, |
| 364 ResourceFetcher* fetcherForReload) { |
367 if (m_multipartParser) | 365 if (m_multipartParser) |
368 m_multipartParser->cancel(); | 366 m_multipartParser->cancel(); |
369 clearData(); | 367 clearData(); |
370 Resource::error(error); | 368 Resource::error(error, fetcherForReload); |
371 updateImage(nullptr, ImageResourceContent::ClearExistingImage, true); | 369 updateImage(nullptr, ImageResourceContent::ClearExistingImage, true, |
| 370 fetcherForReload); |
372 } | 371 } |
373 | 372 |
374 void ImageResource::responseReceived( | 373 void ImageResource::responseReceived( |
375 const ResourceResponse& response, | 374 const ResourceResponse& response, |
376 std::unique_ptr<WebDataConsumerHandle> handle) { | 375 std::unique_ptr<WebDataConsumerHandle> handle) { |
377 DCHECK(!handle); | 376 DCHECK(!handle); |
378 DCHECK(!m_multipartParser); | 377 DCHECK(!m_multipartParser); |
379 // If there's no boundary, just handle the request normally. | 378 // If there's no boundary, just handle the request normally. |
380 if (response.isMultipart() && !response.multipartBoundary().isEmpty()) { | 379 if (response.isMultipart() && !response.multipartBoundary().isEmpty()) { |
381 m_multipartParser = new MultipartImageResourceParser( | 380 m_multipartParser = new MultipartImageResourceParser( |
(...skipping 15 matching lines...) Expand all Loading... |
397 | 396 |
398 static bool isLoFiImage(const ImageResource& resource) { | 397 static bool isLoFiImage(const ImageResource& resource) { |
399 if (resource.resourceRequest().loFiState() != WebURLRequest::LoFiOn) | 398 if (resource.resourceRequest().loFiState() != WebURLRequest::LoFiOn) |
400 return false; | 399 return false; |
401 return !resource.isLoaded() || | 400 return !resource.isLoaded() || |
402 resource.response() | 401 resource.response() |
403 .httpHeaderField("chrome-proxy-content-transform") | 402 .httpHeaderField("chrome-proxy-content-transform") |
404 .contains("empty-image"); | 403 .contains("empty-image"); |
405 } | 404 } |
406 | 405 |
407 void ImageResource::reloadIfLoFiOrPlaceholder( | 406 void ImageResource::detachContent() { |
| 407 bool hasObservers = getContent() && getContent()->hasObservers(); |
| 408 |
| 409 clearData(); |
| 410 memoryCache()->remove(this); |
| 411 |
| 412 if (hasObservers) |
| 413 didRemoveClientOrObserver(); |
| 414 } |
| 415 |
| 416 ImageResource* ImageResource::reloadIfLoFiOrPlaceholder( |
408 ResourceFetcher* fetcher, | 417 ResourceFetcher* fetcher, |
409 ReloadCachePolicy reloadCachePolicy) { | 418 ReloadCachePolicy reloadCachePolicy) { |
| 419 if (!fetcher) |
| 420 return nullptr; |
410 if (!m_isPlaceholder && !isLoFiImage(*this)) | 421 if (!m_isPlaceholder && !isLoFiImage(*this)) |
411 return; | 422 return nullptr; |
| 423 ImageResourceContent* content = getContent(); |
| 424 if (!content) |
| 425 return nullptr; |
412 | 426 |
413 // Prevent clients and observers from being notified of completion while the | 427 // Creates request/options for new ImageResource for reloading. |
414 // reload is being scheduled, so that e.g. canceling an existing load in | 428 ResourceRequest reloadingRequest = resourceRequest(); |
415 // progress doesn't cause clients and observers to be notified of completion | 429 ResourceLoaderOptions reloadingOptions = options(); |
416 // prematurely. | 430 if (reloadCachePolicy == ReloadCachePolicy::BypassCache) |
417 DCHECK(!m_isSchedulingReload); | 431 reloadingRequest.setCachePolicy(WebCachePolicy::BypassingCache); |
418 m_isSchedulingReload = true; | 432 reloadingRequest.setLoFiState(WebURLRequest::LoFiOff); |
| 433 if (m_isPlaceholder) |
| 434 reloadingRequest.clearHTTPHeaderField("range"); |
419 | 435 |
420 if (reloadCachePolicy == ReloadCachePolicy::BypassCache) | 436 detachContent(); |
421 setCachePolicyBypassingCache(); | 437 // Do not touch |this| after this point. |
422 setLoFiStateOff(); | |
423 | 438 |
424 if (m_isPlaceholder) { | 439 ImageResource* reloadingResource = |
425 m_isPlaceholder = false; | 440 new ImageResource(reloadingRequest, reloadingOptions, content, false); |
426 clearRangeRequestHeader(); | 441 fetcher->startLoad(reloadingResource); |
427 } | 442 return reloadingResource; |
428 | |
429 if (isLoading()) { | |
430 loader()->cancel(); | |
431 // Canceling the loader causes error() to be called, which in turn calls | |
432 // clear() and notifyObservers(), so there's no need to call these again | |
433 // here. | |
434 } else { | |
435 clearData(); | |
436 setEncodedSize(0); | |
437 updateImage(nullptr, ImageResourceContent::ClearExistingImage, false); | |
438 } | |
439 | |
440 setStatus(NotStarted); | |
441 | |
442 DCHECK(m_isSchedulingReload); | |
443 m_isSchedulingReload = false; | |
444 | |
445 fetcher->startLoad(this); | |
446 } | 443 } |
447 | 444 |
448 void ImageResource::onePartInMultipartReceived( | 445 void ImageResource::onePartInMultipartReceived( |
449 const ResourceResponse& response) { | 446 const ResourceResponse& response) { |
450 DCHECK(m_multipartParser); | 447 DCHECK(m_multipartParser); |
451 | 448 |
452 setResponse(response); | 449 setResponse(response); |
453 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { | 450 if (m_multipartParsingState == MultipartParsingState::WaitingForFirstPart) { |
454 // We have nothing to do because we don't have any data. | 451 // We have nothing to do because we don't have any data. |
455 m_multipartParsingState = MultipartParsingState::ParsingFirstPart; | 452 m_multipartParsingState = MultipartParsingState::ParsingFirstPart; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 if (passesAccessControlCheck(securityOrigin)) | 486 if (passesAccessControlCheck(securityOrigin)) |
490 return true; | 487 return true; |
491 return !securityOrigin->taintsCanvas(response().url()); | 488 return !securityOrigin->taintsCanvas(response().url()); |
492 } | 489 } |
493 | 490 |
494 ImageResourceContent* ImageResource::getContent() const { | 491 ImageResourceContent* ImageResource::getContent() const { |
495 return m_content; | 492 return m_content; |
496 } | 493 } |
497 | 494 |
498 ResourcePriority ImageResource::priorityFromObservers() { | 495 ResourcePriority ImageResource::priorityFromObservers() { |
| 496 if (!getContent()) |
| 497 return ResourcePriority(); |
| 498 |
499 return getContent()->priorityFromObservers(); | 499 return getContent()->priorityFromObservers(); |
500 } | 500 } |
501 | 501 |
502 void ImageResource::updateImage( | 502 void ImageResource::updateImage( |
503 PassRefPtr<SharedBuffer> sharedBuffer, | 503 PassRefPtr<SharedBuffer> sharedBuffer, |
504 ImageResourceContent::ClearImageOption clearImageOption, | 504 ImageResourceContent::ClearImageOption clearImageOption, |
505 bool allDataReceived) { | 505 bool allDataReceived, |
| 506 ResourceFetcher* fetcherForReload) { |
506 if (!m_isUpdateImageCalled) | 507 if (!m_isUpdateImageCalled) |
507 clearImageOption = ImageResourceContent::ClearExistingImage; | 508 clearImageOption = ImageResourceContent::ClearExistingImage; |
508 m_isUpdateImageCalled = true; | 509 m_isUpdateImageCalled = true; |
509 getContent()->updateImage(std::move(sharedBuffer), clearImageOption, | 510 if (getContent()) { |
510 allDataReceived); | 511 getContent()->updateImage(std::move(sharedBuffer), clearImageOption, |
| 512 allDataReceived, fetcherForReload); |
| 513 } |
511 } | 514 } |
512 | 515 |
513 } // namespace blink | 516 } // namespace blink |
OLD | NEW |