Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2000 Simon Hausmann (hausmann (at) kde.org)
      5  *           (C) 2001 Dirk Mueller (mueller (at) 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 "core/html/HTMLBodyElement.h"
     26 
     27 #include "CSSValueKeywords.h"
     28 #include "HTMLNames.h"
     29 #include "bindings/v8/ScriptEventListener.h"
     30 #include "core/css/CSSImageValue.h"
     31 #include "core/css/CSSParser.h"
     32 #include "core/css/StylePropertySet.h"
     33 #include "core/dom/Attribute.h"
     34 #include "core/dom/EventNames.h"
     35 #include "core/html/HTMLFrameElementBase.h"
     36 #include "core/html/parser/HTMLParserIdioms.h"
     37 #include "core/page/Frame.h"
     38 #include "core/page/FrameView.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     ScriptWrappable::init(this);
     49 }
     50 
     51 PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(Document* document)
     52 {
     53     return adoptRef(new HTMLBodyElement(bodyTag, document));
     54 }
     55 
     56 PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(const QualifiedName& tagName, Document* document)
     57 {
     58     return adoptRef(new HTMLBodyElement(tagName, document));
     59 }
     60 
     61 HTMLBodyElement::~HTMLBodyElement()
     62 {
     63 }
     64 
     65 bool 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 
     72 void 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 
     98 void 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()->textLinkColors().resetLinkColor();
    104             else if (name == vlinkAttr)
    105                 document()->textLinkColors().resetVisitedLinkColor();
    106             else
    107                 document()->textLinkColors().resetActiveLinkColor();
    108         } else {
    109             RGBA32 color;
    110             if (CSSParser::parseColor(color, value, !document()->inQuirksMode())) {
    111                 if (name == linkAttr)
    112                     document()->textLinkColors().setLinkColor(color);
    113                 else if (name == vlinkAttr)
    114                     document()->textLinkColors().setVisitedLinkColor(color);
    115                 else
    116                     document()->textLinkColors().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 
    159 Node::InsertionNotificationRequest HTMLBodyElement::insertedInto(ContainerNode* insertionPoint)
    160 {
    161     HTMLElement::insertedInto(insertionPoint);
    162     if (insertionPoint->inDocument())
    163         return InsertionShouldCallDidNotifySubtreeInsertions;
    164     return InsertionDone;
    165 }
    166 
    167 void 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 
    190 bool HTMLBodyElement::isURLAttribute(const Attribute& attribute) const
    191 {
    192     return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute);
    193 }
    194 
    195 bool HTMLBodyElement::supportsFocus() const
    196 {
    197     // This override is needed because the inherited method bails if the parent is editable.
    198     // The <body> should be focusable even if <html> is editable.
    199     return rendererIsEditable() || HTMLElement::supportsFocus();
    200 }
    201 
    202 String HTMLBodyElement::aLink() const
    203 {
    204     return getAttribute(alinkAttr);
    205 }
    206 
    207 void HTMLBodyElement::setALink(const String& value)
    208 {
    209     setAttribute(alinkAttr, value);
    210 }
    211 
    212 String HTMLBodyElement::bgColor() const
    213 {
    214     return getAttribute(bgcolorAttr);
    215 }
    216 
    217 void HTMLBodyElement::setBgColor(const String& value)
    218 {
    219     setAttribute(bgcolorAttr, value);
    220 }
    221 
    222 String HTMLBodyElement::link() const
    223 {
    224     return getAttribute(linkAttr);
    225 }
    226 
    227 void HTMLBodyElement::setLink(const String& value)
    228 {
    229     setAttribute(linkAttr, value);
    230 }
    231 
    232 String HTMLBodyElement::text() const
    233 {
    234     return getAttribute(textAttr);
    235 }
    236 
    237 void HTMLBodyElement::setText(const String& value)
    238 {
    239     setAttribute(textAttr, value);
    240 }
    241 
    242 String HTMLBodyElement::vLink() const
    243 {
    244     return getAttribute(vlinkAttr);
    245 }
    246 
    247 void HTMLBodyElement::setVLink(const String& value)
    248 {
    249     setAttribute(vlinkAttr, value);
    250 }
    251 
    252 static int adjustForZoom(int value, Document* document)
    253 {
    254     Frame* frame = document->frame();
    255     float zoomFactor = frame->pageZoomFactor();
    256     if (zoomFactor == 1)
    257         return value;
    258     // Needed because of truncation (rather than rounding) when scaling up.
    259     if (zoomFactor > 1)
    260         value++;
    261     return static_cast<int>(value / zoomFactor);
    262 }
    263 
    264 int HTMLBodyElement::scrollLeft()
    265 {
    266     // Update the document's layout.
    267     Document* document = this->document();
    268     document->updateLayoutIgnorePendingStylesheets();
    269     FrameView* view = document->view();
    270     return view ? adjustForZoom(view->scrollX(), document) : 0;
    271 }
    272 
    273 void HTMLBodyElement::setScrollLeft(int scrollLeft)
    274 {
    275     Document* document = this->document();
    276     document->updateLayoutIgnorePendingStylesheets();
    277     Frame* frame = document->frame();
    278     if (!frame)
    279         return;
    280     FrameView* view = frame->view();
    281     if (!view)
    282         return;
    283     view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor()), view->scrollY()));
    284 }
    285 
    286 int HTMLBodyElement::scrollTop()
    287 {
    288     // Update the document's layout.
    289     Document* document = this->document();
    290     document->updateLayoutIgnorePendingStylesheets();
    291     FrameView* view = document->view();
    292     return view ? adjustForZoom(view->scrollY(), document) : 0;
    293 }
    294 
    295 void HTMLBodyElement::setScrollTop(int scrollTop)
    296 {
    297     Document* document = this->document();
    298     document->updateLayoutIgnorePendingStylesheets();
    299     Frame* frame = document->frame();
    300     if (!frame)
    301         return;
    302     FrameView* view = frame->view();
    303     if (!view)
    304         return;
    305     view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor())));
    306 }
    307 
    308 int HTMLBodyElement::scrollHeight()
    309 {
    310     // Update the document's layout.
    311     Document* document = this->document();
    312     document->updateLayoutIgnorePendingStylesheets();
    313     FrameView* view = document->view();
    314     return view ? adjustForZoom(view->contentsHeight(), document) : 0;
    315 }
    316 
    317 int HTMLBodyElement::scrollWidth()
    318 {
    319     // Update the document's layout.
    320     Document* document = this->document();
    321     document->updateLayoutIgnorePendingStylesheets();
    322     FrameView* view = document->view();
    323     return view ? adjustForZoom(view->contentsWidth(), document) : 0;
    324 }
    325 
    326 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
    327 {
    328     HTMLElement::addSubresourceAttributeURLs(urls);
    329 
    330     addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr)));
    331 }
    332 
    333 } // namespace WebCore
    334