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 Apple Computer, Inc.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  */
     22 
     23 #include "config.h"
     24 #include "HTMLPlugInElement.h"
     25 
     26 #include "Attribute.h"
     27 #include "Chrome.h"
     28 #include "ChromeClient.h"
     29 #include "CSSPropertyNames.h"
     30 #include "Document.h"
     31 #include "Frame.h"
     32 #include "FrameLoader.h"
     33 #include "FrameTree.h"
     34 #include "HTMLNames.h"
     35 #include "Page.h"
     36 #include "RenderEmbeddedObject.h"
     37 #include "RenderWidget.h"
     38 #include "ScriptController.h"
     39 #include "Settings.h"
     40 #include "Widget.h"
     41 
     42 #if ENABLE(NETSCAPE_PLUGIN_API)
     43 #include "npruntime_impl.h"
     44 #endif
     45 
     46 namespace WebCore {
     47 
     48 using namespace HTMLNames;
     49 
     50 HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document* doc)
     51     : HTMLFrameOwnerElement(tagName, doc)
     52     , m_inBeforeLoadEventHandler(false)
     53 #if ENABLE(NETSCAPE_PLUGIN_API)
     54     , m_NPObject(0)
     55 #endif
     56     , m_isCapturingMouseEvents(false)
     57 {
     58 }
     59 
     60 HTMLPlugInElement::~HTMLPlugInElement()
     61 {
     62     ASSERT(!m_instance); // cleared in detach()
     63 
     64 #if ENABLE(NETSCAPE_PLUGIN_API)
     65     if (m_NPObject) {
     66         _NPN_ReleaseObject(m_NPObject);
     67         m_NPObject = 0;
     68     }
     69 #endif
     70 }
     71 
     72 void HTMLPlugInElement::detach()
     73 {
     74     m_instance.clear();
     75 
     76     if (m_isCapturingMouseEvents) {
     77         if (Frame* frame = document()->frame())
     78             frame->eventHandler()->setCapturingMouseEventsNode(0);
     79         m_isCapturingMouseEvents = false;
     80     }
     81 
     82     HTMLFrameOwnerElement::detach();
     83 }
     84 
     85 PassScriptInstance HTMLPlugInElement::getInstance() const
     86 {
     87     Frame* frame = document()->frame();
     88     if (!frame)
     89         return 0;
     90 
     91     // If the host dynamically turns off JavaScript (or Java) we will still return
     92     // the cached allocated Bindings::Instance.  Not supporting this edge-case is OK.
     93     if (m_instance)
     94         return m_instance;
     95 
     96     if (Widget* widget = pluginWidget())
     97         m_instance = frame->script()->createScriptInstanceForWidget(widget);
     98 
     99     return m_instance;
    100 }
    101 
    102 Widget* HTMLPlugInElement::pluginWidget() const
    103 {
    104     if (m_inBeforeLoadEventHandler) {
    105         // The plug-in hasn't loaded yet, and it makes no sense to try to load if beforeload handler happened to touch the plug-in element.
    106         // That would recursively call beforeload for the same element.
    107         return 0;
    108     }
    109 
    110     RenderWidget* renderWidget = renderWidgetForJSBindings();
    111     if (!renderWidget)
    112         return 0;
    113 
    114     return renderWidget->widget();
    115 }
    116 
    117 bool HTMLPlugInElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
    118 {
    119     if (attrName == widthAttr ||
    120         attrName == heightAttr ||
    121         attrName == vspaceAttr ||
    122         attrName == hspaceAttr) {
    123             result = eUniversal;
    124             return false;
    125     }
    126 
    127     if (attrName == alignAttr) {
    128         result = eReplaced; // Share with <img> since the alignment behavior is the same.
    129         return false;
    130     }
    131 
    132     return HTMLFrameOwnerElement::mapToEntry(attrName, result);
    133 }
    134 
    135 void HTMLPlugInElement::parseMappedAttribute(Attribute* attr)
    136 {
    137     if (attr->name() == widthAttr)
    138         addCSSLength(attr, CSSPropertyWidth, attr->value());
    139     else if (attr->name() == heightAttr)
    140         addCSSLength(attr, CSSPropertyHeight, attr->value());
    141     else if (attr->name() == vspaceAttr) {
    142         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
    143         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
    144     } else if (attr->name() == hspaceAttr) {
    145         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
    146         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
    147     } else if (attr->name() == alignAttr)
    148         addHTMLAlignment(attr);
    149     else
    150         HTMLFrameOwnerElement::parseMappedAttribute(attr);
    151 }
    152 
    153 void HTMLPlugInElement::defaultEventHandler(Event* event)
    154 {
    155     // Firefox seems to use a fake event listener to dispatch events to plug-in (tested with mouse events only).
    156     // This is observable via different order of events - in Firefox, event listeners specified in HTML attributes fires first, then an event
    157     // gets dispatched to plug-in, and only then other event listeners fire. Hopefully, this difference does not matter in practice.
    158 
    159     // FIXME: Mouse down and scroll events are passed down to plug-in via custom code in EventHandler; these code paths should be united.
    160 
    161     RenderObject* r = renderer();
    162     if (r && r->isEmbeddedObject() && toRenderEmbeddedObject(r)->showsMissingPluginIndicator()) {
    163         toRenderEmbeddedObject(r)->handleMissingPluginIndicatorEvent(event);
    164         return;
    165     }
    166 
    167     if (!r || !r->isWidget())
    168         return;
    169     RefPtr<Widget> widget = toRenderWidget(r)->widget();
    170     if (!widget)
    171         return;
    172     widget->handleEvent(event);
    173 }
    174 
    175 #if ENABLE(NETSCAPE_PLUGIN_API)
    176 
    177 NPObject* HTMLPlugInElement::getNPObject()
    178 {
    179     ASSERT(document()->frame());
    180     if (!m_NPObject)
    181         m_NPObject = document()->frame()->script()->createScriptObjectForPluginElement(this);
    182     return m_NPObject;
    183 }
    184 
    185 #endif /* ENABLE(NETSCAPE_PLUGIN_API) */
    186 
    187 #if PLATFORM(ANDROID)
    188 bool HTMLPlugInElement::supportsFocus() const
    189 {
    190     return true;
    191 }
    192 #endif
    193 
    194 }
    195