blob: d1110c11c09e51513d0ef9afbacc35e3a5f1e0d3 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/media_feature_overrides.h"
#include "third_party/blink/renderer/core/css/media_features.h"
#include "third_party/blink/renderer/core/css/media_query_exp.h"
#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
namespace blink {
namespace {
std::optional<ColorSpaceGamut> ConvertColorGamut(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
if (value.Id() == CSSValueID::kSRGB) {
return ColorSpaceGamut::SRGB;
}
if (value.Id() == CSSValueID::kP3) {
return ColorSpaceGamut::P3;
}
// Rec. 2020 is also known as ITU-R-Empfehlung BT.2020.
if (value.Id() == CSSValueID::kRec2020) {
return ColorSpaceGamut::BT2020;
}
return std::nullopt;
}
std::optional<ForcedColors> ConvertForcedColors(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
return CSSValueIDToForcedColors(value.Id());
}
} // namespace
std::optional<mojom::blink::PreferredColorScheme>
MediaFeatureOverrides::ConvertPreferredColorScheme(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
return CSSValueIDToPreferredColorScheme(value.Id());
}
std::optional<mojom::blink::PreferredContrast>
MediaFeatureOverrides::ConvertPreferredContrast(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
return CSSValueIDToPreferredContrast(value.Id());
}
std::optional<bool> MediaFeatureOverrides::ConvertPrefersReducedMotion(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
return value.Id() == CSSValueID::kReduce;
}
std::optional<bool> MediaFeatureOverrides::ConvertPrefersReducedData(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
return value.Id() == CSSValueID::kReduce;
}
std::optional<bool> MediaFeatureOverrides::ConvertPrefersReducedTransparency(
const MediaQueryExpValue& value) {
if (!value.IsValid()) {
return std::nullopt;
}
return value.Id() == CSSValueID::kReduce;
}
MediaQueryExpValue MediaFeatureOverrides::ParseMediaQueryValue(
const AtomicString& feature,
const String& value_string) {
CSSTokenizer tokenizer(value_string);
auto [tokens, raw_offsets] = tokenizer.TokenizeToEOFWithOffsets();
CSSParserTokenRange range(tokens);
CSSParserTokenOffsets offsets(tokens, std::move(raw_offsets), value_string);
// TODO(xiaochengh): This is a fake CSSParserContext that only passes
// down the CSSParserMode. Plumb the real CSSParserContext through, so that
// web features can be counted correctly.
const CSSParserContext* fake_context = MakeGarbageCollected<CSSParserContext>(
kHTMLStandardMode, SecureContextMode::kInsecureContext);
// MediaFeatureOverrides are used to emulate various media feature values.
// These don't need to pass an ExecutionContext, since the parsing of
// the actual CSS will determine whether or not the emulated values will come
// into play (i.e. if you can parse an origin trial enabled feature, you
// will never ask for the emulated override value).
// Note that once a real CSSParserContext is plumbed through we can use its
// Document to get the ExecutionContext so the extra parameter should be
// removed.
MediaQueryExpBounds bounds =
MediaQueryExp::Create(feature, range, offsets, *fake_context).Bounds();
DCHECK(!bounds.left.IsValid());
return bounds.right.value;
}
void MediaFeatureOverrides::SetOverride(const AtomicString& feature,
const String& value_string) {
MediaQueryExpValue value = ParseMediaQueryValue(feature, value_string);
if (feature == media_feature_names::kColorGamutMediaFeature) {
color_gamut_ = ConvertColorGamut(value);
} else if (feature == media_feature_names::kPrefersColorSchemeMediaFeature) {
preferred_color_scheme_ = ConvertPreferredColorScheme(value);
} else if (feature == media_feature_names::kPrefersContrastMediaFeature) {
preferred_contrast_ = ConvertPreferredContrast(value);
} else if (feature ==
media_feature_names::kPrefersReducedMotionMediaFeature) {
prefers_reduced_motion_ = ConvertPrefersReducedMotion(value);
} else if (feature == media_feature_names::kPrefersReducedDataMediaFeature) {
prefers_reduced_data_ = ConvertPrefersReducedData(value);
} else if (feature ==
media_feature_names::kPrefersReducedTransparencyMediaFeature) {
prefers_reduced_transparency_ = ConvertPrefersReducedTransparency(value);
} else if (feature == media_feature_names::kForcedColorsMediaFeature) {
forced_colors_ = ConvertForcedColors(value);
}
}
} // namespace blink