Rubber-stamped by Brady Eidson.
[webbrowser.git] / WebCore / html / HTMLBodyElement.cpp
blob35133c08e319ec4bb42fb0507e547dfe6014d9b3
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 Apple Inc. All rights reserved.
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.
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.
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.
24 #include "config.h"
25 #include "HTMLBodyElement.h"
27 #include "CSSStyleSelector.h"
28 #include "CSSStyleSheet.h"
29 #include "CSSValueKeywords.h"
30 #include "EventNames.h"
31 #include "Frame.h"
32 #include "FrameView.h"
33 #include "HTMLFrameElementBase.h"
34 #include "HTMLNames.h"
35 #include "MappedAttribute.h"
36 #include "ScriptEventListener.h"
38 namespace WebCore {
40 using namespace HTMLNames;
42 HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document* document)
43 : HTMLElement(tagName, document)
45 ASSERT(hasTagName(bodyTag));
48 HTMLBodyElement::~HTMLBodyElement()
50 if (m_linkDecl) {
51 m_linkDecl->setNode(0);
52 m_linkDecl->setParent(0);
56 void HTMLBodyElement::createLinkDecl()
58 m_linkDecl = CSSMutableStyleDeclaration::create();
59 m_linkDecl->setParent(document()->elementSheet());
60 m_linkDecl->setNode(this);
61 m_linkDecl->setStrictParsing(!document()->inCompatMode());
64 bool HTMLBodyElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
66 if (attrName == backgroundAttr) {
67 result = (MappedAttributeEntry)(eLastEntry + document()->docID());
68 return false;
71 if (attrName == bgcolorAttr ||
72 attrName == textAttr ||
73 attrName == marginwidthAttr ||
74 attrName == leftmarginAttr ||
75 attrName == marginheightAttr ||
76 attrName == topmarginAttr ||
77 attrName == bgpropertiesAttr) {
78 result = eUniversal;
79 return false;
82 return HTMLElement::mapToEntry(attrName, result);
85 void HTMLBodyElement::parseMappedAttribute(MappedAttribute *attr)
87 if (attr->name() == backgroundAttr) {
88 String url = deprecatedParseURL(attr->value());
89 if (!url.isEmpty())
90 addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string());
91 } else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) {
92 addCSSLength(attr, CSSPropertyMarginRight, attr->value());
93 addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
94 } else if (attr->name() == marginheightAttr || attr->name() == topmarginAttr) {
95 addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
96 addCSSLength(attr, CSSPropertyMarginTop, attr->value());
97 } else if (attr->name() == bgcolorAttr) {
98 addCSSColor(attr, CSSPropertyBackgroundColor, attr->value());
99 } else if (attr->name() == textAttr) {
100 addCSSColor(attr, CSSPropertyColor, attr->value());
101 } else if (attr->name() == bgpropertiesAttr) {
102 if (equalIgnoringCase(attr->value(), "fixed"))
103 addCSSProperty(attr, CSSPropertyBackgroundAttachment, CSSValueFixed);
104 } else if (attr->name() == vlinkAttr ||
105 attr->name() == alinkAttr ||
106 attr->name() == linkAttr) {
107 if (attr->isNull()) {
108 if (attr->name() == linkAttr)
109 document()->resetLinkColor();
110 else if (attr->name() == vlinkAttr)
111 document()->resetVisitedLinkColor();
112 else
113 document()->resetActiveLinkColor();
114 } else {
115 if (!m_linkDecl)
116 createLinkDecl();
117 m_linkDecl->setProperty(CSSPropertyColor, attr->value(), false, false);
118 RefPtr<CSSValue> val = m_linkDecl->getPropertyCSSValue(CSSPropertyColor);
119 if (val && val->isPrimitiveValue()) {
120 Color col = document()->styleSelector()->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValue*>(val.get()));
121 if (attr->name() == linkAttr)
122 document()->setLinkColor(col);
123 else if (attr->name() == vlinkAttr)
124 document()->setVisitedLinkColor(col);
125 else
126 document()->setActiveLinkColor(col);
130 if (attached())
131 document()->recalcStyle(Force);
132 } else if (attr->name() == onloadAttr)
133 document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), attr));
134 else if (attr->name() == onbeforeunloadAttr)
135 document()->setWindowAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(document()->frame(), attr));
136 else if (attr->name() == onunloadAttr)
137 document()->setWindowAttributeEventListener(eventNames().unloadEvent, createAttributeEventListener(document()->frame(), attr));
138 else if (attr->name() == onpagehideAttr)
139 document()->setWindowAttributeEventListener(eventNames().pagehideEvent, createAttributeEventListener(document()->frame(), attr));
140 else if (attr->name() == onpageshowAttr)
141 document()->setWindowAttributeEventListener(eventNames().pageshowEvent, createAttributeEventListener(document()->frame(), attr));
142 else if (attr->name() == onpopstateAttr)
143 document()->setWindowAttributeEventListener(eventNames().popstateEvent, createAttributeEventListener(document()->frame(), attr));
144 else if (attr->name() == onblurAttr)
145 document()->setWindowAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(document()->frame(), attr));
146 else if (attr->name() == onfocusAttr)
147 document()->setWindowAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(document()->frame(), attr));
148 #if ENABLE(ORIENTATION_EVENTS)
149 else if (attr->name() == onorientationchangeAttr)
150 document()->setWindowAttributeEventListener(eventNames().orientationchangeEvent, createAttributeEventListener(document()->frame(), attr));
151 #endif
152 else if (attr->name() == onhashchangeAttr)
153 document()->setWindowAttributeEventListener(eventNames().hashchangeEvent, createAttributeEventListener(document()->frame(), attr));
154 else if (attr->name() == onresizeAttr)
155 document()->setWindowAttributeEventListener(eventNames().resizeEvent, createAttributeEventListener(document()->frame(), attr));
156 else if (attr->name() == onscrollAttr)
157 document()->setWindowAttributeEventListener(eventNames().scrollEvent, createAttributeEventListener(document()->frame(), attr));
158 else if (attr->name() == onstorageAttr)
159 document()->setWindowAttributeEventListener(eventNames().storageEvent, createAttributeEventListener(document()->frame(), attr));
160 else if (attr->name() == ononlineAttr)
161 document()->setWindowAttributeEventListener(eventNames().onlineEvent, createAttributeEventListener(document()->frame(), attr));
162 else if (attr->name() == onofflineAttr)
163 document()->setWindowAttributeEventListener(eventNames().offlineEvent, createAttributeEventListener(document()->frame(), attr));
164 else
165 HTMLElement::parseMappedAttribute(attr);
168 void HTMLBodyElement::insertedIntoDocument()
170 HTMLElement::insertedIntoDocument();
172 // FIXME: Perhaps this code should be in attach() instead of here.
173 Element* ownerElement = document()->ownerElement();
174 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
175 HTMLFrameElementBase* ownerFrameElement = static_cast<HTMLFrameElementBase*>(ownerElement);
176 int marginWidth = ownerFrameElement->getMarginWidth();
177 if (marginWidth != -1)
178 setAttribute(marginwidthAttr, String::number(marginWidth));
179 int marginHeight = ownerFrameElement->getMarginHeight();
180 if (marginHeight != -1)
181 setAttribute(marginheightAttr, String::number(marginHeight));
184 // FIXME: This call to scheduleRelayout should not be needed here.
185 // But without it we hang during WebKit tests; need to fix that and remove this.
186 if (FrameView* view = document()->view())
187 view->scheduleRelayout();
190 bool HTMLBodyElement::isURLAttribute(Attribute *attr) const
192 return attr->name() == backgroundAttr;
195 String HTMLBodyElement::aLink() const
197 return getAttribute(alinkAttr);
200 void HTMLBodyElement::setALink(const String& value)
202 setAttribute(alinkAttr, value);
205 String HTMLBodyElement::bgColor() const
207 return getAttribute(bgcolorAttr);
210 void HTMLBodyElement::setBgColor(const String& value)
212 setAttribute(bgcolorAttr, value);
215 String HTMLBodyElement::link() const
217 return getAttribute(linkAttr);
220 void HTMLBodyElement::setLink(const String& value)
222 setAttribute(linkAttr, value);
225 String HTMLBodyElement::text() const
227 return getAttribute(textAttr);
230 void HTMLBodyElement::setText(const String& value)
232 setAttribute(textAttr, value);
235 String HTMLBodyElement::vLink() const
237 return getAttribute(vlinkAttr);
240 void HTMLBodyElement::setVLink(const String& value)
242 setAttribute(vlinkAttr, value);
245 static int adjustForZoom(int value, FrameView* frameView)
247 float zoomFactor = frameView->frame()->zoomFactor();
248 if (zoomFactor == 1)
249 return value;
250 // Needed because of truncation (rather than rounding) when scaling up.
251 if (zoomFactor > 1)
252 value++;
253 return static_cast<int>(value / zoomFactor);
256 int HTMLBodyElement::scrollLeft() const
258 // Update the document's layout.
259 Document* doc = document();
260 doc->updateLayoutIgnorePendingStylesheets();
261 FrameView* view = doc->view();
262 return view ? adjustForZoom(view->scrollX(), view) : 0;
265 void HTMLBodyElement::setScrollLeft(int scrollLeft)
267 FrameView* sview = ownerDocument()->view();
268 if (sview) {
269 // Update the document's layout
270 document()->updateLayoutIgnorePendingStylesheets();
271 sview->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * sview->frame()->zoomFactor()), sview->scrollY()));
275 int HTMLBodyElement::scrollTop() const
277 // Update the document's layout.
278 Document* doc = document();
279 doc->updateLayoutIgnorePendingStylesheets();
280 FrameView* view = doc->view();
281 return view ? adjustForZoom(view->scrollY(), view) : 0;
284 void HTMLBodyElement::setScrollTop(int scrollTop)
286 FrameView* sview = ownerDocument()->view();
287 if (sview) {
288 // Update the document's layout
289 document()->updateLayoutIgnorePendingStylesheets();
290 sview->setScrollPosition(IntPoint(sview->scrollX(), static_cast<int>(scrollTop * sview->frame()->zoomFactor())));
294 int HTMLBodyElement::scrollHeight() const
296 // Update the document's layout.
297 Document* doc = document();
298 doc->updateLayoutIgnorePendingStylesheets();
299 FrameView* view = doc->view();
300 return view ? adjustForZoom(view->contentsHeight(), view) : 0;
303 int HTMLBodyElement::scrollWidth() const
305 // Update the document's layout.
306 Document* doc = document();
307 doc->updateLayoutIgnorePendingStylesheets();
308 FrameView* view = doc->view();
309 return view ? adjustForZoom(view->contentsWidth(), view) : 0;
312 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
314 HTMLElement::addSubresourceAttributeURLs(urls);
316 addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr)));
319 void HTMLBodyElement::didMoveToNewOwnerDocument()
321 // When moving body elements between documents, we should have to reset the parent sheet for any
322 // link style declarations. If we don't we might crash later.
323 // In practice I can't reproduce this theoretical problem.
324 // webarchive/adopt-attribute-styled-body-webarchive.html tries to make sure this crash won't surface.
325 if (m_linkDecl)
326 m_linkDecl->setParent(document()->elementSheet());
328 HTMLElement::didMoveToNewOwnerDocument();
331 } // namespace WebCore