Bug 1446470: Allow @-moz-document url-prefix() on content. r?xidorn draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 16 Mar 2018 18:50:16 +0100
changeset 768860 3872f50716d91e673c1ca8fd1a3b5079c30a4a7f
parent 768859 2561fc23fb762b08d1a6bed33db4b4e91a7aede5
child 768861 2e9f6bfd8c7f6fe570bb4b6708dd7af68e779120
push id102993
push userbmo:emilio@crisal.io
push dateFri, 16 Mar 2018 23:07:24 +0000
reviewersxidorn
bugs1446470
milestone61.0a1
Bug 1446470: Allow @-moz-document url-prefix() on content. r?xidorn MozReview-Commit-ID: zaT41fpsDT
layout/reftests/bugs/1035091-2.html
layout/reftests/bugs/1446470.html
layout/reftests/bugs/reftest.list
servo/components/style/stylesheets/document_rule.rs
servo/components/style/stylesheets/rule_parser.rs
--- a/layout/reftests/bugs/1035091-2.html
+++ b/layout/reftests/bugs/1035091-2.html
@@ -1,8 +1,8 @@
 <!doctype html>
 <style>
 div { color: green; }
-@-moz-document url-prefix() {
+@-moz-document url-prefix(foo) {
   div { color: red; }
 }
 </style>
 <div>Should be green</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1446470.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<style>
+div { color: red; }
+@-moz-document url-prefix() {
+  div { color: green; }
+}
+</style>
+<div>Should be green</div>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -2058,8 +2058,9 @@ test-pref(font.size.systemFontScale,200)
 == 1420946-1.html 1420946-1-ref.html
 == 1422393.html 1422393-ref.html
 == 1424177.html 1424177-ref.html
 == 1424680.html 1424680-ref.html
 == 1424798-1.html 1424798-ref.html
 fuzzy(74,2234) random-if(webrender) == 1425243-1.html 1425243-1-ref.html
 fuzzy-if(Android,66,574) fuzzy-if(d2d,89,777) fuzzy-if(!Android&&!d2d,1,31219) == 1425243-2.html 1425243-2-ref.html
 == 1432541.html 1432541-ref.html
+pref(layout.css.moz-document.content.enabled,false) fails-if(!stylo||styloVsGecko) == 1446470.html 1035091-ref.html
--- a/servo/components/style/stylesheets/document_rule.rs
+++ b/servo/components/style/stylesheets/document_rule.rs
@@ -10,18 +10,18 @@ use cssparser::{Parser, SourceLocation};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
 use media_queries::Device;
 use parser::{Parse, ParserContext};
 use servo_arc::Arc;
 use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
 use std::fmt::{self, Write};
 use str::CssStringWriter;
-use style_traits::{CssWriter, ParseError, ToCss};
-use stylesheets::CssRules;
+use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
+use stylesheets::{CssRules, Origin};
 use values::CssUrl;
 
 #[derive(Debug)]
 /// A @-moz-document rule
 pub struct DocumentRule {
     /// The parsed condition
     pub condition: DocumentCondition,
     /// Child rules
@@ -181,19 +181,61 @@ impl UrlMatchingFunction {
 pub struct DocumentCondition(#[css(iterable)] Vec<UrlMatchingFunction>);
 
 impl DocumentCondition {
     /// Parse a document condition.
     pub fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
-        input.parse_comma_separated(|input| UrlMatchingFunction::parse(context, input))
-             .map(DocumentCondition)
+        let conditions = input.parse_comma_separated(|input| {
+            UrlMatchingFunction::parse(context, input)
+        })?;
+
+        let condition = DocumentCondition(conditions);
+
+        if !condition.allowed_in(context) {
+            return Err(input.new_custom_error(
+                StyleParseErrorKind::UnsupportedAtRule("-moz-document".into())
+            ))
+        }
+
+        Ok(condition)
     }
 
     /// Evaluate a document condition.
     pub fn evaluate(&self, device: &Device) -> bool {
         self.0.iter().any(|url_matching_function| {
             url_matching_function.evaluate(device)
         })
     }
+
+    #[cfg(feature = "servo")]
+    fn allowed_in(&self, _: &ParserContext) -> bool {
+        false
+    }
+
+    #[cfg(feature = "gecko")]
+    fn allowed_in(&self, context: &ParserContext) -> bool {
+        use gecko_bindings::structs;
+
+        if context.stylesheet_origin != Origin::Author {
+            return true;
+        }
+
+        if unsafe { structs::StylePrefs_sMozDocumentEnabledInContent } {
+            return true;
+        }
+
+        // Allow a single url-prefix() for compatibility.
+        //
+        // See bug 1446470 and dependencies.
+        if self.0.len() != 1 {
+            return false;
+        }
+
+        // NOTE(emilio): This technically allows url-prefix("") too, but...
+        match self.0[0] {
+            UrlMatchingFunction::UrlPrefix(ref prefix) => prefix.is_empty(),
+            _ => false
+        }
+    }
 }
--- a/servo/components/style/stylesheets/rule_parser.rs
+++ b/servo/components/style/stylesheets/rule_parser.rs
@@ -417,29 +417,16 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> 
             },
             "-moz-document" => {
                 if !cfg!(feature = "gecko") {
                     return Err(input.new_custom_error(
                         StyleParseErrorKind::UnsupportedAtRule(name.clone())
                     ))
                 }
 
-                #[cfg(feature = "gecko")]
-                {
-                    use gecko_bindings::structs;
-
-                    if self.stylesheet_origin == Origin::Author &&
-                        unsafe { !structs::StylePrefs_sMozDocumentEnabledInContent }
-                    {
-                        return Err(input.new_custom_error(
-                            StyleParseErrorKind::UnsupportedAtRule(name.clone())
-                        ))
-                    }
-                }
-
                 let cond = DocumentCondition::parse(self.context, input)?;
                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Document(cond, location)))
             },
             _ => Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
         }
     }
 
     fn parse_block<'t>(