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.cpp59
-rw-r--r--dom/html/HTMLLinkElement.h16
-rw-r--r--dom/html/HTMLStyleElement.cpp6
-rw-r--r--dom/html/HTMLStyleElement.h5
-rw-r--r--dom/svg/SVGStyleElement.cpp4
-rw-r--r--dom/svg/SVGStyleElement.h3
-rw-r--r--dom/webidl/HTMLLinkElement.webidl2
-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
-rw-r--r--modules/libpref/init/all.js8
15 files changed, 123 insertions, 44 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 8afe767bd..1b78cbd69 100644
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -33,6 +33,8 @@
#define LINK_ELEMENT_FLAG_BIT(n_) \
NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
+#define LINK_DISABLED Preferences::GetBool("dom.link.disabled_attribute.enabled", true)
+
// Link element specific bits
enum {
// Indicates that a DNS Prefetch has been requested from this Link element.
@@ -92,9 +94,14 @@ NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
NS_IMPL_ELEMENT_CLONE(HTMLLinkElement)
+
bool
-HTMLLinkElement::Disabled()
+HTMLLinkElement::Disabled() const
{
+ if (LINK_DISABLED) {
+ return GetBoolAttr(nsGkAtoms::disabled);
+ }
+
StyleSheet* ss = GetSheet();
return ss && ss->Disabled();
}
@@ -107,8 +114,12 @@ HTMLLinkElement::GetMozDisabled(bool* aDisabled)
}
void
-HTMLLinkElement::SetDisabled(bool aDisabled)
-{
+HTMLLinkElement::SetDisabled(bool aDisabled, ErrorResult& aRv)
+{
+ if (LINK_DISABLED) {
+ return SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aRv);
+ }
+
if (StyleSheet* ss = GetSheet()) {
ss->SetDisabled(aDisabled);
}
@@ -117,11 +128,11 @@ HTMLLinkElement::SetDisabled(bool aDisabled)
NS_IMETHODIMP
HTMLLinkElement::SetMozDisabled(bool aDisabled)
{
- SetDisabled(aDisabled);
- return NS_OK;
+ ErrorResult rv;
+ SetDisabled(aDisabled, rv);
+ return rv.StealNSResult();
}
-
NS_IMPL_STRING_ATTR(HTMLLinkElement, Charset, charset)
NS_IMPL_URI_ATTR(HTMLLinkElement, Href, href)
NS_IMPL_STRING_ATTR(HTMLLinkElement, Hreflang, hreflang)
@@ -369,7 +380,8 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
aName == nsGkAtoms::rel ||
aName == nsGkAtoms::title ||
aName == nsGkAtoms::media ||
- aName == nsGkAtoms::type)) {
+ aName == nsGkAtoms::type ||
+ (LINK_DISABLED && aName == nsGkAtoms::disabled))) {
bool dropSheet = false;
if (aName == nsGkAtoms::rel) {
nsAutoString value;
@@ -396,17 +408,24 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
dropSheet ||
(aName == nsGkAtoms::title ||
aName == nsGkAtoms::media ||
- aName == nsGkAtoms::type));
+ aName == nsGkAtoms::type ||
+ (LINK_DISABLED && 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 && LINK_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 ||
aName == nsGkAtoms::media ||
- aName == nsGkAtoms::type) {
+ aName == nsGkAtoms::type ||
+ (LINK_DISABLED && aName == nsGkAtoms::disabled)) {
UpdateStyleSheetInternal(nullptr, nullptr, true);
}
if (aName == nsGkAtoms::href ||
@@ -499,13 +518,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);
@@ -515,6 +536,20 @@ HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
return;
}
+ if (LINK_DISABLED) {
+
+ // 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 421b149e9..f9c832c8d 100644
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -84,8 +84,8 @@ public:
virtual bool HasDeferredDNSPrefetchRequest() override;
// WebIDL
- bool Disabled();
- void SetDisabled(bool aDisabled);
+ bool Disabled() const;
+ void SetDisabled(bool aDisabled, ErrorResult& aRv);
// XPCOM GetHref is fine.
void SetHref(const nsAString& aHref, ErrorResult& aRv)
{
@@ -179,10 +179,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 329dda648..87dc68f83 100644
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -66,7 +66,7 @@ HTMLStyleElement::GetMozDisabled(bool* aDisabled)
}
bool
-HTMLStyleElement::Disabled()
+HTMLStyleElement::Disabled() const
{
StyleSheet* ss = GetSheet();
return ss && ss->Disabled();
@@ -222,12 +222,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 6b2a12b1f..9f82b8e51 100644
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -58,7 +58,7 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
- bool Disabled();
+ bool Disabled() const;
void SetDisabled(bool aDisabled);
void SetMedia(const nsAString& aMedia, ErrorResult& aError)
{
@@ -87,7 +87,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/webidl/HTMLLinkElement.webidl b/dom/webidl/HTMLLinkElement.webidl
index ec094e55e..0b77e9ea7 100644
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -13,7 +13,7 @@
// http://www.whatwg.org/specs/web-apps/current-work/#the-link-element
interface HTMLLinkElement : HTMLElement {
- [Pure]
+ [CEReactions, SetterThrows, Pure]
attribute boolean disabled;
[SetterThrows, Pure]
attribute DOMString href;
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 0ce337e29..df523174d 100644
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1277,7 +1277,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!");
@@ -1306,7 +1307,7 @@ Loader::PrepareSheet(StyleSheet* aSheet,
sheet->SetMedia(mediaList);
sheet->SetTitle(aTitle);
- sheet->SetEnabled(!isAlternate);
+ sheet->SetEnabled(!isAlternate || isExplicitlyEnabled);
sheet->SetScopeElement(aScopeElement);
}
@@ -1984,7 +1985,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?");
@@ -2016,8 +2018,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();
@@ -2058,7 +2061,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");
@@ -2111,8 +2115,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);
@@ -2137,9 +2142,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,
@@ -2266,6 +2272,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,
@@ -2276,7 +2283,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);
@@ -2389,6 +2396,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
StyleSheetState state;
bool isAlternate;
+ bool isExplicitlyEnabled;
RefPtr<StyleSheet> sheet;
bool syncLoad = (aObserver == nullptr);
const nsSubstring& empty = EmptyString();
@@ -2398,7 +2406,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,
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 60851e55e..7dbeec54a 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1185,6 +1185,14 @@ pref("dom.storage.default_quota", 5120);
pref("dom.send_after_paint_to_content", false);
+// Whether the disabled attribute in HTMLLinkElement disables the sheet loading
+// altogether, or forwards to the inner stylesheet method without attribute
+// reflection.
+//
+// Historical behavior is the second, the first is being discussed at:
+// https://github.com/whatwg/html/issues/3840
+pref("dom.link.disabled_attribute.enabled", true);
+
// Timeout clamp in ms for timeouts we clamp
pref("dom.min_timeout_value", 4);
// And for background windows