Bug 1456435: Make UpdateStyleSheet less bool-happy. r=heycam

MozReview-Commit-ID: FlTD390lMhg
This commit is contained in:
Emilio Cobos Álvarez
2018-04-24 12:50:35 +02:00
parent 5a15cde7a0
commit 78f32b94e5
13 changed files with 185 additions and 140 deletions

View File

@@ -9,6 +9,7 @@
#include "nsISupports.h" #include "nsISupports.h"
#include "mozilla/StyleSheet.h" #include "mozilla/StyleSheet.h"
#include "mozilla/Result.h"
class nsICSSLoaderObserver; class nsICSSLoaderObserver;
class nsIURI; class nsIURI;
@@ -19,6 +20,57 @@ class nsIURI;
class nsIStyleSheetLinkingElement : public nsISupports { class nsIStyleSheetLinkingElement : public nsISupports {
public: public:
enum class ForceUpdate
{
Yes,
No,
};
enum class IsAlternate
{
Yes,
No,
};
enum class WillNotify
{
Yes,
No,
};
struct Update
{
private:
bool mWillNotify;
bool mIsAlternate;
public:
Update()
: mWillNotify(false)
, mIsAlternate(false)
{
}
Update(WillNotify aWillNotify, IsAlternate aIsAlternate)
: mWillNotify(aWillNotify == WillNotify::Yes)
, mIsAlternate(aIsAlternate == IsAlternate::Yes)
{ }
bool WillNotify() const
{
return mWillNotify;
}
bool ShouldBlock() const
{
if (!mWillNotify) {
return false;
}
return !mIsAlternate;
}
};
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISTYLESHEETLINKINGELEMENT_IID) NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISTYLESHEETLINKINGELEMENT_IID)
/** /**
@@ -50,21 +102,12 @@ public:
* *
* @param aObserver observer to notify once the stylesheet is loaded. * @param aObserver observer to notify once the stylesheet is loaded.
* This will be passed to the CSSLoader * This will be passed to the CSSLoader
* @param [out] aWillNotify whether aObserver will be notified when the sheet
* loads. If this is false, then either we didn't
* start the sheet load at all, the load failed, or
* this was an inline sheet that completely finished
* loading. In the case when the load failed the
* failure code will be returned.
* @param [out] whether the sheet is an alternate sheet. This value is only
* meaningful if aWillNotify is true.
* @param aForceUpdate whether we wand to force the update, flushing the * @param aForceUpdate whether we wand to force the update, flushing the
* cached version if any. * cached version if any.
*/ */
virtual nsresult UpdateStyleSheet(nsICSSLoaderObserver* aObserver, virtual mozilla::Result<Update, nsresult>
bool *aWillNotify, UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
bool *aIsAlternate, ForceUpdate = ForceUpdate::No) = 0;
bool aForceUpdate = false) = 0;
/** /**
* Tells this element whether to update the stylesheet when the * Tells this element whether to update the stylesheet when the

View File

@@ -176,13 +176,11 @@ uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
return linkMask; return linkMask;
} }
nsresult Result<nsStyleLinkElement::Update, nsresult>
nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver, nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
bool* aWillNotify, ForceUpdate aForceUpdate)
bool* aIsAlternate,
bool aForceReload)
{ {
if (aForceReload) { if (aForceUpdate == ForceUpdate::Yes) {
// We remove this stylesheet from the cache to load a new version. // We remove this stylesheet from the cache to load a new version.
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this); nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ? nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
@@ -192,30 +190,24 @@ nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
doc->CSSLoader()->ObsoleteSheet(mStyleSheet->GetOriginalURI()); doc->CSSLoader()->ObsoleteSheet(mStyleSheet->GetOriginalURI());
} }
} }
return DoUpdateStyleSheet(nullptr, nullptr, aObserver, aWillNotify, return DoUpdateStyleSheet(nullptr, nullptr, aObserver, aForceUpdate);
aIsAlternate, aForceReload);
} }
nsresult Result<nsStyleLinkElement::Update, nsresult>
nsStyleLinkElement::UpdateStyleSheetInternal(nsIDocument *aOldDocument, nsStyleLinkElement::UpdateStyleSheetInternal(nsIDocument* aOldDocument,
ShadowRoot *aOldShadowRoot, ShadowRoot* aOldShadowRoot,
bool aForceUpdate) ForceUpdate aForceUpdate)
{ {
bool notify, alternate; return DoUpdateStyleSheet(
return DoUpdateStyleSheet(aOldDocument, aOldShadowRoot, nullptr, &notify, aOldDocument, aOldShadowRoot, nullptr, aForceUpdate);
&alternate, aForceUpdate);
} }
nsresult Result<nsStyleLinkElement::Update, nsresult>
nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument, nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
ShadowRoot* aOldShadowRoot, ShadowRoot* aOldShadowRoot,
nsICSSLoaderObserver* aObserver, nsICSSLoaderObserver* aObserver,
bool* aWillNotify, ForceUpdate aForceUpdate)
bool* aIsAlternate,
bool aForceUpdate)
{ {
*aWillNotify = false;
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this); nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
// All instances of nsStyleLinkElement should implement nsIContent. // All instances of nsStyleLinkElement should implement nsIContent.
MOZ_ASSERT(thisContent); MOZ_ASSERT(thisContent);
@@ -224,7 +216,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
thisContent->IsAnonymousContentInSVGUseSubtree()) { thisContent->IsAnonymousContentInSVGUseSubtree()) {
// Stylesheets in <use>-cloned subtrees are disabled until we figure out // Stylesheets in <use>-cloned subtrees are disabled until we figure out
// how they should behave. // how they should behave.
return NS_OK; return Update { };
} }
// Check for a ShadowRoot because link elements are inert in a // Check for a ShadowRoot because link elements are inert in a
@@ -232,7 +224,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
ShadowRoot* containingShadow = thisContent->GetContainingShadow(); ShadowRoot* containingShadow = thisContent->GetContainingShadow();
if (thisContent->IsHTMLElement(nsGkAtoms::link) && if (thisContent->IsHTMLElement(nsGkAtoms::link) &&
(aOldShadowRoot || containingShadow)) { (aOldShadowRoot || containingShadow)) {
return NS_OK; return Update { };
} }
if (mStyleSheet && (aOldDocument || aOldShadowRoot)) { if (mStyleSheet && (aOldDocument || aOldShadowRoot)) {
@@ -259,26 +251,25 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
// When static documents are created, stylesheets are cloned manually. // When static documents are created, stylesheets are cloned manually.
if (mDontLoadStyle || !mUpdatesEnabled || if (mDontLoadStyle || !mUpdatesEnabled ||
thisContent->OwnerDoc()->IsStaticDocument()) { thisContent->OwnerDoc()->IsStaticDocument()) {
return NS_OK; return Update { };
} }
nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ? nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
thisContent->OwnerDoc() : thisContent->GetUncomposedDoc(); thisContent->OwnerDoc() : thisContent->GetUncomposedDoc();
if (!doc || !doc->CSSLoader()->GetEnabled()) { if (!doc || !doc->CSSLoader()->GetEnabled()) {
return NS_OK; return Update { };
} }
bool isInline; bool isInline;
nsCOMPtr<nsIPrincipal> triggeringPrincipal; nsCOMPtr<nsIPrincipal> triggeringPrincipal;
nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline, getter_AddRefs(triggeringPrincipal)); nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline, getter_AddRefs(triggeringPrincipal));
if (!aForceUpdate && mStyleSheet && !isInline && uri) { if (aForceUpdate == ForceUpdate::No && mStyleSheet && !isInline && uri) {
nsIURI* oldURI = mStyleSheet->GetSheetURI(); if (nsIURI* oldURI = mStyleSheet->GetSheetURI()) {
if (oldURI) {
bool equal; bool equal;
nsresult rv = oldURI->Equals(uri, &equal); nsresult rv = oldURI->Equals(uri, &equal);
if (NS_SUCCEEDED(rv) && equal) { if (NS_SUCCEEDED(rv) && equal) {
return NS_OK; // We already loaded this stylesheet return Update { };
} }
} }
} }
@@ -297,20 +288,18 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
} }
if (!uri && !isInline) { if (!uri && !isInline) {
return NS_OK; // If href is empty and this is not inline style then just bail // If href is empty and this is not inline style then just bail
return Update { };
} }
nsAutoString title, type, media; nsAutoString title, type, media;
bool isAlternate; bool hasAlternateRel;
GetStyleSheetInfo(title, type, media, &hasAlternateRel);
GetStyleSheetInfo(title, type, media, &isAlternate);
if (!type.LowerCaseEqualsLiteral("text/css")) { if (!type.LowerCaseEqualsLiteral("text/css")) {
return NS_OK; return Update { };
} }
bool doneLoading = false; bool doneLoading = false;
nsresult rv = NS_OK;
// Load the link's referrerpolicy attribute. If the link does not provide a // Load the link's referrerpolicy attribute. If the link does not provide a
// referrerpolicy attribute, ignore this and use the document's referrer // referrerpolicy attribute, ignore this and use the document's referrer
@@ -321,27 +310,37 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
referrerPolicy = doc->GetReferrerPolicy(); referrerPolicy = doc->GetReferrerPolicy();
} }
bool isAlternate;
if (isInline) { if (isInline) {
nsAutoString text; nsAutoString text;
if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) { if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) {
return NS_ERROR_OUT_OF_MEMORY; return Err(NS_ERROR_OUT_OF_MEMORY);
} }
MOZ_ASSERT(thisContent->NodeInfo()->NameAtom() != nsGkAtoms::link, MOZ_ASSERT(thisContent->NodeInfo()->NameAtom() != nsGkAtoms::link,
"<link> is not 'inline', and needs different CSP checks"); "<link> is not 'inline', and needs different CSP checks");
MOZ_ASSERT(thisContent->IsElement()); MOZ_ASSERT(thisContent->IsElement());
nsresult rv = NS_OK;
if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent->AsElement(), if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent->AsElement(),
thisContent->NodePrincipal(), thisContent->NodePrincipal(),
triggeringPrincipal, triggeringPrincipal,
doc->GetDocumentURI(), doc->GetDocumentURI(),
mLineNumber, text, &rv)) mLineNumber, text, &rv)) {
return rv; if (NS_FAILED(rv)) {
return Err(rv);
}
return Update { };
}
// Parse the style sheet. // Parse the style sheet.
rv = doc->CSSLoader()-> rv = doc->CSSLoader()->
LoadInlineStyle(thisContent, text, triggeringPrincipal, mLineNumber, LoadInlineStyle(thisContent, text, triggeringPrincipal, mLineNumber,
title, media, referrerPolicy, title, media, referrerPolicy,
aObserver, &doneLoading, &isAlternate); aObserver, &doneLoading, &isAlternate);
if (NS_FAILED(rv)) {
return Err(rv);
}
} else { } else {
nsAutoString integrity; nsAutoString integrity;
if (thisContent->IsElement()) { if (thisContent->IsElement()) {
@@ -354,24 +353,19 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
NS_ConvertUTF16toUTF8(integrity).get())); NS_ConvertUTF16toUTF8(integrity).get()));
} }
rv = doc->CSSLoader()-> nsresult rv = doc->CSSLoader()->
LoadStyleLink(thisContent, uri, triggeringPrincipal, title, media, LoadStyleLink(thisContent, uri, triggeringPrincipal, title, media,
isAlternate, GetCORSMode(), referrerPolicy, integrity, hasAlternateRel, GetCORSMode(), referrerPolicy, integrity,
aObserver, &isAlternate); aObserver, &isAlternate);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
// Don't propagate LoadStyleLink() errors further than this, since some // Don't propagate LoadStyleLink() errors further than this, since some
// consumers (e.g. nsXMLContentSink) will completely abort on innocuous // consumers (e.g. nsXMLContentSink) will completely abort on innocuous
// things like a stylesheet load being blocked by the security system. // things like a stylesheet load being blocked by the security system.
doneLoading = true; return Update { };
isAlternate = false;
rv = NS_OK;
} }
} }
NS_ENSURE_SUCCESS(rv, rv); auto willNotify = doneLoading ? WillNotify::No : WillNotify::Yes;
auto alternate = isAlternate ? IsAlternate::Yes : IsAlternate::No;
*aWillNotify = !doneLoading; return Update { willNotify, alternate };
*aIsAlternate = isAlternate;
return NS_OK;
} }

View File

@@ -16,6 +16,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/CORSMode.h" #include "mozilla/CORSMode.h"
#include "mozilla/StyleSheetInlines.h" #include "mozilla/StyleSheetInlines.h"
#include "mozilla/Unused.h"
#include "mozilla/net/ReferrerPolicy.h" #include "mozilla/net/ReferrerPolicy.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIStyleSheetLinkingElement.h" #include "nsIStyleSheetLinkingElement.h"
@@ -45,16 +46,16 @@ public:
void SetStyleSheet(mozilla::StyleSheet* aStyleSheet) override; void SetStyleSheet(mozilla::StyleSheet* aStyleSheet) override;
mozilla::StyleSheet* GetStyleSheet() override; mozilla::StyleSheet* GetStyleSheet() override;
void InitStyleLinkElement(bool aDontLoadStyle) override; void InitStyleLinkElement(bool aDontLoadStyle) override;
nsresult UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
bool* aWillNotify, mozilla::Result<Update, nsresult>
bool* aIsAlternate, UpdateStyleSheet(nsICSSLoaderObserver*, ForceUpdate) override;
bool aForceReload) override;
void SetEnableUpdates(bool aEnableUpdates) override; void SetEnableUpdates(bool aEnableUpdates) override;
void GetCharset(nsAString& aCharset) override; void GetCharset(nsAString& aCharset) override;
virtual void OverrideBaseURI(nsIURI* aNewBaseURI) override; void OverrideBaseURI(nsIURI* aNewBaseURI) override;
virtual void SetLineNumber(uint32_t aLineNumber) override; void SetLineNumber(uint32_t aLineNumber) override;
virtual uint32_t GetLineNumber() override; uint32_t GetLineNumber() override;
enum RelValue { enum RelValue {
ePREFETCH = 0x00000001, ePREFETCH = 0x00000001,
@@ -72,20 +73,25 @@ public:
void UpdateStyleSheetInternal() void UpdateStyleSheetInternal()
{ {
UpdateStyleSheetInternal(nullptr, nullptr); mozilla::Unused << UpdateStyleSheetInternal(nullptr, nullptr);
} }
protected: protected:
/** /**
* @param aOldDocument should be non-null only if we're updating because we * @param aOldDocument should be non-null only if we're updating because we
* removed the node from the document. * removed the node from the document.
* @param aOldShadowRoot should be non-null only if we're updating because we
* removed the node from a shadow tree.
* @param aForceUpdate true will force the update even if the URI has not * @param aForceUpdate true will force the update even if the URI has not
* changed. This should be used in cases when something * changed. This should be used in cases when something
* about the content that affects the resulting sheet * about the content that affects the resulting sheet
* changed but the URI may not have changed. * changed but the URI may not have changed.
*
* TODO(emilio): Should probably pass a single DocumentOrShadowRoot.
*/ */
nsresult UpdateStyleSheetInternal(nsIDocument *aOldDocument, mozilla::Result<Update, nsresult> UpdateStyleSheetInternal(
mozilla::dom::ShadowRoot *aOldShadowRoot, nsIDocument* aOldDocument,
bool aForceUpdate = false); mozilla::dom::ShadowRoot* aOldShadowRoot,
ForceUpdate = ForceUpdate::No);
virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) = 0; virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) = 0;
virtual void GetStyleSheetInfo(nsAString& aTitle, virtual void GetStyleSheetInfo(nsAString& aTitle,
@@ -121,12 +127,11 @@ private:
* about the content that affects the resulting sheet * about the content that affects the resulting sheet
* changed but the URI may not have changed. * changed but the URI may not have changed.
*/ */
nsresult DoUpdateStyleSheet(nsIDocument* aOldDocument, mozilla::Result<Update, nsresult>
mozilla::dom::ShadowRoot* aOldShadowRoot, DoUpdateStyleSheet(nsIDocument* aOldDocument,
nsICSSLoaderObserver* aObserver, mozilla::dom::ShadowRoot* aOldShadowRoot,
bool* aWillNotify, nsICSSLoaderObserver* aObserver,
bool* aIsAlternate, ForceUpdate);
bool aForceUpdate);
RefPtr<mozilla::StyleSheet> mStyleSheet; RefPtr<mozilla::StyleSheet> mStyleSheet;
protected: protected:

View File

@@ -192,7 +192,7 @@ HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent)
CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved")); CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved"));
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheetInternal(oldDoc, oldShadowRoot); Unused << UpdateStyleSheetInternal(oldDoc, oldShadowRoot);
} }
bool bool
@@ -328,11 +328,13 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
UpdatePreload(aName, aValue, aOldValue); UpdatePreload(aName, aValue, aOldValue);
} }
UpdateStyleSheetInternal(nullptr, nullptr, const bool forceUpdate = dropSheet ||
dropSheet || aName == nsGkAtoms::title ||
(aName == nsGkAtoms::title || aName == nsGkAtoms::media ||
aName == nsGkAtoms::media || aName == nsGkAtoms::type;
aName == nsGkAtoms::type));
Unused << UpdateStyleSheetInternal(
nullptr, nullptr, forceUpdate ? ForceUpdate::Yes : ForceUpdate::No);
} }
} else { } else {
// Since removing href or rel makes us no longer link to a // Since removing href or rel makes us no longer link to a
@@ -343,7 +345,7 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
aName == nsGkAtoms::title || aName == nsGkAtoms::title ||
aName == nsGkAtoms::media || aName == nsGkAtoms::media ||
aName == nsGkAtoms::type) { aName == nsGkAtoms::type) {
UpdateStyleSheetInternal(nullptr, nullptr, true); Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
} }
if ((aName == nsGkAtoms::as || aName == nsGkAtoms::type || if ((aName == nsGkAtoms::as || aName == nsGkAtoms::type ||
aName == nsGkAtoms::crossorigin || aName == nsGkAtoms::media) && aName == nsGkAtoms::crossorigin || aName == nsGkAtoms::media) &&

View File

@@ -94,7 +94,7 @@ HTMLStyleElement::ContentChanged(nsIContent* aContent)
{ {
mTriggeringPrincipal = nullptr; mTriggeringPrincipal = nullptr;
if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) { if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
UpdateStyleSheetInternal(nullptr, nullptr); Unused << UpdateStyleSheetInternal(nullptr, nullptr);
} }
} }
@@ -130,7 +130,7 @@ HTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
return; return;
} }
UpdateStyleSheetInternal(oldDoc, oldShadow); Unused << UpdateStyleSheetInternal(oldDoc, oldShadow);
} }
nsresult nsresult
@@ -144,7 +144,7 @@ HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
if (aName == nsGkAtoms::title || if (aName == nsGkAtoms::title ||
aName == nsGkAtoms::media || aName == nsGkAtoms::media ||
aName == nsGkAtoms::type) { aName == nsGkAtoms::type) {
UpdateStyleSheetInternal(nullptr, nullptr, true); Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
} }
} }
@@ -191,7 +191,7 @@ HTMLStyleElement::SetTextContentInternal(const nsAString& aTextContent,
mTriggeringPrincipal = aScriptedPrincipal; mTriggeringPrincipal = aScriptedPrincipal;
UpdateStyleSheetInternal(nullptr, nullptr); Unused << UpdateStyleSheetInternal(nullptr, nullptr);
} }
already_AddRefed<nsIURI> already_AddRefed<nsIURI>

