18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLPlugInImageElement.h"
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoader.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoaderClient.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLImageLoader.h"
282bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "HTMLNames.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Image.h"
305abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick#include "Page.h"
315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "RenderEmbeddedObject.h"
325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "RenderImage.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
362bde8e466a4451c7319e3a072d118917957d6554Steve BlockHTMLPlugInImageElement::HTMLPlugInImageElement(const QualifiedName& tagName, Document* document, bool createdByParser, PreferPlugInsForImagesOption preferPlugInsForImagesOption)
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : HTMLPlugInElement(tagName, document)
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // m_needsWidgetUpdate(!createdByParser) allows HTMLObjectElement to delay
395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // widget updates until after all children are parsed.  For HTMLEmbedElement
405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // this delay is unnecessary, but it is simpler to make both classes share
415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // the same codepath in this class.
425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    , m_needsWidgetUpdate(!createdByParser)
432bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPreferPlugInsForImages)
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenRenderEmbeddedObject* HTMLPlugInImageElement::renderEmbeddedObject() const
485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // HTMLObjectElement and HTMLEmbedElement may return arbitrary renderers
505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // when using fallback content.
515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!renderer() || !renderer()->isEmbeddedObject())
525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 0;
535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return toRenderEmbeddedObject(renderer());
545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool HTMLPlugInImageElement::isImageType()
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_serviceType.isEmpty() && protocolIs(m_url, "data"))
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_serviceType = mimeTypeFromDataURL(m_url);
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Frame* frame = document()->frame()) {
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        KURL completedURL = frame->loader()->completeURL(m_url);
632bde8e466a4451c7319e3a072d118917957d6554Steve Block        return frame->loader()->client()->objectContentType(completedURL, m_serviceType, shouldPreferPlugInsForImages()) == ObjectContentImage;
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Image::supportsType(m_serviceType);
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
695abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick// We don't use m_url, as it may not be the final URL that the object loads,
705abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick// depending on <param> values.
715abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickbool HTMLPlugInImageElement::allowedToLoadFrameURL(const String& url)
725abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
735abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ASSERT(document());
745abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ASSERT(document()->frame());
755abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (document()->frame()->page()->frameCount() >= Page::maxNumberOfFrames)
765abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return false;
775abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
785abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    // We allow one level of self-reference because some sites depend on that.
795abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    // But we don't allow more than one.
805abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    KURL completeURL = document()->completeURL(url);
815abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    bool foundSelfReference = false;
825abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    for (Frame* frame = document()->frame(); frame; frame = frame->tree()->parent()) {
832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (equalIgnoringFragmentIdentifier(frame->document()->url(), completeURL)) {
845abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            if (foundSelfReference)
855abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                return false;
865abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            foundSelfReference = true;
875abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        }
885abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    }
895abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    return true;
905abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
915abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
925abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick// We don't use m_url, or m_serviceType as they may not be the final values
935abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick// that <object> uses depending on <param> values.
945abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickbool HTMLPlugInImageElement::wouldLoadAsNetscapePlugin(const String& url, const String& serviceType)
955abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
965abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ASSERT(document());
975abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ASSERT(document()->frame());
985abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    FrameLoader* frameLoader = document()->frame()->loader();
995abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ASSERT(frameLoader);
1005abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    KURL completedURL;
1015abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (!url.isEmpty())
1025abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        completedURL = frameLoader->completeURL(url);
1035abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
1042bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (frameLoader->client()->objectContentType(completedURL, serviceType, shouldPreferPlugInsForImages()) == ObjectContentNetscapePlugin)
1055abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return true;
1065abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    return false;
1075abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
1085abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
1095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenRenderObject* HTMLPlugInImageElement::createRenderer(RenderArena* arena, RenderStyle* style)
1105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // Fallback content breaks the DOM->Renderer class relationship of this
1125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // class and all superclasses because createObject won't necessarily
1135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // return a RenderEmbeddedObject, RenderPart or even RenderWidget.
1145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (useFallbackContent())
1155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return RenderObject::createObject(this, style);
1165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (isImageType()) {
1175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        RenderImage* image = new (arena) RenderImage(this);
1185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        image->setImageResource(RenderImageResource::create());
1195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return image;
1205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
1215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return new (arena) RenderEmbeddedObject(this);
1225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid HTMLPlugInImageElement::recalcStyle(StyleChange ch)
1255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // FIXME: Why is this necessary?  Manual re-attach is almost always wrong.
1275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!useFallbackContent() && needsWidgetUpdate() && renderer() && !isImageType()) {
1285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        detach();
1295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        attach();
1305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
1315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    HTMLPlugInElement::recalcStyle(ch);
1325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid HTMLPlugInImageElement::attach()
1355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    bool isImage = isImageType();
1375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!isImage)
1395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        queuePostAttachCallback(&HTMLPlugInImageElement::updateWidgetCallback, this);
1405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    HTMLPlugInElement::attach();
1425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (isImage && renderer() && !useFallbackContent()) {
1445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (!m_imageLoader)
1455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            m_imageLoader = adoptPtr(new HTMLImageLoader(this));
1465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        m_imageLoader->updateFromElement();
1475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
1485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid HTMLPlugInImageElement::detach()
1515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1525abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    // FIXME: Because of the insanity that is HTMLPlugInImageElement::recalcStyle,
1535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // we can end up detaching during an attach() call, before we even have a
1545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // renderer.  In that case, don't mark the widget for update.
1555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (attached() && renderer() && !useFallbackContent())
1565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        // Update the widget the next time we attach (detaching destroys the plugin).
1575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        setNeedsWidgetUpdate(true);
1585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    HTMLPlugInElement::detach();
1595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1615abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickvoid HTMLPlugInImageElement::updateWidgetIfNecessary()
1625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    document()->updateStyleIfNeeded();
1645abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
1655abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (!needsWidgetUpdate() || useFallbackContent() || isImageType())
1665abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return;
1675abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
1685abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (!renderEmbeddedObject() || renderEmbeddedObject()->pluginCrashedOrWasMissing())
1695abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return;
1705abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    updateWidget(CreateOnlyNonNetscapePlugins);
1725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid HTMLPlugInImageElement::finishParsingChildren()
1755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    HTMLPlugInElement::finishParsingChildren();
1775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (useFallbackContent())
1785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return;
1795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    setNeedsWidgetUpdate(true);
1815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (inDocument())
1825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        setNeedsStyleRecalc();
1835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid HTMLPlugInImageElement::willMoveToNewOwnerDocument()
186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
187dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_imageLoader)
188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_imageLoader->elementWillMoveToNewOwnerDocument();
189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    HTMLPlugInElement::willMoveToNewOwnerDocument();
190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid HTMLPlugInImageElement::updateWidgetCallback(Node* n)
1935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1945abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    static_cast<HTMLPlugInImageElement*>(n)->updateWidgetIfNecessary();
1955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
198