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.