Line data Source code
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 :
7 : #include "AnonymousContent.h"
8 : #include "mozilla/dom/Element.h"
9 : #include "mozilla/dom/AnonymousContentBinding.h"
10 : #include "nsComputedDOMStyle.h"
11 : #include "nsCycleCollectionParticipant.h"
12 : #include "nsIDocument.h"
13 : #include "nsIDOMHTMLCollection.h"
14 : #include "nsIFrame.h"
15 : #include "nsStyledElement.h"
16 : #include "HTMLCanvasElement.h"
17 :
18 : namespace mozilla {
19 : namespace dom {
20 :
21 : // Ref counting and cycle collection
22 0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnonymousContent, AddRef)
23 0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnonymousContent, Release)
24 0 : NS_IMPL_CYCLE_COLLECTION(AnonymousContent, mContentNode)
25 :
26 0 : AnonymousContent::AnonymousContent(Element* aContentNode) :
27 0 : mContentNode(aContentNode)
28 0 : {}
29 :
30 0 : AnonymousContent::~AnonymousContent()
31 : {
32 0 : }
33 :
34 : Element*
35 0 : AnonymousContent::GetContentNode()
36 : {
37 0 : return mContentNode;
38 : }
39 :
40 : void
41 0 : AnonymousContent::SetContentNode(Element* aContentNode)
42 : {
43 0 : mContentNode = aContentNode;
44 0 : }
45 :
46 : void
47 0 : AnonymousContent::SetTextContentForElement(const nsAString& aElementId,
48 : const nsAString& aText,
49 : ErrorResult& aRv)
50 : {
51 0 : Element* element = GetElementById(aElementId);
52 0 : if (!element) {
53 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
54 0 : return;
55 : }
56 :
57 0 : element->SetTextContent(aText, aRv);
58 : }
59 :
60 : void
61 0 : AnonymousContent::GetTextContentForElement(const nsAString& aElementId,
62 : DOMString& aText,
63 : ErrorResult& aRv)
64 : {
65 0 : Element* element = GetElementById(aElementId);
66 0 : if (!element) {
67 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
68 0 : return;
69 : }
70 :
71 0 : element->GetTextContent(aText, aRv);
72 : }
73 :
74 : void
75 0 : AnonymousContent::SetAttributeForElement(const nsAString& aElementId,
76 : const nsAString& aName,
77 : const nsAString& aValue,
78 : ErrorResult& aRv)
79 : {
80 0 : Element* element = GetElementById(aElementId);
81 0 : if (!element) {
82 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
83 0 : return;
84 : }
85 :
86 0 : element->SetAttribute(aName, aValue, aRv);
87 : }
88 :
89 : void
90 0 : AnonymousContent::GetAttributeForElement(const nsAString& aElementId,
91 : const nsAString& aName,
92 : DOMString& aValue,
93 : ErrorResult& aRv)
94 : {
95 0 : Element* element = GetElementById(aElementId);
96 0 : if (!element) {
97 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
98 0 : return;
99 : }
100 :
101 0 : element->GetAttribute(aName, aValue);
102 : }
103 :
104 : void
105 0 : AnonymousContent::RemoveAttributeForElement(const nsAString& aElementId,
106 : const nsAString& aName,
107 : ErrorResult& aRv)
108 : {
109 0 : Element* element = GetElementById(aElementId);
110 0 : if (!element) {
111 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
112 0 : return;
113 : }
114 :
115 0 : element->RemoveAttribute(aName, aRv);
116 : }
117 :
118 : already_AddRefed<nsISupports>
119 0 : AnonymousContent::GetCanvasContext(const nsAString& aElementId,
120 : const nsAString& aContextId,
121 : ErrorResult& aRv)
122 : {
123 0 : Element* element = GetElementById(aElementId);
124 :
125 0 : if (!element) {
126 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
127 0 : return nullptr;
128 : }
129 :
130 0 : if (!element->IsHTMLElement(nsGkAtoms::canvas)) {
131 0 : return nullptr;
132 : }
133 :
134 0 : nsCOMPtr<nsISupports> context;
135 :
136 0 : HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(element);
137 0 : canvas->GetContext(aContextId, getter_AddRefs(context));
138 :
139 0 : return context.forget();
140 : }
141 :
142 : already_AddRefed<Animation>
143 0 : AnonymousContent::SetAnimationForElement(JSContext* aContext,
144 : const nsAString& aElementId,
145 : JS::Handle<JSObject*> aKeyframes,
146 : const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
147 : ErrorResult& aRv)
148 : {
149 0 : Element* element = GetElementById(aElementId);
150 :
151 0 : if (!element) {
152 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
153 0 : return nullptr;
154 : }
155 :
156 0 : return element->Animate(aContext, aKeyframes, aOptions, aRv);
157 : }
158 :
159 : void
160 0 : AnonymousContent::SetCutoutRectsForElement(const nsAString& aElementId,
161 : const Sequence<OwningNonNull<DOMRect>>& aRects,
162 : ErrorResult& aRv)
163 : {
164 0 : Element* element = GetElementById(aElementId);
165 :
166 0 : if (!element) {
167 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
168 0 : return;
169 : }
170 :
171 0 : nsRegion cutOutRegion;
172 0 : for (const auto& r : aRects) {
173 0 : CSSRect rect(r->X(), r->Y(), r->Width(), r->Height());
174 0 : cutOutRegion.OrWith(CSSRect::ToAppUnits(rect));
175 : }
176 :
177 0 : element->SetProperty(nsGkAtoms::cutoutregion, new nsRegion(cutOutRegion),
178 0 : nsINode::DeleteProperty<nsRegion>);
179 :
180 0 : nsIFrame* frame = element->GetPrimaryFrame();
181 0 : if (frame) {
182 0 : frame->SchedulePaint();
183 : }
184 : }
185 :
186 : Element*
187 0 : AnonymousContent::GetElementById(const nsAString& aElementId)
188 : {
189 : // This can be made faster in the future if needed.
190 0 : nsCOMPtr<nsIAtom> elementId = NS_Atomize(aElementId);
191 0 : for (nsIContent* node = mContentNode; node;
192 0 : node = node->GetNextNode(mContentNode)) {
193 0 : if (!node->IsElement()) {
194 0 : continue;
195 : }
196 0 : nsIAtom* id = node->AsElement()->GetID();
197 0 : if (id && id == elementId) {
198 0 : return node->AsElement();
199 : }
200 : }
201 0 : return nullptr;
202 : }
203 :
204 : bool
205 0 : AnonymousContent::WrapObject(JSContext* aCx,
206 : JS::Handle<JSObject*> aGivenProto,
207 : JS::MutableHandle<JSObject*> aReflector)
208 : {
209 0 : return AnonymousContentBinding::Wrap(aCx, this, aGivenProto, aReflector);
210 : }
211 :
212 : void
213 0 : AnonymousContent::GetComputedStylePropertyValue(const nsAString& aElementId,
214 : const nsAString& aPropertyName,
215 : DOMString& aResult,
216 : ErrorResult& aRv)
217 : {
218 0 : Element* element = GetElementById(aElementId);
219 0 : if (!element) {
220 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
221 0 : return;
222 : }
223 :
224 0 : nsIPresShell* shell = element->OwnerDoc()->GetShell();
225 0 : if (!shell) {
226 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
227 0 : return;
228 : }
229 :
230 : RefPtr<nsComputedDOMStyle> cs =
231 0 : new nsComputedDOMStyle(element, NS_LITERAL_STRING(""), shell,
232 0 : nsComputedDOMStyle::eAll);
233 0 : aRv = cs->GetPropertyValue(aPropertyName, aResult);
234 : }
235 :
236 : } // namespace dom
237 : } // namespace mozilla
|