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, 2012 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 "core/html/HTMLAppletElement.h"
     26 
     27 #include "core/HTMLNames.h"
     28 #include "core/dom/shadow/ShadowRoot.h"
     29 #include "core/html/HTMLParamElement.h"
     30 #include "core/loader/FrameLoader.h"
     31 #include "core/loader/FrameLoaderClient.h"
     32 #include "core/frame/LocalFrame.h"
     33 #include "core/frame/Settings.h"
     34 #include "core/frame/csp/ContentSecurityPolicy.h"
     35 #include "core/rendering/RenderApplet.h"
     36 #include "platform/Widget.h"
     37 #include "platform/weborigin/KURL.h"
     38 #include "platform/weborigin/SecurityOrigin.h"
     39 
     40 namespace WebCore {
     41 
     42 using namespace HTMLNames;
     43 
     44 HTMLAppletElement::HTMLAppletElement(Document& document, bool createdByParser)
     45     : HTMLPlugInElement(appletTag, document, createdByParser, ShouldNotPreferPlugInsForImages)
     46 {
     47     ScriptWrappable::init(this);
     48 
     49     m_serviceType = "application/x-java-applet";
     50 }
     51 
     52 PassRefPtrWillBeRawPtr<HTMLAppletElement> HTMLAppletElement::create(Document& document, bool createdByParser)
     53 {
     54     RefPtrWillBeRawPtr<HTMLAppletElement> element = adoptRefWillBeNoop(new HTMLAppletElement(document, createdByParser));
     55     element->ensureUserAgentShadowRoot();
     56     return element.release();
     57 }
     58 
     59 void HTMLAppletElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     60 {
     61     if (name == altAttr
     62         || name == archiveAttr
     63         || name == codeAttr
     64         || name == codebaseAttr
     65         || name == mayscriptAttr
     66         || name == objectAttr) {
     67         // Do nothing.
     68         return;
     69     }
     70 
     71     HTMLPlugInElement::parseAttribute(name, value);
     72 }
     73 
     74 bool HTMLAppletElement::isURLAttribute(const Attribute& attribute) const
     75 {
     76     return attribute.name() == codebaseAttr || attribute.name() == objectAttr
     77         || HTMLPlugInElement::isURLAttribute(attribute);
     78 }
     79 
     80 bool HTMLAppletElement::hasLegalLinkAttribute(const QualifiedName& name) const
     81 {
     82     return name == codebaseAttr || HTMLPlugInElement::hasLegalLinkAttribute(name);
     83 }
     84 
     85 bool HTMLAppletElement::rendererIsNeeded(const RenderStyle& style)
     86 {
     87     if (!fastHasAttribute(codeAttr) && !hasAuthorShadowRoot())
     88         return false;
     89     return HTMLPlugInElement::rendererIsNeeded(style);
     90 }
     91 
     92 RenderObject* HTMLAppletElement::createRenderer(RenderStyle* style)
     93 {
     94     if (!canEmbedJava() || hasAuthorShadowRoot())
     95         return RenderObject::createObject(this, style);
     96 
     97     return new RenderApplet(this);
     98 }
     99 
    100 RenderWidget* HTMLAppletElement::renderWidgetForJSBindings() const
    101 {
    102     if (!canEmbedJava())
    103         return 0;
    104     return HTMLPlugInElement::renderWidgetForJSBindings();
    105 }
    106 
    107 RenderWidget* HTMLAppletElement::existingRenderWidget() const
    108 {
    109     return renderPart();
    110 }
    111 
    112 void HTMLAppletElement::updateWidgetInternal()
    113 {
    114     ASSERT(!m_isDelayingLoadEvent);
    115     setNeedsWidgetUpdate(false);
    116     // FIXME: This should ASSERT isFinishedParsingChildren() instead.
    117     if (!isFinishedParsingChildren())
    118         return;
    119 
    120     RenderEmbeddedObject* renderer = renderEmbeddedObject();
    121 
    122     LocalFrame* frame = document().frame();
    123     ASSERT(frame);
    124 
    125     Vector<String> paramNames;
    126     Vector<String> paramValues;
    127 
    128     const AtomicString& codeBase = getAttribute(codebaseAttr);
    129     if (!codeBase.isNull()) {
    130         KURL codeBaseURL = document().completeURL(codeBase);
    131         paramNames.append("codeBase");
    132         paramValues.append(codeBase.string());
    133     }
    134 
    135     const AtomicString& archive = getAttribute(archiveAttr);
    136     if (!archive.isNull()) {
    137         paramNames.append("archive");
    138         paramValues.append(archive.string());
    139     }
    140 
    141     const AtomicString& code = getAttribute(codeAttr);
    142     paramNames.append("code");
    143     paramValues.append(code.string());
    144 
    145     // If the 'codebase' attribute is set, it serves as a relative root for the file that the Java
    146     // plugin will load. If the 'code' attribute is set, and the 'archive' is not set, then we need
    147     // to check the url generated by resolving 'code' against 'codebase'. If the 'archive'
    148     // attribute is set, then 'code' points to a class inside the archive, so we need to check the
    149     // url generated by resolving 'archive' against 'codebase'.
    150     KURL urlToCheck;
    151     KURL rootURL = codeBase.isNull() ? document().url() : document().completeURL(codeBase);
    152     if (!archive.isNull())
    153         urlToCheck = KURL(rootURL, archive);
    154     else if (!code.isNull())
    155         urlToCheck = KURL(rootURL, code);
    156     if (!canEmbedURL(urlToCheck))
    157         return;
    158 
    159     const AtomicString& name = document().isHTMLDocument() ? getNameAttribute() : getIdAttribute();
    160     if (!name.isNull()) {
    161         paramNames.append("name");
    162         paramValues.append(name.string());
    163     }
    164 
    165     paramNames.append("baseURL");
    166     KURL baseURL = document().baseURL();
    167     paramValues.append(baseURL.string());
    168 
    169     const AtomicString& mayScript = getAttribute(mayscriptAttr);
    170     if (!mayScript.isNull()) {
    171         paramNames.append("mayScript");
    172         paramValues.append(mayScript.string());
    173     }
    174 
    175     for (HTMLParamElement* param = Traversal<HTMLParamElement>::firstChild(*this); param; param = Traversal<HTMLParamElement>::nextSibling(*param)) {
    176         if (param->name().isEmpty())
    177             continue;
    178 
    179         paramNames.append(param->name());
    180         paramValues.append(param->value());
    181     }
    182 
    183     RefPtr<Widget> widget;
    184     if (frame->loader().allowPlugins(AboutToInstantiatePlugin))
    185         widget = frame->loader().client()->createJavaAppletWidget(this, baseURL, paramNames, paramValues);
    186 
    187     if (!widget) {
    188         if (!renderer->showsUnavailablePluginIndicator())
    189             renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing);
    190         return;
    191     }
    192     document().setContainsPlugins();
    193     setWidget(widget);
    194 }
    195 
    196 bool HTMLAppletElement::canEmbedJava() const
    197 {
    198     if (document().isSandboxed(SandboxPlugins))
    199         return false;
    200 
    201     Settings* settings = document().settings();
    202     if (!settings)
    203         return false;
    204 
    205     if (!settings->javaEnabled())
    206         return false;
    207 
    208     return true;
    209 }
    210 
    211 bool HTMLAppletElement::canEmbedURL(const KURL& url) const
    212 {
    213     DEFINE_STATIC_LOCAL(String, appletMimeType, ("application/x-java-applet"));
    214 
    215     if (!document().securityOrigin()->canDisplay(url)) {
    216         FrameLoader::reportLocalLoadFailed(document().frame(), url.string());
    217         return false;
    218     }
    219 
    220     if (!document().contentSecurityPolicy()->allowObjectFromSource(url)
    221         || !document().contentSecurityPolicy()->allowPluginType(appletMimeType, appletMimeType, url)) {
    222         renderEmbeddedObject()->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy);
    223         return false;
    224     }
    225     return true;
    226 }
    227 
    228 }
    229