View File

@@ -86,7 +86,7 @@ SVGStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc(); nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc();
ShadowRoot* oldShadow = GetContainingShadow(); ShadowRoot* oldShadow = GetContainingShadow();
SVGStyleElementBase::UnbindFromTree(aDeep, aNullParent); SVGStyleElementBase::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheetInternal(oldDoc, oldShadow); Unused << UpdateStyleSheetInternal(oldDoc, oldShadow);
} }
nsresult nsresult
@@ -100,7 +100,7 @@ SVGStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
if (aName == nsGkAtoms::title || if (aName == nsGkAtoms::title ||
aName == nsGkAtoms::media || aName == nsGkAtoms::media ||
aName == nsGkAtoms::type) { aName == nsGkAtoms::type) {
UpdateStyleSheetInternal(nullptr, nullptr, true); Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
} }
} }
@@ -159,7 +159,7 @@ void
SVGStyleElement::ContentChanged(nsIContent* aContent) SVGStyleElement::ContentChanged(nsIContent* aContent)
{ {
if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) { if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
UpdateStyleSheetInternal(nullptr, nullptr); Unused << UpdateStyleSheetInternal(nullptr, nullptr);
} }
} }

View File

@@ -69,7 +69,7 @@ XMLStylesheetProcessingInstruction::UnbindFromTree(bool aDeep, bool aNullParent)
nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc(); nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc();
ProcessingInstruction::UnbindFromTree(aDeep, aNullParent); ProcessingInstruction::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheetInternal(oldDoc, nullptr); Unused << UpdateStyleSheetInternal(oldDoc, nullptr);
} }
// nsIDOMNode // nsIDOMNode
@@ -80,7 +80,7 @@ XMLStylesheetProcessingInstruction::SetNodeValueInternal(const nsAString& aNodeV
{ {
CharacterData::SetNodeValueInternal(aNodeValue, aError); CharacterData::SetNodeValueInternal(aNodeValue, aError);
if (!aError.Failed()) { if (!aError.Failed()) {
UpdateStyleSheetInternal(nullptr, nullptr, true); Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
} }
} }

View File

@@ -8,6 +8,7 @@
#define mozilla_dom_XMLStylesheetProcessingInstruction_h #define mozilla_dom_XMLStylesheetProcessingInstruction_h
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/ProcessingInstruction.h" #include "mozilla/dom/ProcessingInstruction.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsStyleLinkElement.h" #include "nsStyleLinkElement.h"
@@ -68,7 +69,7 @@ public:
if (rv.Failed()) { if (rv.Failed()) {
return; return;
} }
UpdateStyleSheetInternal(nullptr, nullptr, true); Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
} }
protected: protected:

