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