Bug 1355408 - Part 1: Support @-moz-document rule in stylo. r=xidorn draft
authorFernando Jimenez Moreno <ferjmoreno@gmail.com>
Tue, 18 Apr 2017 18:59:43 +0200
changeset 574814 1329b4c008b4ee3e2623a496c8ef82f610d6e3ce
parent 574813 b0ff0c5c0a35a1ee9f19cec2bae5cc2cd5772db6
child 574815 e4dc029597d8e65fdea18489ba091ecfdb3c4b97
push id57825
push userferjmoreno@gmail.com
push dateTue, 09 May 2017 12:47:36 +0000
reviewersxidorn
bugs1355408
milestone55.0a1
Bug 1355408 - Part 1: Support @-moz-document rule in stylo. r=xidorn MozReview-Commit-ID: BMoA7tb7ixj
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/URLMatchingFunction.h
layout/style/moz.build
layout/style/nsCSSParser.cpp
layout/style/nsCSSRules.cpp
layout/style/nsCSSRules.h
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -22,16 +22,17 @@
 #include "nsIDOMNode.h"
 #include "nsIDocument.h"
 #include "nsIDocumentInlines.h"
 #include "nsIFrame.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
 #include "nsIPresShellInlines.h"
 #include "nsIPrincipal.h"
+#include "nsIURI.h"
 #include "nsFontMetrics.h"
 #include "nsMappedAttributes.h"
 #include "nsMediaFeatures.h"
 #include "nsNameSpaceManager.h"
 #include "nsNetUtil.h"
 #include "nsRuleNode.h"
 #include "nsString.h"
 #include "nsStyleStruct.h"
@@ -2021,16 +2022,36 @@ Gecko_RegisterProfilerThread(const char*
 }
 
 void
 Gecko_UnregisterProfilerThread()
 {
   profiler_unregister_thread();
 }
 
+bool
+Gecko_DocumentRule_UseForPresentation(RawGeckoPresContextBorrowed aPresContext,
+                                      const nsACString* aPattern,
+                                      css::URLMatchingFunction aURLMatchingFunction)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsIDocument *doc = aPresContext->Document();
+  nsIURI *docURI = doc->GetDocumentURI();
+  nsAutoCString docURISpec;
+  if (docURI) {
+    // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
+    nsresult rv = docURI->GetSpec(docURISpec);
+    NS_ENSURE_SUCCESS(rv, false);
+  }
+
+  return css::DocumentRule::UseForPresentation(doc, docURI, docURISpec,
+                                               *aPattern, aURLMatchingFunction);
+}
+
 #include "nsStyleStructList.h"
 
 #undef STYLE_STRUCT
 
 #ifndef MOZ_STYLO
 #define SERVO_BINDING_FUNC(name_, return_, ...)                               \
   return_ name_(__VA_ARGS__) {                                                \
     MOZ_CRASH("stylo: shouldn't be calling " #name_ "in a non-stylo build");  \
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -8,16 +8,17 @@
 #define mozilla_ServoBindings_h
 
 #include <stdint.h>
 
 #include "mozilla/ServoTypes.h"
 #include "mozilla/ServoBindingTypes.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "mozilla/css/SheetParsingMode.h"
+#include "mozilla/css/URLMatchingFunction.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/ComputedTimingFunction.h"
 #include "nsChangeHint.h"
 #include "nsCSSPseudoClasses.h"
 #include "nsStyleStruct.h"
 
 /*
  * API for Servo to access Gecko data structures. This file must compile as valid
@@ -488,15 +489,19 @@ bool Gecko_MatchStringArgPseudo(RawGecko
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
 void Gecko_Construct_nsStyleVariables(nsStyleVariables* ptr);
 
 void Gecko_RegisterProfilerThread(const char* name);
 void Gecko_UnregisterProfilerThread();
 
+bool Gecko_DocumentRule_UseForPresentation(RawGeckoPresContextBorrowed,
+                                           const nsACString* aPattern,
+                                           mozilla::css::URLMatchingFunction aURLMatchingFunction);
+
 #define SERVO_BINDING_FUNC(name_, return_, ...) return_ name_(__VA_ARGS__);
 #include "mozilla/ServoBindingList.h"
 #undef SERVO_BINDING_FUNC
 
 } // extern "C"
 
 #endif // mozilla_ServoBindings_h
new file mode 100644
--- /dev/null
+++ b/layout/style/URLMatchingFunction.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_css_URLMatchingFunction_h
+#define mozilla_css_URLMatchingFunction_h
+
+namespace mozilla {
+namespace css {
+
+/**
+ * Enum defining the type of URL matching function for a @-moz-document rule
+ * condition.
+ */
+enum class URLMatchingFunction {
+  eURL = 0,
+  eURLPrefix,
+  eDomain,
+  eRegExp,
+};
+
+} // namespace css
+} // namespace mozilla
+
+#endif // mozilla_css_URLMatchingFunction_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -151,16 +151,17 @@ EXPORTS.mozilla.css += [
     'GroupRule.h',
     'ImageLoader.h',
     'ImportRule.h',
     'Loader.h',
     'NameSpaceRule.h',
     'Rule.h',
     'SheetParsingMode.h',
     'StyleRule.h',
