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 "ScriptEventListener.h" 39#include "StylePropertySet.h" 40 41namespace WebCore { 42 43using namespace HTMLNames; 44 45HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document* document) 46 : HTMLElement(tagName, document) 47{ 48 ASSERT(hasTagName(bodyTag)); 49} 50 51PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(Document* document) 52{ 53 return adoptRef(new HTMLBodyElement(bodyTag, document)); 54} 55 56PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(const QualifiedName& tagName, Document* document) 57{ 58 return adoptRef(new HTMLBodyElement(tagName, document)); 59} 60 61HTMLBodyElement::~HTMLBodyElement() 62{ 63} 64 65bool HTMLBodyElement::isPresentationAttribute(const QualifiedName& name) const 66{ 67 if (name == backgroundAttr || name == marginwidthAttr || name == leftmarginAttr || name == marginheightAttr || name == topmarginAttr || name == bgcolorAttr || name == textAttr || name == bgpropertiesAttr) 68 return true; 69 return HTMLElement::isPresentationAttribute(name); 70} 71 72void HTMLBodyElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 73{ 74 if (name == backgroundAttr) { 75 String url = stripLeadingAndTrailingHTMLSpaces(value); 76 if (!url.isEmpty()) { 77 RefPtr<CSSImageValue> imageValue = CSSImageValue::create(document()->completeURL(url).string()); 78 imageValue->setInitiator(localName()); 79 style->setProperty(CSSProperty(CSSPropertyBackgroundImage, imageValue.release())); 80 } 81 } else if (name == marginwidthAttr || name == leftmarginAttr) { 82 addHTMLLengthToStyle(style, CSSPropertyMarginRight, value); 83 addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value); 84 } else if (name == marginheightAttr || name == topmarginAttr) { 85 addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value); 86 addHTMLLengthToStyle(style, CSSPropertyMarginTop, value); 87 } else if (name == bgcolorAttr) { 88 addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value); 89 } else if (name == textAttr) { 90 addHTMLColorToStyle(style, CSSPropertyColor, value); 91 } else if (name == bgpropertiesAttr) { 92 if (equalIgnoringCase(value, "fixed")) 93 addPropertyToPresentationAttributeStyle(style, CSSPropertyBackgroundAttachment, CSSValueFixed); 94 } else 95 HTMLElement::collectStyleForPresentationAttribute(name, value, style); 96} 97 98void HTMLBodyElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 99{ 100 if (name == vlinkAttr || name == alinkAttr || name == linkAttr) { 101 if (value.isNull()) { 102 if (name == linkAttr) 103 document()->resetLinkColor(); 104 else if (name == vlinkAttr) 105 document()->resetVisitedLinkColor(); 106 else 107 document()->resetActiveLinkColor(); 108 } else { 109 RGBA32 color; 110 if (CSSParser::parseColor(color, value, !document()->inQuirksMode())) { 111 if (name == linkAttr) 112 document()->setLinkColor(color); 113 else if (name == vlinkAttr) 114 document()->setVisitedLinkColor(color); 115 else 116 document()->setActiveLinkColor(color); 117 } 118 } 119 120 setNeedsStyleRecalc(); 121 } else if (name == onloadAttr) 122 document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), name, value)); 123 else if (name == onbeforeunloadAttr) 124 document()->setWindowAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(document()->frame(), name, value)); 125 else if (name == onunloadAttr) 126 document()->setWindowAttributeEventListener(eventNames().unloadEvent, createAttributeEventListener(document()->frame(), name, value)); 127 else if (name == onpagehideAttr) 128 document()->setWindowAttributeEventListener(eventNames().pagehideEvent, createAttributeEventListener(document()->frame(), name, value)); 129 else if (name == onpageshowAttr) 130 document()->setWindowAttributeEventListener(eventNames().pageshowEvent, createAttributeEventListener(document()->frame(), name, value)); 131 else if (name == onpopstateAttr) 132 document()->setWindowAttributeEventListener(eventNames().popstateEvent, createAttributeEventListener(document()->frame(), name, value)); 133 else if (name == onblurAttr) 134 document()->setWindowAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(document()->frame(), name, value)); 135 else if (name == onfocusAttr) 136 document()->setWindowAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(document()->frame(), name, value)); 137#if ENABLE(ORIENTATION_EVENTS) 138 else if (name == onorientationchangeAttr) 139 document()->setWindowAttributeEventListener(eventNames().orientationchangeEvent, createAttributeEventListener(document()->frame(), name, value)); 140#endif 141 else if (name == onhashchangeAttr) 142 document()->setWindowAttributeEventListener(eventNames().hashchangeEvent, createAttributeEventListener(document()->frame(), name, value)); 143 else if (name == onresizeAttr) 144 document()->setWindowAttributeEventListener(eventNames().resizeEvent, createAttributeEventListener(document()->frame(), name, value)); 145 else if (name == onscrollAttr) 146 document()->setWindowAttributeEventListener(eventNames().scrollEvent, createAttributeEventListener(document()->frame(), name, value)); 147 else if (name == onselectionchangeAttr) 148 document()->setAttributeEventListener(eventNames().selectionchangeEvent, createAttributeEventListener(document()->frame(), name, value)); 149 else if (name == onstorageAttr) 150 document()->setWindowAttributeEventListener(eventNames().storageEvent, createAttributeEventListener(document()->frame(), name, value)); 151 else if (name == ononlineAttr) 152 document()->setWindowAttributeEventListener(eventNames().onlineEvent, createAttributeEventListener(document()->frame(), name, value)); 153 else if (name == onofflineAttr) 154 document()->setWindowAttributeEventListener(eventNames().offlineEvent, createAttributeEventListener(document()->frame(), name, value)); 155 else 156 HTMLElement::parseAttribute(name, value); 157} 158 159Node::InsertionNotificationRequest HTMLBodyElement::insertedInto(ContainerNode* insertionPoint) 160{ 161 HTMLElement::insertedInto(insertionPoint); 162 if (insertionPoint->inDocument()) 163 return InsertionShouldCallDidNotifySubtreeInsertions; 164 return InsertionDone; 165} 166 167void HTMLBodyElement::didNotifySubtreeInsertions(ContainerNode* insertionPoint) 168{ 169 ASSERT_UNUSED(insertionPoint, insertionPoint->inDocument()); 170 ASSERT(document()); 171 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->marginWidth(); 177 if (marginWidth != -1) 178 setAttribute(marginwidthAttr, String::number(marginWidth)); 179 int marginHeight = ownerFrameElement->marginHeight(); 180 if (marginHeight != -1) 181 setAttribute(marginheightAttr, String::number(marginHeight)); 182 } 183 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(); 188} 189 190bool HTMLBodyElement::isURLAttribute(const Attribute& attribute) const 191{ 192 return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute); 193} 194 195bool HTMLBodyElement::supportsFocus() const 196{ 197 return rendererIsEditable() || HTMLElement::supportsFocus(); 198} 199 200String HTMLBodyElement::aLink() const 201{ 202 return getAttribute(alinkAttr); 203} 204 205void HTMLBodyElement::setALink(const String& value) 206{ 207 setAttribute(alinkAttr, value); 208} 209 210String HTMLBodyElement::bgColor() const 211{ 212 return getAttribute(bgcolorAttr); 213} 214 215void HTMLBodyElement::setBgColor(const String& value) 216{ 217 setAttribute(bgcolorAttr, value); 218} 219 220String HTMLBodyElement::link() const 221{ 222 return getAttribute(linkAttr); 223} 224 225void HTMLBodyElement::setLink(const String& value) 226{ 227 setAttribute(linkAttr, value); 228} 229 230String HTMLBodyElement::text() const 231{ 232 return getAttribute(textAttr); 233} 234 235void HTMLBodyElement::setText(const String& value) 236{ 237 setAttribute(textAttr, value); 238} 239 240String HTMLBodyElement::vLink() const 241{ 242 return getAttribute(vlinkAttr); 243} 244 245void HTMLBodyElement::setVLink(const String& value) 246{ 247 setAttribute(vlinkAttr, value); 248} 249 250static int adjustForZoom(int value, Document* document) 251{ 252 Frame* frame = document->frame(); 253 float zoomFactor = frame->pageZoomFactor() * frame->frameScaleFactor(); 254 if (zoomFactor == 1) 255 return value; 256 // Needed because of truncation (rather than rounding) when scaling up. 257 if (zoomFactor > 1) 258 value++; 259 return static_cast<int>(value / zoomFactor); 260} 261 262int HTMLBodyElement::scrollLeft() 263{ 264 // Update the document's layout. 265 Document* document = this->document(); 266 document->updateLayoutIgnorePendingStylesheets(); 267 FrameView* view = document->view(); 268 return view ? adjustForZoom(view->scrollX(), document) : 0; 269} 270 271void HTMLBodyElement::setScrollLeft(int scrollLeft) 272{ 273 Document* document = this->document(); 274 document->updateLayoutIgnorePendingStylesheets(); 275 Frame* frame = document->frame(); 276 if (!frame) 277 return; 278 FrameView* view = frame->view(); 279 if (!view) 280 return; 281 view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), view->scrollY())); 282} 283 284int HTMLBodyElement::scrollTop() 285{ 286 // Update the document's layout. 287 Document* document = this->document(); 288 document->updateLayoutIgnorePendingStylesheets(); 289 FrameView* view = document->view(); 290 return view ? adjustForZoom(view->scrollY(), document) : 0; 291} 292 293void HTMLBodyElement::setScrollTop(int scrollTop) 294{ 295 Document* document = this->document(); 296 document->updateLayoutIgnorePendingStylesheets(); 297 Frame* frame = document->frame(); 298 if (!frame) 299 return; 300 FrameView* view = frame->view(); 301 if (!view) 302 return; 303 view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor() * frame->frameScaleFactor()))); 304} 305 306int HTMLBodyElement::scrollHeight() 307{ 308 // Update the document's layout. 309 Document* document = this->document(); 310 document->updateLayoutIgnorePendingStylesheets(); 311 FrameView* view = document->view(); 312 return view ? adjustForZoom(view->contentsHeight(), document) : 0; 313} 314 315int HTMLBodyElement::scrollWidth() 316{ 317 // Update the document's layout. 318 Document* document = this->document(); 319 document->updateLayoutIgnorePendingStylesheets(); 320 FrameView* view = document->view(); 321 return view ? adjustForZoom(view->contentsWidth(), document) : 0; 322} 323 324void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 325{ 326 HTMLElement::addSubresourceAttributeURLs(urls); 327 328 addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr))); 329} 330 331} // namespace WebCore 332