blob: 61e0ef7e3a4fca4eacf6a9889fa7bdb2bdb7a930 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// 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_values.h"
#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
#include "third_party/blink/renderer/core/css/media_feature_overrides.h"
#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
#include "third_party/blink/renderer/core/css/media_values_dynamic.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/widget/frame_widget.h"
namespace blink {
mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme(
CSSValueID id) {
switch (id) {
case CSSValueID::kLight:
return mojom::blink::PreferredColorScheme::kLight;
case CSSValueID::kDark:
return mojom::blink::PreferredColorScheme::kDark;
default:
NOTREACHED();
return mojom::blink::PreferredColorScheme::kLight;
}
}
MediaValues* MediaValues::CreateDynamicIfFrameExists(LocalFrame* frame) {
if (frame)
return MediaValuesDynamic::Create(frame);
return MakeGarbageCollected<MediaValuesCached>();
}
double MediaValues::CalculateViewportWidth(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->View());
DCHECK(frame->GetDocument());
return frame->View()->ViewportSizeForMediaQueries().Width();
}
double MediaValues::CalculateViewportHeight(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->View());
DCHECK(frame->GetDocument());
return frame->View()->ViewportSizeForMediaQueries().Height();
}
int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
const ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
int device_width = screen_info.rect.width();
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
device_width = static_cast<int>(
lroundf(device_width * screen_info.device_scale_factor));
}
return device_width;
}
int MediaValues::CalculateDeviceHeight(LocalFrame* frame) {
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
const ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
int device_height = screen_info.rect.height();
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
device_height = static_cast<int>(
lroundf(device_height * screen_info.device_scale_factor));
}
return device_height;
}
bool MediaValues::CalculateStrictMode(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetDocument());
return !frame->GetDocument()->InQuirksMode();
}
float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) {
return frame->DevicePixelRatio();
}
int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
const ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
if (screen_info.is_monochrome)
return 0;
return screen_info.depth_per_component;
}
int MediaValues::CalculateMonochromeBitsPerComponent(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
const ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
if (!screen_info.is_monochrome)
return 0;
return screen_info.depth_per_component;
}
int MediaValues::CalculateDefaultFontSize(LocalFrame* frame) {
return frame->GetPage()->GetSettings().GetDefaultFontSize();
}
const String MediaValues::CalculateMediaType(LocalFrame* frame) {
DCHECK(frame);
if (!frame->View())
return g_empty_atom;
return frame->View()->MediaType();
}
mojom::blink::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) {
DCHECK(frame);
blink::mojom::DisplayMode mode =
frame->GetPage()->GetSettings().GetDisplayModeOverride();
if (mode != mojom::blink::DisplayMode::kUndefined)
return mode;
FrameWidget* widget = frame->GetWidgetForLocalRoot();
if (!widget) // Is null in non-ordinary Pages.
return mojom::blink::DisplayMode::kBrowser;
return widget->DisplayMode();
}
bool MediaValues::CalculateThreeDEnabled(LocalFrame* frame) {
return frame->GetPage()->GetSettings().GetAcceleratedCompositingEnabled();
}
bool MediaValues::CalculateInImmersiveMode(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetImmersiveModeEnabled();
}
mojom::blink::PointerType MediaValues::CalculatePrimaryPointerType(
LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetPrimaryPointerType();
}
int MediaValues::CalculateAvailablePointerTypes(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetAvailablePointerTypes();
}
mojom::blink::HoverType MediaValues::CalculatePrimaryHoverType(
LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetPrimaryHoverType();
}
int MediaValues::CalculateAvailableHoverTypes(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetAvailableHoverTypes();
}
ColorSpaceGamut MediaValues::CalculateColorGamut(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
MediaQueryExpValue value = overrides->GetOverride("color-gamut");
if (value.IsValid()) {
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;
NOTREACHED();
}
}
return color_space_utilities::GetColorSpaceGamut(
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame));
}
mojom::blink::PreferredColorScheme MediaValues::CalculatePreferredColorScheme(
LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
DCHECK(frame->GetDocument());
DCHECK(frame->GetPage());
if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme");
if (value.IsValid())
return CSSValueIDToPreferredColorScheme(value.id);
}
return frame->GetDocument()->GetStyleEngine().GetPreferredColorScheme();
}
mojom::blink::PreferredContrast MediaValues::CalculatePreferredContrast(
LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetPreferredContrast();
}
bool MediaValues::CalculatePrefersReducedMotion(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
MediaQueryExpValue value = overrides->GetOverride("prefers-reduced-motion");
if (value.IsValid())
return value.id == CSSValueID::kReduce;
}
return frame->GetSettings()->GetPrefersReducedMotion();
}
bool MediaValues::CalculatePrefersReducedData(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
MediaQueryExpValue value = overrides->GetOverride("prefers-reduced-data");
if (value.IsValid())
return value.id == CSSValueID::kReduce;
}
return (GetNetworkStateNotifier().SaveDataEnabled() &&
!frame->GetSettings()->GetDataSaverHoldbackWebApi());
}
ForcedColors MediaValues::CalculateForcedColors() {
if (Platform::Current() && Platform::Current()->ThemeEngine())
return Platform::Current()->ThemeEngine()->GetForcedColors();
else
return ForcedColors::kNone;
}
NavigationControls MediaValues::CalculateNavigationControls(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
return frame->GetSettings()->GetNavigationControls();
}
ScreenSpanning MediaValues::CalculateScreenSpanning(LocalFrame* frame) {
if (!frame->GetWidgetForLocalRoot())
return ScreenSpanning::kNone;
WebVector<gfx::Rect> window_segments =
frame->GetWidgetForLocalRoot()->WindowSegments();
if (window_segments.size() == 2) {
// If there are two segments and the y value of the segments is the same,
// we have side-by-side segments which are represented as a single vertical
// fold.
if (window_segments[0].y() == window_segments[1].y())
return ScreenSpanning::kSingleFoldVertical;
// If the x value of the segments is the same, we have stacked segments
// which are represented as a single horizontal fold.
if (window_segments[0].x() == window_segments[1].x())
return ScreenSpanning::kSingleFoldHorizontal;
}
return ScreenSpanning::kNone;
}
ScreenFoldPosture MediaValues::CalculateScreenFoldPosture(LocalFrame* frame) {
// TODO(darktears): Retrieve information from the host.
return ScreenFoldPosture::kNoFold;
}
bool MediaValues::ComputeLengthImpl(double value,
CSSPrimitiveValue::UnitType type,
unsigned default_font_size,
double viewport_width,
double viewport_height,
double& result) {
// The logic in this function is duplicated from
// CSSToLengthConversionData::ZoomedComputedPixels() because
// MediaValues::ComputeLength() needs nearly identical logic, but we haven't
// found a way to make CSSToLengthConversionData::ZoomedComputedPixels() more
// generic (to solve both cases) without hurting performance.
// FIXME - Unite the logic here with CSSToLengthConversionData in a performant
// way.
switch (type) {
case CSSPrimitiveValue::UnitType::kEms:
case CSSPrimitiveValue::UnitType::kRems:
result = value * default_font_size;
return true;
case CSSPrimitiveValue::UnitType::kPixels:
case CSSPrimitiveValue::UnitType::kUserUnits:
result = value;
return true;
case CSSPrimitiveValue::UnitType::kExs:
// FIXME: We have a bug right now where the zoom will be applied twice to EX
// units.
case CSSPrimitiveValue::UnitType::kChs:
// FIXME: We don't seem to be able to cache fontMetrics related values.
// Trying to access them is triggering some sort of microtask. Serving the
// spec's default instead.
result = (value * default_font_size) / 2.0;
return true;
case CSSPrimitiveValue::UnitType::kViewportWidth:
result = (value * viewport_width) / 100.0;
return true;
case CSSPrimitiveValue::UnitType::kViewportHeight:
result = (value * viewport_height) / 100.0;
return true;
case CSSPrimitiveValue::UnitType::kViewportMin:
result = (value * std::min(viewport_width, viewport_height)) / 100.0;
return true;
case CSSPrimitiveValue::UnitType::kViewportMax:
result = (value * std::max(viewport_width, viewport_height)) / 100.0;
return true;
case CSSPrimitiveValue::UnitType::kCentimeters:
result = value * kCssPixelsPerCentimeter;
return true;
case CSSPrimitiveValue::UnitType::kMillimeters:
result = value * kCssPixelsPerMillimeter;
return true;
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
result = value * kCssPixelsPerQuarterMillimeter;
return true;
case CSSPrimitiveValue::UnitType::kInches:
result = value * kCssPixelsPerInch;
return true;
case CSSPrimitiveValue::UnitType::kPoints:
result = value * kCssPixelsPerPoint;
return true;
case CSSPrimitiveValue::UnitType::kPicas:
result = value * kCssPixelsPerPica;
return true;
default:
return false;
}
}
} // namespace blink