• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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 "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"
37 
38 #ifdef ANDROID_META_SUPPORT
39 #include "Settings.h"
40 #include "WebViewCore.h"
41 #endif
42 
43 namespace WebCore {
44 
45 using namespace HTMLNames;
46 
HTMLBodyElement(const QualifiedName & tagName,Document * document)47 HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document* document)
48     : HTMLElement(tagName, document)
49 {
50     ASSERT(hasTagName(bodyTag));
51 }
52 
~HTMLBodyElement()53 HTMLBodyElement::~HTMLBodyElement()
54 {
55     if (m_linkDecl) {
56         m_linkDecl->setNode(0);
57         m_linkDecl->setParent(0);
58     }
59 }
60 
createLinkDecl()61 void HTMLBodyElement::createLinkDecl()
62 {
63     m_linkDecl = CSSMutableStyleDeclaration::create();
64     m_linkDecl->setParent(document()->elementSheet());
65     m_linkDecl->setNode(this);
66     m_linkDecl->setStrictParsing(!document()->inCompatMode());
67 }
68 
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const69 bool HTMLBodyElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
70 {
71     if (attrName == backgroundAttr) {
72         result = (MappedAttributeEntry)(eLastEntry + document()->docID());
73         return false;
74     }
75 
76     if (attrName == bgcolorAttr ||
77         attrName == textAttr ||
78         attrName == marginwidthAttr ||
79         attrName == leftmarginAttr ||
80         attrName == marginheightAttr ||
81         attrName == topmarginAttr ||
82         attrName == bgpropertiesAttr) {
83         result = eUniversal;
84         return false;
85     }
86 
87     return HTMLElement::mapToEntry(attrName, result);
88 }
89 
parseMappedAttribute(MappedAttribute * attr)90 void HTMLBodyElement::parseMappedAttribute(MappedAttribute *attr)
91 {
92     if (attr->name() == backgroundAttr) {
93         String url = deprecatedParseURL(attr->value());
94         if (!url.isEmpty())
95             addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string());
96     } else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) {
97         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
98         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
99     } else if (attr->name() == marginheightAttr || attr->name() == topmarginAttr) {
100         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
101         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
102     } else if (attr->name() == bgcolorAttr) {
103         addCSSColor(attr, CSSPropertyBackgroundColor, attr->value());
104     } else if (attr->name() == textAttr) {
105         addCSSColor(attr, CSSPropertyColor, attr->value());
106     } else if (attr->name() == bgpropertiesAttr) {
107         if (equalIgnoringCase(attr->value(), "fixed"))
108             addCSSProperty(attr, CSSPropertyBackgroundAttachment, CSSValueFixed);
109     } else if (attr->name() == vlinkAttr ||
110                attr->name() == alinkAttr ||
111                attr->name() == linkAttr) {
112         if (attr->isNull()) {
113             if (attr->name() == linkAttr)
114                 document()->resetLinkColor();
115             else if (attr->name() == vlinkAttr)
116                 document()->resetVisitedLinkColor();
117             else
118                 document()->resetActiveLinkColor();
119         } else {
120             if (!m_linkDecl)
121                 createLinkDecl();
122             m_linkDecl->setProperty(CSSPropertyColor, attr->value(), false, false);
123             RefPtr<CSSValue> val = m_linkDecl->getPropertyCSSValue(CSSPropertyColor);
124             if (val && val->isPrimitiveValue()) {
125                 Color col = document()->styleSelector()->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValue*>(val.get()));
126                 if (attr->name() == linkAttr)
127                     document()->setLinkColor(col);
128                 else if (attr->name() == vlinkAttr)
129                     document()->setVisitedLinkColor(col);
130                 else
131                     document()->setActiveLinkColor(col);
132             }
133         }
134 
135         if (attached())
136             document()->recalcStyle(Force);
137     } else if (attr->name() == onloadAttr)
138         document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), attr));
139     else if (attr->name() == onbeforeunloadAttr)
140         document()->setWindowAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(document()->frame(), attr));
141     else if (attr->name() == onunloadAttr)
142         document()->setWindowAttributeEventListener(eventNames().unloadEvent, createAttributeEventListener(document()->frame(), attr));
143     else if (attr->name() == onblurAttr)
144         document()->setWindowAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(document()->frame(), attr));
145     else if (attr->name() == onfocusAttr)
146         document()->setWindowAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(document()->frame(), attr));
147     else if (attr->name() == onhashchangeAttr)
148         document()->setWindowAttributeEventListener(eventNames().hashchangeEvent, createAttributeEventListener(document()->frame(), attr));
149     else if (attr->name() == onresizeAttr)
150         document()->setWindowAttributeEventListener(eventNames().resizeEvent, createAttributeEventListener(document()->frame(), attr));
151     else if (attr->name() == onscrollAttr)
152         document()->setWindowAttributeEventListener(eventNames().scrollEvent, createAttributeEventListener(document()->frame(), attr));
153     else if (attr->name() == onstorageAttr)
154         document()->setWindowAttributeEventListener(eventNames().storageEvent, createAttributeEventListener(document()->frame(), attr));
155     else if (attr->name() == ononlineAttr)
156         document()->setWindowAttributeEventListener(eventNames().onlineEvent, createAttributeEventListener(document()->frame(), attr));
157     else if (attr->name() == onofflineAttr)
158         document()->setWindowAttributeEventListener(eventNames().offlineEvent, createAttributeEventListener(document()->frame(), attr));
159     else
160         HTMLElement::parseMappedAttribute(attr);
161 }
162 
insertedIntoDocument()163 void HTMLBodyElement::insertedIntoDocument()
164 {
165     HTMLElement::insertedIntoDocument();
166 
167     // FIXME: Perhaps this code should be in attach() instead of here.
168     Element* ownerElement = document()->ownerElement();
169     if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
170         HTMLFrameElementBase* ownerFrameElement = static_cast<HTMLFrameElementBase*>(ownerElement);
171         int marginWidth = ownerFrameElement->getMarginWidth();
172         if (marginWidth != -1)
173             setAttribute(marginwidthAttr, String::number(marginWidth));
174         int marginHeight = ownerFrameElement->getMarginHeight();
175         if (marginHeight != -1)
176             setAttribute(marginheightAttr, String::number(marginHeight));
177     }
178 
179 #ifdef ANDROID_META_SUPPORT
180     Settings * settings = document()->settings();
181     if (settings) {
182         String host = document()->baseURI().host().lower();
183         if (settings->viewportWidth() == -1 && (host.startsWith("m.") || host.startsWith("mobile.")
184                 || host.contains(".m.") || host.contains(".mobile."))) {
185             // fit mobile sites directly in the screen
186             settings->setMetadataSettings("width", "device-width");
187             // update the meta data if it is the top document
188             if (!ownerElement) {
189                 FrameView* view = document()->view();
190                 if (view)
191                     android::WebViewCore::getWebViewCore(view)->updateViewport();
192             }
193         }
194     }
195 #endif
196 
197     // FIXME: This call to scheduleRelayout should not be needed here.
198     // But without it we hang during WebKit tests; need to fix that and remove this.
199     if (FrameView* view = document()->view())
200         view->scheduleRelayout();
201 }
202 
isURLAttribute(Attribute * attr) const203 bool HTMLBodyElement::isURLAttribute(Attribute *attr) const
204 {
205     return attr->name() == backgroundAttr;
206 }
207 
aLink() const208 String HTMLBodyElement::aLink() const
209 {
210     return getAttribute(alinkAttr);
211 }
212 
setALink(const String & value)213 void HTMLBodyElement::setALink(const String& value)
214 {
215     setAttribute(alinkAttr, value);
216 }
217 
bgColor() const218 String HTMLBodyElement::bgColor() const
219 {
220     return getAttribute(bgcolorAttr);
221 }
222 
setBgColor(const String & value)223 void HTMLBodyElement::setBgColor(const String& value)
224 {
225     setAttribute(bgcolorAttr, value);
226 }
227 
link() const228 String HTMLBodyElement::link() const
229 {
230     return getAttribute(linkAttr);
231 }
232 
setLink(const String & value)233 void HTMLBodyElement::setLink(const String& value)
234 {
235     setAttribute(linkAttr, value);
236 }
237 
text() const238 String HTMLBodyElement::text() const
239 {
240     return getAttribute(textAttr);
241 }
242 
setText(const String & value)243 void HTMLBodyElement::setText(const String& value)
244 {
245     setAttribute(textAttr, value);
246 }
247 
vLink() const248 String HTMLBodyElement::vLink() const
249 {
250     return getAttribute(vlinkAttr);
251 }
252 
setVLink(const String & value)253 void HTMLBodyElement::setVLink(const String& value)
254 {
255     setAttribute(vlinkAttr, value);
256 }
257 
adjustForZoom(int value,FrameView * frameView)258 static int adjustForZoom(int value, FrameView* frameView)
259 {
260     float zoomFactor = frameView->frame()->zoomFactor();
261     if (zoomFactor == 1)
262         return value;
263     // Needed because of truncation (rather than rounding) when scaling up.
264     if (zoomFactor > 1)
265         value++;
266     return static_cast<int>(value / zoomFactor);
267 }
268 
scrollLeft() const269 int HTMLBodyElement::scrollLeft() const
270 {
271     // Update the document's layout.
272     Document* doc = document();
273     doc->updateLayoutIgnorePendingStylesheets();
274     FrameView* view = doc->view();
275     return view ? adjustForZoom(view->scrollX(), view) : 0;
276 }
277 
setScrollLeft(int scrollLeft)278 void HTMLBodyElement::setScrollLeft(int scrollLeft)
279 {
280     FrameView* sview = ownerDocument()->view();
281     if (sview) {
282         // Update the document's layout
283         document()->updateLayoutIgnorePendingStylesheets();
284         sview->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * sview->frame()->zoomFactor()), sview->scrollY()));
285     }
286 }
287 
scrollTop() const288 int HTMLBodyElement::scrollTop() const
289 {
290     // Update the document's layout.
291     Document* doc = document();
292     doc->updateLayoutIgnorePendingStylesheets();
293     FrameView* view = doc->view();
294     return view ? adjustForZoom(view->scrollY(), view) : 0;
295 }
296 
setScrollTop(int scrollTop)297 void HTMLBodyElement::setScrollTop(int scrollTop)
298 {
299     FrameView* sview = ownerDocument()->view();
300     if (sview) {
301         // Update the document's layout
302         document()->updateLayoutIgnorePendingStylesheets();
303         sview->setScrollPosition(IntPoint(sview->scrollX(), static_cast<int>(scrollTop * sview->frame()->zoomFactor())));
304     }
305 }
306 
scrollHeight() const307 int HTMLBodyElement::scrollHeight() const
308 {
309     // Update the document's layout.
310     Document* doc = document();
311     doc->updateLayoutIgnorePendingStylesheets();
312     FrameView* view = doc->view();
313     return view ? adjustForZoom(view->contentsHeight(), view) : 0;
314 }
315 
scrollWidth() const316 int HTMLBodyElement::scrollWidth() const
317 {
318     // Update the document's layout.
319     Document* doc = document();
320     doc->updateLayoutIgnorePendingStylesheets();
321     FrameView* view = doc->view();
322     return view ? adjustForZoom(view->contentsWidth(), view) : 0;
323 }
324 
addSubresourceAttributeURLs(ListHashSet<KURL> & urls) const325 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
326 {
327     HTMLElement::addSubresourceAttributeURLs(urls);
328 
329     addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr)));
330 }
331 
didMoveToNewOwnerDocument()332 void HTMLBodyElement::didMoveToNewOwnerDocument()
333 {
334     // When moving body elements between documents, we should have to reset the parent sheet for any
335     // link style declarations.  If we don't we might crash later.
336     // In practice I can't reproduce this theoretical problem.
337     // webarchive/adopt-attribute-styled-body-webarchive.html tries to make sure this crash won't surface.
338     if (m_linkDecl)
339         m_linkDecl->setParent(document()->elementSheet());
340 
341     HTMLElement::didMoveToNewOwnerDocument();
342 }
343 
onblur() const344 EventListener* HTMLBodyElement::onblur() const
345 {
346     return document()->getWindowAttributeEventListener(eventNames().blurEvent);
347 }
348 
setOnblur(PassRefPtr<EventListener> eventListener)349 void HTMLBodyElement::setOnblur(PassRefPtr<EventListener> eventListener)
350 {
351     document()->setAttributeEventListener(eventNames().blurEvent, eventListener);
352 }
353 
onerror() const354 EventListener* HTMLBodyElement::onerror() const
355 {
356     return document()->getWindowAttributeEventListener(eventNames().errorEvent);
357 }
358 
setOnerror(PassRefPtr<EventListener> eventListener)359 void HTMLBodyElement::setOnerror(PassRefPtr<EventListener> eventListener)
360 {
361     document()->setAttributeEventListener(eventNames().errorEvent, eventListener);
362 }
363 
onfocus() const364 EventListener* HTMLBodyElement::onfocus() const
365 {
366     return document()->getWindowAttributeEventListener(eventNames().focusEvent);
367 }
368 
setOnfocus(PassRefPtr<EventListener> eventListener)369 void HTMLBodyElement::setOnfocus(PassRefPtr<EventListener> eventListener)
370 {
371     document()->setAttributeEventListener(eventNames().focusEvent, eventListener);
372 }
373 
onload() const374 EventListener* HTMLBodyElement::onload() const
375 {
376     return document()->getWindowAttributeEventListener(eventNames().loadEvent);
377 }
378 
setOnload(PassRefPtr<EventListener> eventListener)379 void HTMLBodyElement::setOnload(PassRefPtr<EventListener> eventListener)
380 {
381     document()->setAttributeEventListener(eventNames().loadEvent, eventListener);
382 }
383 
onbeforeunload() const384 EventListener* HTMLBodyElement::onbeforeunload() const
385 {
386     return document()->getWindowAttributeEventListener(eventNames().beforeunloadEvent);
387 }
388 
setOnbeforeunload(PassRefPtr<EventListener> eventListener)389 void HTMLBodyElement::setOnbeforeunload(PassRefPtr<EventListener> eventListener)
390 {
391     document()->setAttributeEventListener(eventNames().beforeunloadEvent, eventListener);
392 }
393 
onmessage() const394 EventListener* HTMLBodyElement::onmessage() const
395 {
396     return document()->getWindowAttributeEventListener(eventNames().messageEvent);
397 }
398 
setOnmessage(PassRefPtr<EventListener> eventListener)399 void HTMLBodyElement::setOnmessage(PassRefPtr<EventListener> eventListener)
400 {
401     document()->setAttributeEventListener(eventNames().messageEvent, eventListener);
402 }
403 
onoffline() const404 EventListener* HTMLBodyElement::onoffline() const
405 {
406     return document()->getWindowAttributeEventListener(eventNames().offlineEvent);
407 }
408 
setOnoffline(PassRefPtr<EventListener> eventListener)409 void HTMLBodyElement::setOnoffline(PassRefPtr<EventListener> eventListener)
410 {
411     document()->setAttributeEventListener(eventNames().offlineEvent, eventListener);
412 }
413 
ononline() const414 EventListener* HTMLBodyElement::ononline() const
415 {
416     return document()->getWindowAttributeEventListener(eventNames().onlineEvent);
417 }
418 
setOnonline(PassRefPtr<EventListener> eventListener)419 void HTMLBodyElement::setOnonline(PassRefPtr<EventListener> eventListener)
420 {
421     document()->setAttributeEventListener(eventNames().onlineEvent, eventListener);
422 }
423 
onresize() const424 EventListener* HTMLBodyElement::onresize() const
425 {
426     return document()->getWindowAttributeEventListener(eventNames().resizeEvent);
427 }
428 
setOnresize(PassRefPtr<EventListener> eventListener)429 void HTMLBodyElement::setOnresize(PassRefPtr<EventListener> eventListener)
430 {
431     document()->setAttributeEventListener(eventNames().resizeEvent, eventListener);
432 }
433 
onstorage() const434 EventListener* HTMLBodyElement::onstorage() const
435 {
436     return document()->getWindowAttributeEventListener(eventNames().storageEvent);
437 }
438 
setOnstorage(PassRefPtr<EventListener> eventListener)439 void HTMLBodyElement::setOnstorage(PassRefPtr<EventListener> eventListener)
440 {
441     document()->setAttributeEventListener(eventNames().storageEvent, eventListener);
442 }
443 
onunload() const444 EventListener* HTMLBodyElement::onunload() const
445 {
446     return document()->getWindowAttributeEventListener(eventNames().unloadEvent);
447 }
448 
setOnunload(PassRefPtr<EventListener> eventListener)449 void HTMLBodyElement::setOnunload(PassRefPtr<EventListener> eventListener)
450 {
451     document()->setAttributeEventListener(eventNames().unloadEvent, eventListener);
452 }
453 
454 } // namespace WebCore
455