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

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

Issue 2930323003: Show client placeholders for Server LoFi images. (Closed)
Patch Set: rebase flag_descriptions.cc Created 3 years, 5 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
(...skipping 30 matching lines...) Expand all
41 #include "platform/loader/fetch/ResourceLoadingLog.h" 41 #include "platform/loader/fetch/ResourceLoadingLog.h"
42 #include "platform/network/HTTPParsers.h" 42 #include "platform/network/HTTPParsers.h"
43 #include "platform/weborigin/KURL.h" 43 #include "platform/weborigin/KURL.h"
44 #include "platform/weborigin/SecurityViolationReportingPolicy.h" 44 #include "platform/weborigin/SecurityViolationReportingPolicy.h"
45 #include "platform/wtf/CurrentTime.h" 45 #include "platform/wtf/CurrentTime.h"
46 #include "platform/wtf/StdLibExtras.h" 46 #include "platform/wtf/StdLibExtras.h"
47 #include "public/platform/Platform.h" 47 #include "public/platform/Platform.h"
48 #include "v8/include/v8.h" 48 #include "v8/include/v8.h"
49 49
50 namespace blink { 50 namespace blink {
51
51 namespace { 52 namespace {
53
52 // The amount of time to wait before informing the clients that the image has 54 // The amount of time to wait before informing the clients that the image has
53 // been updated (in seconds). This effectively throttles invalidations that 55 // been updated (in seconds). This effectively throttles invalidations that
54 // result from new data arriving for this image. 56 // result from new data arriving for this image.
55 constexpr double kFlushDelaySeconds = 1.; 57 constexpr double kFlushDelaySeconds = 1.;
58
59 bool HasServerLoFiResponseHeaders(const ResourceResponse& response) {
60 return response.HttpHeaderField("chrome-proxy-content-transform")
61 .Contains("empty-image") ||
62 // Check for the legacy Server Lo-Fi response headers, since it's
63 // possible that an old Lo-Fi image could be served from the cache.
64 response.HttpHeaderField("chrome-proxy").Contains("q=low");
65 }
66
56 } // namespace 67 } // namespace
57 68
58 class ImageResource::ImageResourceInfoImpl final 69 class ImageResource::ImageResourceInfoImpl final
59 : public GarbageCollectedFinalized<ImageResourceInfoImpl>, 70 : public GarbageCollectedFinalized<ImageResourceInfoImpl>,
60 public ImageResourceInfo { 71 public ImageResourceInfo {
61 USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl); 72 USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl);
62 73
63 public: 74 public:
64 ImageResourceInfoImpl(ImageResource* resource) : resource_(resource) { 75 ImageResourceInfoImpl(ImageResource* resource) : resource_(resource) {
65 DCHECK(resource_); 76 DCHECK(resource_);
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 void ImageResource::ResponseReceived( 433 void ImageResource::ResponseReceived(
423 const ResourceResponse& response, 434 const ResourceResponse& response,
424 std::unique_ptr<WebDataConsumerHandle> handle) { 435 std::unique_ptr<WebDataConsumerHandle> handle) {
425 DCHECK(!handle); 436 DCHECK(!handle);
426 DCHECK(!multipart_parser_); 437 DCHECK(!multipart_parser_);
427 // If there's no boundary, just handle the request normally. 438 // If there's no boundary, just handle the request normally.
428 if (response.IsMultipart() && !response.MultipartBoundary().IsEmpty()) { 439 if (response.IsMultipart() && !response.MultipartBoundary().IsEmpty()) {
429 multipart_parser_ = new MultipartImageResourceParser( 440 multipart_parser_ = new MultipartImageResourceParser(
430 response, response.MultipartBoundary(), this); 441 response, response.MultipartBoundary(), this);
431 } 442 }
443
444 // Notify the base class that a response has been received. Note that after
445 // this call, |GetResponse()| will represent the full effective
446 // ResourceResponse, while |response| might just be a revalidation response
447 // (e.g. a 304) with a partial set of updated headers that were folded into
448 // the cached response.
432 Resource::ResponseReceived(response, std::move(handle)); 449 Resource::ResponseReceived(response, std::move(handle));
450
433 if (RuntimeEnabledFeatures::ClientHintsEnabled()) { 451 if (RuntimeEnabledFeatures::ClientHintsEnabled()) {
434 device_pixel_ratio_header_value_ = 452 device_pixel_ratio_header_value_ =
435 this->GetResponse() 453 GetResponse()
436 .HttpHeaderField(HTTPNames::Content_DPR) 454 .HttpHeaderField(HTTPNames::Content_DPR)
437 .ToFloat(&has_device_pixel_ratio_header_value_); 455 .ToFloat(&has_device_pixel_ratio_header_value_);
438 if (!has_device_pixel_ratio_header_value_ || 456 if (!has_device_pixel_ratio_header_value_ ||
439 device_pixel_ratio_header_value_ <= 0.0) { 457 device_pixel_ratio_header_value_ <= 0.0) {
440 device_pixel_ratio_header_value_ = 1.0; 458 device_pixel_ratio_header_value_ = 1.0;
441 has_device_pixel_ratio_header_value_ = false; 459 has_device_pixel_ratio_header_value_ = false;
442 } 460 }
443 } 461 }
444 462
445 if (placeholder_option_ == 463 if (placeholder_option_ ==
446 PlaceholderOption::kShowAndReloadPlaceholderAlways && 464 PlaceholderOption::kShowAndReloadPlaceholderAlways &&
447 IsEntireResource(this->GetResponse())) { 465 IsEntireResource(GetResponse())) {
448 if (this->GetResponse().HttpStatusCode() < 400 || 466 if (GetResponse().HttpStatusCode() < 400 ||
449 this->GetResponse().HttpStatusCode() >= 600) { 467 GetResponse().HttpStatusCode() >= 600) {
450 // Don't treat a complete and broken image as a placeholder if the 468 // Don't treat a complete and broken image as a placeholder if the
451 // response code is something other than a 4xx or 5xx error. 469 // response code is something other than a 4xx or 5xx error.
452 // This is done to prevent reissuing the request in cases like 470 // This is done to prevent reissuing the request in cases like
453 // "204 No Content" responses to tracking requests triggered by <img> 471 // "204 No Content" responses to tracking requests triggered by <img>
454 // tags, and <img> tags used to preload non-image resources. 472 // tags, and <img> tags used to preload non-image resources.
455 placeholder_option_ = PlaceholderOption::kDoNotReloadPlaceholder; 473 placeholder_option_ = PlaceholderOption::kDoNotReloadPlaceholder;
456 } else { 474 } else {
457 placeholder_option_ = PlaceholderOption::kReloadPlaceholderOnDecodeError; 475 placeholder_option_ = PlaceholderOption::kReloadPlaceholderOnDecodeError;
458 } 476 }
459 } 477 }
478
479 if (HasServerLoFiResponseHeaders(GetResponse())) {
480 // Ensure that the PreviewsState bit for Server Lo-Fi is set iff Chrome
481 // received the appropriate Server Lo-Fi response headers for this image.
482 //
483 // Normally, the |kServerLoFiOn| bit should already be set if Server Lo-Fi
484 // response headers are coming back, but it's possible for legacy Lo-Fi
485 // images to be served from the cache even if Chrome isn't in Lo-Fi mode.
486 // This also serves as a nice last line of defence to ensure that Server
487 // Lo-Fi images can be reloaded to show the original even if e.g. a server
488 // bug causes Lo-Fi images to be sent when they aren't expected.
489 SetPreviewsState(GetResourceRequest().GetPreviewsState() |
490 WebURLRequest::kServerLoFiOn);
491 } else if (GetResourceRequest().GetPreviewsState() &
492 WebURLRequest::kServerLoFiOn) {
493 // If Chrome expects a Lo-Fi response, but the server decided to send the
494 // full image, then clear the Server Lo-Fi Previews state bit.
495 WebURLRequest::PreviewsState new_previews_state =
496 GetResourceRequest().GetPreviewsState();
497
498 new_previews_state &= ~WebURLRequest::kServerLoFiOn;
499 if (new_previews_state == WebURLRequest::kPreviewsUnspecified)
500 new_previews_state = WebURLRequest::kPreviewsOff;
501
502 SetPreviewsState(new_previews_state);
503 }
460 } 504 }
461 505
462 bool ImageResource::ShouldShowPlaceholder() const { 506 bool ImageResource::ShouldShowPlaceholder() const {
507 if (RuntimeEnabledFeatures::ClientPlaceholdersForServerLoFiEnabled() &&
508 (GetResourceRequest().GetPreviewsState() &
509 WebURLRequest::kServerLoFiOn)) {
510 // If the runtime feature is enabled, show Client Lo-Fi placeholder images
511 // in place of Server Lo-Fi responses. This is done so that all Lo-Fi images
512 // have a consistent appearance.
513 return true;
514 }
515
463 switch (placeholder_option_) { 516 switch (placeholder_option_) {
464 case PlaceholderOption::kShowAndReloadPlaceholderAlways: 517 case PlaceholderOption::kShowAndReloadPlaceholderAlways:
465 case PlaceholderOption::kShowAndDoNotReloadPlaceholder: 518 case PlaceholderOption::kShowAndDoNotReloadPlaceholder:
466 return true; 519 return true;
467 case PlaceholderOption::kReloadPlaceholderOnDecodeError: 520 case PlaceholderOption::kReloadPlaceholderOnDecodeError:
468 case PlaceholderOption::kDoNotReloadPlaceholder: 521 case PlaceholderOption::kDoNotReloadPlaceholder:
469 return false; 522 return false;
470 } 523 }
471 NOTREACHED(); 524 NOTREACHED();
472 return false; 525 return false;
473 } 526 }
474 527
475 bool ImageResource::ShouldReloadBrokenPlaceholder() const { 528 bool ImageResource::ShouldReloadBrokenPlaceholder() const {
476 switch (placeholder_option_) { 529 switch (placeholder_option_) {
477 case PlaceholderOption::kShowAndReloadPlaceholderAlways: 530 case PlaceholderOption::kShowAndReloadPlaceholderAlways:
478 return ErrorOccurred(); 531 return ErrorOccurred();
479 case PlaceholderOption::kReloadPlaceholderOnDecodeError: 532 case PlaceholderOption::kReloadPlaceholderOnDecodeError:
480 return GetStatus() == ResourceStatus::kDecodeError; 533 return GetStatus() == ResourceStatus::kDecodeError;
481 case PlaceholderOption::kShowAndDoNotReloadPlaceholder: 534 case PlaceholderOption::kShowAndDoNotReloadPlaceholder:
482 case PlaceholderOption::kDoNotReloadPlaceholder: 535 case PlaceholderOption::kDoNotReloadPlaceholder:
483 return false; 536 return false;
484 } 537 }
485 NOTREACHED(); 538 NOTREACHED();
486 return false; 539 return false;
487 } 540 }
488 541
489 static bool IsLoFiImage(const ImageResource& resource) {
490 if (resource.IsLoaded()) {
491 return resource.GetResponse()
492 .HttpHeaderField("chrome-proxy-content-transform")
493 .Contains("empty-image") ||
494 resource.GetResponse()
495 .HttpHeaderField("chrome-proxy")
496 .Contains("q=low");
497 }
498 return resource.GetResourceRequest().GetPreviewsState() &
499 WebURLRequest::kServerLoFiOn;
500 }
501
502 void ImageResource::ReloadIfLoFiOrPlaceholderImage( 542 void ImageResource::ReloadIfLoFiOrPlaceholderImage(
503 ResourceFetcher* fetcher, 543 ResourceFetcher* fetcher,
504 ReloadLoFiOrPlaceholderPolicy policy) { 544 ReloadLoFiOrPlaceholderPolicy policy) {
505 if (policy == kReloadIfNeeded && !ShouldReloadBrokenPlaceholder()) 545 if (policy == kReloadIfNeeded && !ShouldReloadBrokenPlaceholder())
506 return; 546 return;
507 547
548 // If the image is loaded, then the |PreviewsState::kServerLoFiOn| bit should
549 // be set iff the image has Server Lo-Fi response headers.
550 DCHECK(!IsLoaded() ||
551 HasServerLoFiResponseHeaders(GetResponse()) ==
552 static_cast<bool>(GetResourceRequest().GetPreviewsState() &
553 WebURLRequest::kServerLoFiOn));
554
508 if (placeholder_option_ == PlaceholderOption::kDoNotReloadPlaceholder && 555 if (placeholder_option_ == PlaceholderOption::kDoNotReloadPlaceholder &&
509 !IsLoFiImage(*this)) 556 !(GetResourceRequest().GetPreviewsState() & WebURLRequest::kServerLoFiOn))
510 return; 557 return;
511 558
512 // Prevent clients and observers from being notified of completion while the 559 // Prevent clients and observers from being notified of completion while the
513 // reload is being scheduled, so that e.g. canceling an existing load in 560 // reload is being scheduled, so that e.g. canceling an existing load in
514 // progress doesn't cause clients and observers to be notified of completion 561 // progress doesn't cause clients and observers to be notified of completion
515 // prematurely. 562 // prematurely.
516 DCHECK(!is_scheduling_reload_); 563 DCHECK(!is_scheduling_reload_);
517 is_scheduling_reload_ = true; 564 is_scheduling_reload_ = true;
518 565
519 SetCachePolicyBypassingCache(); 566 SetCachePolicyBypassingCache();
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 // reloading in Step 3 due to notifyObservers()'s 693 // reloading in Step 3 due to notifyObservers()'s
647 // schedulingReloadOrShouldReloadBrokenPlaceholder() check. 694 // schedulingReloadOrShouldReloadBrokenPlaceholder() check.
648 // 3. reloadIfLoFiOrPlaceholderImage() is called via ResourceFetcher 695 // 3. reloadIfLoFiOrPlaceholderImage() is called via ResourceFetcher
649 // (a) via didFinishLoading() called in decodeError(), or 696 // (a) via didFinishLoading() called in decodeError(), or
650 // (b) after returning ImageResource::updateImage(). 697 // (b) after returning ImageResource::updateImage().
651 DecodeError(all_data_received); 698 DecodeError(all_data_received);
652 } 699 }
653 } 700 }
654 701
655 } // namespace blink 702 } // namespace blink
OLDNEW
« no previous file with comments | « content/child/runtime_features.cc ('k') | third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698