Coverage Report

Created: 2018-09-25 14:53

/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