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 17 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |