1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 *           (C) 2000 Stefan Schimanski (1Stein@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 "HTMLAppletElement.h"
26
27#include "Attribute.h"
28#include "Frame.h"
29#include "FrameLoader.h"
30#include "HTMLDocument.h"
31#include "HTMLNames.h"
32#include "HTMLParamElement.h"
33#include "RenderApplet.h"
34#include "SecurityOrigin.h"
35#include "Settings.h"
36#include "Widget.h"
37
38namespace WebCore {
39
40using namespace HTMLNames;
41
42HTMLAppletElement::HTMLAppletElement(const QualifiedName& tagName, Document* document, bool createdByParser)
43    : HTMLPlugInImageElement(tagName, document, createdByParser, ShouldNotPreferPlugInsForImages)
44{
45    ASSERT(hasTagName(appletTag));
46
47    m_serviceType = "application/x-java-applet";
48}
49
50PassRefPtr<HTMLAppletElement> HTMLAppletElement::create(const QualifiedName& tagName, Document* document, bool createdByParser)
51{
52    return adoptRef(new HTMLAppletElement(tagName, document, createdByParser));
53}
54
55void HTMLAppletElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
56{
57    if (name == altAttr
58        || name == archiveAttr
59        || name == codeAttr
60        || name == codebaseAttr
61        || name == mayscriptAttr
62        || name == objectAttr) {
63        // Do nothing.
64        return;
65    }
66
67    HTMLPlugInImageElement::parseAttribute(name, value);
68}
69
70bool HTMLAppletElement::rendererIsNeeded(const NodeRenderingContext& context)
71{
72    if (!fastHasAttribute(codeAttr))
73        return false;
74    return HTMLPlugInImageElement::rendererIsNeeded(context);
75}
76
77RenderObject* HTMLAppletElement::createRenderer(RenderArena*, RenderStyle* style)
78{
79    if (!canEmbedJava())
80        return RenderObject::createObject(this, style);
81
82    return new (document()->renderArena()) RenderApplet(this);
83}
84
85RenderWidget* HTMLAppletElement::renderWidgetForJSBindings() const
86{
87    if (!canEmbedJava())
88        return 0;
89
90    // Needs to load the plugin immediatedly because this function is called
91    // when JavaScript code accesses the plugin.
92    // FIXME: <rdar://16893708> Check if dispatching events here is safe.
93    document()->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
94    return renderPart();
95}
96
97void HTMLAppletElement::updateWidget(PluginCreationOption pluginCreationOption)
98{
99    setNeedsWidgetUpdate(false);
100    // FIXME: This should ASSERT isFinishedParsingChildren() instead.
101    if (!isFinishedParsingChildren())
102        return;
103
104    // FIXME: It's sadness that we have this special case here.
105    //        See http://trac.webkit.org/changeset/25128 and
106    //        plugins/netscape-plugin-setwindow-size.html
107    if (pluginCreationOption == CreateOnlyNonNetscapePlugins) {
108        // Ensure updateWidget() is called again during layout to create the Netscape plug-in.
109        setNeedsWidgetUpdate(true);
110        return;
111    }
112
113    RenderEmbeddedObject* renderer = renderEmbeddedObject();
114
115    LayoutUnit contentWidth = renderer->style()->width().isFixed() ? LayoutUnit(renderer->style()->width().value()) :
116        renderer->width() - renderer->borderAndPaddingWidth();
117    LayoutUnit contentHeight = renderer->style()->height().isFixed() ? LayoutUnit(renderer->style()->height().value()) :
118        renderer->height() - renderer->borderAndPaddingHeight();
119
120    Vector<String> paramNames;
121    Vector<String> paramValues;
122
123    paramNames.append("code");
124    paramValues.append(getAttribute(codeAttr).string());
125
126    const AtomicString& codeBase = getAttribute(codebaseAttr);
127    if (!codeBase.isNull()) {
128        paramNames.append("codeBase");
129        paramValues.append(codeBase.string());
130    }
131
132    const AtomicString& name = document()->isHTMLDocument() ? getNameAttribute() : getIdAttribute();
133    if (!name.isNull()) {
134        paramNames.append("name");
135        paramValues.append(name.string());
136    }
137
138    const AtomicString& archive = getAttribute(archiveAttr);
139    if (!archive.isNull()) {
140        paramNames.append("archive");
141        paramValues.append(archive.string());
142    }
143
144    paramNames.append("baseURL");
145    paramValues.append(document()->baseURL().string());
146
147    const AtomicString& mayScript = getAttribute(mayscriptAttr);
148    if (!mayScript.isNull()) {
149        paramNames.append("mayScript");
150        paramValues.append(mayScript.string());
151    }
152
153    for (Node* child = firstChild(); child; child = child->nextSibling()) {
154        if (!child->hasTagName(paramTag))
155            continue;
156
157        HTMLParamElement* param = static_cast<HTMLParamElement*>(child);
158        if (param->name().isEmpty())
159            continue;
160
161        paramNames.append(param->name());
162        paramValues.append(param->value());
163    }
164
165    Frame* frame = document()->frame();
166    ASSERT(frame);
167
168    renderer->setWidget(frame->loader()->subframeLoader()->createJavaAppletWidget(roundedIntSize(LayoutSize(contentWidth, contentHeight)), this, paramNames, paramValues));
169}
170
171bool HTMLAppletElement::canEmbedJava() const
172{
173    if (document()->isSandboxed(SandboxPlugins))
174        return false;
175
176    Settings* settings = document()->settings();
177    if (!settings)
178        return false;
179
180    if (!settings->isJavaEnabled())
181        return false;
182
183    if (document()->securityOrigin()->isLocal() && !settings->isJavaEnabledForLocalFiles())
184        return false;
185
186    return true;
187}
188
189}
190