View File

@@ -603,12 +603,11 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aContent)); nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aContent));
if (ssle) { if (ssle) {
ssle->SetEnableUpdates(true); ssle->SetEnableUpdates(true);
bool willNotify; auto updateOrError =
bool isAlternate; ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this);
rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, if (updateOrError.isErr()) {
&willNotify, rv = updateOrError.unwrapErr();
&isAlternate); } else if (updateOrError.unwrap().ShouldBlock() && !mRunsToCompletion) {
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
++mPendingSheetCount; ++mPendingSheetCount;
mScriptLoader->AddParserBlockingScriptExecutionBlocker(); mScriptLoader->AddParserBlockingScriptExecutionBlocker();
} }
@@ -1268,20 +1267,19 @@ nsXMLContentSink::HandleProcessingInstruction(const char16_t *aTarget,
// This is an xml-stylesheet processing instruction... but it might not be // This is an xml-stylesheet processing instruction... but it might not be
// a CSS one if the type is set to something else. // a CSS one if the type is set to something else.
ssle->SetEnableUpdates(true); ssle->SetEnableUpdates(true);
bool willNotify; auto updateOrError =
bool isAlternate; ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this);
rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, if (updateOrError.isErr()) {
&willNotify, return updateOrError.unwrapErr();
&isAlternate); }
NS_ENSURE_SUCCESS(rv, rv);
if (willNotify) { auto update = updateOrError.unwrap();
if (update.WillNotify()) {
// Successfully started a stylesheet load // Successfully started a stylesheet load
if (!isAlternate && !mRunsToCompletion) { if (update.ShouldBlock() && !mRunsToCompletion) {
++mPendingSheetCount; ++mPendingSheetCount;
mScriptLoader->AddParserBlockingScriptExecutionBlocker(); mScriptLoader->AddParserBlockingScriptExecutionBlocker();
} }
return NS_OK; return NS_OK;
} }
} }

