Add WTF::move()
[WebKit-https.git] / Source / WebCore / html / HTMLBodyElement.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Simon Hausmann (hausmann@kde.org)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include "config.h"
25 #include "HTMLBodyElement.h"
26
27 #include "Attribute.h"
28 #include "CSSImageValue.h"
29 #include "CSSParser.h"
30 #include "CSSValueKeywords.h"
31 #include "EventNames.h"
32 #include "Frame.h"
33 #include "FrameView.h"
34 #include "HTMLFrameElementBase.h"
35 #include "HTMLNames.h"
36 #include "HTMLParserIdioms.h"
37 #include "Page.h"
38 #include "StyleProperties.h"
39
40 namespace WebCore {
41
42 using namespace HTMLNames;
43
44 HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document& document)
45     : HTMLElement(tagName, document)
46 {
47     ASSERT(hasTagName(bodyTag));
48 }
49
50 PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(Document& document)
51 {
52     return adoptRef(new HTMLBodyElement(bodyTag, document));
53 }
54
55 PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(const QualifiedName& tagName, Document& document)
56 {
57     return adoptRef(new HTMLBodyElement(tagName, document));
58 }
59
60 HTMLBodyElement::~HTMLBodyElement()
61 {
62 }
63
64 bool HTMLBodyElement::isPresentationAttribute(const QualifiedName& name) const
65 {
66     if (name == backgroundAttr || name == marginwidthAttr || name == leftmarginAttr || name == marginheightAttr || name == topmarginAttr || name == bgcolorAttr || name == textAttr || name == bgpropertiesAttr)
67         return true;
68     return HTMLElement::isPresentationAttribute(name);
69 }
70
71 void HTMLBodyElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
72 {
73     if (name == backgroundAttr) {
74         String url = stripLeadingAndTrailingHTMLSpaces(value);
75         if (!url.isEmpty()) {
76             auto imageValue = CSSImageValue::create(document().completeURL(url).string());
77             imageValue.get().setInitiator(localName());
78             style.setProperty(CSSProperty(CSSPropertyBackgroundImage, WTF::move(imageValue)));
79         }
80     } else if (name == marginwidthAttr || name == leftmarginAttr) {
81         addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
82         addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
83     } else if (name == marginheightAttr || name == topmarginAttr) {
84         addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
85         addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
86     } else if (name == bgcolorAttr) {
87         addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value);
88     } else if (name == textAttr) {
89         addHTMLColorToStyle(style, CSSPropertyColor, value);
90     } else if (name == bgpropertiesAttr) {
91         if (equalIgnoringCase(value, "fixed"))
92            addPropertyToPresentationAttributeStyle(style, CSSPropertyBackgroundAttachment, CSSValueFixed);
93     } else
94         HTMLElement::collectStyleForPresentationAttribute(name, value, style);
95 }
96
97 void HTMLBodyElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
98 {
99     if (name == vlinkAttr || name == alinkAttr || name == linkAttr) {
100         if (value.isNull()) {
101             if (name == linkAttr)
102                 document().resetLinkColor();
103             else if (name == vlinkAttr)
104                 document().resetVisitedLinkColor();
105             else
106                 document().resetActiveLinkColor();
107         } else {
108             RGBA32 color;
109             if (CSSParser::parseColor(color, value, !document().inQuirksMode())) {
110                 if (name == linkAttr)
111                     document().setLinkColor(color);
112                 else if (name == vlinkAttr)
113                     document().setVisitedLinkColor(color);
114                 else
115                     document().setActiveLinkColor(color);
116             }
117         }
118
119         setNeedsStyleRecalc();
120     } else if (name == onloadAttr)
121         document().setWindowAttributeEventListener(eventNames().loadEvent, name, value);
122     else if (name == onbeforeunloadAttr)
123         document().setWindowAttributeEventListener(eventNames().beforeunloadEvent, name, value);
124     else if (name == onunloadAttr)
125         document().setWindowAttributeEventListener(eventNames().unloadEvent, name, value);
126     else if (name == onpagehideAttr)
127         document().setWindowAttributeEventListener(eventNames().pagehideEvent, name, value);
128     else if (name == onpageshowAttr)
129         document().setWindowAttributeEventListener(eventNames().pageshowEvent, name, value);
130     else if (name == onpopstateAttr)
131         document().setWindowAttributeEventListener(eventNames().popstateEvent, name, value);
132     else if (name == onblurAttr)
133         document().setWindowAttributeEventListener(eventNames().blurEvent, name, value);
134     else if (name == onfocusAttr)
135         document().setWindowAttributeEventListener(eventNames().focusEvent, name, value);
136 #if ENABLE(ORIENTATION_EVENTS)
137     else if (name == onorientationchangeAttr)
138         document().setWindowAttributeEventListener(eventNames().orientationchangeEvent, name, value);
139 #endif
140     else if (name == onhashchangeAttr)
141         document().setWindowAttributeEventListener(eventNames().hashchangeEvent, name, value);
142     else if (name == onresizeAttr)
143         document().setWindowAttributeEventListener(eventNames().resizeEvent, name, value);
144     else if (name == onscrollAttr)
145         document().setWindowAttributeEventListener(eventNames().scrollEvent, name, value);
146     else if (name == onselectionchangeAttr)
147         document().setAttributeEventListener(eventNames().selectionchangeEvent, name, value);
148     else if (name == onstorageAttr)
149         document().setWindowAttributeEventListener(eventNames().storageEvent, name, value);
150     else if (name == ononlineAttr)
151         document().setWindowAttributeEventListener(eventNames().onlineEvent, name, value);
152     else if (name == onofflineAttr)
153         document().setWindowAttributeEventListener(eventNames().offlineEvent, name, value);
154 #if ENABLE(WILL_REVEAL_EDGE_EVENTS)
155     else if (name == onwebkitwillrevealbottomAttr)
156         document().setWindowAttributeEventListener(eventNames().webkitwillrevealbottomEvent, name, value);
157     else if (name == onwebkitwillrevealleftAttr)
158         document().setWindowAttributeEventListener(eventNames().webkitwillrevealleftEvent, name, value);
159     else if (name == onwebkitwillrevealrightAttr)
160         document().setWindowAttributeEventListener(eventNames().webkitwillrevealrightEvent, name, value);
161     else if (name == onwebkitwillrevealtopAttr)
162         document().setWindowAttributeEventListener(eventNames().webkitwillrevealtopEvent, name, value);
163 #endif
164     else
165         HTMLElement::parseAttribute(name, value);
166 }
167
168 Node::InsertionNotificationRequest HTMLBodyElement::insertedInto(ContainerNode& insertionPoint)
169 {
170     HTMLElement::insertedInto(insertionPoint);
171     if (!insertionPoint.inDocument())
172         return InsertionDone;
173
174     // FIXME: It's surprising this is web compatible since it means a marginwidth and marginheight attribute can
175     // magically appear on the <body> of all documents embedded through <iframe> or <frame>.
176     // FIXME: Perhaps this code should be in attach() instead of here.
177     Element* ownerElement = document().ownerElement();
178     if (ownerElement && isHTMLFrameElementBase(*ownerElement)) {
179         HTMLFrameElementBase& ownerFrameElement = toHTMLFrameElementBase(*ownerElement);
180         int marginWidth = ownerFrameElement.marginWidth();
181         if (marginWidth != -1)
182             setIntegralAttribute(marginwidthAttr, marginWidth);
183         int marginHeight = ownerFrameElement.marginHeight();
184         if (marginHeight != -1)
185             setIntegralAttribute(marginheightAttr, marginHeight);
186     }
187
188     return InsertionDone;
189 }
190
191 bool HTMLBodyElement::isURLAttribute(const Attribute& attribute) const
192 {
193     return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute);
194 }
195
196 bool HTMLBodyElement::supportsFocus() const
197 {
198     return hasEditableStyle() || HTMLElement::supportsFocus();
199 }
200
201 static double adjustForZoom(int value, const Frame& frame)
202 {
203     double zoomFactor = frame.pageZoomFactor() * frame.frameScaleFactor();
204     if (zoomFactor == 1)
205         return value;
206     // Needed because of truncation (rather than rounding) when scaling up.
207     if (zoomFactor > 1)
208         value++;
209     return value / zoomFactor;
210 }
211
212 double HTMLBodyElement::scrollLeft()
213 {
214     document().updateLayoutIgnorePendingStylesheets();
215     Frame* frame = document().frame();
216     if (!frame)
217         return 0;
218     FrameView* view = frame->view();
219     if (!view)
220         return 0;
221     return floor(adjustForZoom(view->contentsScrollPosition().x(), *frame));
222 }
223
224 void HTMLBodyElement::setScrollLeft(double scrollLeft)
225 {
226     document().updateLayoutIgnorePendingStylesheets();
227     Frame* frame = document().frame();
228     if (!frame)
229         return;
230     FrameView* view = frame->view();
231     if (!view)
232         return;
233     view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), view->scrollY()));
234 }
235
236 double HTMLBodyElement::scrollTop()
237 {
238     document().updateLayoutIgnorePendingStylesheets();
239     Frame* frame = document().frame();
240     if (!frame)
241         return 0;
242     FrameView* view = frame->view();
243     if (!view)
244         return 0;
245     return floor(adjustForZoom(view->contentsScrollPosition().y(), *frame));
246 }
247
248 void HTMLBodyElement::setScrollTop(double scrollTop)
249 {
250     document().updateLayoutIgnorePendingStylesheets();
251     Frame* frame = document().frame();
252     if (!frame)
253         return;
254     FrameView* view = frame->view();
255     if (!view)
256         return;
257     view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
258 }
259
260 double HTMLBodyElement::scrollHeight()
261 {
262     // Update the document's layout.
263     document().updateLayoutIgnorePendingStylesheets();
264     Frame* frame = document().frame();
265     if (!frame)
266         return 0;
267     FrameView* view = frame->view();
268     if (!view)
269         return 0;
270     return floor(adjustForZoom(view->contentsHeight(), *frame));
271 }
272
273 double HTMLBodyElement::scrollWidth()
274 {
275     // Update the document's layout.
276     document().updateLayoutIgnorePendingStylesheets();
277     Frame* frame = document().frame();
278     if (!frame)
279         return 0;
280     FrameView* view = frame->view();
281     if (!view)
282         return 0;
283     return floor(adjustForZoom(view->contentsWidth(), *frame));
284 }
285
286 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
287 {
288     HTMLElement::addSubresourceAttributeURLs(urls);
289
290     addSubresourceURL(urls, document().completeURL(getAttribute(backgroundAttr)));
291 }
292
293 } // namespace WebCore