1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/dom/HTMLStyleElement.h"
7 #include "mozilla/dom/HTMLStyleElementBinding.h"
9 #include "nsStyleConsts.h"
10 #include "mozilla/dom/Document.h"
11 #include "nsUnicharUtils.h"
12 #include "nsThreadUtils.h"
13 #include "nsContentUtils.h"
14 #include "nsStubMutationObserver.h"
16 NS_IMPL_NS_NEW_HTML_ELEMENT(Style
)
18 namespace mozilla::dom
{
20 HTMLStyleElement::HTMLStyleElement(
21 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
)
22 : nsGenericHTMLElement(std::move(aNodeInfo
)) {
23 AddMutationObserver(this);
26 HTMLStyleElement::~HTMLStyleElement() = default;
28 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLStyleElement
)
30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLStyleElement
,
32 tmp
->LinkStyle::Traverse(cb
);
33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
35 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLStyleElement
,
37 tmp
->LinkStyle::Unlink();
38 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
40 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLStyleElement
,
44 NS_IMPL_ELEMENT_CLONE(HTMLStyleElement
)
46 bool HTMLStyleElement::Disabled() const {
47 StyleSheet
* ss
= GetSheet();
48 return ss
&& ss
->Disabled();
51 void HTMLStyleElement::SetDisabled(bool aDisabled
) {
52 if (StyleSheet
* ss
= GetSheet()) {
53 ss
->SetDisabled(aDisabled
);
57 void HTMLStyleElement::CharacterDataChanged(nsIContent
* aContent
,
58 const CharacterDataChangeInfo
&) {
59 ContentChanged(aContent
);
62 void HTMLStyleElement::ContentAppended(nsIContent
* aFirstNewContent
) {
63 ContentChanged(aFirstNewContent
->GetParent());
66 void HTMLStyleElement::ContentInserted(nsIContent
* aChild
) {
67 ContentChanged(aChild
);
70 void HTMLStyleElement::ContentRemoved(nsIContent
* aChild
,
71 nsIContent
* aPreviousSibling
) {
72 ContentChanged(aChild
);
75 void HTMLStyleElement::ContentChanged(nsIContent
* aContent
) {
76 mTriggeringPrincipal
= nullptr;
77 if (nsContentUtils::IsInSameAnonymousTree(this, aContent
)) {
78 Unused
<< UpdateStyleSheetInternal(nullptr, nullptr);
82 nsresult
HTMLStyleElement::BindToTree(BindContext
& aContext
, nsINode
& aParent
) {
83 nsresult rv
= nsGenericHTMLElement::BindToTree(aContext
, aParent
);
84 NS_ENSURE_SUCCESS(rv
, rv
);
86 void (HTMLStyleElement::*update
)() =
87 &HTMLStyleElement::UpdateStyleSheetInternal
;
88 nsContentUtils::AddScriptRunner(
89 NewRunnableMethod("dom::HTMLStyleElement::BindToTree", this, update
));
94 void HTMLStyleElement::UnbindFromTree(bool aNullParent
) {
95 nsCOMPtr
<Document
> oldDoc
= GetUncomposedDoc();
96 ShadowRoot
* oldShadow
= GetContainingShadow();
98 nsGenericHTMLElement::UnbindFromTree(aNullParent
);
100 if (oldShadow
&& GetContainingShadow()) {
101 // The style is in a shadow tree and is still in the
102 // shadow tree. Thus the sheets in the shadow DOM
103 // do not need to be updated.
107 Unused
<< UpdateStyleSheetInternal(oldDoc
, oldShadow
);
110 nsresult
HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID
, nsAtom
* aName
,
111 const nsAttrValue
* aValue
,
112 const nsAttrValue
* aOldValue
,
113 nsIPrincipal
* aSubjectPrincipal
,
115 if (aNameSpaceID
== kNameSpaceID_None
) {
116 if (aName
== nsGkAtoms::title
|| aName
== nsGkAtoms::media
||
117 aName
== nsGkAtoms::type
) {
118 Unused
<< UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes
);
122 return nsGenericHTMLElement::AfterSetAttr(
123 aNameSpaceID
, aName
, aValue
, aOldValue
, aSubjectPrincipal
, aNotify
);
126 void HTMLStyleElement::GetInnerHTML(nsAString
& aInnerHTML
,
127 OOMReporter
& aError
) {
128 if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML
, fallible
)) {
133 void HTMLStyleElement::SetInnerHTML(const nsAString
& aInnerHTML
,
134 nsIPrincipal
* aScriptedPrincipal
,
135 ErrorResult
& aError
) {
136 SetTextContentInternal(aInnerHTML
, aScriptedPrincipal
, aError
);
139 void HTMLStyleElement::SetTextContentInternal(const nsAString
& aTextContent
,
140 nsIPrincipal
* aScriptedPrincipal
,
141 ErrorResult
& aError
) {
142 // Per spec, if we're setting text content to an empty string and don't
143 // already have any children, we should not trigger any mutation observers, or
144 // re-parse the stylesheet.
145 if (aTextContent
.IsEmpty() && !GetFirstChild()) {
146 nsIPrincipal
* principal
=
147 mTriggeringPrincipal
? mTriggeringPrincipal
.get() : NodePrincipal();
148 if (principal
== aScriptedPrincipal
) {
153 SetEnableUpdates(false);
155 aError
= nsContentUtils::SetNodeTextContent(this, aTextContent
, true);
157 SetEnableUpdates(true);
159 mTriggeringPrincipal
= aScriptedPrincipal
;
161 Unused
<< UpdateStyleSheetInternal(nullptr, nullptr);
164 void HTMLStyleElement::SetDevtoolsAsTriggeringPrincipal() {
165 mTriggeringPrincipal
= CreateDevtoolsPrincipal();
168 Maybe
<LinkStyle::SheetInfo
> HTMLStyleElement::GetStyleSheetInfo() {
169 if (!IsCSSMimeTypeAttributeForStyleElement(*this)) {
175 GetTitleAndMediaForElement(*this, title
, media
);
177 return Some(SheetInfo
{
181 do_AddRef(mTriggeringPrincipal
),
182 MakeAndAddRef
<ReferrerInfo
>(*this),
186 /* integrity = */ u
""_ns
,
187 /* nsStyleUtil::CSPAllowsInlineStyle takes care of nonce checking for
188 inline styles. Bug 1607011 */
189 /* nonce = */ u
""_ns
,
192 IsExplicitlyEnabled::No
,
196 JSObject
* HTMLStyleElement::WrapNode(JSContext
* aCx
,
197 JS::Handle
<JSObject
*> aGivenProto
) {
198 return HTMLStyleElement_Binding::Wrap(aCx
, this, aGivenProto
);
201 } // namespace mozilla::dom