aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/gecko/generated/bindings.rs2
-rw-r--r--components/style/stylesheets/supports_rule.rs51
2 files changed, 52 insertions, 1 deletions
diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs
index dec8338ee75..d4e2bf86851 100644
--- a/components/style/gecko/generated/bindings.rs
+++ b/components/style/gecko/generated/bindings.rs
@@ -1595,4 +1595,6 @@ extern "C" {
pub fn Gecko_ContentList_AppendAll ( aContentList : * mut nsSimpleContentList , aElements : * mut * const RawGeckoElement , aLength : usize , ) ;
} extern "C" {
pub fn Gecko_GetElementsWithId ( aDocument : * const nsIDocument , aId : * mut nsAtom , ) -> * const nsTArray < * mut Element > ;
+} extern "C" {
+ pub fn Gecko_GetBoolPrefValue ( pref_name : * const :: std :: os :: raw :: c_char , ) -> bool ;
} \ No newline at end of file
diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs
index 6539560e097..d9870641e43 100644
--- a/components/style/stylesheets/supports_rule.rs
+++ b/components/style/stylesheets/supports_rule.rs
@@ -13,7 +13,10 @@ use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
use selectors::parser::SelectorParseErrorKind;
use servo_arc::Arc;
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
+#[allow(unused_imports)] use std::ascii::AsciiExt;
+use std::ffi::{CStr, CString};
use std::fmt;
+use std::str;
use style_traits::{ToCss, ParseError};
use stylesheets::{CssRuleType, CssRules};
@@ -83,6 +86,10 @@ pub enum SupportsCondition {
Or(Vec<SupportsCondition>),
/// `property-ident: value` (value can be any tokens)
Declaration(Declaration),
+ /// `-moz-bool-pref("pref-name")`
+ /// Since we need to pass it through FFI to get the pref value,
+ /// we store it as CString directly.
+ MozBoolPref(CString),
/// `(any tokens)` or `func(any tokens)`
FutureSyntax(String),
}
@@ -145,7 +152,26 @@ impl SupportsCondition {
return nested;
}
}
- Token::Function(_) => {}
+ Token::Function(ident) => {
+ // Although this is an internal syntax, it is not necessary to check
+ // parsing context as far as we accept any unexpected token as future
+ // syntax, and evaluate it to false when not in chrome / ua sheet.
+ // See https://drafts.csswg.org/css-conditional-3/#general_enclosed
+ if ident.eq_ignore_ascii_case("-moz-bool-pref") {
+ if let Ok(name) = input.try(|i| {
+ i.parse_nested_block(|i| {
+ i.expect_string()
+ .map(|s| s.to_string())
+ .map_err(CssParseError::<()>::from)
+ }).and_then(|s| {
+ CString::new(s)
+ .map_err(|_| location.new_custom_error(()))
+ })
+ }) {
+ return Ok(SupportsCondition::MozBoolPref(name));
+ }
+ }
+ }
t => return Err(location.new_unexpected_token_error(t)),
}
input.parse_nested_block(|i| consume_any_value(i))?;
@@ -160,11 +186,27 @@ impl SupportsCondition {
SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)),
SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)),
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
+ SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
SupportsCondition::FutureSyntax(_) => false
}
}
}
+#[cfg(feature = "gecko")]
+fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool {
+ use gecko_bindings::bindings;
+ use stylesheets::Origin;
+ if cx.stylesheet_origin != Origin::UserAgent && !cx.chrome_rules_enabled() {
+ return false;
+ }
+ unsafe { bindings::Gecko_GetBoolPrefValue(name.as_ptr()) }
+}
+
+#[cfg(feature = "servo")]
+fn eval_moz_bool_pref(_: &CStr, _: &ParserContext) -> bool {
+ false
+}
+
/// supports_condition | declaration
/// <https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext>
pub fn parse_condition_or_declaration<'i, 't>(input: &mut Parser<'i, 't>)
@@ -217,6 +259,13 @@ impl ToCss for SupportsCondition {
decl.to_css(dest)?;
dest.write_str(")")
}
+ SupportsCondition::MozBoolPref(ref name) => {
+ dest.write_str("-moz-bool-pref(")?;
+ let name = str::from_utf8(name.as_bytes())
+ .expect("Should be parsed from valid UTF-8");
+ name.to_css(dest)?;
+ dest.write_str(")")
+ }
SupportsCondition::FutureSyntax(ref s) => dest.write_str(&s),
}
}