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

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

Issue 2650113002: Phase II Step 2: Remove setIsPlaceholder() in updateImage() (Closed)
Patch Set: compile fix Created 3 years, 10 months 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
11 version 2 of the License, or (at your option) any later version. 11 version 2 of the License, or (at your option) any later version.
12 12
13 This library is distributed in the hope that it will be useful, 13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details. 16 Library General Public License for more details.
17 17
18 You should have received a copy of the GNU Library General Public License 18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to 19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. 21 Boston, MA 02110-1301, USA.
22 */ 22 */
23 23
24 #include "core/loader/resource/ImageResource.h" 24 #include "core/loader/resource/ImageResource.h"
25 25
26 #include <stdint.h>
27 #include <v8.h>
28 #include <memory>
26 #include "core/loader/resource/ImageResourceContent.h" 29 #include "core/loader/resource/ImageResourceContent.h"
27 #include "core/loader/resource/ImageResourceInfo.h" 30 #include "core/loader/resource/ImageResourceInfo.h"
28 #include "platform/Histogram.h" 31 #include "platform/Histogram.h"
29 #include "platform/RuntimeEnabledFeatures.h" 32 #include "platform/RuntimeEnabledFeatures.h"
30 #include "platform/SharedBuffer.h" 33 #include "platform/SharedBuffer.h"
31 #include "platform/instrumentation/tracing/TraceEvent.h" 34 #include "platform/instrumentation/tracing/TraceEvent.h"
32 #include "platform/loader/fetch/MemoryCache.h" 35 #include "platform/loader/fetch/MemoryCache.h"
33 #include "platform/loader/fetch/ResourceClient.h" 36 #include "platform/loader/fetch/ResourceClient.h"
34 #include "platform/loader/fetch/ResourceFetcher.h" 37 #include "platform/loader/fetch/ResourceFetcher.h"
35 #include "platform/loader/fetch/ResourceLoader.h" 38 #include "platform/loader/fetch/ResourceLoader.h"
36 #include "platform/loader/fetch/ResourceLoadingLog.h" 39 #include "platform/loader/fetch/ResourceLoadingLog.h"
40 #include "platform/network/HTTPParsers.h"
37 #include "public/platform/Platform.h" 41 #include "public/platform/Platform.h"
38 #include "wtf/CurrentTime.h" 42 #include "wtf/CurrentTime.h"
39 #include "wtf/StdLibExtras.h" 43 #include "wtf/StdLibExtras.h"
40 #include <memory>
41 #include <v8.h>
42 44
43 namespace blink { 45 namespace blink {
44 namespace { 46 namespace {
45 // The amount of time to wait before informing the clients that the image has 47 // The amount of time to wait before informing the clients that the image has
46 // been updated (in seconds). This effectively throttles invalidations that 48 // been updated (in seconds). This effectively throttles invalidations that
47 // result from new data arriving for this image. 49 // result from new data arriving for this image.
48 constexpr double kFlushDelaySeconds = 1.; 50 constexpr double kFlushDelaySeconds = 1.;
49 } // namespace 51 } // namespace
50 52
51 class ImageResource::ImageResourceInfoImpl final 53 class ImageResource::ImageResourceInfoImpl final
(...skipping 18 matching lines...) Expand all
70 bool hasDevicePixelRatioHeaderValue() const override { 72 bool hasDevicePixelRatioHeaderValue() const override {
71 return m_resource->m_hasDevicePixelRatioHeaderValue; 73 return m_resource->m_hasDevicePixelRatioHeaderValue;
72 } 74 }
73 float devicePixelRatioHeaderValue() const override { 75 float devicePixelRatioHeaderValue() const override {
74 return m_resource->m_devicePixelRatioHeaderValue; 76 return m_resource->m_devicePixelRatioHeaderValue;
75 } 77 }
76 const ResourceResponse& response() const override { 78 const ResourceResponse& response() const override {
77 return m_resource->response(); 79 return m_resource->response();
78 } 80 }
79 ResourceStatus getStatus() const override { return m_resource->getStatus(); } 81 ResourceStatus getStatus() const override { return m_resource->getStatus(); }
80 bool isPlaceholder() const override { return m_resource->isPlaceholder(); } 82 bool shouldShowPlaceholder() const override {
83 return m_resource->shouldShowPlaceholder();
84 }
81 bool isCacheValidator() const override { 85 bool isCacheValidator() const override {
82 return m_resource->isCacheValidator(); 86 return m_resource->isCacheValidator();
83 } 87 }
84 bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override { 88 bool schedulingReloadOrShouldReloadBrokenPlaceholder() const override {
85 return m_resource->m_isSchedulingReload || 89 return m_resource->m_isSchedulingReload ||
86 m_resource->shouldReloadBrokenPlaceholder(); 90 m_resource->shouldReloadBrokenPlaceholder();
87 } 91 }
88 bool isAccessAllowed( 92 bool isAccessAllowed(
89 SecurityOrigin* securityOrigin, 93 SecurityOrigin* securityOrigin,
90 DoesCurrentFrameHaveSingleSecurityOrigin 94 DoesCurrentFrameHaveSingleSecurityOrigin
91 doesCurrentFrameHasSingleSecurityOrigin) const override { 95 doesCurrentFrameHasSingleSecurityOrigin) const override {
92 return m_resource->isAccessAllowed(securityOrigin, 96 return m_resource->isAccessAllowed(securityOrigin,
93 doesCurrentFrameHasSingleSecurityOrigin); 97 doesCurrentFrameHasSingleSecurityOrigin);
94 } 98 }
95 bool hasCacheControlNoStoreHeader() const override { 99 bool hasCacheControlNoStoreHeader() const override {
96 return m_resource->hasCacheControlNoStoreHeader(); 100 return m_resource->hasCacheControlNoStoreHeader();
97 } 101 }
98 const ResourceError& resourceError() const override { 102 const ResourceError& resourceError() const override {
99 return m_resource->resourceError(); 103 return m_resource->resourceError();
100 } 104 }
101 105
102 void setIsPlaceholder(bool isPlaceholder) override {
103 m_resource->m_isPlaceholder = isPlaceholder;
104 }
105 void setDecodedSize(size_t size) override { 106 void setDecodedSize(size_t size) override {
106 m_resource->setDecodedSize(size); 107 m_resource->setDecodedSize(size);
107 } 108 }
108 void willAddClientOrObserver() override { 109 void willAddClientOrObserver() override {
109 m_resource->willAddClientOrObserver(Resource::MarkAsReferenced); 110 m_resource->willAddClientOrObserver(Resource::MarkAsReferenced);
110 } 111 }
111 void didRemoveClientOrObserver() override { 112 void didRemoveClientOrObserver() override {
112 m_resource->didRemoveClientOrObserver(); 113 m_resource->didRemoveClientOrObserver();
113 } 114 }
114 void emulateLoadStartedForInspector( 115 void emulateLoadStartedForInspector(
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 if (blockReason == ResourceRequestBlockedReason::None) 166 if (blockReason == ResourceRequestBlockedReason::None)
166 fetcher->context().sendImagePing(requestURL); 167 fetcher->context().sendImagePing(requestURL);
167 } 168 }
168 return nullptr; 169 return nullptr;
169 } 170 }
170 171
171 ImageResource* resource = toImageResource( 172 ImageResource* resource = toImageResource(
172 fetcher->requestResource(request, ImageResourceFactory(request))); 173 fetcher->requestResource(request, ImageResourceFactory(request)));
173 if (resource && 174 if (resource &&
174 request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder && 175 request.placeholderImageRequestType() != FetchRequest::AllowPlaceholder &&
175 resource->m_isPlaceholder) { 176 resource->shouldShowPlaceholder()) {
176 // If the image is a placeholder, but this fetch doesn't allow a 177 // If the image is a placeholder, but this fetch doesn't allow a
177 // placeholder, then load the original image. Note that the cache is not 178 // placeholder, then load the original image. Note that the cache is not
178 // bypassed here - it should be fine to use a cached copy if possible. 179 // bypassed here - it should be fine to use a cached copy if possible.
179 resource->reloadIfLoFiOrPlaceholderImage( 180 resource->reloadIfLoFiOrPlaceholderImage(
180 fetcher, kReloadAlwaysWithExistingCachePolicy); 181 fetcher, kReloadAlwaysWithExistingCachePolicy);
181 } 182 }
182 return resource; 183 return resource;
183 } 184 }
184 185
185 ImageResource* ImageResource::create(const ResourceRequest& request) { 186 ImageResource* ImageResource::create(const ResourceRequest& request) {
186 return new ImageResource(request, ResourceLoaderOptions(), 187 return new ImageResource(request, ResourceLoaderOptions(),
187 ImageResourceContent::create(), false); 188 ImageResourceContent::create(), false);
188 } 189 }
189 190
190 ImageResource::ImageResource(const ResourceRequest& resourceRequest, 191 ImageResource::ImageResource(const ResourceRequest& resourceRequest,
191 const ResourceLoaderOptions& options, 192 const ResourceLoaderOptions& options,
192 ImageResourceContent* content, 193 ImageResourceContent* content,
193 bool isPlaceholder) 194 bool isPlaceholder)
194 : Resource(resourceRequest, Image, options), 195 : Resource(resourceRequest, Image, options),
195 m_content(content), 196 m_content(content),
196 m_devicePixelRatioHeaderValue(1.0), 197 m_devicePixelRatioHeaderValue(1.0),
197 m_hasDevicePixelRatioHeaderValue(false), 198 m_hasDevicePixelRatioHeaderValue(false),
198 m_isSchedulingReload(false), 199 m_isSchedulingReload(false),
199 m_isPlaceholder(isPlaceholder), 200 m_placeholderOption(isPlaceholder ? ShowAndReloadPlaceholderAlways
201 : DoNotReloadPlaceholder),
200 m_flushTimer(this, &ImageResource::flushImageIfNeeded) { 202 m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
201 DCHECK(getContent()); 203 DCHECK(getContent());
202 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; 204 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this;
203 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this)); 205 getContent()->setImageResourceInfo(new ImageResourceInfoImpl(this));
204 } 206 }
205 207
206 ImageResource::~ImageResource() { 208 ImageResource::~ImageResource() {
207 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; 209 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this;
208 } 210 }
209 211
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 314
313 void ImageResource::flushImageIfNeeded(TimerBase*) { 315 void ImageResource::flushImageIfNeeded(TimerBase*) {
314 // We might have already loaded the image fully, in which case we don't need 316 // We might have already loaded the image fully, in which case we don't need
315 // to call |updateImage()|. 317 // to call |updateImage()|.
316 if (isLoading()) { 318 if (isLoading()) {
317 m_lastFlushTime = WTF::monotonicallyIncreasingTime(); 319 m_lastFlushTime = WTF::monotonicallyIncreasingTime();
318 updateImage(this->data(), ImageResourceContent::UpdateImage, false); 320 updateImage(this->data(), ImageResourceContent::UpdateImage, false);
319 } 321 }
320 } 322 }
321 323
322 bool ImageResource::willPaintBrokenImage() const {
323 return errorOccurred();
324 }
325
326 void ImageResource::decodeError(bool allDataReceived) { 324 void ImageResource::decodeError(bool allDataReceived) {
327 size_t size = encodedSize(); 325 size_t size = encodedSize();
328 326
329 clearData(); 327 clearData();
330 setEncodedSize(0); 328 setEncodedSize(0);
331 if (!errorOccurred()) 329 if (!errorOccurred())
332 setStatus(ResourceStatus::DecodeError); 330 setStatus(ResourceStatus::DecodeError);
333 331
334 // Finishes loading if needed, and notifies observers. 332 // Finishes loading if needed, and notifies observers.
335 if (!allDataReceived && loader()) { 333 if (!allDataReceived && loader()) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 if (m_multipartParser) 370 if (m_multipartParser)
373 m_multipartParser->cancel(); 371 m_multipartParser->cancel();
374 // TODO(hiroshige): Move setEncodedSize() call to Resource::error() if it 372 // TODO(hiroshige): Move setEncodedSize() call to Resource::error() if it
375 // is really needed, or remove it otherwise. 373 // is really needed, or remove it otherwise.
376 setEncodedSize(0); 374 setEncodedSize(0);
377 Resource::error(error); 375 Resource::error(error);
378 updateImage(nullptr, ImageResourceContent::ClearImageAndNotifyObservers, 376 updateImage(nullptr, ImageResourceContent::ClearImageAndNotifyObservers,
379 true); 377 true);
380 } 378 }
381 379
380 // Determines if |response| likely contains the entire resource for the purposes
381 // of determining whether or not to show a placeholder, e.g. if the server
382 // responded with a full 200 response or if the full image is smaller than the
383 // requested range.
384 static bool isEntireResource(const ResourceResponse& response) {
385 if (response.httpStatusCode() != 206)
386 return true;
387
388 int64_t firstBytePosition = -1, lastBytePosition = -1, instanceLength = -1;
389 return parseContentRangeHeaderFor206(
390 response.httpHeaderField("Content-Range"), &firstBytePosition,
391 &lastBytePosition, &instanceLength) &&
392 firstBytePosition == 0 && lastBytePosition + 1 == instanceLength;
393 }
394
382 void ImageResource::responseReceived( 395 void ImageResource::responseReceived(
383 const ResourceResponse& response, 396 const ResourceResponse& response,
384 std::unique_ptr<WebDataConsumerHandle> handle) { 397 std::unique_ptr<WebDataConsumerHandle> handle) {
385 DCHECK(!handle); 398 DCHECK(!handle);
386 DCHECK(!m_multipartParser); 399 DCHECK(!m_multipartParser);
387 // If there's no boundary, just handle the request normally. 400 // If there's no boundary, just handle the request normally.
388 if (response.isMultipart() && !response.multipartBoundary().isEmpty()) { 401 if (response.isMultipart() && !response.multipartBoundary().isEmpty()) {
389 m_multipartParser = new MultipartImageResourceParser( 402 m_multipartParser = new MultipartImageResourceParser(
390 response, response.multipartBoundary(), this); 403 response, response.multipartBoundary(), this);
391 } 404 }
392 Resource::responseReceived(response, std::move(handle)); 405 Resource::responseReceived(response, std::move(handle));
393 if (RuntimeEnabledFeatures::clientHintsEnabled()) { 406 if (RuntimeEnabledFeatures::clientHintsEnabled()) {
394 m_devicePixelRatioHeaderValue = 407 m_devicePixelRatioHeaderValue =
395 this->response() 408 this->response()
396 .httpHeaderField(HTTPNames::Content_DPR) 409 .httpHeaderField(HTTPNames::Content_DPR)
397 .toFloat(&m_hasDevicePixelRatioHeaderValue); 410 .toFloat(&m_hasDevicePixelRatioHeaderValue);
398 if (!m_hasDevicePixelRatioHeaderValue || 411 if (!m_hasDevicePixelRatioHeaderValue ||
399 m_devicePixelRatioHeaderValue <= 0.0) { 412 m_devicePixelRatioHeaderValue <= 0.0) {
400 m_devicePixelRatioHeaderValue = 1.0; 413 m_devicePixelRatioHeaderValue = 1.0;
401 m_hasDevicePixelRatioHeaderValue = false; 414 m_hasDevicePixelRatioHeaderValue = false;
402 } 415 }
403 } 416 }
417
418 if (isEntireResource(this->response())) {
419 if (this->response().httpStatusCode() < 400 ||
420 this->response().httpStatusCode() >= 600) {
421 // Don't treat a complete and broken image as a placeholder if the
422 // response code is something other than a 4xx or 5xx error.
423 // This is done to prevent reissuing the request in cases like
424 // "204 No Content" responses to tracking requests triggered by <img>
425 // tags, and <img> tags used to preload non-image resources.
426 m_placeholderOption = DoNotReloadPlaceholder;
427 } else {
428 m_placeholderOption = ReloadPlaceholderOnDecodeError;
yhirano 2017/02/13 11:36:57 Is DoNotReloadPlaceholder => ReloadPlaceholderOnDe
hiroshige 2017/02/23 20:52:38 Oh, looks invalid. Fixed.
429 }
430 }
404 } 431 }
405 432
433 bool ImageResource::shouldShowPlaceholder() const {
434 switch (m_placeholderOption) {
435 case ShowAndReloadPlaceholderAlways:
436 return true;
437 case ReloadPlaceholderOnDecodeError:
438 case DoNotReloadPlaceholder:
439 return false;
440 }
441 NOTREACHED();
442 return false;
443 }
444
445 bool ImageResource::shouldReloadBrokenPlaceholder() const {
446 switch (m_placeholderOption) {
447 case ShowAndReloadPlaceholderAlways:
448 return errorOccurred();
449 case ReloadPlaceholderOnDecodeError:
450 return getStatus() == ResourceStatus::DecodeError;
451 case DoNotReloadPlaceholder:
452 return false;
453 }
454 NOTREACHED();
455 return false;
456 }
457
406 static bool isLoFiImage(const ImageResource& resource) { 458 static bool isLoFiImage(const ImageResource& resource) {
407 if (!(resource.resourceRequest().previewsState() & 459 if (!(resource.resourceRequest().previewsState() &
408 WebURLRequest::ServerLoFiOn)) { 460 WebURLRequest::ServerLoFiOn)) {
409 return false; 461 return false;
410 } 462 }
411 return !resource.isLoaded() || 463 return !resource.isLoaded() ||
412 resource.response() 464 resource.response()
413 .httpHeaderField("chrome-proxy-content-transform") 465 .httpHeaderField("chrome-proxy-content-transform")
414 .contains("empty-image"); 466 .contains("empty-image");
415 } 467 }
416 468
417 void ImageResource::reloadIfLoFiOrPlaceholderImage( 469 void ImageResource::reloadIfLoFiOrPlaceholderImage(
418 ResourceFetcher* fetcher, 470 ResourceFetcher* fetcher,
419 ReloadLoFiOrPlaceholderPolicy policy) { 471 ReloadLoFiOrPlaceholderPolicy policy) {
420 if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder()) 472 if (policy == kReloadIfNeeded && !shouldReloadBrokenPlaceholder())
421 return; 473 return;
422 474
423 if (!m_isPlaceholder && !isLoFiImage(*this)) 475 if (m_placeholderOption == DoNotReloadPlaceholder && !isLoFiImage(*this))
424 return; 476 return;
425 477
426 // Prevent clients and observers from being notified of completion while the 478 // Prevent clients and observers from being notified of completion while the
427 // reload is being scheduled, so that e.g. canceling an existing load in 479 // reload is being scheduled, so that e.g. canceling an existing load in
428 // progress doesn't cause clients and observers to be notified of completion 480 // progress doesn't cause clients and observers to be notified of completion
429 // prematurely. 481 // prematurely.
430 DCHECK(!m_isSchedulingReload); 482 DCHECK(!m_isSchedulingReload);
431 m_isSchedulingReload = true; 483 m_isSchedulingReload = true;
432 484
433 if (policy != kReloadAlwaysWithExistingCachePolicy) 485 if (policy != kReloadAlwaysWithExistingCachePolicy)
434 setCachePolicyBypassingCache(); 486 setCachePolicyBypassingCache();
435 487
436 setPreviewsStateNoTransform(); 488 setPreviewsStateNoTransform();
437 489
438 if (m_isPlaceholder) { 490 if (m_placeholderOption != DoNotReloadPlaceholder)
439 m_isPlaceholder = false;
440 clearRangeRequestHeader(); 491 clearRangeRequestHeader();
441 } 492 m_placeholderOption = DoNotReloadPlaceholder;
442 493
443 if (isLoading()) { 494 if (isLoading()) {
444 loader()->cancel(); 495 loader()->cancel();
445 // Canceling the loader causes error() to be called, which in turn calls 496 // Canceling the loader causes error() to be called, which in turn calls
446 // clear() and notifyObservers(), so there's no need to call these again 497 // clear() and notifyObservers(), so there's no need to call these again
447 // here. 498 // here.
448 } else { 499 } else {
449 clearData(); 500 clearData();
450 setEncodedSize(0); 501 setEncodedSize(0);
451 updateImage(nullptr, ImageResourceContent::ClearImageAndNotifyObservers, 502 updateImage(nullptr, ImageResourceContent::ClearImageAndNotifyObservers,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 // reloading in Step 3 due to notifyObservers()'s 589 // reloading in Step 3 due to notifyObservers()'s
539 // schedulingReloadOrShouldReloadBrokenPlaceholder() check. 590 // schedulingReloadOrShouldReloadBrokenPlaceholder() check.
540 // 3. reloadIfLoFiOrPlaceholderImage() is called via ResourceFetcher 591 // 3. reloadIfLoFiOrPlaceholderImage() is called via ResourceFetcher
541 // (a) via didFinishLoading() called in decodeError(), or 592 // (a) via didFinishLoading() called in decodeError(), or
542 // (b) after returning ImageResource::updateImage(). 593 // (b) after returning ImageResource::updateImage().
543 decodeError(allDataReceived); 594 decodeError(allDataReceived);
544 } 595 }
545 } 596 }
546 597
547 } // namespace blink 598 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698