Bug 1475511: Add @-moz-document media-document(image|video|plugin). r=xidorn draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 19 Jul 2018 19:50:19 +0200
changeset 820837 b5871e10bf93cae96d4c7a5605d7769f4e75e205
parent 820836 8983bc9ae92833222f6d7d129e441a208e45f510
child 820838 726935af93ba6aad05b0a54e3d5bb288aeea3be9
push id116953
push userbmo:emilio@crisal.io
push dateFri, 20 Jul 2018 13:44:17 +0000
reviewersxidorn
bugs1475511
milestone63.0a1
Bug 1475511: Add @-moz-document media-document(image|video|plugin). r=xidorn MozReview-Commit-ID: CD3O1vGLAoV
layout/style/CSSMozDocumentRule.cpp
layout/style/DocumentMatchingFunction.h
servo/components/style/stylesheets/document_rule.rs
--- a/layout/style/CSSMozDocumentRule.cpp
+++ b/layout/style/CSSMozDocumentRule.cpp
@@ -23,16 +23,34 @@ CSSMozDocumentRule::WrapObject(JSContext
 bool
 CSSMozDocumentRule::Match(nsIDocument* aDoc,
                           nsIURI* aDocURI,
                           const nsACString& aDocURISpec,
                           const nsACString& aPattern,
                           DocumentMatchingFunction aMatchingFunction)
 {
   switch (aMatchingFunction) {
+    case DocumentMatchingFunction::AllMediaDocuments:
+      return aDoc->MediaDocumentKind() != nsIDocument::MediaDocumentKind::None;
+    case DocumentMatchingFunction::VideoMediaDocuments:
+    case DocumentMatchingFunction::ImageMediaDocuments:
+    case DocumentMatchingFunction::PluginMediaDocuments: {
+      switch (aDoc->MediaDocumentKind()) {
+        case nsIDocument::MediaDocumentKind::None:
+          return false;
+        case nsIDocument::MediaDocumentKind::Plugin:
+          return aMatchingFunction == DocumentMatchingFunction::PluginMediaDocuments;
+        case nsIDocument::MediaDocumentKind::Image:
+          return aMatchingFunction == DocumentMatchingFunction::ImageMediaDocuments;
+        case nsIDocument::MediaDocumentKind::Video:
+          return aMatchingFunction == DocumentMatchingFunction::VideoMediaDocuments;
+      }
+      MOZ_ASSERT_UNREACHABLE("Unknown media document kind");
+      return false;
+    }
     case DocumentMatchingFunction::URL:
       return aDocURISpec == aPattern;
     case DocumentMatchingFunction::URLPrefix:
       return StringBeginsWith(aDocURISpec, aPattern);
     case DocumentMatchingFunction::Domain: {
       nsAutoCString host;
       if (aDocURI) {
         aDocURI->GetHost(host);
--- a/layout/style/DocumentMatchingFunction.h
+++ b/layout/style/DocumentMatchingFunction.h
@@ -14,14 +14,18 @@ namespace css {
  * Enum defining the type of matching function for a @-moz-document rule
  * condition.
  */
 enum class DocumentMatchingFunction {
   URL = 0,
   URLPrefix,
   Domain,
   RegExp,
+  AllMediaDocuments,
+  ImageMediaDocuments,
+  PluginMediaDocuments,
+  VideoMediaDocuments,
 };
 
 } // namespace css
 } // namespace mozilla
 
 #endif // mozilla_css_DocumentMatchingFunction_h
--- a/servo/components/style/stylesheets/document_rule.rs
+++ b/servo/components/style/stylesheets/document_rule.rs
@@ -66,16 +66,26 @@ impl DeepCloneWithLock for DocumentRule 
         DocumentRule {
             condition: self.condition.clone(),
             rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
             source_location: self.source_location.clone(),
         }
     }
 }
 
+/// The kind of media document that the rule will match.
+#[derive(Clone, Copy, Debug, Parse, PartialEq, ToCss)]
+#[allow(missing_docs)]
+pub enum MediaDocumentKind {
+    All,
+    Plugin,
+    Image,
+    Video,
+}
+
 /// A matching function for a `@document` rule's condition.
 #[derive(Clone, Debug, ToCss)]
 pub enum DocumentMatchingFunction {
     /// Exact URL matching function. It evaluates to true whenever the
     /// URL of the document being styled is exactly the URL given.
     Url(CssUrl),
     /// URL prefix matching function. It evaluates to true whenever the
     /// URL of the document being styled has the argument to the
@@ -92,16 +102,19 @@ pub enum DocumentMatchingFunction {
     /// ‘domain()’ function.
     #[css(function)]
     Domain(String),
     /// Regular expression matching function. It evaluates to true
     /// whenever the regular expression matches the entirety of the URL
     /// of the document being styled.
     #[css(function)]
     Regexp(String),
+    /// Matching function for a media document.
+    #[css(function)]
+    MediaDocument(MediaDocumentKind)
 }
 
 macro_rules! parse_quoted_or_unquoted_string {
     ($input:ident, $url_matching_function:expr) => {
         $input.parse_nested_block(|input| {
             let start = input.position();
             input
                 .parse_entirely(|input| {
@@ -130,16 +143,20 @@ impl DocumentMatchingFunction {
         let function = input.expect_function()?.clone();
         match_ignore_ascii_case! { &function,
             "url-prefix" => {
                 parse_quoted_or_unquoted_string!(input, DocumentMatchingFunction::UrlPrefix)
             }
             "domain" => {
                 parse_quoted_or_unquoted_string!(input, DocumentMatchingFunction::Domain)
             }
+            "media-document" => {
+                let kind = MediaDocumentKind::parse(input)?;
+                Ok(DocumentMatchingFunction::MediaDocument(kind))
+            }
             "regex" => {
                 Ok(DocumentMatchingFunction::Regexp(
                     input.expect_string()?.as_ref().to_owned(),
                 ))
             }
             _ => {
                 return Err(location.new_custom_error(
                     StyleParseErrorKind::UnexpectedFunction(function.clone())
@@ -155,23 +172,32 @@ impl DocumentMatchingFunction {
         use gecko_bindings::structs::DocumentMatchingFunction as GeckoDocumentMatchingFunction;
         use nsstring::nsCStr;
 
         let func = match *self {
             DocumentMatchingFunction::Url(_) => GeckoDocumentMatchingFunction::URL,
             DocumentMatchingFunction::UrlPrefix(_) => GeckoDocumentMatchingFunction::URLPrefix,
             DocumentMatchingFunction::Domain(_) => GeckoDocumentMatchingFunction::Domain,
             DocumentMatchingFunction::Regexp(_) => GeckoDocumentMatchingFunction::RegExp,
+            DocumentMatchingFunction::MediaDocument(kind) => {
+                match kind {
+                    MediaDocumentKind::All => GeckoDocumentMatchingFunction::AllMediaDocuments,
+                    MediaDocumentKind::Video => GeckoDocumentMatchingFunction::VideoMediaDocuments,
+                    MediaDocumentKind::Image => GeckoDocumentMatchingFunction::ImageMediaDocuments,
+                    MediaDocumentKind::Plugin => GeckoDocumentMatchingFunction::PluginMediaDocuments,
+                }
+            }
         };
 
         let pattern = nsCStr::from(match *self {
             DocumentMatchingFunction::Url(ref url) => url.as_str(),
             DocumentMatchingFunction::UrlPrefix(ref pat) |
             DocumentMatchingFunction::Domain(ref pat) |
             DocumentMatchingFunction::Regexp(ref pat) => pat,
+            DocumentMatchingFunction::MediaDocument(..) => "",
         });
         unsafe { Gecko_DocumentRule_UseForPresentation(device.pres_context(), &*pattern, func) }
     }
 
     #[cfg(not(feature = "gecko"))]
     /// Evaluate a URL matching function.
     pub fn evaluate(&self, _: &Device) -> bool {
         false