diff options
-rw-r--r-- | components/style/gecko/generated/bindings.rs | 2 | ||||
-rw-r--r-- | components/style/stylesheets/supports_rule.rs | 51 |
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), } } |