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