View File

@@ -322,11 +322,10 @@ txMozillaXMLOutput::endElement()
do_QueryInterface(mCurrentNode); do_QueryInterface(mCurrentNode);
if (ssle) { if (ssle) {
ssle->SetEnableUpdates(true); ssle->SetEnableUpdates(true);
bool willNotify; auto updateOrError = ssle->UpdateStyleSheet(mNotifier);
bool isAlternate; if (mNotifier &&
nsresult rv = ssle->UpdateStyleSheet(mNotifier, &willNotify, updateOrError.isOk() &&
&isAlternate); updateOrError.unwrap().ShouldBlock()) {
if (mNotifier && NS_SUCCEEDED(rv) && willNotify && !isAlternate) {
mNotifier->AddPendingStylesheet(); mNotifier->AddPendingStylesheet();
} }
} }
@@ -400,10 +399,10 @@ txMozillaXMLOutput::processingInstruction(const nsString& aTarget, const nsStrin
if (ssle) { if (ssle) {
ssle->SetEnableUpdates(true); ssle->SetEnableUpdates(true);
bool willNotify; auto updateOrError = ssle->UpdateStyleSheet(mNotifier);
bool isAlternate; if (mNotifier &&
rv = ssle->UpdateStyleSheet(mNotifier, &willNotify, &isAlternate); updateOrError.isOk() &&
if (mNotifier && NS_SUCCEEDED(rv) && willNotify && !isAlternate) { updateOrError.unwrap().ShouldBlock()) {
mNotifier->AddPendingStylesheet(); mNotifier->AddPendingStylesheet();
} }
} }

View File

@@ -2104,18 +2104,20 @@ XULDocument::InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI,
// load the stylesheet if necessary, passing ourselves as // load the stylesheet if necessary, passing ourselves as
// nsICSSObserver // nsICSSObserver
bool willNotify; auto result = ssle->UpdateStyleSheet(this);
bool isAlternate; if (result.isErr()) {
rv = ssle->UpdateStyleSheet(this, &willNotify, &isAlternate); // Ignore errors from UpdateStyleSheet; we don't want failure to
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate) { // do that to break the XUL document load. But do propagate out
++mPendingSheets; // NS_ERROR_OUT_OF_MEMORY.
if (result.unwrapErr() == NS_ERROR_OUT_OF_MEMORY) {
return result.unwrapErr();
}
return NS_OK;
} }
// Ignore errors from UpdateStyleSheet; we don't want failure to auto update = result.unwrap();
// do that to break the XUL document load. But do propagate out if (update.ShouldBlock()) {
// NS_ERROR_OUT_OF_MEMORY. ++mPendingSheets;
if (rv == NS_ERROR_OUT_OF_MEMORY) {
return rv;
} }
return NS_OK; return NS_OK;
@@ -2492,10 +2494,7 @@ XULDocument::ResumeWalk()
do_QueryInterface(element); do_QueryInterface(element);
NS_ASSERTION(ssle, "<html:style> doesn't implement " NS_ASSERTION(ssle, "<html:style> doesn't implement "
"nsIStyleSheetLinkingElement?"); "nsIStyleSheetLinkingElement?");
bool willNotify; Unused << ssle->UpdateStyleSheet(nullptr);
bool isAlternate;
ssle->UpdateStyleSheet(nullptr, &willNotify,
&isAlternate);
} }
} }
} }

