1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 /* the features that media queries can test */
8
9 #include "nsMediaFeatures.h"
10 #include "nsGkAtoms.h"
11 #include "nsCSSKeywords.h"
12 #include "nsStyleConsts.h"
13 #include "nsPresContext.h"
14 #include "nsCSSValue.h"
15 #ifdef XP_WIN
16 #include "mozilla/LookAndFeel.h"
17 #endif
18 #include "nsCSSRuleProcessor.h"
19 #include "nsDeviceContext.h"
20 #include "nsIBaseWindow.h"
21 #include "nsIDocument.h"
22 #include "nsContentUtils.h"
23 #include "mozilla/StyleSheet.h"
24 #include "mozilla/StyleSheetInlines.h"
25
26 using namespace mozilla;
27
28 static const nsCSSProps::KTableEntry kOrientationKeywords[] = {
29 { eCSSKeyword_portrait, NS_STYLE_ORIENTATION_PORTRAIT },
30 { eCSSKeyword_landscape, NS_STYLE_ORIENTATION_LANDSCAPE },
31 { eCSSKeyword_UNKNOWN, -1 }
32 };
33
34 static const nsCSSProps::KTableEntry kScanKeywords[] = {
35 { eCSSKeyword_progressive, NS_STYLE_SCAN_PROGRESSIVE },
36 { eCSSKeyword_interlace, NS_STYLE_SCAN_INTERLACE },
37 { eCSSKeyword_UNKNOWN, -1 }
38 };
39
40 static const nsCSSProps::KTableEntry kDisplayModeKeywords[] = {
41 { eCSSKeyword_browser, NS_STYLE_DISPLAY_MODE_BROWSER },
42 { eCSSKeyword_minimal_ui, NS_STYLE_DISPLAY_MODE_MINIMAL_UI },
43 { eCSSKeyword_standalone, NS_STYLE_DISPLAY_MODE_STANDALONE },
44 { eCSSKeyword_fullscreen, NS_STYLE_DISPLAY_MODE_FULLSCREEN },
45 { eCSSKeyword_UNKNOWN, -1 }
46 };
47
48 #ifdef XP_WIN
49 struct WindowsThemeName {
50 LookAndFeel::WindowsTheme id;
51 const wchar_t* name;
52 };
53
54 // Windows theme identities used in the -moz-windows-theme media query.
55 const WindowsThemeName themeStrings[] = {
56 { LookAndFeel::eWindowsTheme_Aero, L"aero" },
57 { LookAndFeel::eWindowsTheme_AeroLite, L"aero-lite" },
58 { LookAndFeel::eWindowsTheme_LunaBlue, L"luna-blue" },
59 { LookAndFeel::eWindowsTheme_LunaOlive, L"luna-olive" },
60 { LookAndFeel::eWindowsTheme_LunaSilver, L"luna-silver" },
61 { LookAndFeel::eWindowsTheme_Royale, L"royale" },
62 { LookAndFeel::eWindowsTheme_Zune, L"zune" },
63 { LookAndFeel::eWindowsTheme_Generic, L"generic" }
64 };
65
66 struct OperatingSystemVersionInfo {
67 LookAndFeel::OperatingSystemVersion id;
68 const wchar_t* name;
69 };
70
71 // Os version identities used in the -moz-os-version media query.
72 const OperatingSystemVersionInfo osVersionStrings[] = {
73 { LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" },
74 { LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" },
75 { LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" },
76 { LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" },
77 { LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" }
78 };
79 #endif
80
81 // A helper for four features below
82 static nsSize
GetSize(nsPresContext * aPresContext)83 GetSize(nsPresContext* aPresContext)
84 {
85 nsSize size;
86 if (aPresContext->IsRootPaginatedDocument())
87 // We want the page size, including unprintable areas and margins.
88 size = aPresContext->GetPageSize();
89 else
90 size = aPresContext->GetVisibleArea().Size();
91 return size;
92 }
93
94 static nsresult
GetWidth(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)95 GetWidth(nsPresContext* aPresContext, const nsMediaFeature*,
96 nsCSSValue& aResult)
97 {
98 nsSize size = GetSize(aPresContext);
99 float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
100 aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
101 return NS_OK;
102 }
103
104 static nsresult
GetHeight(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)105 GetHeight(nsPresContext* aPresContext, const nsMediaFeature*,
106 nsCSSValue& aResult)
107 {
108 nsSize size = GetSize(aPresContext);
109 float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
110 aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
111 return NS_OK;
112 }
113
114 inline static nsDeviceContext*
GetDeviceContextFor(nsPresContext * aPresContext)115 GetDeviceContextFor(nsPresContext* aPresContext)
116 {
117 // It would be nice to call
118 // nsLayoutUtils::GetDeviceContextForScreenInfo here, except for two
119 // things: (1) it can flush, and flushing is bad here, and (2) it
120 // doesn't really get us consistency in multi-monitor situations
121 // *anyway*.
122 return aPresContext->DeviceContext();
123 }
124
125 static bool
ShouldResistFingerprinting(nsPresContext * aPresContext)126 ShouldResistFingerprinting(nsPresContext* aPresContext)
127 {
128 return nsContentUtils::ShouldResistFingerprinting(aPresContext->GetDocShell());
129 }
130
131 // A helper for three features below.
132 static nsSize
GetDeviceSize(nsPresContext * aPresContext)133 GetDeviceSize(nsPresContext* aPresContext)
134 {
135 nsSize size;
136
137 if (ShouldResistFingerprinting(aPresContext) || aPresContext->IsDeviceSizePageSize()) {
138 size = GetSize(aPresContext);
139 } else if (aPresContext->IsRootPaginatedDocument()) {
140 // We want the page size, including unprintable areas and margins.
141 // XXX The spec actually says we want the "page sheet size", but
142 // how is that different?
143 size = aPresContext->GetPageSize();
144 } else {
145 GetDeviceContextFor(aPresContext)->
146 GetDeviceSurfaceDimensions(size.width, size.height);
147 }
148 return size;
149 }
150
151 static nsresult
GetDeviceWidth(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)152 GetDeviceWidth(nsPresContext* aPresContext, const nsMediaFeature*,
153 nsCSSValue& aResult)
154 {
155 nsSize size = GetDeviceSize(aPresContext);
156 float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
157 aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
158 return NS_OK;
159 }
160
161 static nsresult
GetDeviceHeight(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)162 GetDeviceHeight(nsPresContext* aPresContext, const nsMediaFeature*,
163 nsCSSValue& aResult)
164 {
165 nsSize size = GetDeviceSize(aPresContext);
166 float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
167 aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
168 return NS_OK;
169 }
170
171 static nsresult
GetOrientation(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)172 GetOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
173 nsCSSValue& aResult)
174 {
175 nsSize size = GetSize(aPresContext);
176 int32_t orientation;
177 if (size.width > size.height) {
178 orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
179 } else {
180 // Per spec, square viewports should be 'portrait'
181 orientation = NS_STYLE_ORIENTATION_PORTRAIT;
182 }
183
184 aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
185 return NS_OK;
186 }
187
188 static nsresult
GetDeviceOrientation(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)189 GetDeviceOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
190 nsCSSValue& aResult)
191 {
192 nsSize size = GetDeviceSize(aPresContext);
193 int32_t orientation;
194 if (size.width > size.height) {
195 orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
196 } else {
197 // Per spec, square viewports should be 'portrait'
198 orientation = NS_STYLE_ORIENTATION_PORTRAIT;
199 }
200
201 aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
202 return NS_OK;
203 }
204
205 static nsresult
GetIsResourceDocument(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)206 GetIsResourceDocument(nsPresContext* aPresContext, const nsMediaFeature*,
207 nsCSSValue& aResult)
208 {
209 nsIDocument* doc = aPresContext->Document();
210 aResult.SetIntValue(doc && doc->IsResourceDoc() ? 1 : 0, eCSSUnit_Integer);
211 return NS_OK;
212 }
213
214 // Helper for two features below
215 static nsresult
MakeArray(const nsSize & aSize,nsCSSValue & aResult)216 MakeArray(const nsSize& aSize, nsCSSValue& aResult)
217 {
218 RefPtr<nsCSSValue::Array> a = nsCSSValue::Array::Create(2);
219
220 a->Item(0).SetIntValue(aSize.width, eCSSUnit_Integer);
221 a->Item(1).SetIntValue(aSize.height, eCSSUnit_Integer);
222
223 aResult.SetArrayValue(a, eCSSUnit_Array);
224 return NS_OK;
225 }
226
227 static nsresult
GetAspectRatio(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)228 GetAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
229 nsCSSValue& aResult)
230 {
231 return MakeArray(GetSize(aPresContext), aResult);
232 }
233
234 static nsresult
GetDeviceAspectRatio(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)235 GetDeviceAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
236 nsCSSValue& aResult)
237 {
238 return MakeArray(GetDeviceSize(aPresContext), aResult);
239 }
240
241 static nsresult
GetColor(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)242 GetColor(nsPresContext* aPresContext, const nsMediaFeature*,
243 nsCSSValue& aResult)
244 {
245 uint32_t depth = 24; // Use depth of 24 when resisting fingerprinting.
246
247 if (!ShouldResistFingerprinting(aPresContext)) {
248 // FIXME: This implementation is bogus. nsDeviceContext
249 // doesn't provide reliable information (should be fixed in bug
250 // 424386).
251 // FIXME: On a monochrome device, return 0!
252 nsDeviceContext *dx = GetDeviceContextFor(aPresContext);
253 dx->GetDepth(depth);
254 }
255
256 // The spec says to use bits *per color component*, so divide by 3,
257 // and round down, since the spec says to use the smallest when the
258 // color components differ.
259 depth /= 3;
260 aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer);
261 return NS_OK;
262 }
263
264 static nsresult
GetColorIndex(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)265 GetColorIndex(nsPresContext* aPresContext, const nsMediaFeature*,
266 nsCSSValue& aResult)
267 {
268 // We should return zero if the device does not use a color lookup
269 // table. Stuart says that our handling of displays with 8-bit
270 // color is bad enough that we never change the lookup table to
271 // match what we're trying to display, so perhaps we should always
272 // return zero. Given that there isn't any better information
273 // exposed, we don't have much other choice.
274 aResult.SetIntValue(0, eCSSUnit_Integer);
275 return NS_OK;
276 }
277
278 static nsresult
GetMonochrome(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)279 GetMonochrome(nsPresContext* aPresContext, const nsMediaFeature*,
280 nsCSSValue& aResult)
281 {
282 // For color devices we should return 0.
283 // FIXME: On a monochrome device, return the actual color depth, not
284 // 0!
285 aResult.SetIntValue(0, eCSSUnit_Integer);
286 return NS_OK;
287 }
288
289 static nsresult
GetResolution(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)290 GetResolution(nsPresContext* aPresContext, const nsMediaFeature*,
291 nsCSSValue& aResult)
292 {
293 float dpi = 96; // Use 96 when resisting fingerprinting.
294
295 if (!ShouldResistFingerprinting(aPresContext)) {
296 // Resolution measures device pixels per CSS (inch/cm/pixel). We
297 // return it in device pixels per CSS inches.
298 dpi = float(nsPresContext::AppUnitsPerCSSInch()) /
299 float(aPresContext->AppUnitsPerDevPixel());
300 }
301
302 aResult.SetFloatValue(dpi, eCSSUnit_Inch);
303 return NS_OK;
304 }
305
306 static nsresult
GetScan(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)307 GetScan(nsPresContext* aPresContext, const nsMediaFeature*,
308 nsCSSValue& aResult)
309 {
310 // Since Gecko doesn't support the 'tv' media type, the 'scan'
311 // feature is never present.
312 aResult.Reset();
313 return NS_OK;
314 }
315
316 static nsresult
GetDisplayMode(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)317 GetDisplayMode(nsPresContext* aPresContext, const nsMediaFeature*,
318 nsCSSValue& aResult)
319 {
320 nsCOMPtr<nsISupports> container;
321 if (aPresContext) {
322 // Calling GetRootPresContext() can be slow, so make sure to call it
323 // just once.
324 nsRootPresContext* root = aPresContext->GetRootPresContext();
325 if (root && root->Document()) {
326 container = root->Document()->GetContainer();
327 }
328 }
329 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
330 if (!baseWindow) {
331 aResult.SetIntValue(NS_STYLE_DISPLAY_MODE_BROWSER, eCSSUnit_Enumerated);
332 return NS_OK;
333 }
334 nsCOMPtr<nsIWidget> mainWidget;
335 baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
336 int32_t displayMode;
337 nsSizeMode mode = mainWidget ? mainWidget->SizeMode() : nsSizeMode_Normal;
338 // Background tabs are always in 'browser' mode for now.
339 // If new modes are supported, please ensure not cause the regression in
340 // Bug 1259641.
341 switch (mode) {
342 case nsSizeMode_Fullscreen:
343 displayMode = NS_STYLE_DISPLAY_MODE_FULLSCREEN;
344 break;
345 default:
346 displayMode = NS_STYLE_DISPLAY_MODE_BROWSER;
347 break;
348 }
349
350 aResult.SetIntValue(displayMode, eCSSUnit_Enumerated);
351 return NS_OK;
352 }
353
354 static nsresult
GetGrid(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)355 GetGrid(nsPresContext* aPresContext, const nsMediaFeature*,
356 nsCSSValue& aResult)
357 {
358 // Gecko doesn't support grid devices (e.g., ttys), so the 'grid'
359 // feature is always 0.
360 aResult.SetIntValue(0, eCSSUnit_Integer);
361 return NS_OK;
362 }
363
364 static nsresult
GetDevicePixelRatio(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)365 GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*,
366 nsCSSValue& aResult)
367 {
368 if (!ShouldResistFingerprinting(aPresContext)) {
369 float ratio = aPresContext->CSSPixelsToDevPixels(1.0f);
370 aResult.SetFloatValue(ratio, eCSSUnit_Number);
371 } else {
372 aResult.SetFloatValue(1.0, eCSSUnit_Number);
373 }
374 return NS_OK;
375 }
376
377 static nsresult
GetTransform3d(nsPresContext * aPresContext,const nsMediaFeature *,nsCSSValue & aResult)378 GetTransform3d(nsPresContext* aPresContext, const nsMediaFeature*,
379 nsCSSValue& aResult)
380 {
381 // Gecko supports 3d transforms, so this feature is always 1.
382 aResult.SetIntValue(1, eCSSUnit_Integer);
383 return NS_OK;
384 }
385
386 static nsresult
GetSystemMetric(nsPresContext * aPresContext,const nsMediaFeature * aFeature,nsCSSValue & aResult)387 GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
388 nsCSSValue& aResult)
389 {
390 aResult.Reset();
391 if (ShouldResistFingerprinting(aPresContext)) {
392 // If "privacy.resistFingerprinting" is enabled, then we simply don't
393 // return any system-backed media feature values. (No spoofed values returned.)
394 return NS_OK;
395 }
396
397 MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
398 "unexpected type");
399 nsIAtom *metricAtom = *aFeature->mData.mMetric;
400 bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom);
401 aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
402 return NS_OK;
403 }
404
405 static nsresult
GetWindowsTheme(nsPresContext * aPresContext,const nsMediaFeature * aFeature,nsCSSValue & aResult)406 GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
407 nsCSSValue& aResult)
408 {
409 aResult.Reset();
410 if (ShouldResistFingerprinting(aPresContext)) {
411 return NS_OK;
412 }
413
414 #ifdef XP_WIN
415 uint8_t windowsThemeId =
416 nsCSSRuleProcessor::GetWindowsThemeIdentifier();
417
418 // Classic mode should fail to match.
419 if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic)
420 return NS_OK;
421
422 // Look up the appropriate theme string
423 for (size_t i = 0; i < ArrayLength(themeStrings); ++i) {
424 if (windowsThemeId == themeStrings[i].id) {
425 aResult.SetStringValue(nsDependentString(themeStrings[i].name),
426 eCSSUnit_Ident);
427 break;
428 }
429 }
430 #endif
431 return NS_OK;
432 }
433
434 static nsresult
GetOperatingSystemVersion(nsPresContext * aPresContext,const nsMediaFeature * aFeature,nsCSSValue & aResult)435 GetOperatingSystemVersion(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
436 nsCSSValue& aResult)
437 {
438 aResult.Reset();
439 if (ShouldResistFingerprinting(aPresContext)) {
440 return NS_OK;
441 }
442
443 #ifdef XP_WIN
444 int32_t metricResult;
445 if (NS_SUCCEEDED(
446 LookAndFeel::GetInt(LookAndFeel::eIntID_OperatingSystemVersionIdentifier,
447 &metricResult))) {
448 for (size_t i = 0; i < ArrayLength(osVersionStrings); ++i) {
449 if (metricResult == osVersionStrings[i].id) {
450 aResult.SetStringValue(nsDependentString(osVersionStrings[i].name),
451 eCSSUnit_Ident);
452 break;
453 }
454 }
455 }
456 #endif
457 return NS_OK;
458 }
459
460 static nsresult
GetIsGlyph(nsPresContext * aPresContext,const nsMediaFeature * aFeature,nsCSSValue & aResult)461 GetIsGlyph(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
462 nsCSSValue& aResult)
463 {
464 aResult.SetIntValue(aPresContext->IsGlyph() ? 1 : 0, eCSSUnit_Integer);
465 return NS_OK;
466 }
467
468 /*
469 * Adding new media features requires (1) adding the new feature to this
470 * array, with appropriate entries (and potentially any new code needed
471 * to support new types in these entries and (2) ensuring that either
472 * nsPresContext::MediaFeatureValuesChanged or
473 * nsPresContext::PostMediaFeatureValuesChangedEvent is called when the
474 * value that would be returned by the entry's mGetter changes.
475 */
476
477 /* static */ const nsMediaFeature
478 nsMediaFeatures::features[] = {
479 {
480 &nsGkAtoms::width,
481 nsMediaFeature::eMinMaxAllowed,
482 nsMediaFeature::eLength,
483 nsMediaFeature::eNoRequirements,
484 { nullptr },
485 GetWidth
486 },
487 {
488 &nsGkAtoms::height,
489 nsMediaFeature::eMinMaxAllowed,
490 nsMediaFeature::eLength,
491 nsMediaFeature::eNoRequirements,
492 { nullptr },
493 GetHeight
494 },
495 {
496 &nsGkAtoms::deviceWidth,
497 nsMediaFeature::eMinMaxAllowed,
498 nsMediaFeature::eLength,
499 nsMediaFeature::eNoRequirements,
500 { nullptr },
501 GetDeviceWidth
502 },
503 {
504 &nsGkAtoms::deviceHeight,
505 nsMediaFeature::eMinMaxAllowed,
506 nsMediaFeature::eLength,
507 nsMediaFeature::eNoRequirements,
508 { nullptr },
509 GetDeviceHeight
510 },
511 {
512 &nsGkAtoms::orientation,
513 nsMediaFeature::eMinMaxNotAllowed,
514 nsMediaFeature::eEnumerated,
515 nsMediaFeature::eNoRequirements,
516 { kOrientationKeywords },
517 GetOrientation
518 },
519 {
520 &nsGkAtoms::aspectRatio,
521 nsMediaFeature::eMinMaxAllowed,
522 nsMediaFeature::eIntRatio,
523 nsMediaFeature::eNoRequirements,
524 { nullptr },
525 GetAspectRatio
526 },
527 {
528 &nsGkAtoms::deviceAspectRatio,
529 nsMediaFeature::eMinMaxAllowed,
530 nsMediaFeature::eIntRatio,
531 nsMediaFeature::eNoRequirements,
532 { nullptr },
533 GetDeviceAspectRatio
534 },
535 {
536 &nsGkAtoms::color,
537 nsMediaFeature::eMinMaxAllowed,
538 nsMediaFeature::eInteger,
539 nsMediaFeature::eNoRequirements,
540 { nullptr },
541 GetColor
542 },
543 {
544 &nsGkAtoms::colorIndex,
545 nsMediaFeature::eMinMaxAllowed,
546 nsMediaFeature::eInteger,
547 nsMediaFeature::eNoRequirements,
548 { nullptr },
549 GetColorIndex
550 },
551 {
552 &nsGkAtoms::monochrome,
553 nsMediaFeature::eMinMaxAllowed,
554 nsMediaFeature::eInteger,
555 nsMediaFeature::eNoRequirements,
556 { nullptr },
557 GetMonochrome
558 },
559 {
560 &nsGkAtoms::resolution,
561 nsMediaFeature::eMinMaxAllowed,
562 nsMediaFeature::eResolution,
563 nsMediaFeature::eNoRequirements,
564 { nullptr },
565 GetResolution
566 },
567 {
568 &nsGkAtoms::scan,
569 nsMediaFeature::eMinMaxNotAllowed,
570 nsMediaFeature::eEnumerated,
571 nsMediaFeature::eNoRequirements,
572 { kScanKeywords },
573 GetScan
574 },
575 {
576 &nsGkAtoms::grid,
577 nsMediaFeature::eMinMaxNotAllowed,
578 nsMediaFeature::eBoolInteger,
579 nsMediaFeature::eNoRequirements,
580 { nullptr },
581 GetGrid
582 },
583 {
584 &nsGkAtoms::displayMode,
585 nsMediaFeature::eMinMaxNotAllowed,
586 nsMediaFeature::eEnumerated,
587 nsMediaFeature::eNoRequirements,
588 { kDisplayModeKeywords },
589 GetDisplayMode
590 },
591
592 // Webkit extensions that we support for de-facto web compatibility
593 // -webkit-{min|max}-device-pixel-ratio (controlled with its own pref):
594 {
595 &nsGkAtoms::devicePixelRatio,
596 nsMediaFeature::eMinMaxAllowed,
597 nsMediaFeature::eFloat,
598 nsMediaFeature::eHasWebkitPrefix |
599 nsMediaFeature::eWebkitDevicePixelRatioPrefEnabled,
600 { nullptr },
601 GetDevicePixelRatio
602 },
603 // -webkit-transform-3d:
604 {
605 &nsGkAtoms::transform_3d,
606 nsMediaFeature::eMinMaxNotAllowed,
607 nsMediaFeature::eBoolInteger,
608 nsMediaFeature::eHasWebkitPrefix,
609 { nullptr },
610 GetTransform3d
611 },
612
613 // Mozilla extensions
614 {
615 &nsGkAtoms::_moz_device_pixel_ratio,
616 nsMediaFeature::eMinMaxAllowed,
617 nsMediaFeature::eFloat,
618 nsMediaFeature::eNoRequirements,
619 { nullptr },
620 GetDevicePixelRatio
621 },
622 {
623 &nsGkAtoms::_moz_device_orientation,
624 nsMediaFeature::eMinMaxNotAllowed,
625 nsMediaFeature::eEnumerated,
626 nsMediaFeature::eNoRequirements,
627 { kOrientationKeywords },
628 GetDeviceOrientation
629 },
630 {
631 &nsGkAtoms::_moz_is_resource_document,
632 nsMediaFeature::eMinMaxNotAllowed,
633 nsMediaFeature::eBoolInteger,
634 nsMediaFeature::eNoRequirements,
635 { nullptr },
636 GetIsResourceDocument
637 },
638 {
639 &nsGkAtoms::_moz_color_picker_available,
640 nsMediaFeature::eMinMaxNotAllowed,
641 nsMediaFeature::eBoolInteger,
642 nsMediaFeature::eNoRequirements,
643 { &nsGkAtoms::color_picker_available },
644 GetSystemMetric
645 },
646 {
647 &nsGkAtoms::_moz_scrollbar_start_backward,
648 nsMediaFeature::eMinMaxNotAllowed,
649 nsMediaFeature::eBoolInteger,
650 nsMediaFeature::eNoRequirements,
651 { &nsGkAtoms::scrollbar_start_backward },
652 GetSystemMetric
653 },
654 {
655 &nsGkAtoms::_moz_scrollbar_start_forward,
656 nsMediaFeature::eMinMaxNotAllowed,
657 nsMediaFeature::eBoolInteger,
658 nsMediaFeature::eNoRequirements,
659 { &nsGkAtoms::scrollbar_start_forward },
660 GetSystemMetric
661 },
662 {
663 &nsGkAtoms::_moz_scrollbar_end_backward,
664 nsMediaFeature::eMinMaxNotAllowed,
665 nsMediaFeature::eBoolInteger,
666 nsMediaFeature::eNoRequirements,
667 { &nsGkAtoms::scrollbar_end_backward },
668 GetSystemMetric
669 },
670 {
671 &nsGkAtoms::_moz_scrollbar_end_forward,
672 nsMediaFeature::eMinMaxNotAllowed,
673 nsMediaFeature::eBoolInteger,
674 nsMediaFeature::eNoRequirements,
675 { &nsGkAtoms::scrollbar_end_forward },
676 GetSystemMetric
677 },
678 {
679 &nsGkAtoms::_moz_scrollbar_thumb_proportional,
680 nsMediaFeature::eMinMaxNotAllowed,
681 nsMediaFeature::eBoolInteger,
682 nsMediaFeature::eNoRequirements,
683 { &nsGkAtoms::scrollbar_thumb_proportional },
684 GetSystemMetric
685 },
686 {
687 &nsGkAtoms::_moz_overlay_scrollbars,
688 nsMediaFeature::eMinMaxNotAllowed,
689 nsMediaFeature::eBoolInteger,
690 nsMediaFeature::eNoRequirements,
691 { &nsGkAtoms::overlay_scrollbars },
692 GetSystemMetric
693 },
694 {
695 &nsGkAtoms::_moz_windows_default_theme,
696 nsMediaFeature::eMinMaxNotAllowed,
697 nsMediaFeature::eBoolInteger,
698 nsMediaFeature::eNoRequirements,
699 { &nsGkAtoms::windows_default_theme },
700 GetSystemMetric
701 },
702 {
703 &nsGkAtoms::_moz_mac_graphite_theme,
704 nsMediaFeature::eMinMaxNotAllowed,
705 nsMediaFeature::eBoolInteger,
706 nsMediaFeature::eNoRequirements,
707 { &nsGkAtoms::mac_graphite_theme },
708 GetSystemMetric
709 },
710 {
711 &nsGkAtoms::_moz_mac_yosemite_theme,
712 nsMediaFeature::eMinMaxNotAllowed,
713 nsMediaFeature::eBoolInteger,
714 nsMediaFeature::eNoRequirements,
715 { &nsGkAtoms::mac_yosemite_theme },
716 GetSystemMetric
717 },
718 {
719 &nsGkAtoms::_moz_windows_compositor,
720 nsMediaFeature::eMinMaxNotAllowed,
721 nsMediaFeature::eBoolInteger,
722 nsMediaFeature::eNoRequirements,
723 { &nsGkAtoms::windows_compositor },
724 GetSystemMetric
725 },
726 {
727 &nsGkAtoms::_moz_windows_classic,
728 nsMediaFeature::eMinMaxNotAllowed,
729 nsMediaFeature::eBoolInteger,
730 nsMediaFeature::eNoRequirements,
731 { &nsGkAtoms::windows_classic },
732 GetSystemMetric
733 },
734 {
735 &nsGkAtoms::_moz_windows_glass,
736 nsMediaFeature::eMinMaxNotAllowed,
737 nsMediaFeature::eBoolInteger,
738 nsMediaFeature::eNoRequirements,
739 { &nsGkAtoms::windows_glass },
740 GetSystemMetric
741 },
742 {
743 &nsGkAtoms::_moz_touch_enabled,
744 nsMediaFeature::eMinMaxNotAllowed,
745 nsMediaFeature::eBoolInteger,
746 nsMediaFeature::eNoRequirements,
747 { &nsGkAtoms::touch_enabled },
748 GetSystemMetric
749 },
750 {
751 &nsGkAtoms::_moz_menubar_drag,
752 nsMediaFeature::eMinMaxNotAllowed,
753 nsMediaFeature::eBoolInteger,
754 nsMediaFeature::eNoRequirements,
755 { &nsGkAtoms::menubar_drag },
756 GetSystemMetric
757 },
758 {
759 &nsGkAtoms::_moz_windows_theme,
760 nsMediaFeature::eMinMaxNotAllowed,
761 nsMediaFeature::eIdent,
762 nsMediaFeature::eNoRequirements,
763 { nullptr },
764 GetWindowsTheme
765 },
766 {
767 &nsGkAtoms::_moz_os_version,
768 nsMediaFeature::eMinMaxNotAllowed,
769 nsMediaFeature::eIdent,
770 nsMediaFeature::eNoRequirements,
771 { nullptr },
772 GetOperatingSystemVersion
773 },
774
775 {
776 &nsGkAtoms::_moz_swipe_animation_enabled,
777 nsMediaFeature::eMinMaxNotAllowed,
778 nsMediaFeature::eBoolInteger,
779 nsMediaFeature::eNoRequirements,
780 { &nsGkAtoms::swipe_animation_enabled },
781 GetSystemMetric
782 },
783
784 {
785 &nsGkAtoms::_moz_physical_home_button,
786 nsMediaFeature::eMinMaxNotAllowed,
787 nsMediaFeature::eBoolInteger,
788 nsMediaFeature::eNoRequirements,
789 { &nsGkAtoms::physical_home_button },
790 GetSystemMetric
791 },
792
793 // Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
794 // Internal because it is really only useful in the user agent anyway
795 // and therefore not worth standardizing.
796 {
797 &nsGkAtoms::_moz_is_glyph,
798 nsMediaFeature::eMinMaxNotAllowed,
799 nsMediaFeature::eBoolInteger,
800 nsMediaFeature::eNoRequirements,
801 { nullptr },
802 GetIsGlyph
803 },
804 // Null-mName terminator:
805 {
806 nullptr,
807 nsMediaFeature::eMinMaxAllowed,
808 nsMediaFeature::eInteger,
809 nsMediaFeature::eNoRequirements,
810 { nullptr },
811 nullptr
812 },
813 };
814