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 Stefan Schimanski (1Stein (at) gmx.de)
      5  * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
      6  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      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 "HTMLEmbedElement.h"
     26 
     27 #include "CSSHelper.h"
     28 #include "CSSPropertyNames.h"
     29 #include "Frame.h"
     30 #include "HTMLDocument.h"
     31 #include "HTMLImageLoader.h"
     32 #include "HTMLNames.h"
     33 #include "HTMLObjectElement.h"
     34 #include "MappedAttribute.h"
     35 #include "RenderEmbeddedObject.h"
     36 #include "RenderImage.h"
     37 #include "RenderWidget.h"
     38 #include "ScriptController.h"
     39 #include "Settings.h"
     40 
     41 namespace WebCore {
     42 
     43 using namespace HTMLNames;
     44 
     45 inline HTMLEmbedElement::HTMLEmbedElement(const QualifiedName& tagName, Document* document)
     46     : HTMLPlugInImageElement(tagName, document)
     47     , m_needWidgetUpdate(false)
     48 {
     49     ASSERT(hasTagName(embedTag));
     50 }
     51 
     52 PassRefPtr<HTMLEmbedElement> HTMLEmbedElement::create(const QualifiedName& tagName, Document* document)
     53 {
     54     return adoptRef(new HTMLEmbedElement(tagName, document));
     55 }
     56 
     57 static inline RenderWidget* findWidgetRenderer(const Node* n)
     58 {
     59     if (!n->renderer())
     60         do
     61             n = n->parentNode();
     62         while (n && !n->hasTagName(objectTag));
     63 
     64     if (n && n->renderer() && n->renderer()->isWidget())
     65         return toRenderWidget(n->renderer());
     66 
     67     return 0;
     68 }
     69 
     70 RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() const
     71 {
     72     document()->updateLayoutIgnorePendingStylesheets();
     73     return findWidgetRenderer(this);
     74 }
     75 
     76 bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
     77 {
     78     if (attrName == hiddenAttr) {
     79         result = eUniversal;
     80         return false;
     81     }
     82 
     83     return HTMLPlugInElement::mapToEntry(attrName, result);
     84 }
     85 
     86 void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr)
     87 {
     88     const AtomicString& value = attr->value();
     89 
     90     if (attr->name() == typeAttr) {
     91         m_serviceType = value.string().lower();
     92         int pos = m_serviceType.find(";");
     93         if (pos != -1)
     94             m_serviceType = m_serviceType.left(pos);
     95         if (!isImageType() && m_imageLoader)
     96             m_imageLoader.clear();
     97     } else if (attr->name() == codeAttr)
     98         m_url = deprecatedParseURL(value.string());
     99     else if (attr->name() == srcAttr) {
    100         m_url = deprecatedParseURL(value.string());
    101         if (renderer() && isImageType()) {
    102             if (!m_imageLoader)
    103                 m_imageLoader.set(new HTMLImageLoader(this));
    104             m_imageLoader->updateFromElementIgnoringPreviousError();
    105         }
    106     } else if (attr->name() == hiddenAttr) {
    107         if (equalIgnoringCase(value.string(), "yes") || equalIgnoringCase(value.string(), "true")) {
    108             // FIXME: Not dynamic, since we add this but don't remove it, but it may be OK for now
    109             // that this rarely-used attribute won't work properly if you remove it.
    110             addCSSLength(attr, CSSPropertyWidth, "0");
    111             addCSSLength(attr, CSSPropertyHeight, "0");
    112         }
    113     } else if (attr->name() == nameAttr) {
    114         if (inDocument() && document()->isHTMLDocument()) {
    115             HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
    116             document->removeNamedItem(m_name);
    117             document->addNamedItem(value);
    118         }
    119         m_name = value;
    120     } else
    121         HTMLPlugInElement::parseMappedAttribute(attr);
    122 }
    123 
    124 bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style)
    125 {
    126     if (isImageType())
    127         return HTMLPlugInElement::rendererIsNeeded(style);
    128 
    129     Frame* frame = document()->frame();
    130     if (!frame)
    131         return false;
    132 
    133     Node* p = parentNode();
    134     if (p && p->hasTagName(objectTag)) {
    135         ASSERT(p->renderer());
    136         return false;
    137     }
    138 
    139 #if ENABLE(DASHBOARD_SUPPORT)
    140     // Workaround for <rdar://problem/6642221>.
    141     if (Settings* settings = frame->settings()) {
    142         if (settings->usesDashboardBackwardCompatibilityMode())
    143             return true;
    144     }
    145 #endif
    146 
    147     return HTMLPlugInElement::rendererIsNeeded(style);
    148 }
    149 
    150 RenderObject* HTMLEmbedElement::createRenderer(RenderArena* arena, RenderStyle*)
    151 {
    152     if (isImageType())
    153         return new (arena) RenderImage(this);
    154     return new (arena) RenderEmbeddedObject(this);
    155 }
    156 
    157 void HTMLEmbedElement::attach()
    158 {
    159     m_needWidgetUpdate = true;
    160 
    161     bool isImage = isImageType();
    162 
    163     if (!isImage)
    164         queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this);
    165 
    166     HTMLPlugInElement::attach();
    167 
    168     if (isImage && renderer()) {
    169         if (!m_imageLoader)
    170             m_imageLoader.set(new HTMLImageLoader(this));
    171         m_imageLoader->updateFromElement();
    172 
    173         if (renderer())
    174             toRenderImage(renderer())->setCachedImage(m_imageLoader->image());
    175     }
    176 }
    177 
    178 void HTMLEmbedElement::updateWidget()
    179 {
    180     document()->updateStyleIfNeeded();
    181     if (m_needWidgetUpdate && renderer() && !isImageType())
    182         toRenderEmbeddedObject(renderer())->updateWidget(true);
    183 }
    184 
    185 void HTMLEmbedElement::insertedIntoDocument()
    186 {
    187     if (document()->isHTMLDocument())
    188         static_cast<HTMLDocument*>(document())->addNamedItem(m_name);
    189 
    190     String width = getAttribute(widthAttr);
    191     String height = getAttribute(heightAttr);
    192     if (!width.isEmpty() || !height.isEmpty()) {
    193         Node* n = parent();
    194         while (n && !n->hasTagName(objectTag))
    195             n = n->parent();
    196         if (n) {
    197             if (!width.isEmpty())
    198                 static_cast<HTMLObjectElement*>(n)->setAttribute(widthAttr, width);
    199             if (!height.isEmpty())
    200                 static_cast<HTMLObjectElement*>(n)->setAttribute(heightAttr, height);
    201         }
    202     }
    203 
    204     HTMLPlugInElement::insertedIntoDocument();
    205 }
    206 
    207 void HTMLEmbedElement::removedFromDocument()
    208 {
    209     if (document()->isHTMLDocument())
    210         static_cast<HTMLDocument*>(document())->removeNamedItem(m_name);
    211 
    212     HTMLPlugInElement::removedFromDocument();
    213 }
    214 
    215 void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls)
    216 {
    217     HTMLPlugInElement::attributeChanged(attr, preserveDecls);
    218 
    219     if ((attr->name() == widthAttr || attr->name() == heightAttr) && !attr->isEmpty()) {
    220         Node* n = parent();
    221         while (n && !n->hasTagName(objectTag))
    222             n = n->parent();
    223         if (n)
    224             static_cast<HTMLObjectElement*>(n)->setAttribute(attr->name(), attr->value());
    225     }
    226 }
    227 
    228 bool HTMLEmbedElement::isURLAttribute(Attribute* attr) const
    229 {
    230     return attr->name() == srcAttr;
    231 }
    232 
    233 const QualifiedName& HTMLEmbedElement::imageSourceAttributeName() const
    234 {
    235     return srcAttr;
    236 }
    237 
    238 void HTMLEmbedElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
    239 {
    240     HTMLPlugInImageElement::addSubresourceAttributeURLs(urls);
    241 
    242     addSubresourceURL(urls, document()->completeURL(getAttribute(srcAttr)));
    243 }
    244 
    245 }
    246