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/. */
7 #include "AnonymousContent.h"
8 #include "mozilla/PresShell.h"
9 #include "mozilla/dom/Document.h"
10 #include "mozilla/dom/Element.h"
11 #include "mozilla/dom/Event.h"
12 #include "mozilla/dom/AnonymousContentBinding.h"
13 #include "nsComputedDOMStyle.h"
14 #include "nsCycleCollectionParticipant.h"
16 #include "nsStyledElement.h"
17 #include "HTMLCanvasElement.h"
19 namespace mozilla::dom
{
21 // Ref counting and cycle collection
22 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnonymousContent
, AddRef
)
23 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnonymousContent
, Release
)
24 NS_IMPL_CYCLE_COLLECTION(AnonymousContent
, mContentNode
)
26 AnonymousContent::AnonymousContent(already_AddRefed
<Element
> aContentNode
)
27 : mContentNode(aContentNode
) {
28 MOZ_ASSERT(mContentNode
);
31 AnonymousContent::~AnonymousContent() = default;
33 void AnonymousContent::SetTextContentForElement(const nsAString
& aElementId
,
34 const nsAString
& aText
,
36 Element
* element
= GetElementById(aElementId
);
38 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
42 element
->SetTextContent(aText
, aRv
);
45 void AnonymousContent::GetTextContentForElement(const nsAString
& aElementId
,
48 Element
* element
= GetElementById(aElementId
);
50 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
54 element
->GetTextContent(aText
, aRv
);
57 void AnonymousContent::SetAttributeForElement(const nsAString
& aElementId
,
58 const nsAString
& aName
,
59 const nsAString
& aValue
,
60 nsIPrincipal
* aSubjectPrincipal
,
62 Element
* element
= GetElementById(aElementId
);
64 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
68 element
->SetAttribute(aName
, aValue
, aSubjectPrincipal
, aRv
);
71 void AnonymousContent::GetAttributeForElement(const nsAString
& aElementId
,
72 const nsAString
& aName
,
75 Element
* element
= GetElementById(aElementId
);
77 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
81 element
->GetAttribute(aName
, aValue
);
84 void AnonymousContent::RemoveAttributeForElement(const nsAString
& aElementId
,
85 const nsAString
& aName
,
87 Element
* element
= GetElementById(aElementId
);
89 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
93 element
->RemoveAttribute(aName
, aRv
);
96 already_AddRefed
<nsISupports
> AnonymousContent::GetCanvasContext(
97 const nsAString
& aElementId
, const nsAString
& aContextId
,
99 Element
* element
= GetElementById(aElementId
);
102 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
106 if (!element
->IsHTMLElement(nsGkAtoms::canvas
)) {
110 nsCOMPtr
<nsISupports
> context
;
112 HTMLCanvasElement
* canvas
= static_cast<HTMLCanvasElement
*>(element
);
113 canvas
->GetContext(aContextId
, getter_AddRefs(context
));
115 return context
.forget();
118 already_AddRefed
<Animation
> AnonymousContent::SetAnimationForElement(
119 JSContext
* aContext
, const nsAString
& aElementId
,
120 JS::Handle
<JSObject
*> aKeyframes
,
121 const UnrestrictedDoubleOrKeyframeAnimationOptions
& aOptions
,
123 Element
* element
= GetElementById(aElementId
);
126 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
130 return element
->Animate(aContext
, aKeyframes
, aOptions
, aRv
);
133 void AnonymousContent::SetCutoutRectsForElement(
134 const nsAString
& aElementId
, const Sequence
<OwningNonNull
<DOMRect
>>& aRects
,
136 Element
* element
= GetElementById(aElementId
);
139 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
143 nsRegion cutOutRegion
;
144 for (const auto& r
: aRects
) {
145 CSSRect
rect(r
->X(), r
->Y(), r
->Width(), r
->Height());
146 cutOutRegion
.OrWith(CSSRect::ToAppUnits(rect
));
149 element
->SetProperty(nsGkAtoms::cutoutregion
, new nsRegion(cutOutRegion
),
150 nsINode::DeleteProperty
<nsRegion
>);
152 nsIFrame
* frame
= element
->GetPrimaryFrame();
154 frame
->SchedulePaint();
158 Element
* AnonymousContent::GetElementById(const nsAString
& aElementId
) {
159 // This can be made faster in the future if needed.
160 RefPtr
<nsAtom
> elementId
= NS_Atomize(aElementId
);
161 for (nsIContent
* node
= mContentNode
; node
;
162 node
= node
->GetNextNode(mContentNode
)) {
163 if (!node
->IsElement()) {
166 nsAtom
* id
= node
->AsElement()->GetID();
167 if (id
&& id
== elementId
) {
168 return node
->AsElement();
174 bool AnonymousContent::WrapObject(JSContext
* aCx
,
175 JS::Handle
<JSObject
*> aGivenProto
,
176 JS::MutableHandle
<JSObject
*> aReflector
) {
177 return AnonymousContent_Binding::Wrap(aCx
, this, aGivenProto
, aReflector
);
180 void AnonymousContent::GetComputedStylePropertyValue(
181 const nsAString
& aElementId
, const nsACString
& aPropertyName
,
182 nsACString
& aResult
, ErrorResult
& aRv
) {
183 Element
* element
= GetElementById(aElementId
);
185 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
189 if (!element
->OwnerDoc()->GetPresShell()) {
190 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
194 RefPtr
<nsComputedDOMStyle
> cs
= new nsComputedDOMStyle(
195 element
, u
""_ns
, element
->OwnerDoc(), nsComputedDOMStyle::eAll
);
196 aRv
= cs
->GetPropertyValue(aPropertyName
, aResult
);
199 void AnonymousContent::GetTargetIdForEvent(Event
& aEvent
, DOMString
& aResult
) {
200 nsCOMPtr
<Element
> el
= do_QueryInterface(aEvent
.GetOriginalTarget());
201 if (el
&& el
->IsInNativeAnonymousSubtree() && mContentNode
->Contains(el
)) {
202 aResult
.SetKnownLiveAtom(el
->GetID(), DOMString::eTreatNullAsNull
);
209 void AnonymousContent::SetStyle(const nsACString
& aProperty
,
210 const nsACString
& aValue
, ErrorResult
& aRv
) {
211 if (!mContentNode
->IsHTMLElement()) {
212 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
216 nsGenericHTMLElement
* element
= nsGenericHTMLElement::FromNode(mContentNode
);
217 nsCOMPtr
<nsICSSDeclaration
> declaration
= element
->Style();
218 declaration
->SetProperty(aProperty
, aValue
, ""_ns
, IgnoreErrors());
221 } // namespace mozilla::dom