summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/base/nsContentSink.cpp5
-rw-r--r--dom/base/nsStyleLinkElement.cpp8
-rw-r--r--dom/base/nsStyleLinkElement.h3
-rw-r--r--dom/html/HTMLLinkElement.cpp20
-rw-r--r--dom/html/HTMLLinkElement.h12
-rw-r--r--dom/html/HTMLStyleElement.cpp4
-rw-r--r--dom/html/HTMLStyleElement.h3
-rw-r--r--dom/svg/SVGStyleElement.cpp4
-rw-r--r--dom/svg/SVGStyleElement.h3
-rw-r--r--dom/xml/XMLStylesheetProcessingInstruction.cpp4
-rw-r--r--dom/xml/XMLStylesheetProcessingInstruction.h3
-rw-r--r--layout/style/Loader.cpp28
-rw-r--r--layout/style/Loader.h13
13 files changed, 79 insertions, 31 deletions
diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp
index 1e6465a1b..59f4a9f9a 100644
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -789,13 +789,14 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
// If this is a fragment parser, we don't want to observe.
// We don't support CORS for processing instructions
bool isAlternate;
+ bool isExplicitlyEnabled;
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
CORS_NONE, mDocument->GetReferrerPolicy(),
integrity, mRunsToCompletion ? nullptr : this,
- &isAlternate);
+ &isAlternate, &isExplicitlyEnabled);
NS_ENSURE_SUCCESS(rv, rv);
- if (!isAlternate && !mRunsToCompletion) {
+ if ((!isAlternate || isExplicitlyEnabled) && !mRunsToCompletion) {
++mPendingSheetCount;
mScriptLoader->AddParserBlockingScriptExecutionBlocker();
}
diff --git a/dom/base/nsStyleLinkElement.cpp b/dom/base/nsStyleLinkElement.cpp
index 8ab2dab0b..2e5cdac6f 100644
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -393,8 +393,9 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
nsAutoString title, type, media;
bool isScoped;
bool isAlternate;
+ bool isExplicitlyEnabled;
- GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate);
+ GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate, &isExplicitlyEnabled);
if (!type.LowerCaseEqualsLiteral("text/css")) {
return NS_OK;
@@ -425,7 +426,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
// Parse the style sheet.
rv = doc->CSSLoader()->
LoadInlineStyle(thisContent, text, mLineNumber, title, media,
- scopeElement, aObserver, &doneLoading, &isAlternate);
+ scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled);
}
else {
nsAutoString integrity;
@@ -452,13 +453,14 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
rv = doc->CSSLoader()->
LoadStyleLink(thisContent, clonedURI, title, media, isAlternate,
GetCORSMode(), referrerPolicy, integrity,
- aObserver, &isAlternate);
+ aObserver, &isAlternate, &isExplicitlyEnabled);
if (NS_FAILED(rv)) {
// Don't propagate LoadStyleLink() errors further than this, since some
// consumers (e.g. nsXMLContentSink) will completely abort on innocuous
// things like a stylesheet load being blocked by the security system.
doneLoading = true;
isAlternate = false;
+ isExplicitlyEnabled = false;
rv = NS_OK;
}
}
diff --git a/dom/base/nsStyleLinkElement.h b/dom/base/nsStyleLinkElement.h
index a41ae5e1d..d9042c756 100644
--- a/dom/base/nsStyleLinkElement.h
+++ b/dom/base/nsStyleLinkElement.h
@@ -98,7 +98,8 @@ protected:
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate) = 0;
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled) = 0;
virtual mozilla::CORSMode GetCORSMode() const
{
diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp
index ed83836aa..352cbc755 100644
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -126,7 +126,6 @@ HTMLLinkElement::SetMozDisabled(bool aDisabled)
return rv.StealNSResult();
}
-
NS_IMPL_STRING_ATTR(HTMLLinkElement, Charset, charset)
NS_IMPL_URI_ATTR(HTMLLinkElement, Href, href)
NS_IMPL_STRING_ATTR(HTMLLinkElement, Hreflang, hreflang)
@@ -407,9 +406,14 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
aName == nsGkAtoms::disabled));
}
} else {
- // Since removing href or rel makes us no longer link to a
- // stylesheet, force updates for those too.
+ // If the disabled attribute is removed from a link element, the
+ // stylesheet may be explicitly enabled.
if (aNameSpaceID == kNameSpaceID_None) {
+ if (aName == nsGkAtoms::disabled) {
+ mExplicitlyEnabled = true;
+ }
+ // Since removing href or rel makes us no longer link to a
+ // stylesheet, force updates for those too.
if (aName == nsGkAtoms::href ||
aName == nsGkAtoms::rel ||
aName == nsGkAtoms::title ||
@@ -508,13 +512,15 @@ HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate)
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled)
{
aTitle.Truncate();
aType.Truncate();
aMedia.Truncate();
*aIsScoped = false;
*aIsAlternate = false;
+ *aIsExplicitlyEnabled = false;
nsAutoString rel;
GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
@@ -524,10 +530,16 @@ HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
return;
}
+ // Is the link disabled?
if (Disabled()) {
return;
}
+ // Is it explicitly enabled?
+ if (mExplicitlyEnabled) {
+ *aIsExplicitlyEnabled = true;
+ }
+
nsAutoString title;
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
title.CompressWhitespace();
diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h
index e024d42bb..190213028 100644
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -181,10 +181,18 @@ protected:
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate) override;
-protected:
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled) override;
+
RefPtr<nsDOMTokenList> mRelList;
+ // The "explicitly enabled" flag. This flag is set whenever the 'disabled'
+ // attribute is explicitly unset, and makes alternate stylesheets not be
+ // disabled by default anymore.
+ //
+ // See https://github.com/whatwg/html/issues/3840#issuecomment-481034206.
+ bool mExplicitlyEnabled = false;
+
private:
RefPtr<ImportLoader> mImportLoader;
};
diff --git a/dom/html/HTMLStyleElement.cpp b/dom/html/HTMLStyleElement.cpp
index 95cf025d1..c37e1a32d 100644
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -223,12 +223,14 @@ HTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate)
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled)
{
aTitle.Truncate();
aType.Truncate();
aMedia.Truncate();
*aIsAlternate = false;
+ *aIsExplicitlyEnabled = false;
nsAutoString title;
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
diff --git a/dom/html/HTMLStyleElement.h b/dom/html/HTMLStyleElement.h
index 8b69c3f62..7d98a494a 100644
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -88,7 +88,8 @@ protected:
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate) override;
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled) override;
/**
* Common method to call from the various mutation observer methods.
* aContent is a content node that's either the one that changed or its
diff --git a/dom/svg/SVGStyleElement.cpp b/dom/svg/SVGStyleElement.cpp
index 22fb204df..7655c1198 100644
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -271,9 +271,11 @@ SVGStyleElement::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate)
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled)
{
*aIsAlternate = false;
+ *aIsExplicitlyEnabled = false;
nsAutoString title;
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
diff --git a/dom/svg/SVGStyleElement.h b/dom/svg/SVGStyleElement.h
index 9b126e7e8..e637dfb18 100644
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -95,7 +95,8 @@ protected:
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate) override;
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled) override;
virtual CORSMode GetCORSMode() const override;
/**
diff --git a/dom/xml/XMLStylesheetProcessingInstruction.cpp b/dom/xml/XMLStylesheetProcessingInstruction.cpp
index 3d94e179b..43e45131a 100644
--- a/dom/xml/XMLStylesheetProcessingInstruction.cpp
+++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp
@@ -131,13 +131,15 @@ XMLStylesheetProcessingInstruction::GetStyleSheetInfo(nsAString& aTitle,
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate)
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled)
{
aTitle.Truncate();
aType.Truncate();
aMedia.Truncate();
*aIsScoped = false;
*aIsAlternate = false;
+ *aIsExplicitlyEnabled = false;
// xml-stylesheet PI is special only in prolog
if (!nsContentUtils::InProlog(this)) {
diff --git a/dom/xml/XMLStylesheetProcessingInstruction.h b/dom/xml/XMLStylesheetProcessingInstruction.h
index 818b3392f..28061834a 100644
--- a/dom/xml/XMLStylesheetProcessingInstruction.h
+++ b/dom/xml/XMLStylesheetProcessingInstruction.h
@@ -82,7 +82,8 @@ protected:
nsAString& aType,
nsAString& aMedia,
bool* aIsScoped,
- bool* aIsAlternate) override;
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled) override;
virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo,
bool aCloneText) const override;
};
diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp
index 68a7be21e..c21199238 100644
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1278,7 +1278,8 @@ Loader::PrepareSheet(StyleSheet* aSheet,
const nsSubstring& aMediaString,
nsMediaList* aMediaList,
Element* aScopeElement,
- bool isAlternate)
+ bool isAlternate,
+ bool isExplicitlyEnabled)
{
NS_PRECONDITION(aSheet, "Must have a sheet!");
@@ -1307,7 +1308,7 @@ Loader::PrepareSheet(StyleSheet* aSheet,
sheet->SetMedia(mediaList);
sheet->SetTitle(aTitle);
- sheet->SetEnabled(!isAlternate);
+ sheet->SetEnabled(!isAlternate || isExplicitlyEnabled);
sheet->SetScopeElement(aScopeElement);
}
@@ -1985,7 +1986,8 @@ Loader::LoadInlineStyle(nsIContent* aElement,
Element* aScopeElement,
nsICSSLoaderObserver* aObserver,
bool* aCompleted,
- bool* aIsAlternate)
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled)
{
LOG(("css::Loader::LoadInlineStyle"));
NS_ASSERTION(mParsingDatas.Length() == 0, "We're in the middle of a parse?");
@@ -2017,8 +2019,9 @@ Loader::LoadInlineStyle(nsIContent* aElement,
"Inline sheets should not be cached");
LOG((" Sheet is alternate: %d", *aIsAlternate));
+ LOG((" Sheet is explicitly enabled: %d", *aIsExplicitlyEnabled));
- PrepareSheet(sheet, aTitle, aMedia, nullptr, aScopeElement, *aIsAlternate);
+ PrepareSheet(sheet, aTitle, aMedia, nullptr, aScopeElement, *aIsAlternate, *aIsExplicitlyEnabled);
if (aElement->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
ShadowRoot* containingShadow = aElement->GetContainingShadow();
@@ -2059,7 +2062,8 @@ Loader::LoadStyleLink(nsIContent* aElement,
ReferrerPolicy aReferrerPolicy,
const nsAString& aIntegrity,
nsICSSLoaderObserver* aObserver,
- bool* aIsAlternate)
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled)
{
LOG(("css::Loader::LoadStyleLink"));
NS_PRECONDITION(aURL, "Must have URL to load");
@@ -2112,8 +2116,9 @@ Loader::LoadStyleLink(nsIContent* aElement,
NS_ENSURE_SUCCESS(rv, rv);
LOG((" Sheet is alternate: %d", *aIsAlternate));
+ LOG((" Sheet is explicitly enabled: %d", *aIsExplicitlyEnabled));
- PrepareSheet(sheet, aTitle, aMedia, nullptr, nullptr, *aIsAlternate);
+ PrepareSheet(sheet, aTitle, aMedia, nullptr, nullptr, *aIsAlternate, *aIsExplicitlyEnabled);
rv = InsertSheetInDoc(sheet, aElement, mDocument);
NS_ENSURE_SUCCESS(rv, rv);
@@ -2138,9 +2143,10 @@ Loader::LoadStyleLink(nsIContent* aElement,
aObserver, principal, requestingNode);
NS_ADDREF(data);
- // If we have to parse and it's an alternate non-inline, defer it
+ // If we have to parse and it's an alternate non-inline, defer it unless
+ // it's explicitly enabled.
if (aURL && state == eSheetNeedsParser && mSheets->mLoadingDatas.Count() != 0 &&
- *aIsAlternate) {
+ *aIsAlternate && !*aIsExplicitlyEnabled) {
LOG((" Deferring alternate sheet load"));
URIPrincipalReferrerPolicyAndCORSModeHashKey key(data->mURI,
data->mLoaderPrincipal,
@@ -2267,6 +2273,7 @@ Loader::LoadChildSheet(StyleSheet* aParentSheet,
state = eSheetComplete;
} else {
bool isAlternate;
+ bool isExplicitlyEnabled;
const nsSubstring& empty = EmptyString();
// For now, use CORS_NONE for child sheets
rv = CreateSheet(aURL, nullptr, principal,
@@ -2277,7 +2284,7 @@ Loader::LoadChildSheet(StyleSheet* aParentSheet,
false, empty, state, &isAlternate, &sheet);
NS_ENSURE_SUCCESS(rv, rv);
- PrepareSheet(sheet, empty, empty, aMedia, nullptr, isAlternate);
+ PrepareSheet(sheet, empty, empty, aMedia, nullptr, isAlternate, isExplicitlyEnabled);
}
rv = InsertChildSheet(sheet, aParentSheet, aParentRule);
@@ -2390,6 +2397,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
StyleSheetState state;
bool isAlternate;
+ bool isExplicitlyEnabled;
RefPtr<StyleSheet> sheet;
bool syncLoad = (aObserver == nullptr);
const nsSubstring& empty = EmptyString();
@@ -2399,7 +2407,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
false, empty, state, &isAlternate, &sheet);
NS_ENSURE_SUCCESS(rv, rv);
- PrepareSheet(sheet, empty, empty, nullptr, nullptr, isAlternate);
+ PrepareSheet(sheet, empty, empty, nullptr, nullptr, isAlternate, isExplicitlyEnabled);
if (state == eSheetComplete) {
LOG((" Sheet already complete"));
diff --git a/layout/style/Loader.h b/layout/style/Loader.h
index 209783a80..4a3088b6b 100644
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -230,6 +230,8 @@ public:
* @param [out] aCompleted whether parsing of the sheet completed.
* @param [out] aIsAlternate whether the stylesheet ended up being an
* alternate sheet.
+ * @param [out] aIsExplicitlyEnabled whether the stylesheet was explicitly
+ * enabled by having the disabled attribute removed.
*/
nsresult LoadInlineStyle(nsIContent* aElement,
const nsAString& aBuffer,
@@ -239,7 +241,8 @@ public:
mozilla::dom::Element* aScopeElement,
nsICSSLoaderObserver* aObserver,
bool* aCompleted,
- bool* aIsAlternate);
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled);
/**
* Load a linked (document) stylesheet. If a successful result is returned,
@@ -260,6 +263,8 @@ public:
* @param [out] aIsAlternate whether the stylesheet actually ended up beinga
* an alternate sheet. Note that this need not match
* aHasAlternateRel.
+ * @param [out] aIsExplicitlyEnabled whether the stylesheet was explicitly
+ * enabled by having the disabled attribute removed.
*/
nsresult LoadStyleLink(nsIContent* aElement,
nsIURI* aURL,
@@ -270,7 +275,8 @@ public:
ReferrerPolicy aReferrerPolicy,
const nsAString& aIntegrity,
nsICSSLoaderObserver* aObserver,
- bool* aIsAlternate);
+ bool* aIsAlternate,
+ bool* aIsExplicitlyEnabled);
/**
* Load a child (@import-ed) style sheet. In addition to loading the sheet,
@@ -476,7 +482,8 @@ private:
const nsAString& aMediaString,
nsMediaList* aMediaList,
dom::Element* aScopeElement,
- bool isAlternate);
+ bool isAlternate,
+ bool isExplicitlyEnabled);
nsresult InsertSheetInDoc(StyleSheet* aSheet,
nsIContent* aLinkingContent,