Bug 1403694 Part 1: Prevent nsStyleSheetService from storing null servo stylesheets.
MozReview-Commit-ID: 2PxurAtACtd
--- 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)
{