diff --git a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc b/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc index c794037e2454c9..b0ee1b05f6ee1c 100644 --- a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc +++ b/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc @@ -46,6 +46,7 @@ #include "third_party/blink/renderer/platform/json/json_values.h" #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/text/character_visitor.h" #include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" @@ -425,10 +426,20 @@ static ImageCandidate PickBestImageCandidate( Vector& image_candidates, Document* document = nullptr) { const float kDefaultDensityValue = 1.0; + // The srcset image source selection mechanism is user-agent specific: + // https://html.spec.whatwg.org/multipage/images.html#selecting-an-image-source + // + // Setting max density value based on https://github.com/whatwg/html/pull/5901 + const float kMaxDensity = 2.2; bool ignore_src = false; if (image_candidates.IsEmpty()) return ImageCandidate(); + if (RuntimeEnabledFeatures::SrcsetMaxDensityEnabled() && + device_scale_factor > kMaxDensity) { + device_scale_factor = kMaxDensity; + } + // http://picture.responsiveimages.org/#normalize-source-densities for (ImageCandidate& image : image_candidates) { if (image.GetResourceWidth() > 0) { diff --git a/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc b/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc index 9b8791ad9dbdb4..856ec9c3d8656a 100644 --- a/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc +++ b/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc @@ -10,6 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/web_network_state_notifier.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -323,4 +324,25 @@ TEST(HTMLSrcsetParserTest, SaveDataEnabledBasic) { } } +TEST(HTMLSrcsetParserTest, MaxDensityEnabled) { + RuntimeEnabledFeatures::SetSrcsetMaxDensityEnabled(true); + SrcsetParserTestCase test_cases[] = { + {10.0, -1, "src.gif", "2x.gif 2e1x", "src.gif", 1.0, -1}, + {2.5, -1, "src.gif", "1.5x.gif 1.5x, 3x.gif 3x", "3x.gif", 3.0, -1}, + {4.0, 400, "", "400.gif 400w, 1000.gif 1000w", "1000.gif", 2.5, 1000}, + {0, 0, nullptr, nullptr, nullptr, + 0} // Do not remove the terminator line. + }; + + for (unsigned i = 0; test_cases[i].src_input; ++i) { + SrcsetParserTestCase test = test_cases[i]; + ImageCandidate candidate = BestFitSourceForImageAttributes( + test.device_scale_factor, test.effective_size, test.src_input, + test.srcset_input); + ASSERT_EQ(test.output_density, candidate.Density()); + ASSERT_EQ(test.output_resource_width, candidate.GetResourceWidth()); + ASSERT_EQ(test.output_url, candidate.ToString().Ascii()); + } +} + } // namespace blink diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ebc165d852696f..437ad78eddd374 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 @@ -1784,6 +1784,9 @@ name: "SmsReceiver", status: {"default": "experimental", "Android": "stable"}, }, + { + name: "SrcsetMaxDensity", + }, // Used as argument in attribute of stable-release functions/interfaces // where a runtime-enabled feature name is required for correct IDL syntax. // This is a global flag; do not change its status.