+    'URLMatchingFunction.h',
 ]
 
 UNIFIED_SOURCES += [
     'AnimationCollection.cpp',
     'BindingStyleRule.cpp',
     'CounterStyleManager.cpp',
     'CSS.cpp',
     'CSSLexer.cpp',
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -23,16 +23,17 @@
 #include "nsAlgorithm.h"
 #include "nsCSSProps.h"
 #include "nsCSSKeywords.h"
 #include "nsCSSScanner.h"
 #include "mozilla/css/ErrorReporter.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/css/StyleRule.h"
 #include "mozilla/css/ImportRule.h"
+#include "mozilla/css/URLMatchingFunction.h"
 #include "nsCSSRules.h"
 #include "nsCSSFontFaceRule.h"
 #include "mozilla/css/NameSpaceRule.h"
 #include "nsTArray.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Declaration.h"
 #include "nsStyleConsts.h"
 #include "nsNetUtil.h"
@@ -3895,38 +3896,38 @@ CSSParserImpl::ParseMozDocumentRule(Rule
       REPORT_UNEXPECTED_TOKEN(PEMozDocRuleBadFunc2);
       UngetToken();
       delete urls;
       return false;
     }
     css::DocumentRule::URL *cur = *next = new css::DocumentRule::URL;
     next = &cur->next;
     if (mToken.mType == eCSSToken_URL) {
-      cur->func = css::DocumentRule::eURL;
+      cur->func = URLMatchingFunction::eURL;
       CopyUTF16toUTF8(mToken.mIdent, cur->url);
     } else if (mToken.mIdent.LowerCaseEqualsLiteral("regexp")) {
       // regexp() is different from url-prefix() and domain() (but
       // probably the way they *should* have been* in that it requires a
       // string argument, and doesn't try to behave like url().
-      cur->func = css::DocumentRule::eRegExp;
+      cur->func = URLMatchingFunction::eRegExp;
       GetToken(true);
       // copy before we know it's valid (but before ExpectSymbol changes
       // mToken.mIdent)
       CopyUTF16toUTF8(mToken.mIdent, cur->url);
       if (eCSSToken_String != mToken.mType || !ExpectSymbol(')', true)) {
         REPORT_UNEXPECTED_TOKEN(PEMozDocRuleNotString);
         SkipUntil(')');
         delete urls;
         return false;
       }
     } else {
       if (mToken.mIdent.LowerCaseEqualsLiteral("url-prefix")) {
-        cur->func = css::DocumentRule::eURLPrefix;
+        cur->func = URLMatchingFunction::eURLPrefix;
       } else if (mToken.mIdent.LowerCaseEqualsLiteral("domain")) {
-        cur->func = css::DocumentRule::eDomain;
+        cur->func = URLMatchingFunction::eDomain;
       }
 
       NS_ASSERTION(!mHavePushBack, "mustn't have pushback at this point");
       mScanner->NextURL(mToken);
       if (mToken.mType != eCSSToken_URL) {
         REPORT_UNEXPECTED_TOKEN(PEMozDocRuleNotURI);
         SkipUntil(')');
         delete urls;
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -558,26 +558,26 @@ DocumentRule::List(FILE* out, int32_t aI
   for (int32_t indent = aIndent; --indent >= 0; ) {
     indentStr.AppendLiteral("  ");
   }
 
   nsAutoCString str;
   str.AppendLiteral("@-moz-document ");
   for (URL *url = mURLs; url; url = url->next) {
     switch (url->func) {
-      case eURL:
+      case URLMatchingFunction::eURL:
         str.AppendLiteral("url(\"");
         break;
-      case eURLPrefix:
+      case URLMatchingFunction::eURLPrefix:
         str.AppendLiteral("url-prefix(\"");
         break;
-      case eDomain:
+      case URLMatchingFunction::eDomain:
         str.AppendLiteral("domain(\"");
         break;
-      case eRegExp:
+      case URLMatchingFunction::eRegExp:
         str.AppendLiteral("regexp(\"");
         break;
     }
     nsAutoCString escapedURL(url->url);
     escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
     str.Append(escapedURL);
     str.AppendLiteral("\"), ");
   }
@@ -675,47 +675,66 @@ DocumentRule::UseForPresentation(nsPresC
   nsAutoCString docURISpec;
   if (docURI) {
     // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
     nsresult rv = docURI->GetSpec(docURISpec);
     NS_ENSURE_SUCCESS(rv, false);
   }
 
   for (URL *url = mURLs; url; url = url->next) {
-    switch (url->func) {
-      case eURL: {
-        if (docURISpec == url->url)
-          return true;
-      } break;
-      case eURLPrefix: {
-        if (StringBeginsWith(docURISpec, url->url))
-          return true;
-      } break;
-      case eDomain: {
-        nsAutoCString host;
-        if (docURI)
-          docURI->GetHost(host);
-        int32_t lenDiff = host.Length() - url->url.Length();
-        if (lenDiff == 0) {
-          if (host == url->url)
-            return true;
-        } else {
-          if (StringEndsWith(host, url->url) &&
-              host.CharAt(lenDiff - 1) == '.')
-            return true;
-        }
-      } break;
-      case eRegExp: {
-        NS_ConvertUTF8toUTF16 spec(docURISpec);
-        NS_ConvertUTF8toUTF16 regex(url->url);
-        if (nsContentUtils::IsPatternMatching(spec, regex, doc)) {
+    if (UseForPresentation(doc, docURI, docURISpec, url->url, url->func)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool
+DocumentRule::UseForPresentation(nsIDocument* aDoc,
+                                 nsIURI* aDocURI,
+                                 const nsACString& aDocURISpec,
+                                 const nsACString& aPattern,
+                                 URLMatchingFunction aUrlMatchingFunction)
+{
+  switch (aUrlMatchingFunction) {
+    case URLMatchingFunction::eURL: {
+      if (aDocURISpec == aPattern) {
+        return true;
+      }
+    } break;
+    case URLMatchingFunction::eURLPrefix: {
+      if (StringBeginsWith(aDocURISpec, aPattern)) {
+        return true;
+      }
+    } break;
+    case URLMatchingFunction::eDomain: {
+      nsAutoCString host;
+      if (aDocURI) {
+        aDocURI->GetHost(host);
+      }
+      int32_t lenDiff = host.Length() - aPattern.Length();
+      if (lenDiff == 0) {
+        if (host == aPattern) {
           return true;
         }
-      } break;
-    }
+      } else {
+        if (StringEndsWith(host, aPattern) &&
+            host.CharAt(lenDiff - 1) == '.') {
+          return true;
+        }
+      }
+    } break;
+    case URLMatchingFunction::eRegExp: {
+      NS_ConvertUTF8toUTF16 spec(aDocURISpec);
+      NS_ConvertUTF8toUTF16 regex(aPattern);
+      if (nsContentUtils::IsPatternMatching(spec, regex, aDoc)) {
+        return true;
+      }
+    } break;
   }
 
   return false;
 }
 
 DocumentRule::URL::~URL()
 {
   NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
@@ -741,26 +760,26 @@ DocumentRule::WrapObject(JSContext* aCx,
   return CSSMozDocumentRuleBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 DocumentRule::AppendConditionText(nsAString& aCssText) const
 {
   for (URL *url = mURLs; url; url = url->next) {
     switch (url->func) {
-      case eURL:
+      case URLMatchingFunction::eURL:
         aCssText.AppendLiteral("url(");
         break;
-      case eURLPrefix:
+      case URLMatchingFunction::eURLPrefix:
         aCssText.AppendLiteral("url-prefix(");
         break;
-      case eDomain:
+      case URLMatchingFunction::eDomain:
         aCssText.AppendLiteral("domain(");
         break;
-      case eRegExp:
+      case URLMatchingFunction::eRegExp:
         aCssText.AppendLiteral("regexp(");
         break;
     }
     nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
                                         aCssText);
     aCssText.AppendLiteral("), ");
   }
   aCssText.Truncate(aCssText.Length() - 2); // remove last ", "
@@ -1164,17 +1183,17 @@ nsCSSFontFaceStyleDecl::GetParentObject(
 JSObject*
 nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
 {
   return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, this, aGivenProto);
 }
 
 // -------------------------------------------
 // nsCSSFontFaceRule
-// 
+//
 
 /* virtual */ already_AddRefed<css::Rule>
 nsCSSFontFaceRule::Clone() const
 {
   RefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
   return clone.forget();
 }
 
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -12,16 +12,17 @@
 #include "Declaration.h"
 #include "StyleRule.h"
 #include "gfxFontFeatures.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/SheetType.h"
 #include "mozilla/css/GroupRule.h"
+#include "mozilla/css/URLMatchingFunction.h"
 #include "mozilla/dom/CSSMediaRule.h"
 #include "mozilla/dom/CSSPageRule.h"
 #include "mozilla/dom/CSSSupportsRule.h"
 #include "nsAutoPtr.h"
 #include "nsCSSPropertyID.h"
 #include "nsCSSValue.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsIDOMCSSConditionRule.h"
@@ -119,29 +120,28 @@ public:
   // nsIDOMCSSConditionRule interface
   NS_DECL_NSIDOMCSSCONDITIONRULE
 
   // nsIDOMCSSMozDocumentRule interface
   NS_DECL_NSIDOMCSSMOZDOCUMENTRULE
 
   // rest of GroupRule
   virtual bool UseForPresentation(nsPresContext* aPresContext,
-                                    nsMediaQueryResultCacheKey& aKey) override;
+                                  nsMediaQueryResultCacheKey& aKey) override;
 
   bool UseForPresentation(nsPresContext* aPresContext);
 
-  enum Function {
-    eURL,
-    eURLPrefix,
-    eDomain,
-    eRegExp
-  };
+  static bool UseForPresentation(nsIDocument* aDoc,
+                                 nsIURI* aDocURI,
+                                 const nsACString& aDocURISpec,
+                                 const nsACString& aPattern,
+                                 URLMatchingFunction aUrlMatchingFunction);
 
   struct URL {
-    Function func;
+    URLMatchingFunction func;
     nsCString url;
     URL *next;
 
     URL() : next(nullptr) {}
     URL(const URL& aOther)
       : func(aOther.func)
       , url(aOther.url)
       , next(aOther.next ? new URL(*aOther.next) : nullptr)
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -309,16 +309,17 @@ dependencies = [
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nsstring_vendor 0.1.0",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
 
 [[package]]
 name = "gkrust-shared"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -307,16 +307,17 @@ dependencies = [
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nsstring_vendor 0.1.0",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.18.0",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
 
 [[package]]
 name = "gkrust-shared"