Bug 1403694 - Prevent nsStyleSheetService from storing null servo stylesheets. r=xidorn, a=ritu
authorBrad Werth <bwerth@mozilla.com>
Thu, 28 Sep 2017 16:45:09 -0700
changeset 432182 8c7645234f86018b46dab62fdcc39955f229c74a
parent 432181 f31efa9dfa8fc6161df364ee6bcd7a7469582ed3
child 432183 1e557c44b8026a247f84ee4570045bb018be6b85
push id7896
push userryanvm@gmail.com
push dateThu, 05 Oct 2017 00:26:16 +0000
treeherdermozilla-beta@8c7645234f86 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn, ritu
bugs1403694
milestone57.0
Bug 1403694 - Prevent nsStyleSheetService from storing null servo stylesheets. r=xidorn, a=ritu MozReview-Commit-ID: 2PxurAtACtd
layout/base/nsStyleSheetService.cpp
layout/base/nsStyleSheetService.h
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -91,28 +91,25 @@ SheetHasURI(StyleSheet* aSheet, nsIURI* 
   bool result;
   nsIURI* uri = aSheet->GetSheetURI();
   return uri &&
          NS_SUCCEEDED(uri->Equals(aSheetURI, &result)) &&
          result;
 }
 
 int32_t
-nsStyleSheetService::FindSheetByURI(uint32_t aSheetType,
+nsStyleSheetService::FindSheetByURI(mozilla::StyleBackendType aBackendType,
+                                    uint32_t aSheetType,
                                     nsIURI* aSheetURI)
 {
-  MOZ_ASSERT(mGeckoSheets[aSheetType].Length() ==
-               mServoSheets[aSheetType].Length());
-
-  SheetArray& sheets = mGeckoSheets[aSheetType];
+  SheetArray& sheets = aBackendType == mozilla::StyleBackendType::Gecko ?
+                         mGeckoSheets[aSheetType] :
+                         mServoSheets[aSheetType];
   for (int32_t i = sheets.Length() - 1; i >= 0; i-- ) {
     if (SheetHasURI(sheets[i], aSheetURI)) {
-#ifdef MOZ_STYLO
-      MOZ_ASSERT(SheetHasURI(mServoSheets[aSheetType][i], aSheetURI));
-#endif
       return i;
     }
   }
 
   return -1;
 }
 
 nsresult
@@ -170,32 +167,37 @@ nsStyleSheetService::LoadAndRegisterShee
         u"URI contains unescaped hash character, which might be truncating "
         u"the sheet, if it's a data URI.";
       consoleService->LogStringMessage(message);
     }
   }
 
   rv = LoadAndRegisterSheetInternal(aSheetURI, aSheetType);
   if (NS_SUCCEEDED(rv)) {
-    // We're guaranteed that the new sheet is the last sheet in
-    // m{Gecko,Servo}Sheets[aSheetType]
-
-    MOZ_ASSERT(mGeckoSheets[aSheetType].Length() ==
-                 mServoSheets[aSheetType].Length());
-
-    RefPtr<StyleSheet> geckoSheet = mGeckoSheets[aSheetType].LastElement();
-    RefPtr<StyleSheet> servoSheet = mServoSheets[aSheetType].LastElement();
+    // Success means that at least the Gecko sheet was loaded. It's possible
+    // that a Servo sheet was also loaded. In both cases, the new sheets are
+    // the last sheets in m{Gecko,Servo}Sheets[aSheetType]
+    bool servoSheetWasAdded = false;
+#ifdef MOZ_STYLO
+    servoSheetWasAdded = nsLayoutUtils::StyloSupportedInCurrentProcess();
+#endif
 
     // Hold on to a copy of the registered PresShells.
     nsTArray<nsCOMPtr<nsIPresShell>> toNotify(mPresShells);
     for (nsIPresShell* presShell : toNotify) {
       if (presShell->StyleSet()) {
-        StyleSheet* sheet = presShell->StyleSet()->IsGecko() ? geckoSheet
-                                                             : servoSheet;
-        presShell->NotifyStyleSheetServiceSheetAdded(sheet, aSheetType);
+        bool isGecko = presShell->StyleSet()->IsGecko();
+        // We always have a Gecko sheet; we sometimes have a Servo sheet.
+        if (isGecko || servoSheetWasAdded) {
+          StyleSheet* sheet = isGecko ? mGeckoSheets[aSheetType].LastElement() :
+            mServoSheets[aSheetType].LastElement();
+          presShell->NotifyStyleSheetServiceSheetAdded(sheet, aSheetType);
+        } else {
+          MOZ_ASSERT_UNREACHABLE("Servo pres shell, but stylo unsupported?");
+        }
       }
     }
 
     if (XRE_IsParentProcess()) {
       nsTArray<dom::ContentParent*> children;
       dom::ContentParent::GetAll(children);
 
       if (children.IsEmpty()) {
@@ -246,47 +248,49 @@ nsStyleSheetService::LoadAndRegisterShee
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
   nsresult rv;
 
   RefPtr<StyleSheet> geckoSheet;
-  RefPtr<StyleSheet> servoSheet;
 
   rv = LoadSheet(aSheetURI, parsingMode, StyleBackendType::Gecko, &geckoSheet);
   NS_ENSURE_SUCCESS(rv, rv);
   MOZ_ASSERT(geckoSheet);
+  mGeckoSheets[aSheetType].AppendElement(geckoSheet);
 
 #ifdef MOZ_STYLO
   if (nsLayoutUtils::StyloSupportedInCurrentProcess()) {
+    RefPtr<StyleSheet> servoSheet;
+
     rv = LoadSheet(aSheetURI, parsingMode, StyleBackendType::Servo, &servoSheet);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(servoSheet);
+    mServoSheets[aSheetType].AppendElement(servoSheet);
   }
 #endif
 
-  mGeckoSheets[aSheetType].AppendElement(geckoSheet);
-  mServoSheets[aSheetType].AppendElement(servoSheet);
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStyleSheetService::SheetRegistered(nsIURI *sheetURI,
                                      uint32_t aSheetType, bool *_retval)
 {
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
                 aSheetType == AUTHOR_SHEET);
   NS_ENSURE_ARG_POINTER(sheetURI);
   NS_PRECONDITION(_retval, "Null out param");
 
-  *_retval = (FindSheetByURI(aSheetType, sheetURI) >= 0);
+  // Check to see if we have the Gecko sheet.
+  *_retval = (FindSheetByURI(mozilla::StyleBackendType::Gecko,
+                             aSheetType, sheetURI) >= 0);
 
   return NS_OK;
 }
 
 static nsresult
 GetParsingMode(uint32_t aSheetType, css::SheetParsingMode* aParsingMode)
 {
   switch (aSheetType) {
@@ -368,35 +372,43 @@ nsStyleSheetService::PreloadSheetAsync(n
 NS_IMETHODIMP
 nsStyleSheetService::UnregisterSheet(nsIURI *aSheetURI, uint32_t aSheetType)
 {
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
                 aSheetType == AUTHOR_SHEET);
   NS_ENSURE_ARG_POINTER(aSheetURI);
 
-  MOZ_ASSERT(mGeckoSheets[aSheetType].Length() ==
-               mServoSheets[aSheetType].Length());
-
-  int32_t foundIndex = FindSheetByURI(aSheetType, aSheetURI);
+  // We have to search for Gecko and Servo sheets separately.
+  // Gecko first, which should always be present.
+  int32_t foundIndex = FindSheetByURI(StyleBackendType::Gecko,
+                                      aSheetType, aSheetURI);
   NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
 
   RefPtr<StyleSheet> geckoSheet = mGeckoSheets[aSheetType][foundIndex];
-  RefPtr<StyleSheet> servoSheet = mServoSheets[aSheetType][foundIndex];
+  mGeckoSheets[aSheetType].RemoveElementAt(foundIndex);
 
-  mGeckoSheets[aSheetType].RemoveElementAt(foundIndex);
-  mServoSheets[aSheetType].RemoveElementAt(foundIndex);
+  // Now search for Servo, which may or may not be present.
+  RefPtr<StyleSheet> servoSheet;
+  foundIndex = FindSheetByURI(StyleBackendType::Servo,
+                              aSheetType, aSheetURI);
+  if (foundIndex >= 0) {
+    servoSheet = mServoSheets[aSheetType][foundIndex];
+    mServoSheets[aSheetType].RemoveElementAt(foundIndex);
+  }
 
   // Hold on to a copy of the registered PresShells.
   nsTArray<nsCOMPtr<nsIPresShell>> toNotify(mPresShells);
   for (nsIPresShell* presShell : toNotify) {
     if (presShell->StyleSet()) {
       StyleSheet* sheet = presShell->StyleSet()->IsGecko() ? geckoSheet
                                                            : servoSheet;
-      presShell->NotifyStyleSheetServiceSheetRemoved(sheet, aSheetType);
+      if (sheet) {
+        presShell->NotifyStyleSheetServiceSheetRemoved(sheet, aSheetType);
+      }
     }
   }
 
   if (XRE_IsParentProcess()) {
     nsTArray<dom::ContentParent*> children;
     dom::ContentParent::GetAll(children);
 
     if (children.IsEmpty()) {
--- a/layout/base/nsStyleSheetService.h
+++ b/layout/base/nsStyleSheetService.h
@@ -69,17 +69,19 @@ public:
 private:
   ~nsStyleSheetService();
 
   void RegisterFromEnumerator(nsICategoryManager  *aManager,
                                           const char          *aCategory,
                                           nsISimpleEnumerator *aEnumerator,
                                           uint32_t             aSheetType);
 
-  int32_t FindSheetByURI(uint32_t aSheetType, nsIURI* aSheetURI);
+  int32_t FindSheetByURI(mozilla::StyleBackendType aBackendType,
+                         uint32_t aSheetType,
+                         nsIURI* aSheetURI);
 
   // Like LoadAndRegisterSheet, but doesn't notify.  If successful, the
   // new sheet will be the last sheet in mSheets[aSheetType].
   nsresult LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
                                         uint32_t aSheetType);
 
   mozilla::Array<SheetArray, 3>& Sheets(mozilla::StyleBackendType aType)
   {