1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/core/css/media_values.h"
6
7 #include "third_party/blink/public/platform/platform.h"
8 #include "third_party/blink/public/platform/web_screen_info.h"
9 #include "third_party/blink/public/platform/web_theme_engine.h"
10 #include "third_party/blink/renderer/core/css/css_resolution_units.h"
11 #include "third_party/blink/renderer/core/css/media_feature_overrides.h"
12 #include "third_party/blink/renderer/core/css/media_values_cached.h"
13 #include "third_party/blink/renderer/core/css/media_values_dynamic.h"
14 #include "third_party/blink/renderer/core/dom/document.h"
15 #include "third_party/blink/renderer/core/dom/element.h"
16 #include "third_party/blink/renderer/core/frame/local_frame.h"
17 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
18 #include "third_party/blink/renderer/core/frame/settings.h"
19 #include "third_party/blink/renderer/core/layout/layout_object.h"
20 #include "third_party/blink/renderer/core/layout/layout_view.h"
21 #include "third_party/blink/renderer/core/page/chrome_client.h"
22 #include "third_party/blink/renderer/core/page/page.h"
23 #include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
24
25 namespace blink {
26
CSSValueIDToPreferredColorScheme(CSSValueID id)27 PreferredColorScheme CSSValueIDToPreferredColorScheme(CSSValueID id) {
28 switch (id) {
29 case CSSValueID::kNoPreference:
30 return PreferredColorScheme::kNoPreference;
31 case CSSValueID::kLight:
32 return PreferredColorScheme::kLight;
33 case CSSValueID::kDark:
34 return PreferredColorScheme::kDark;
35 default:
36 NOTREACHED();
37 return PreferredColorScheme::kNoPreference;
38 }
39 }
40
CreateDynamicIfFrameExists(LocalFrame * frame)41 MediaValues* MediaValues::CreateDynamicIfFrameExists(LocalFrame* frame) {
42 if (frame)
43 return MediaValuesDynamic::Create(frame);
44 return MakeGarbageCollected<MediaValuesCached>();
45 }
46
CalculateViewportWidth(LocalFrame * frame)47 double MediaValues::CalculateViewportWidth(LocalFrame* frame) {
48 DCHECK(frame);
49 DCHECK(frame->View());
50 DCHECK(frame->GetDocument());
51 return frame->View()->ViewportSizeForMediaQueries().Width();
52 }
53
CalculateViewportHeight(LocalFrame * frame)54 double MediaValues::CalculateViewportHeight(LocalFrame* frame) {
55 DCHECK(frame);
56 DCHECK(frame->View());
57 DCHECK(frame->GetDocument());
58 return frame->View()->ViewportSizeForMediaQueries().Height();
59 }
60
CalculateDeviceWidth(LocalFrame * frame)61 int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
62 DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
63 blink::WebScreenInfo screen_info =
64 frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
65 int device_width = screen_info.rect.width;
66 if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
67 device_width = static_cast<int>(
68 lroundf(device_width * screen_info.device_scale_factor));
69 }
70 return device_width;
71 }
72
CalculateDeviceHeight(LocalFrame * frame)73 int MediaValues::CalculateDeviceHeight(LocalFrame* frame) {
74 DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
75 blink::WebScreenInfo screen_info =
76 frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
77 int device_height = screen_info.rect.height;
78 if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
79 device_height = static_cast<int>(
80 lroundf(device_height * screen_info.device_scale_factor));
81 }
82 return device_height;
83 }
84
CalculateStrictMode(LocalFrame * frame)85 bool MediaValues::CalculateStrictMode(LocalFrame* frame) {
86 DCHECK(frame);
87 DCHECK(frame->GetDocument());
88 return !frame->GetDocument()->InQuirksMode();
89 }
90
CalculateDevicePixelRatio(LocalFrame * frame)91 float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) {
92 return frame->DevicePixelRatio();
93 }
94
CalculateColorBitsPerComponent(LocalFrame * frame)95 int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) {
96 DCHECK(frame);
97 DCHECK(frame->GetPage());
98 WebScreenInfo screen_info =
99 frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
100 if (screen_info.is_monochrome)
101 return 0;
102 return screen_info.depth_per_component;
103 }
104
CalculateMonochromeBitsPerComponent(LocalFrame * frame)105 int MediaValues::CalculateMonochromeBitsPerComponent(LocalFrame* frame) {
106 DCHECK(frame);
107 DCHECK(frame->GetPage());
108 WebScreenInfo screen_info =
109 frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
110 if (!screen_info.is_monochrome)
111 return 0;
112 return screen_info.depth_per_component;
113 }
114
CalculateDefaultFontSize(LocalFrame * frame)115 int MediaValues::CalculateDefaultFontSize(LocalFrame* frame) {
116 return frame->GetPage()->GetSettings().GetDefaultFontSize();
117 }
118
CalculateMediaType(LocalFrame * frame)119 const String MediaValues::CalculateMediaType(LocalFrame* frame) {
120 DCHECK(frame);
121 if (!frame->View())
122 return g_empty_atom;
123 return frame->View()->MediaType();
124 }
125
CalculateDisplayMode(LocalFrame * frame)126 blink::mojom::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) {
127 DCHECK(frame);
128 blink::mojom::DisplayMode mode =
129 frame->GetPage()->GetSettings().GetDisplayModeOverride();
130
131 if (mode != blink::mojom::DisplayMode::kUndefined)
132 return mode;
133
134 if (!frame->View())
135 return blink::mojom::DisplayMode::kBrowser;
136
137 return frame->View()->DisplayMode();
138 }
139
CalculateThreeDEnabled(LocalFrame * frame)140 bool MediaValues::CalculateThreeDEnabled(LocalFrame* frame) {
141 return frame->GetPage()->GetSettings().GetAcceleratedCompositingEnabled();
142 }
143
CalculateInImmersiveMode(LocalFrame * frame)144 bool MediaValues::CalculateInImmersiveMode(LocalFrame* frame) {
145 DCHECK(frame);
146 DCHECK(frame->GetSettings());
147 return frame->GetSettings()->GetImmersiveModeEnabled();
148 }
149
CalculatePrimaryPointerType(LocalFrame * frame)150 PointerType MediaValues::CalculatePrimaryPointerType(LocalFrame* frame) {
151 DCHECK(frame);
152 DCHECK(frame->GetSettings());
153 return frame->GetSettings()->GetPrimaryPointerType();
154 }
155
CalculateAvailablePointerTypes(LocalFrame * frame)156 int MediaValues::CalculateAvailablePointerTypes(LocalFrame* frame) {
157 DCHECK(frame);
158 DCHECK(frame->GetSettings());
159 return frame->GetSettings()->GetAvailablePointerTypes();
160 }
161
CalculatePrimaryHoverType(LocalFrame * frame)162 HoverType MediaValues::CalculatePrimaryHoverType(LocalFrame* frame) {
163 DCHECK(frame);
164 DCHECK(frame->GetSettings());
165 return frame->GetSettings()->GetPrimaryHoverType();
166 }
167
CalculateAvailableHoverTypes(LocalFrame * frame)168 int MediaValues::CalculateAvailableHoverTypes(LocalFrame* frame) {
169 DCHECK(frame);
170 DCHECK(frame->GetSettings());
171 return frame->GetSettings()->GetAvailableHoverTypes();
172 }
173
CalculateDisplayShape(LocalFrame * frame)174 DisplayShape MediaValues::CalculateDisplayShape(LocalFrame* frame) {
175 DCHECK(frame);
176 DCHECK(frame->GetPage());
177 return frame->GetPage()
178 ->GetChromeClient()
179 .GetScreenInfo(*frame)
180 .display_shape;
181 }
182
CalculateColorGamut(LocalFrame * frame)183 ColorSpaceGamut MediaValues::CalculateColorGamut(LocalFrame* frame) {
184 DCHECK(frame);
185 DCHECK(frame->GetPage());
186 return color_space_utilities::GetColorSpaceGamut(
187 frame->GetPage()->GetChromeClient().GetScreenInfo(*frame));
188 }
189
CalculatePreferredColorScheme(LocalFrame * frame)190 PreferredColorScheme MediaValues::CalculatePreferredColorScheme(
191 LocalFrame* frame) {
192 DCHECK(frame);
193 DCHECK(frame->GetSettings());
194 DCHECK(frame->GetDocument());
195 DCHECK(frame->GetPage());
196 if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
197 MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme");
198 if (value.IsValid())
199 return CSSValueIDToPreferredColorScheme(value.id);
200 }
201 return frame->GetDocument()->GetStyleEngine().GetPreferredColorScheme();
202 }
203
CalculatePrefersReducedMotion(LocalFrame * frame)204 bool MediaValues::CalculatePrefersReducedMotion(LocalFrame* frame) {
205 DCHECK(frame);
206 DCHECK(frame->GetSettings());
207 if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
208 MediaQueryExpValue value = overrides->GetOverride("prefers-reduced-motion");
209 if (value.IsValid())
210 return value.id == CSSValueID::kReduce;
211 }
212 return frame->GetSettings()->GetPrefersReducedMotion();
213 }
214
CalculateForcedColors()215 ForcedColors MediaValues::CalculateForcedColors() {
216 if (Platform::Current() && Platform::Current()->ThemeEngine())
217 return Platform::Current()->ThemeEngine()->GetForcedColors();
218 else
219 return ForcedColors::kNone;
220 }
221
CalculateNavigationControls(LocalFrame * frame)222 NavigationControls MediaValues::CalculateNavigationControls(LocalFrame* frame) {
223 DCHECK(frame);
224 DCHECK(frame->GetSettings());
225 return frame->GetSettings()->GetNavigationControls();
226 }
227
ComputeLengthImpl(double value,CSSPrimitiveValue::UnitType type,unsigned default_font_size,double viewport_width,double viewport_height,double & result)228 bool MediaValues::ComputeLengthImpl(double value,
229 CSSPrimitiveValue::UnitType type,
230 unsigned default_font_size,
231 double viewport_width,
232 double viewport_height,
233 double& result) {
234 // The logic in this function is duplicated from
235 // CSSToLengthConversionData::ZoomedComputedPixels() because
236 // MediaValues::ComputeLength() needs nearly identical logic, but we haven't
237 // found a way to make CSSToLengthConversionData::ZoomedComputedPixels() more
238 // generic (to solve both cases) without hurting performance.
239 // FIXME - Unite the logic here with CSSToLengthConversionData in a performant
240 // way.
241 switch (type) {
242 case CSSPrimitiveValue::UnitType::kEms:
243 case CSSPrimitiveValue::UnitType::kRems:
244 result = value * default_font_size;
245 return true;
246 case CSSPrimitiveValue::UnitType::kPixels:
247 case CSSPrimitiveValue::UnitType::kUserUnits:
248 result = value;
249 return true;
250 case CSSPrimitiveValue::UnitType::kExs:
251 // FIXME: We have a bug right now where the zoom will be applied twice to EX
252 // units.
253 case CSSPrimitiveValue::UnitType::kChs:
254 // FIXME: We don't seem to be able to cache fontMetrics related values.
255 // Trying to access them is triggering some sort of microtask. Serving the
256 // spec's default instead.
257 result = (value * default_font_size) / 2.0;
258 return true;
259 case CSSPrimitiveValue::UnitType::kViewportWidth:
260 result = (value * viewport_width) / 100.0;
261 return true;
262 case CSSPrimitiveValue::UnitType::kViewportHeight:
263 result = (value * viewport_height) / 100.0;
264 return true;
265 case CSSPrimitiveValue::UnitType::kViewportMin:
266 result = (value * std::min(viewport_width, viewport_height)) / 100.0;
267 return true;
268 case CSSPrimitiveValue::UnitType::kViewportMax:
269 result = (value * std::max(viewport_width, viewport_height)) / 100.0;
270 return true;
271 case CSSPrimitiveValue::UnitType::kCentimeters:
272 result = value * kCssPixelsPerCentimeter;
273 return true;
274 case CSSPrimitiveValue::UnitType::kMillimeters:
275 result = value * kCssPixelsPerMillimeter;
276 return true;
277 case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
278 result = value * kCssPixelsPerQuarterMillimeter;
279 return true;
280 case CSSPrimitiveValue::UnitType::kInches:
281 result = value * kCssPixelsPerInch;
282 return true;
283 case CSSPrimitiveValue::UnitType::kPoints:
284 result = value * kCssPixelsPerPoint;
285 return true;
286 case CSSPrimitiveValue::UnitType::kPicas:
287 result = value * kCssPixelsPerPica;
288 return true;
289 default:
290 return false;
291 }
292 }
293
294 } // namespace blink
295