Bug 1946764 - Support non-boolean media query prefs via -moz-pref(). r=firefox-style-system-reviewers,desktop-theme-reviewers,settings-reviewers,tabbrowser-reviewers,places-reviewers,sidebar-reviewers,urlbar-reviewers,firefox-ai-ml-reviewers,dao,mconley,dshin,mak

Allow querying int and string prefs too via functional syntax:

```
@media -moz-pref("pref-name", <value>) {
```

No argument means the pref exists and has a non-zero/false/empty value.
Unfortunately stylelint is still unhappy with this so we need to keep
the annoying comments...

Differential Revision: https://phabricator.services.mozilla.com/D237275
This commit is contained in:
Emilio Cobos Álvarez
2025-02-12 12:14:42 +00:00
parent faa30a7240
commit c67d8c9c9c
34 changed files with 293 additions and 122 deletions

View File

@@ -66,7 +66,7 @@ body {
z-index: 1; z-index: 1;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
display: none; display: none;
} }
} }

View File

@@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
:host { :host {
--button-size-icon: var(--tab-min-height); --button-size-icon: var(--tab-min-height);
--button-min-height: var(--button-size-icon); --button-min-height: var(--button-size-icon);
@@ -24,7 +24,7 @@
padding-inline: 0; padding-inline: 0;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
:host([expanded]) & { :host([expanded]) & {
/* TODO: Should this be some other pixel value between 5/6? Need to be careful of Linux where font size is larger */ /* TODO: Should this be some other pixel value between 5/6? Need to be careful of Linux where font size is larger */
--tab-pinned-horizontal-count: 5; --tab-pinned-horizontal-count: 5;

View File

@@ -49,7 +49,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "widget.gtk.rounded-bottom-corners.enabled") { @media -moz-pref("widget.gtk.rounded-bottom-corners.enabled") {
#navigator-toolbox { #navigator-toolbox {
/* The body clip below covers this. */ /* The body clip below covers this. */
border-radius: 0; border-radius: 0;
@@ -101,7 +101,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.experimental.expandTextOnFocus") { @media -moz-pref("browser.urlbar.experimental.expandTextOnFocus") {
#urlbar[breakout-extend] { #urlbar[breakout-extend] {
font-size: 1.14em; font-size: 1.14em;
} }
@@ -116,7 +116,7 @@
/* Content area */ /* Content area */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
.sidebar-splitter { .sidebar-splitter {
appearance: none; appearance: none;
width: 6px; width: 6px;
@@ -205,7 +205,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "widget.gtk.non-native-titlebar-buttons.enabled") { @media -moz-pref("widget.gtk.non-native-titlebar-buttons.enabled") {
/* When using lightweight themes, use our own buttons since native ones might /* When using lightweight themes, use our own buttons since native ones might
* assume a native background in order to be visible. */ * assume a native background in order to be visible. */
:root[lwtheme] & { :root[lwtheme] & {

View File

@@ -9,7 +9,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.theme.native-theme") { @media -moz-pref("browser.theme.native-theme") {
@media not (prefers-contrast) { @media not (prefers-contrast) {
:root:not([lwtheme]) { :root:not([lwtheme]) {
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
@@ -125,7 +125,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.experimental.expandTextOnFocus") { @media -moz-pref("browser.urlbar.experimental.expandTextOnFocus") {
#urlbar[breakout-extend] { #urlbar[breakout-extend] {
font-size: 1.36em; font-size: 1.36em;
} }

View File

@@ -41,7 +41,7 @@
--chrome-content-separator-color: light-dark(rgba(0,0,0,.3), rgba(255,255,255,.3)); --chrome-content-separator-color: light-dark(rgba(0,0,0,.3), rgba(255,255,255,.3));
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
&:not([lwtheme]) { &:not([lwtheme]) {
--chrome-content-separator-color: ThreeDShadow; --chrome-content-separator-color: ThreeDShadow;
} }
@@ -77,7 +77,7 @@
* transparencies in order to look more native. * transparencies in order to look more native.
*/ */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not ((prefers-contrast) or (-moz-bool-pref: "browser.theme.native-theme")) { @media not ((prefers-contrast) or -moz-pref("browser.theme.native-theme")) {
:root:not([lwtheme]) { :root:not([lwtheme]) {
--color-accent-primary: light-dark(rgb(0, 97, 224), rgb(0, 221, 255)); --color-accent-primary: light-dark(rgb(0, 97, 224), rgb(0, 221, 255));
--button-text-color-primary: light-dark(rgb(251, 251, 254), rgb(43, 42, 51)); --button-text-color-primary: light-dark(rgb(251, 251, 254), rgb(43, 42, 51));
@@ -107,7 +107,7 @@
--tabs-navbar-separator-style: none; --tabs-navbar-separator-style: none;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not ((-moz-windows-mica) or ((-moz-windows-accent-color-in-titlebar) and (-moz-bool-pref: "browser.theme.windows.accent-color-in-tabs.enabled"))) { @media not ((-moz-windows-mica) or ((-moz-windows-accent-color-in-titlebar) and -moz-pref("browser.theme.windows.accent-color-in-tabs.enabled"))) {
--toolbox-bgcolor: light-dark(rgb(240, 240, 244), rgb(28, 27, 34)); --toolbox-bgcolor: light-dark(rgb(240, 240, 244), rgb(28, 27, 34));
--toolbox-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254)); --toolbox-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254));
--toolbox-bgcolor-inactive: var(--toolbox-bgcolor); --toolbox-bgcolor-inactive: var(--toolbox-bgcolor);
@@ -143,7 +143,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
--chrome-content-separator-color: light-dark(rgb(204, 204, 204), hsl(240, 5%, 5%)); --chrome-content-separator-color: light-dark(rgb(204, 204, 204), hsl(240, 5%, 5%));
} }

View File

@@ -52,7 +52,7 @@ body {
min-height: 120px; min-height: 120px;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
min-width: 732px; min-width: 732px;
@media (-moz-platform: macos) { @media (-moz-platform: macos) {
@@ -192,7 +192,7 @@ body {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-platform: macos) and (-moz-bool-pref: "browser.theme.native-theme") { @media (-moz-platform: macos) and -moz-pref("browser.theme.native-theme") {
/* Don't make the toolbox vibrant when in full-screen. macOS fullscreen has a /* Don't make the toolbox vibrant when in full-screen. macOS fullscreen has a
* native titlebar outside of the window (revealed on hover) anyways. */ * native titlebar outside of the window (revealed on hover) anyways. */
:root[customtitlebar]:not([lwtheme], [macOSNativeFullscreen]) & { :root[customtitlebar]:not([lwtheme], [macOSNativeFullscreen]) & {
@@ -222,7 +222,7 @@ body {
color: inherit; color: inherit;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.verticalTabs") { @media not -moz-pref("sidebar.verticalTabs") {
&:not(.browser-titlebar) { &:not(.browser-titlebar) {
background-color: var(--toolbar-bgcolor); background-color: var(--toolbar-bgcolor);
color: var(--toolbar-color); color: var(--toolbar-color);
@@ -305,7 +305,7 @@ body {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
&[type="pre-tabs"], &[type="post-tabs"] { &[type="pre-tabs"], &[type="post-tabs"] {
display: none; display: none;
} }
@@ -415,7 +415,7 @@ body {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.verticalTabs") { @media not -moz-pref("sidebar.verticalTabs") {
#vertical-spacer { #vertical-spacer {
display: none; display: none;
} }

View File

@@ -909,7 +909,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="panel"] > .toolbarbutton-badg
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "identity.fxaccounts.toolbar.defaultVisible") { @media not -moz-pref("identity.fxaccounts.toolbar.defaultVisible") {
/* Hide the FxA toolbar button when its in the nav-bar, until in use */ /* Hide the FxA toolbar button when its in the nav-bar, until in use */
&[fxastatus="not_configured"] #widget-overflow-list > #fxa-toolbar-menu-button, &[fxastatus="not_configured"] #widget-overflow-list > #fxa-toolbar-menu-button,
&[fxastatus="not_configured"] #nav-bar-customization-target > #fxa-toolbar-menu-button { &[fxastatus="not_configured"] #nav-bar-customization-target > #fxa-toolbar-menu-button {

View File

@@ -30,7 +30,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.searchModeSwitcher.featureGate") or (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media -moz-pref("browser.urlbar.searchModeSwitcher.featureGate") or -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
#identity-box[pageproxystate="invalid"] { #identity-box[pageproxystate="invalid"] {
display: none; display: none;
} }
@@ -74,7 +74,7 @@
#urlbar-label-box { #urlbar-label-box {
margin-inline-end: 8px; margin-inline-end: 8px;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media ((-moz-bool-pref: "browser.urlbar.searchModeSwitcher.featureGate") or (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride")) { @media (-moz-pref("browser.urlbar.searchModeSwitcher.featureGate") or -moz-pref("browser.urlbar.scotchBonnet.enableOverride")) {
margin-inline-end: var(--urlbar-searchmodeswitcher-margin-inline-end); margin-inline-end: var(--urlbar-searchmodeswitcher-margin-inline-end);
} }
} }

View File

@@ -19,7 +19,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
display: none; display: none;
} }
} }

View File

@@ -257,7 +257,7 @@ radio {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "browser.migrate.preferences-entrypoint.enabled") { @media not -moz-pref("browser.migrate.preferences-entrypoint.enabled") {
#dataMigrationGroup { #dataMigrationGroup {
display: none; display: none;
} }

View File

@@ -89,7 +89,7 @@ p {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.privatebrowsing.felt-privacy-v1") { @media -moz-pref("browser.privatebrowsing.felt-privacy-v1") {
.search-inner-wrapper { .search-inner-wrapper {
height: 52px; height: 52px;
padding: 0; padding: 0;
@@ -251,7 +251,7 @@ p {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.privatebrowsing.felt-privacy-v1") { @media -moz-pref("browser.privatebrowsing.felt-privacy-v1") {
.search-handoff-button, .search-handoff-button,
.search-handoff-button:hover:not(.focused), .search-handoff-button:hover:not(.focused),
.search-handoff-button:active, .search-handoff-button:active,
@@ -384,7 +384,7 @@ p {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.privatebrowsing.felt-privacy-v1") { @media -moz-pref("browser.privatebrowsing.felt-privacy-v1") {
.info-border { .info-border {
border-radius: 8px; border-radius: 8px;
margin-top: 64px; margin-top: 64px;
@@ -605,7 +605,7 @@ p {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.privatebrowsing.felt-privacy-v1") { @media -moz-pref("browser.privatebrowsing.felt-privacy-v1") {
.promo.below-search.promo-visible { .promo.below-search.promo-visible {
margin-block: 0 25px; margin-block: 0 25px;

View File

@@ -15,7 +15,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media -moz-pref("sidebar.revamp") {
min-width: 200px; min-width: 200px;
width: 340px; width: 340px;
padding-block-end: var(--space-small); padding-block-end: var(--space-small);
@@ -40,7 +40,7 @@
max-width: 75vw; max-width: 75vw;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
background-color: var(--sidebar-background-color); background-color: var(--sidebar-background-color);
color: var(--sidebar-text-color); color: var(--sidebar-text-color);
/* Note that with sidebar.revamp we apply the --sidebar-background-color to the /* Note that with sidebar.revamp we apply the --sidebar-background-color to the
@@ -65,7 +65,7 @@
flex: 1; flex: 1;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media -moz-pref("sidebar.revamp") {
border-radius: var(--border-radius-medium); border-radius: var(--border-radius-medium);
box-shadow: var(--content-area-shadow); box-shadow: var(--content-area-shadow);
border: 0.5px solid var(--sidebar-border-color); border: 0.5px solid var(--sidebar-border-color);
@@ -81,7 +81,7 @@
z-index: var(--browser-area-z-index-sidebar-splitter); z-index: var(--browser-area-z-index-sidebar-splitter);
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") or (not (-moz-platform: linux)) { @media -moz-pref("sidebar.revamp") or (not (-moz-platform: linux)) {
/* We don't let the splitter overlap the sidebar on Linux since the sidebar's /* We don't let the splitter overlap the sidebar on Linux since the sidebar's
scrollbar is too narrow on Linux. */ scrollbar is too narrow on Linux. */
appearance: none; appearance: none;
@@ -102,7 +102,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media -moz-pref("sidebar.revamp") {
--splitter-width: 4px; --splitter-width: 4px;
transition: background-color 0.5s ease-in-out; transition: background-color 0.5s ease-in-out;
border-style: none; border-style: none;
@@ -116,7 +116,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.verticalTabs") { @media not -moz-pref("sidebar.verticalTabs") {
&#sidebar-launcher-splitter { &#sidebar-launcher-splitter {
display: none; display: none;
} }

View File

@@ -19,7 +19,7 @@
--tabpanel-background-color: #25003e !important; --tabpanel-background-color: #25003e !important;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.privatebrowsing.felt-privacy-v1") { @media -moz-pref("browser.privatebrowsing.felt-privacy-v1") {
--tabpanel-background-color: linear-gradient(45deg, #722291 0%, #45278D 50%, #393473 100%) !important; --tabpanel-background-color: linear-gradient(45deg, #722291 0%, #45278D 50%, #393473 100%) !important;
} }
} }
@@ -29,13 +29,13 @@
border-bottom: 0.01px solid var(--chrome-content-separator-color); border-bottom: 0.01px solid var(--chrome-content-separator-color);
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media -moz-pref("sidebar.revamp") {
/* This reserves space for the content area outline */ /* This reserves space for the content area outline */
border-bottom-color: var(--toolbar-bgcolor); border-bottom-color: var(--toolbar-bgcolor);
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
border-bottom-style: none; border-bottom-style: none;
} }
} }
@@ -72,18 +72,18 @@
margin: 0; margin: 0;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media -moz-pref("sidebar.revamp") {
outline: 0.01px solid var(--chrome-content-separator-color); outline: 0.01px solid var(--chrome-content-separator-color);
box-shadow: var(--content-area-shadow); box-shadow: var(--content-area-shadow);
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp.round-content-area") { @media -moz-pref("sidebar.revamp.round-content-area") {
:root:not([inDOMFullscreen]) &[sidebar-shown] { :root:not([inDOMFullscreen]) &[sidebar-shown] {
overflow: clip; overflow: clip;
border-start-end-radius: var(--border-radius-medium); border-start-end-radius: var(--border-radius-medium);
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.position_start") { @media -moz-pref("sidebar.position_start") {
border-start-start-radius: var(--border-radius-medium); border-start-start-radius: var(--border-radius-medium);
border-start-end-radius: 0; border-start-end-radius: 0;
} }
@@ -192,7 +192,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.tabs.hideStatusPanel") { @media -moz-pref("browser.tabs.hideStatusPanel") {
visibility: hidden; visibility: hidden;
} }
} }

View File

@@ -109,7 +109,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
:root { :root {
--tab-min-height: max(32px, calc(var(--tab-label-line-height) * 1em)); --tab-min-height: max(32px, calc(var(--tab-label-line-height) * 1em));
--tab-block-margin: 2px; --tab-block-margin: 2px;
@@ -444,7 +444,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.tabs.fadeOutUnloadedTabs") { @media -moz-pref("browser.tabs.fadeOutUnloadedTabs") {
&[pending] { &[pending] {
opacity: 0.5; opacity: 0.5;
/* Fade the favicon out */ /* Fade the favicon out */
@@ -793,7 +793,7 @@
/* Tab Groups */ /* Tab Groups */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.verticalTabs") { @media not -moz-pref("sidebar.verticalTabs") {
/* /*
* .tab-group-line needs to span the drop shadows + space between tabs in the * .tab-group-line needs to span the drop shadows + space between tabs in the
* same tab group so that the whole tab group appears to be underlined by an * same tab group so that the whole tab group appears to be underlined by an
@@ -845,7 +845,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
tab-group { tab-group {
flex-direction: column; flex-direction: column;
position: relative; position: relative;
@@ -883,7 +883,7 @@
transition: var(--tab-dragover-transition); transition: var(--tab-dragover-transition);
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.verticalTabs") { @media not -moz-pref("sidebar.verticalTabs") {
position: relative; position: relative;
/* /*
@@ -1405,7 +1405,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.expandOnHover") { @media -moz-pref("sidebar.expandOnHover") {
/* Tab close button when the sidebar is collapsed should /* Tab close button when the sidebar is collapsed should
not be shown when expand on hover is enabled because once not be shown when expand on hover is enabled because once
you hover over the launcher to use the button, the launcher you hover over the launcher to use the button, the launcher

View File

@@ -190,7 +190,7 @@
#sidebar-button { #sidebar-button {
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") { @media not -moz-pref("sidebar.revamp") {
list-style-image: url("chrome://browser/skin/sidebars-right.svg"); list-style-image: url("chrome://browser/skin/sidebars-right.svg");
&:-moz-locale-dir(ltr):not([positionend]), &:-moz-locale-dir(ltr):not([positionend]),
@@ -200,11 +200,11 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media -moz-pref("sidebar.revamp") {
list-style-image: url("chrome://browser/skin/sidebar-collapsed-right.svg"); list-style-image: url("chrome://browser/skin/sidebar-collapsed-right.svg");
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
&:hover { &:hover {
list-style-image: url("chrome://browser/skin/sidebar-expanded-right.svg"); list-style-image: url("chrome://browser/skin/sidebar-expanded-right.svg");
} }
@@ -223,7 +223,7 @@
list-style-image: url("chrome://browser/skin/sidebar-collapsed.svg"); list-style-image: url("chrome://browser/skin/sidebar-collapsed.svg");
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") { @media -moz-pref("sidebar.verticalTabs") {
&:hover { &:hover {
list-style-image: url("chrome://browser/skin/sidebar-expanded.svg"); list-style-image: url("chrome://browser/skin/sidebar-expanded.svg");
} }

View File

@@ -29,7 +29,7 @@
/* When rich suggestions are enabled the urlbar identity icon is given extra padding to /* When rich suggestions are enabled the urlbar identity icon is given extra padding to
* align the results and urlbar text */ * align the results and urlbar text */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.richSuggestions.featureGate") { @media -moz-pref("browser.urlbar.richSuggestions.featureGate") {
#identity-box[pageproxystate="invalid"] > .identity-box-button { #identity-box[pageproxystate="invalid"] > .identity-box-button {
padding-inline: calc(6px + var(--urlbar-icon-padding)); padding-inline: calc(6px + var(--urlbar-icon-padding));
} }
@@ -1146,8 +1146,8 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after {
} }
/* stylelint-disable media-query-no-invalid */ /* stylelint-disable media-query-no-invalid */
@media (not (-moz-bool-pref: "browser.urlbar.searchModeSwitcher.featureGate")) and @media (not -moz-pref("browser.urlbar.searchModeSwitcher.featureGate")) and
(not (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride")) { (not -moz-pref("browser.urlbar.scotchBonnet.enableOverride")) {
display: none; display: none;
} }
/* stylelint-enable media-query-no-invalid */ /* stylelint-enable media-query-no-invalid */
@@ -1172,7 +1172,7 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after {
display: none; display: none;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.searchModeSwitcher.featureGate") or (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media -moz-pref("browser.urlbar.searchModeSwitcher.featureGate") or -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
#urlbar[searchmode] & { #urlbar[searchmode] & {
display: inline-flex; display: inline-flex;
} }
@@ -1232,13 +1232,13 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.searchModeSwitcher.featureGate") or (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media -moz-pref("browser.urlbar.searchModeSwitcher.featureGate") or -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
#urlbar[searchmode] > .urlbar-input-container > #urlbar-search-mode-indicator { #urlbar[searchmode] > .urlbar-input-container > #urlbar-search-mode-indicator {
display: none; display: none;
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "browser.urlbar.unifiedSearchButton.always") { @media not -moz-pref("browser.urlbar.unifiedSearchButton.always") {
#urlbar-searchmode-switcher { #urlbar-searchmode-switcher {
background-color: var(--urlbar-box-bgcolor); background-color: var(--urlbar-box-bgcolor);
#urlbar:not([unifiedsearchbutton-available]) > .urlbar-input-container > & { #urlbar:not([unifiedsearchbutton-available]) > .urlbar-input-container > & {

View File

@@ -72,7 +72,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.richSuggestions.featureGate") { @media -moz-pref("browser.urlbar.richSuggestions.featureGate") {
--urlbarView-favicon-margin-start: calc((var(--urlbarView-rich-suggestion-default-icon-size) - var(--urlbarView-favicon-width)) / 2); --urlbarView-favicon-margin-start: calc((var(--urlbarView-rich-suggestion-default-icon-size) - var(--urlbarView-favicon-width)) / 2);
--urlbarView-favicon-margin-end: calc(var(--urlbar-icon-padding) + var(--identity-box-margin-inline) + ((var(--urlbarView-rich-suggestion-default-icon-size) - var(--urlbarView-favicon-width)) / 2)); --urlbarView-favicon-margin-end: calc(var(--urlbar-icon-padding) + var(--identity-box-margin-inline) + ((var(--urlbarView-rich-suggestion-default-icon-size) - var(--urlbarView-favicon-width)) / 2));
} }
@@ -120,7 +120,7 @@
/* Align icons that are smaller than the default rich suggestion icon size /* Align icons that are smaller than the default rich suggestion icon size
(28px) with default-size rich suggestion icons. */ (28px) with default-size rich suggestion icons. */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.richSuggestions.featureGate") { @media -moz-pref("browser.urlbar.richSuggestions.featureGate") {
&:not([rich-suggestion]), &:not([rich-suggestion]),
&[rich-suggestion][icon-size="16"] { &[rich-suggestion][icon-size="16"] {
--urlbarView-icon-margin-start: var(--urlbarView-favicon-margin-start); --urlbarView-icon-margin-start: var(--urlbarView-favicon-margin-start);
@@ -672,7 +672,7 @@
font-size: var(--urlbarView-small-font-size); font-size: var(--urlbarView-small-font-size);
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media not -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
/* This targets both rich and non-rich results, so not using the child selector here. */ /* This targets both rich and non-rich results, so not using the child selector here. */
.urlbarView-row:not(:hover, [selected], [sponsored]) & { .urlbarView-row:not(:hover, [selected], [sponsored]) & {
color: var(--urlbarView-action-color); color: var(--urlbarView-action-color);
@@ -739,7 +739,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media not -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
color: var(--urlbar-box-text-color); color: var(--urlbar-box-text-color);
background-color: var(--urlbar-box-focus-bgcolor); background-color: var(--urlbar-box-focus-bgcolor);
@@ -749,7 +749,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
-moz-context-properties: fill, fill-opacity; -moz-context-properties: fill, fill-opacity;
padding-inline-start: calc(var(--urlbarView-favicon-width) + 8px); padding-inline-start: calc(var(--urlbarView-favicon-width) + 8px);
background-image: url("chrome://browser/content/firefoxview/view-opentabs.svg"); background-image: url("chrome://browser/content/firefoxview/view-opentabs.svg");
@@ -770,7 +770,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "browser.urlbar.scotchBonnet.enableOverride") { @media not -moz-pref("browser.urlbar.scotchBonnet.enableOverride") {
&:is([selected], :hover) > .urlbarView-row-inner > .urlbarView-no-wrap > .urlbarView-action { &:is([selected], :hover) > .urlbarView-row-inner > .urlbarView-no-wrap > .urlbarView-action {
color: var(--urlbarView-result-button-selected-color); color: var(--urlbarView-result-button-selected-color);
background-color: var(--urlbarView-result-button-selected-background-color); background-color: var(--urlbarView-result-button-selected-background-color);

View File

@@ -34,7 +34,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-windows-mica) or (-moz-bool-pref: "browser.theme.windows.accent-color-in-tabs.enabled") { @media (-moz-windows-mica) or -moz-pref("browser.theme.windows.accent-color-in-tabs.enabled") {
&:not([lwtheme]) #TabsToolbar { &:not([lwtheme]) #TabsToolbar {
/* These colors match the Linux/HCM default button colors. We need to /* These colors match the Linux/HCM default button colors. We need to
* override these on the tabs toolbar because the accent color is * override these on the tabs toolbar because the accent color is
@@ -286,7 +286,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.experimental.expandTextOnFocus") { @media -moz-pref("browser.urlbar.experimental.expandTextOnFocus") {
#urlbar[breakout-extend] { #urlbar[breakout-extend] {
font-size: 1.25em; font-size: 1.25em;
} }

View File

@@ -304,7 +304,7 @@ semantics > :not(:first-child) {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "mathml.legacy_mathvariant_attribute.disabled") { @media -moz-pref("mathml.legacy_mathvariant_attribute.disabled") {
/* Implement MathML Core's automatic italic on mi. /* Implement MathML Core's automatic italic on mi.
https://w3c.github.io/mathml-core/#the-mathvariant-attribute */ https://w3c.github.io/mathml-core/#the-mathvariant-attribute */
mi { mi {

View File

@@ -11,7 +11,7 @@
background: green; background: green;
} }
@media (-moz-bool-pref: "testing.supports.moz-bool-pref") { @media -moz-pref("testing.supports.moz-bool-pref") {
.enabled { .enabled {
background: green; background: green;
} }

View File

@@ -1572,34 +1572,79 @@ const nsTArray<Element*>* Gecko_ShadowRoot_GetElementsWithId(
return aShadowRoot->GetAllElementsForId(aId); return aShadowRoot->GetAllElementsForId(aId);
} }
bool Gecko_ComputeBoolPrefMediaQuery(nsAtom* aPref) { static StyleComputedMozPrefFeatureValue GetPrefValue(const nsCString& aPref) {
using Value = StyleComputedMozPrefFeatureValue;
switch (Preferences::GetType(aPref.get())) {
case nsIPrefBranch::PREF_STRING: {
nsAutoString value;
Preferences::GetString(aPref.get(), value);
return Value::String(StyleAtomString{NS_Atomize(value)});
}
case nsIPrefBranch::PREF_INT:
return Value::Integer(Preferences::GetInt(aPref.get(), 0));
case nsIPrefBranch::PREF_BOOL: {
auto value = Preferences::GetBool(aPref.get(), false)
? StyleBoolValue::True
: StyleBoolValue::False;
return Value::Boolean(value);
}
case nsIPrefBranch::PREF_INVALID:
default:
break;
}
return StyleComputedMozPrefFeatureValue::None();
}
bool Gecko_EvalMozPrefFeature(nsAtom* aPref,
const StyleComputedMozPrefFeatureValue* aValue) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aValue);
using Value = StyleComputedMozPrefFeatureValue;
using PrefMap = nsTHashMap<RefPtr<nsAtom>, Value>;
// This map leaks until shutdown, but that's fine, all the values are // This map leaks until shutdown, but that's fine, all the values are
// controlled by us so it's not expected to be big. // controlled by us so it's not expected to be big.
static StaticAutoPtr<nsTHashMap<RefPtr<nsAtom>, bool>> sRegisteredPrefs; static StaticAutoPtr<PrefMap> sRegisteredPrefs;
if (!sRegisteredPrefs) { if (!sRegisteredPrefs) {
if (PastShutdownPhase(ShutdownPhase::XPCOMShutdownFinal)) { if (PastShutdownPhase(ShutdownPhase::XPCOMShutdownFinal)) {
// Styling doesn't really matter much at this point, don't bother. // Styling doesn't really matter much at this point, don't bother.
return false; return false;
} }
sRegisteredPrefs = new nsTHashMap<RefPtr<nsAtom>, bool>(); sRegisteredPrefs = new PrefMap();
ClearOnShutdown(&sRegisteredPrefs); ClearOnShutdown(&sRegisteredPrefs);
} }
return sRegisteredPrefs->LookupOrInsertWith(aPref, [&] {
const auto& value = sRegisteredPrefs->LookupOrInsertWith(aPref, [&] {
nsAutoAtomCString prefName(aPref); nsAutoAtomCString prefName(aPref);
Preferences::RegisterCallback( Preferences::RegisterCallback(
[](const char* aPrefName, void*) { [](const char* aPrefName, void*) {
nsDependentCString name(aPrefName);
if (sRegisteredPrefs) { if (sRegisteredPrefs) {
RefPtr<nsAtom> name = NS_Atomize(nsDependentCString(aPrefName)); RefPtr<nsAtom> nameAtom = NS_Atomize(name);
sRegisteredPrefs->InsertOrUpdate(name, sRegisteredPrefs->InsertOrUpdate(nameAtom, GetPrefValue(name));
Preferences::GetBool(aPrefName));
} }
LookAndFeel::NotifyChangedAllWindows( LookAndFeel::NotifyChangedAllWindows(
widget::ThemeChangeKind::MediaQueriesOnly); widget::ThemeChangeKind::MediaQueriesOnly);
}, },
prefName); prefName);
return Preferences::GetBool(prefName.get()); return GetPrefValue(prefName);
}); });
if (aValue->IsNone()) {
// For a non-specified query, we return true if the pref is not false, zero,
// empty or invalid
switch (value.tag) {
case Value::Tag::None:
return false;
case Value::Tag::Boolean:
return value.AsBoolean() == StyleBoolValue::True;
case Value::Tag::Integer:
return value.AsInteger() != 0;
case Value::Tag::String:
return !value.AsString().AsAtom()->IsEmpty();
}
return false;
}
return value == *aValue;
} }
bool Gecko_IsFontFormatSupported(StyleFontFaceSourceFormatKeyword aFormat) { bool Gecko_IsFontFormatSupported(StyleFontFaceSourceFormatKeyword aFormat) {

View File

@@ -550,7 +550,8 @@ const nsTArray<mozilla::dom::Element*>* Gecko_Document_GetElementsWithId(
const nsTArray<mozilla::dom::Element*>* Gecko_ShadowRoot_GetElementsWithId( const nsTArray<mozilla::dom::Element*>* Gecko_ShadowRoot_GetElementsWithId(
const mozilla::dom::ShadowRoot*, nsAtom* aId); const mozilla::dom::ShadowRoot*, nsAtom* aId);
bool Gecko_ComputeBoolPrefMediaQuery(nsAtom*); bool Gecko_EvalMozPrefFeature(nsAtom*,
const mozilla::StyleComputedMozPrefFeatureValue*);
// Check whether font format/tech is supported. // Check whether font format/tech is supported.
bool Gecko_IsFontFormatSupported( bool Gecko_IsFontFormatSupported(

View File

@@ -382,6 +382,7 @@ cbindgen-types = [
{ gecko = "StyleOffsetPathFunction", servo = "crate::values::computed::motion::OffsetPathFunction" }, { gecko = "StyleOffsetPathFunction", servo = "crate::values::computed::motion::OffsetPathFunction" },
{ gecko = "StyleGenericOffsetPath", servo = "crate::values::generics::motion::OffsetPath" }, { gecko = "StyleGenericOffsetPath", servo = "crate::values::generics::motion::OffsetPath" },
{ gecko = "StyleGenericOffsetPathFunction", servo = "crate::values::generics::motion::OffsetPathFunction" }, { gecko = "StyleGenericOffsetPathFunction", servo = "crate::values::generics::motion::OffsetPathFunction" },
{ gecko = "StyleComputedMozPrefFeatureValue", servo = "crate::queries::condition::ComputedMozPrefFeatureValue" },
{ gecko = "StyleMozTheme", servo = "crate::values::computed::ui::MozTheme" }, { gecko = "StyleMozTheme", servo = "crate::values::computed::ui::MozTheme" },
{ gecko = "StyleOffsetPosition", servo = "crate::values::computed::motion::OffsetPosition" }, { gecko = "StyleOffsetPosition", servo = "crate::values::computed::motion::OffsetPosition" },
{ gecko = "StyleOffsetRotate", servo = "crate::values::computed::motion::OffsetRotate" }, { gecko = "StyleOffsetRotate", servo = "crate::values::computed::motion::OffsetRotate" },

View File

@@ -206,7 +206,7 @@ h6 {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "layout.css.h1-in-section-ua-styles.enabled") { @media -moz-pref("layout.css.h1-in-section-ua-styles.enabled") {
:is(article, aside, nav, section) :is(article, aside, nav, section)
h1 { h1 {
margin-block: 0.83em; margin-block: 0.83em;

View File

@@ -6,7 +6,7 @@
/* Rules required for style caching of anonymous content scrollbar parts */ /* Rules required for style caching of anonymous content scrollbar parts */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "layout.css.cached-scrollbar-styles.enabled") { @media -moz-pref("layout.css.cached-scrollbar-styles.enabled") {
:is(scrollcorner, resizer, scrollbar, scrollbarbutton, slider):where(:-moz-native-anonymous) { :is(scrollcorner, resizer, scrollbar, scrollbarbutton, slider):where(:-moz-native-anonymous) {
/* All scrollbar parts must not inherit any properties from the scrollable /* All scrollbar parts must not inherit any properties from the scrollable
* element (except for visibility and pointer-events), for the anonymous * element (except for visibility and pointer-events), for the anonymous

View File

@@ -170,7 +170,7 @@
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "layout.css.always_underline_links") { @media -moz-pref("layout.css.always_underline_links") {
:any-link { :any-link {
text-decoration: underline !important; text-decoration: underline !important;
} }
@@ -514,7 +514,7 @@ parsererror|sourcetext {
/* Avoid exposing these keyframe names when view transitions are disabled */ /* Avoid exposing these keyframe names when view transitions are disabled */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "dom.viewTransitions.enabled") { @media -moz-pref("dom.viewTransitions.enabled") {
/* Default cross-fade transition */ /* Default cross-fade transition */
@keyframes -ua-view-transition-fade-out { @keyframes -ua-view-transition-fade-out {
to { opacity: 0; } to { opacity: 0; }

View File

@@ -19,7 +19,7 @@
margin: 0; margin: 0;
padding: 8px; padding: 8px;
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "view_source.wrap_long_lines") { @media -moz-pref("view_source.wrap_long_lines") {
white-space: pre-wrap; white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
} }
@@ -50,7 +50,7 @@ span[id]::before {
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "view_source.syntax_highlight") { @media -moz-pref("view_source.syntax_highlight") {
.start-tag, .start-tag,
.end-tag { .end-tag {
color: light-dark(purple, #f55e5e); color: light-dark(purple, #f55e5e);

View File

@@ -10,7 +10,7 @@ SimpleTest.waitForExplicitFinish();
function expect(q, shouldBeKnown) { function expect(q, shouldBeKnown) {
is(matchMedia(q).media, q, "Serialization should roundtrip"); is(matchMedia(q).media, q, "Serialization should roundtrip");
is(matchMedia(`${q} or (not ${q})`).matches, shouldBeKnown, `Query should${shouldBeKnown ? "" : " not"} be known`); is(matchMedia(`${q} or (not ${q})`).matches, shouldBeKnown, `${q} should${shouldBeKnown ? "" : " not"} be known`);
} }
function expectKnown(q) { function expectKnown(q) {
@@ -21,6 +21,28 @@ function expectUnkown(q) {
expect(q, false); expect(q, false);
} }
function testMatches(q, shouldMatch = true) {
is(matchMedia(q).matches, shouldMatch, `${q} should match`);
}
async function testMozPref(q, prefName, value, otherValue) {
expectKnown(q);
await SpecialPowers.pushPrefEnv({
set:[[prefName, value]],
});
testMatches(q, true);
let mediaList = matchMedia(q);
let change = new Promise(r => {
mediaList.addEventListener("change", r, { once: true });
});
await SpecialPowers.pushPrefEnv({
set:[[prefName, otherValue]],
});
testMatches(q, false);
// Should change dynamically successfully.
await change;
}
// Test a toggle that should always match for `1` or `0`. // Test a toggle that should always match for `1` or `0`.
function testToggle(toggle) { function testToggle(toggle) {
expectKnown(`(${toggle})`); expectKnown(`(${toggle})`);
@@ -63,5 +85,13 @@ expectKnown("(forced-colors)");
expectUnkown("(-moz-platform: )"); expectUnkown("(-moz-platform: )");
(async function() {
await testMozPref('-moz-pref("foo.bar.bool", true)', "foo.bar.bool", true, false);
await testMozPref('-moz-pref("foo.bar.bool")', "foo.bar.bool", true, false);
await testMozPref('-moz-pref("foo.bar.str", "foo")', "foo.bar.str", "foo", "bar");
await testMozPref('-moz-pref("foo.bar.str")', "foo.bar.str", "foo", "");
await testMozPref('-moz-pref("foo.bar.int", 1)', "foo.bar.int", 1, 2);
await testMozPref('-moz-pref("foo.bar.int")', "foo.bar.int", 1, 0);
SimpleTest.finish(); SimpleTest.finish();
}());
</script> </script>

View File

@@ -11,10 +11,8 @@ use crate::queries::feature::{AllowsRanges, Evaluator, FeatureFlags, QueryFeatur
use crate::queries::values::Orientation; use crate::queries::values::Orientation;
use crate::values::computed::{CSSPixelLength, Context, Ratio, Resolution}; use crate::values::computed::{CSSPixelLength, Context, Ratio, Resolution};
use crate::values::specified::color::ForcedColors; use crate::values::specified::color::ForcedColors;
use crate::values::AtomString;
use app_units::Au; use app_units::Au;
use euclid::default::Size2D; use euclid::default::Size2D;
use selectors::kleene_value::KleeneValue;
fn device_size(device: &Device) -> Size2D<Au> { fn device_size(device: &Device) -> Size2D<Au> {
let mut width = 0; let mut width = 0;
@@ -617,13 +615,6 @@ fn eval_moz_overlay_scrollbars(context: &Context) -> bool {
unsafe { bindings::Gecko_MediaFeatures_UseOverlayScrollbars(context.device().document()) } unsafe { bindings::Gecko_MediaFeatures_UseOverlayScrollbars(context.device().document()) }
} }
fn eval_moz_bool_pref(_: &Context, pref: Option<&AtomString>) -> KleeneValue {
let Some(pref) = pref else {
return KleeneValue::False;
};
KleeneValue::from(unsafe { bindings::Gecko_ComputeBoolPrefMediaQuery(pref.as_ptr()) })
}
fn get_lnf_int(int_id: i32) -> i32 { fn get_lnf_int(int_id: i32) -> i32 {
unsafe { bindings::Gecko_GetLookAndFeelInt(int_id) } unsafe { bindings::Gecko_GetLookAndFeelInt(int_id) }
} }
@@ -671,7 +662,7 @@ macro_rules! lnf_int_feature {
/// to support new types in these entries and (2) ensuring that either /// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that /// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change. /// would be returned by the evaluator function could change.
pub static MEDIA_FEATURES: [QueryFeatureDescription; 61] = [ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [
feature!( feature!(
atom!("width"), atom!("width"),
AllowsRanges::Yes, AllowsRanges::Yes,
@@ -936,12 +927,6 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 61] = [
Evaluator::BoolInteger(eval_moz_overlay_scrollbars), Evaluator::BoolInteger(eval_moz_overlay_scrollbars),
FeatureFlags::CHROME_AND_UA_ONLY, FeatureFlags::CHROME_AND_UA_ONLY,
), ),
feature!(
atom!("-moz-bool-pref"),
AllowsRanges::No,
Evaluator::String(eval_moz_bool_pref),
FeatureFlags::CHROME_AND_UA_ONLY,
),
lnf_int_feature!( lnf_int_feature!(
atom!("-moz-scrollbar-start-backward"), atom!("-moz-scrollbar-start-backward"),
ScrollArrowStyle, ScrollArrowStyle,

View File

@@ -9,7 +9,7 @@
use super::{FeatureFlags, FeatureType, QueryFeatureExpression}; use super::{FeatureFlags, FeatureType, QueryFeatureExpression};
use crate::custom_properties; use crate::custom_properties;
use crate::values::computed; use crate::values::{computed, AtomString};
use crate::{error_reporting::ContextualParseError, parser::ParserContext}; use crate::{error_reporting::ContextualParseError, parser::ParserContext};
use cssparser::{Parser, SourcePosition, Token}; use cssparser::{Parser, SourcePosition, Token};
use selectors::kleene_value::KleeneValue; use selectors::kleene_value::KleeneValue;
@@ -107,6 +107,106 @@ impl StyleFeature {
} }
} }
/// A boolean value for a pref query.
#[derive(
Clone,
Debug,
MallocSizeOf,
PartialEq,
Eq,
Parse,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToShmem,
)]
#[repr(u8)]
#[allow(missing_docs)]
pub enum BoolValue {
False,
True,
}
/// Simple values we support for -moz-pref(). We don't want to deal with calc() and other
/// shenanigans for now.
#[derive(
Clone,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToShmem,
)]
#[repr(u8)]
pub enum MozPrefFeatureValue<I> {
/// No pref value, implicitly bool, but also used to represent missing prefs.
#[css(skip)]
None,
/// A bool value.
Boolean(BoolValue),
/// An integer value, useful for int prefs.
Integer(I),
/// A string pref value.
String(crate::values::AtomString),
}
type SpecifiedMozPrefFeatureValue = MozPrefFeatureValue<crate::values::specified::Integer>;
/// The computed -moz-pref() value.
pub type ComputedMozPrefFeatureValue = MozPrefFeatureValue<crate::values::computed::Integer>;
/// A custom -moz-pref(<name>, <value>) query feature.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub struct MozPrefFeature {
name: crate::values::AtomString,
value: SpecifiedMozPrefFeatureValue,
}
impl MozPrefFeature {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
feature_type: FeatureType,
) -> Result<Self, ParseError<'i>> {
use crate::parser::Parse;
if !context.chrome_rules_enabled() || feature_type != FeatureType::Media {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
let name = AtomString::parse(context, input)?;
let value = if input.try_parse(|i| i.expect_comma()).is_ok() {
SpecifiedMozPrefFeatureValue::parse(context, input)?
} else {
SpecifiedMozPrefFeatureValue::None
};
Ok(Self { name, value })
}
fn matches(&self, ctx: &computed::Context) -> KleeneValue {
use crate::values::computed::ToComputedValue;
let value = self.value.to_computed_value(ctx);
KleeneValue::from(unsafe {
crate::gecko_bindings::bindings::Gecko_EvalMozPrefFeature(self.name.as_ptr(), &value)
})
}
}
impl ToCss for MozPrefFeature {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
self.name.to_css(dest)?;
if !matches!(self.value, MozPrefFeatureValue::None) {
dest.write_str(", ")?;
self.value.to_css(dest)?;
}
Ok(())
}
}
/// Represents a condition. /// Represents a condition.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum QueryCondition { pub enum QueryCondition {
@@ -120,6 +220,8 @@ pub enum QueryCondition {
InParens(Box<QueryCondition>), InParens(Box<QueryCondition>),
/// A <style> query. /// A <style> query.
Style(StyleFeature), Style(StyleFeature),
/// A -moz-pref() query.
MozPref(MozPrefFeature),
/// [ <function-token> <any-value>? ) ] | [ ( <any-value>? ) ] /// [ <function-token> <any-value>? ) ] | [ ( <any-value>? ) ]
GeneralEnclosed(String), GeneralEnclosed(String),
} }
@@ -147,6 +249,11 @@ impl ToCss for QueryCondition {
c.to_css(dest)?; c.to_css(dest)?;
dest.write_char(')') dest.write_char(')')
}, },
QueryCondition::MozPref(ref c) => {
dest.write_str("-moz-pref(")?;
c.to_css(dest)?;
dest.write_char(')')
},
QueryCondition::Operation(ref list, op) => { QueryCondition::Operation(ref list, op) => {
let mut iter = list.iter(); let mut iter = list.iter();
iter.next().unwrap().to_css(dest)?; iter.next().unwrap().to_css(dest)?;
@@ -184,7 +291,8 @@ impl QueryCondition {
{ {
visitor(self); visitor(self);
match *self { match *self {
Self::Feature(..) | Self::GeneralEnclosed(..) | Self::Style(..) => {}, Self::Feature(..) | Self::GeneralEnclosed(..) | Self::Style(..) | Self::MozPref(..) => {
},
Self::Not(ref cond) => cond.visit(visitor), Self::Not(ref cond) => cond.visit(visitor),
Self::Operation(ref conds, _op) => { Self::Operation(ref conds, _op) => {
for cond in conds.iter() { for cond in conds.iter() {
@@ -330,13 +438,24 @@ impl QueryCondition {
} }
}, },
Token::Function(ref name) => { Token::Function(ref name) => {
if name.eq_ignore_ascii_case("style") { match_ignore_ascii_case! { name,
"style" => {
let feature = Self::try_parse_block(context, input, start, |input| { let feature = Self::try_parse_block(context, input, start, |input| {
StyleFeature::parse(context, input, feature_type) StyleFeature::parse(context, input, feature_type)
}); });
if let Some(feature) = feature { if let Some(feature) = feature {
return Ok(Self::Style(feature)); return Ok(Self::Style(feature));
} }
},
"-moz-pref" => {
let feature = Self::try_parse_block(context, input, start, |input| {
MozPrefFeature::parse(context, input, feature_type)
});
if let Some(feature) = feature {
return Ok(Self::MozPref(feature));
}
},
_ => {},
} }
}, },
ref t => return Err(start_location.new_unexpected_token_error(t.clone())), ref t => return Err(start_location.new_unexpected_token_error(t.clone())),
@@ -357,6 +476,7 @@ impl QueryCondition {
QueryCondition::InParens(ref c) => c.matches(context), QueryCondition::InParens(ref c) => c.matches(context),
QueryCondition::Not(ref c) => !c.matches(context), QueryCondition::Not(ref c) => !c.matches(context),
QueryCondition::Style(ref c) => c.matches(context), QueryCondition::Style(ref c) => c.matches(context),
QueryCondition::MozPref(ref c) => c.matches(context),
QueryCondition::Operation(ref conditions, op) => { QueryCondition::Operation(ref conditions, op) => {
debug_assert!(!conditions.is_empty(), "We never create an empty op"); debug_assert!(!conditions.is_empty(), "We never create an empty op");
match op { match op {

View File

@@ -6,7 +6,6 @@
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::values::computed::{self, CSSPixelLength, Ratio, Resolution}; use crate::values::computed::{self, CSSPixelLength, Ratio, Resolution};
use crate::values::AtomString;
use crate::Atom; use crate::Atom;
use cssparser::Parser; use cssparser::Parser;
use selectors::kleene_value::KleeneValue; use selectors::kleene_value::KleeneValue;
@@ -45,7 +44,6 @@ pub enum Evaluator {
OptionalNumberRatio(QueryFeatureGetter<Option<Ratio>>), OptionalNumberRatio(QueryFeatureGetter<Option<Ratio>>),
/// A resolution. /// A resolution.
Resolution(QueryFeatureGetter<Resolution>), Resolution(QueryFeatureGetter<Resolution>),
String(fn(&computed::Context, Option<&AtomString>) -> KleeneValue),
/// A keyword value. /// A keyword value.
Enumerated { Enumerated {
/// The parser to get a discriminant given a string. /// The parser to get a discriminant given a string.

View File

@@ -11,7 +11,7 @@ use crate::parser::{Parse, ParserContext};
use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase};
use crate::values::computed::{self, Ratio, ToComputedValue}; use crate::values::computed::{self, Ratio, ToComputedValue};
use crate::values::specified::{Integer, Length, Number, Resolution}; use crate::values::specified::{Integer, Length, Number, Resolution};
use crate::values::{AtomString, CSSFloat}; use crate::values::CSSFloat;
use crate::{Atom, Zero}; use crate::{Atom, Zero};
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use selectors::kleene_value::KleeneValue; use selectors::kleene_value::KleeneValue;
@@ -639,10 +639,6 @@ impl QueryFeatureExpression {
.map(|v| *expect!(Enumerated, v)); .map(|v| *expect!(Enumerated, v));
return evaluator(context, computed); return evaluator(context, computed);
}, },
Evaluator::String(evaluator) => {
let string = self.kind.non_ranged_value().map(|v| expect!(String, v));
return evaluator(context, string);
},
Evaluator::BoolInteger(eval) => { Evaluator::BoolInteger(eval) => {
let computed = self let computed = self
.kind .kind
@@ -681,8 +677,6 @@ pub enum QueryExpressionValue {
/// An enumerated value, defined by the variant keyword table in the /// An enumerated value, defined by the variant keyword table in the
/// feature's `mData` member. /// feature's `mData` member.
Enumerated(KeywordDiscriminant), Enumerated(KeywordDiscriminant),
/// An arbitrary ident value.
String(AtomString),
} }
impl QueryExpressionValue { impl QueryExpressionValue {
@@ -701,7 +695,6 @@ impl QueryExpressionValue {
Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)), Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)),
_ => unreachable!(), _ => unreachable!(),
}, },
QueryExpressionValue::String(ref s) => s.to_css(dest),
} }
} }
@@ -739,9 +732,6 @@ impl QueryExpressionValue {
Evaluator::Resolution(..) => { Evaluator::Resolution(..) => {
QueryExpressionValue::Resolution(Resolution::parse(context, input)?) QueryExpressionValue::Resolution(Resolution::parse(context, input)?)
}, },
Evaluator::String(..) => {
QueryExpressionValue::String(input.expect_string()?.as_ref().into())
},
Evaluator::Enumerated { parser, .. } => { Evaluator::Enumerated { parser, .. } => {
QueryExpressionValue::Enumerated(parser(context, input)?) QueryExpressionValue::Enumerated(parser(context, input)?)
}, },

View File

@@ -112,6 +112,7 @@ include = [
"FontVariantEastAsian", "FontVariantEastAsian",
"FontVariantLigatures", "FontVariantLigatures",
"FontVariantNumeric", "FontVariantNumeric",
"ComputedMozPrefFeatureValue",
"ComputedFontStretchRange", "ComputedFontStretchRange",
"ComputedFontStyleDescriptor", "ComputedFontStyleDescriptor",
"ComputedFontWeightRange", "ComputedFontWeightRange",

View File

@@ -156,7 +156,7 @@ button:disabled {
/* Felt Privacy v1 LARGER SCREEN! */ /* Felt Privacy v1 LARGER SCREEN! */
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "security.certerrors.felt-privacy-v1") { @media -moz-pref("security.certerrors.felt-privacy-v1") {
.felt-privacy-body { .felt-privacy-body {
justify-content: start; justify-content: start;
} }