View File

@@ -840,6 +840,9 @@ Loader::IsAlternate(const nsAString& aTitle, bool aHasAlternateRel)
// style set, the sheet wasn't marked as an alternate explicitly, and aTitle // style set, the sheet wasn't marked as an alternate explicitly, and aTitle
// is nonempty, we should select the style set corresponding to aTitle, since // is nonempty, we should select the style set corresponding to aTitle, since
// that's a preferred sheet. // that's a preferred sheet.
//
// FIXME(emilio): This should return false for Shadow DOM regardless of the
// document.
if (aTitle.IsEmpty()) { if (aTitle.IsEmpty()) {
return false; return false;
} }

View File

@@ -79,11 +79,12 @@ nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
ssle->SetEnableUpdates(true); ssle->SetEnableUpdates(true);
bool willNotify; auto updateOrError =
bool isAlternate; ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this);
nsresult rv = ssle->UpdateStyleSheet(
mRunsToCompletion ? nullptr : this, &willNotify, &isAlternate); if (updateOrError.isOk() &&
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) { updateOrError.unwrap().ShouldBlock() &&
!mRunsToCompletion) {
++mPendingSheetCount; ++mPendingSheetCount;
mScriptLoader->AddParserBlockingScriptExecutionBlocker(); mScriptLoader->AddParserBlockingScriptExecutionBlocker();
} }