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

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

Powered by Google App Engine
This is Rietveld 408576698