/src/mozilla-central/dom/html/HTMLBodyElement.cpp
Line | Count | Source (jump to first uncovered line) |
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 "HTMLBodyElement.h" |
8 | | #include "mozilla/dom/HTMLBodyElementBinding.h" |
9 | | #include "mozilla/MappedDeclarations.h" |
10 | | #include "mozilla/HTMLEditor.h" |
11 | | #include "mozilla/TextEditor.h" |
12 | | #include "nsAttrValueInlines.h" |
13 | | #include "nsGkAtoms.h" |
14 | | #include "nsStyleConsts.h" |
15 | | #include "nsPresContext.h" |
16 | | #include "nsIPresShell.h" |
17 | | #include "nsIDocument.h" |
18 | | #include "nsIDocumentInlines.h" |
19 | | #include "nsHTMLStyleSheet.h" |
20 | | #include "nsMappedAttributes.h" |
21 | | #include "nsIDocShell.h" |
22 | | #include "nsGlobalWindow.h" |
23 | | |
24 | | NS_IMPL_NS_NEW_HTML_ELEMENT(Body) |
25 | | |
26 | | namespace mozilla { |
27 | | namespace dom { |
28 | | |
29 | | //---------------------------------------------------------------------- |
30 | | |
31 | | HTMLBodyElement::~HTMLBodyElement() |
32 | 0 | { |
33 | 0 | } |
34 | | |
35 | | JSObject* |
36 | | HTMLBodyElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) |
37 | 0 | { |
38 | 0 | return HTMLBodyElement_Binding::Wrap(aCx, this, aGivenProto); |
39 | 0 | } |
40 | | |
41 | | NS_IMPL_ELEMENT_CLONE(HTMLBodyElement) |
42 | | |
43 | | bool |
44 | | HTMLBodyElement::ParseAttribute(int32_t aNamespaceID, |
45 | | nsAtom* aAttribute, |
46 | | const nsAString& aValue, |
47 | | nsIPrincipal* aMaybeScriptedPrincipal, |
48 | | nsAttrValue& aResult) |
49 | 0 | { |
50 | 0 | if (aNamespaceID == kNameSpaceID_None) { |
51 | 0 | if (aAttribute == nsGkAtoms::bgcolor || |
52 | 0 | aAttribute == nsGkAtoms::text || |
53 | 0 | aAttribute == nsGkAtoms::link || |
54 | 0 | aAttribute == nsGkAtoms::alink || |
55 | 0 | aAttribute == nsGkAtoms::vlink) { |
56 | 0 | return aResult.ParseColor(aValue); |
57 | 0 | } |
58 | 0 | if (aAttribute == nsGkAtoms::marginwidth || |
59 | 0 | aAttribute == nsGkAtoms::marginheight || |
60 | 0 | aAttribute == nsGkAtoms::topmargin || |
61 | 0 | aAttribute == nsGkAtoms::bottommargin || |
62 | 0 | aAttribute == nsGkAtoms::leftmargin || |
63 | 0 | aAttribute == nsGkAtoms::rightmargin) { |
64 | 0 | return aResult.ParseIntWithBounds(aValue, 0); |
65 | 0 | } |
66 | 0 | } |
67 | 0 | |
68 | 0 | return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID, |
69 | 0 | aAttribute, aValue, |
70 | 0 | aResult) || |
71 | 0 | nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, |
72 | 0 | aMaybeScriptedPrincipal, aResult); |
73 | 0 | } |
74 | | |
75 | | void |
76 | | HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes, |
77 | | MappedDeclarations& aDecls) |
78 | 0 | { |
79 | 0 | // This is the one place where we try to set the same property |
80 | 0 | // multiple times in presentation attributes. Servo does not support |
81 | 0 | // querying if a property is set (because that is O(n) behavior |
82 | 0 | // in ServoSpecifiedValues). Instead, we use the below values to keep |
83 | 0 | // track of whether we have already set a property, and if so, what value |
84 | 0 | // we set it to (which is used when handling margin |
85 | 0 | // attributes from the containing frame element) |
86 | 0 |
|
87 | 0 | int32_t bodyMarginWidth = -1; |
88 | 0 | int32_t bodyMarginHeight = -1; |
89 | 0 | int32_t bodyTopMargin = -1; |
90 | 0 | int32_t bodyBottomMargin = -1; |
91 | 0 | int32_t bodyLeftMargin = -1; |
92 | 0 | int32_t bodyRightMargin = -1; |
93 | 0 |
|
94 | 0 | const nsAttrValue* value; |
95 | 0 | // if marginwidth/marginheight are set, reflect them as 'margin' |
96 | 0 | value = aAttributes->GetAttr(nsGkAtoms::marginwidth); |
97 | 0 | if (value && value->Type() == nsAttrValue::eInteger) { |
98 | 0 | bodyMarginWidth = value->GetIntegerValue(); |
99 | 0 | if (bodyMarginWidth < 0) { |
100 | 0 | bodyMarginWidth = 0; |
101 | 0 | } |
102 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)bodyMarginWidth); |
103 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)bodyMarginWidth); |
104 | 0 | } |
105 | 0 |
|
106 | 0 | value = aAttributes->GetAttr(nsGkAtoms::marginheight); |
107 | 0 | if (value && value->Type() == nsAttrValue::eInteger) { |
108 | 0 | bodyMarginHeight = value->GetIntegerValue(); |
109 | 0 | if (bodyMarginHeight < 0) { |
110 | 0 | bodyMarginHeight = 0; |
111 | 0 | } |
112 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)bodyMarginHeight); |
113 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)bodyMarginHeight); |
114 | 0 | } |
115 | 0 |
|
116 | 0 | // topmargin (IE-attribute) |
117 | 0 | if (bodyMarginHeight == -1) { |
118 | 0 | value = aAttributes->GetAttr(nsGkAtoms::topmargin); |
119 | 0 | if (value && value->Type() == nsAttrValue::eInteger) { |
120 | 0 | bodyTopMargin = value->GetIntegerValue(); |
121 | 0 | if (bodyTopMargin < 0) { |
122 | 0 | bodyTopMargin = 0; |
123 | 0 | } |
124 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)bodyTopMargin); |
125 | 0 | } |
126 | 0 | } |
127 | 0 | // bottommargin (IE-attribute) |
128 | 0 |
|
129 | 0 | if (bodyMarginHeight == -1) { |
130 | 0 | value = aAttributes->GetAttr(nsGkAtoms::bottommargin); |
131 | 0 | if (value && value->Type() == nsAttrValue::eInteger) { |
132 | 0 | bodyBottomMargin = value->GetIntegerValue(); |
133 | 0 | if (bodyBottomMargin < 0) { |
134 | 0 | bodyBottomMargin = 0; |
135 | 0 | } |
136 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)bodyBottomMargin); |
137 | 0 | } |
138 | 0 | } |
139 | 0 |
|
140 | 0 | // leftmargin (IE-attribute) |
141 | 0 | if (bodyMarginWidth == -1) { |
142 | 0 | value = aAttributes->GetAttr(nsGkAtoms::leftmargin); |
143 | 0 | if (value && value->Type() == nsAttrValue::eInteger) { |
144 | 0 | bodyLeftMargin = value->GetIntegerValue(); |
145 | 0 | if (bodyLeftMargin < 0) { |
146 | 0 | bodyLeftMargin = 0; |
147 | 0 | } |
148 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)bodyLeftMargin); |
149 | 0 | } |
150 | 0 | } |
151 | 0 | // rightmargin (IE-attribute) |
152 | 0 | if (bodyMarginWidth == -1) { |
153 | 0 | value = aAttributes->GetAttr(nsGkAtoms::rightmargin); |
154 | 0 | if (value && value->Type() == nsAttrValue::eInteger) { |
155 | 0 | bodyRightMargin = value->GetIntegerValue(); |
156 | 0 | if (bodyRightMargin < 0) { |
157 | 0 | bodyRightMargin = 0; |
158 | 0 | } |
159 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)bodyRightMargin); |
160 | 0 | } |
161 | 0 | } |
162 | 0 |
|
163 | 0 | // if marginwidth or marginheight is set in the <frame> and not set in the <body> |
164 | 0 | // reflect them as margin in the <body> |
165 | 0 | if (bodyMarginWidth == -1 || bodyMarginHeight == -1) { |
166 | 0 | nsCOMPtr<nsIDocShell> docShell(aDecls.Document()->GetDocShell()); |
167 | 0 | if (docShell) { |
168 | 0 | nscoord frameMarginWidth=-1; // default value |
169 | 0 | nscoord frameMarginHeight=-1; // default value |
170 | 0 | docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set |
171 | 0 | docShell->GetMarginHeight(&frameMarginHeight); |
172 | 0 |
|
173 | 0 | if (bodyMarginWidth == -1 && frameMarginWidth >= 0) { |
174 | 0 | if (bodyLeftMargin == -1) { |
175 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)frameMarginWidth); |
176 | 0 | } |
177 | 0 | if (bodyRightMargin == -1) { |
178 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)frameMarginWidth); |
179 | 0 | } |
180 | 0 | } |
181 | 0 |
|
182 | 0 | if (bodyMarginHeight == -1 && frameMarginHeight >= 0) { |
183 | 0 | if (bodyTopMargin == -1) { |
184 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)frameMarginHeight); |
185 | 0 | } |
186 | 0 | if (bodyBottomMargin == -1) { |
187 | 0 | aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)frameMarginHeight); |
188 | 0 | } |
189 | 0 | } |
190 | 0 | } |
191 | 0 | } |
192 | 0 |
|
193 | 0 | // When display if first asked for, go ahead and get our colors set up. |
194 | 0 | if (nsHTMLStyleSheet* styleSheet = aDecls.Document()->GetAttributeStyleSheet()) { |
195 | 0 | nscolor color; |
196 | 0 | value = aAttributes->GetAttr(nsGkAtoms::link); |
197 | 0 | if (value && value->GetColorValue(color)) { |
198 | 0 | styleSheet->SetLinkColor(color); |
199 | 0 | } |
200 | 0 |
|
201 | 0 | value = aAttributes->GetAttr(nsGkAtoms::alink); |
202 | 0 | if (value && value->GetColorValue(color)) { |
203 | 0 | styleSheet->SetActiveLinkColor(color); |
204 | 0 | } |
205 | 0 |
|
206 | 0 | value = aAttributes->GetAttr(nsGkAtoms::vlink); |
207 | 0 | if (value && value->GetColorValue(color)) { |
208 | 0 | styleSheet->SetVisitedLinkColor(color); |
209 | 0 | } |
210 | 0 | } |
211 | 0 |
|
212 | 0 | if (!aDecls.PropertyIsSet(eCSSProperty_color)) { |
213 | 0 | // color: color |
214 | 0 | nscolor color; |
215 | 0 | value = aAttributes->GetAttr(nsGkAtoms::text); |
216 | 0 | if (value && value->GetColorValue(color)) { |
217 | 0 | aDecls.SetColorValue(eCSSProperty_color, color); |
218 | 0 | } |
219 | 0 | } |
220 | 0 |
|
221 | 0 | nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls); |
222 | 0 | nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls); |
223 | 0 | } |
224 | | |
225 | | nsMapRuleToAttributesFunc |
226 | | HTMLBodyElement::GetAttributeMappingFunction() const |
227 | 0 | { |
228 | 0 | return &MapAttributesIntoRule; |
229 | 0 | } |
230 | | |
231 | | NS_IMETHODIMP_(bool) |
232 | | HTMLBodyElement::IsAttributeMapped(const nsAtom* aAttribute) const |
233 | 0 | { |
234 | 0 | static const MappedAttributeEntry attributes[] = { |
235 | 0 | { &nsGkAtoms::link }, |
236 | 0 | { &nsGkAtoms::vlink }, |
237 | 0 | { &nsGkAtoms::alink }, |
238 | 0 | { &nsGkAtoms::text }, |
239 | 0 | { &nsGkAtoms::marginwidth }, |
240 | 0 | { &nsGkAtoms::marginheight }, |
241 | 0 | { &nsGkAtoms::topmargin }, |
242 | 0 | { &nsGkAtoms::rightmargin }, |
243 | 0 | { &nsGkAtoms::bottommargin }, |
244 | 0 | { &nsGkAtoms::leftmargin }, |
245 | 0 | { nullptr }, |
246 | 0 | }; |
247 | 0 |
|
248 | 0 | static const MappedAttributeEntry* const map[] = { |
249 | 0 | attributes, |
250 | 0 | sCommonAttributeMap, |
251 | 0 | sBackgroundAttributeMap, |
252 | 0 | }; |
253 | 0 |
|
254 | 0 | return FindAttributeDependence(aAttribute, map); |
255 | 0 | } |
256 | | |
257 | | already_AddRefed<TextEditor> |
258 | | HTMLBodyElement::GetAssociatedEditor() |
259 | 0 | { |
260 | 0 | RefPtr<TextEditor> textEditor = GetTextEditorInternal(); |
261 | 0 | if (textEditor) { |
262 | 0 | return textEditor.forget(); |
263 | 0 | } |
264 | 0 | |
265 | 0 | // Make sure this is the actual body of the document |
266 | 0 | if (this != OwnerDoc()->GetBodyElement()) { |
267 | 0 | return nullptr; |
268 | 0 | } |
269 | 0 | |
270 | 0 | // For designmode, try to get document's editor |
271 | 0 | nsPresContext* presContext = GetPresContext(eForComposedDoc); |
272 | 0 | if (!presContext) { |
273 | 0 | return nullptr; |
274 | 0 | } |
275 | 0 | |
276 | 0 | nsCOMPtr<nsIDocShell> docShell = presContext->GetDocShell(); |
277 | 0 | if (!docShell) { |
278 | 0 | return nullptr; |
279 | 0 | } |
280 | 0 | |
281 | 0 | RefPtr<HTMLEditor> htmlEditor = docShell->GetHTMLEditor(); |
282 | 0 | return htmlEditor.forget(); |
283 | 0 | } |
284 | | |
285 | | bool |
286 | | HTMLBodyElement::IsEventAttributeNameInternal(nsAtom *aName) |
287 | 0 | { |
288 | 0 | return nsContentUtils::IsEventAttributeName(aName, |
289 | 0 | EventNameType_HTML | |
290 | 0 | EventNameType_HTMLBodyOrFramesetOnly); |
291 | 0 | } |
292 | | |
293 | | nsresult |
294 | | HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, |
295 | | nsIContent* aBindingParent) |
296 | 0 | { |
297 | 0 | nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, |
298 | 0 | aBindingParent); |
299 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
300 | 0 | return mAttrs.ForceMapped(this, OwnerDoc()); |
301 | 0 | } |
302 | | |
303 | | nsresult |
304 | | HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, |
305 | | const nsAttrValue* aValue, |
306 | | const nsAttrValue* aOldValue, |
307 | | nsIPrincipal* aSubjectPrincipal, |
308 | | bool aNotify) |
309 | 0 | { |
310 | 0 | nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, |
311 | 0 | aName, aValue, aOldValue, |
312 | 0 | aSubjectPrincipal, aNotify); |
313 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
314 | 0 | // if the last mapped attribute was removed, don't clear the |
315 | 0 | // nsMappedAttributes, our style can still depend on the containing frame element |
316 | 0 | if (!aValue && IsAttributeMapped(aName)) { |
317 | 0 | nsresult rv = mAttrs.ForceMapped(this, OwnerDoc()); |
318 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
319 | 0 | } |
320 | 0 |
|
321 | 0 | return NS_OK; |
322 | 0 | } |
323 | | |
324 | | #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */ |
325 | | // nsGenericHTMLElement::GetOnError returns |
326 | | // already_AddRefed<EventHandlerNonNull> while other getters return |
327 | | // EventHandlerNonNull*, so allow passing in the type to use here. |
328 | | #define WINDOW_EVENT_HELPER(name_, type_) \ |
329 | | type_* \ |
330 | | HTMLBodyElement::GetOn##name_() \ |
331 | 0 | { \ |
332 | 0 | if (nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow()) { \ |
333 | 0 | nsGlobalWindowInner* globalWin = nsGlobalWindowInner::Cast(win); \ |
334 | 0 | return globalWin->GetOn##name_(); \ |
335 | 0 | } \ |
336 | 0 | return nullptr; \ |
337 | 0 | } \ Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnafterprint() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnbeforeprint() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnbeforeunload() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnhashchange() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnlanguagechange() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnmessage() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnmessageerror() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnoffline() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnonline() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnpagehide() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnpageshow() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnpopstate() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnstorage() Unexecuted instantiation: mozilla::dom::HTMLBodyElement::GetOnunload() |
338 | | void \ |
339 | | HTMLBodyElement::SetOn##name_(type_* handler) \ |
340 | 0 | { \ |
341 | 0 | nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow(); \ |
342 | 0 | if (!win) { \ |
343 | 0 | return; \ |
344 | 0 | } \ |
345 | 0 | \ |
346 | 0 | nsGlobalWindowInner* globalWin = nsGlobalWindowInner::Cast(win); \ |
347 | 0 | return globalWin->SetOn##name_(handler); \ |
348 | 0 | } Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnafterprint(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnbeforeprint(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnbeforeunload(mozilla::dom::OnBeforeUnloadEventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnhashchange(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnlanguagechange(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnmessage(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnmessageerror(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnoffline(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnonline(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnpagehide(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnpageshow(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnpopstate(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnstorage(mozilla::dom::EventHandlerNonNull*) Unexecuted instantiation: mozilla::dom::HTMLBodyElement::SetOnunload(mozilla::dom::EventHandlerNonNull*) |
349 | | #define WINDOW_EVENT(name_, id_, type_, struct_) \ |
350 | | WINDOW_EVENT_HELPER(name_, EventHandlerNonNull) |
351 | | #define BEFOREUNLOAD_EVENT(name_, id_, type_, struct_) \ |
352 | | WINDOW_EVENT_HELPER(name_, OnBeforeUnloadEventHandlerNonNull) |
353 | | #include "mozilla/EventNameList.h" // IWYU pragma: keep |
354 | | #undef BEFOREUNLOAD_EVENT |
355 | | #undef WINDOW_EVENT |
356 | | #undef WINDOW_EVENT_HELPER |
357 | | #undef EVENT |
358 | | |
359 | | } // namespace dom |
360 | | } // namespace mozilla |