1/*
2 * Copyright (C) 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#ifndef HTMLPlugInImageElement_h
22#define HTMLPlugInImageElement_h
23
24#include "HTMLPlugInElement.h"
25
26#include "RenderStyle.h"
27#include <wtf/OwnPtr.h>
28#include <wtf/RefPtr.h>
29
30namespace WebCore {
31
32class HTMLImageLoader;
33class FrameLoader;
34class Image;
35class MouseEvent;
36class Widget;
37
38enum PluginCreationOption {
39    CreateAnyWidgetType,
40    CreateOnlyNonNetscapePlugins,
41};
42
43enum PreferPlugInsForImagesOption {
44    ShouldPreferPlugInsForImages,
45    ShouldNotPreferPlugInsForImages
46};
47
48// Base class for HTMLObjectElement and HTMLEmbedElement
49class HTMLPlugInImageElement : public HTMLPlugInElement {
50public:
51    virtual ~HTMLPlugInImageElement();
52
53    RenderEmbeddedObject* renderEmbeddedObject() const;
54
55    virtual void setDisplayState(DisplayState) OVERRIDE;
56
57    virtual void updateWidget(PluginCreationOption) = 0;
58
59    const String& serviceType() const { return m_serviceType; }
60    const String& url() const { return m_url; }
61    const KURL& loadedUrl() const { return m_loadedUrl; }
62
63    const String loadedMimeType() const
64    {
65        String mimeType = serviceType();
66        if (mimeType.isEmpty())
67            mimeType = mimeTypeFromURL(m_loadedUrl);
68        return mimeType;
69    }
70
71    bool shouldPreferPlugInsForImages() const { return m_shouldPreferPlugInsForImages; }
72
73    // Public for FrameView::addWidgetToUpdate()
74    bool needsWidgetUpdate() const { return m_needsWidgetUpdate; }
75    void setNeedsWidgetUpdate(bool needsWidgetUpdate) { m_needsWidgetUpdate = needsWidgetUpdate; }
76
77    void userDidClickSnapshot(PassRefPtr<MouseEvent>, bool forwardEvent);
78    void checkSnapshotStatus();
79    Image* snapshotImage() const { return m_snapshotImage.get(); }
80    void restartSnapshottedPlugIn();
81
82    // Plug-in URL might not be the same as url() with overriding parameters.
83    void subframeLoaderWillCreatePlugIn(const KURL& plugInURL);
84    void subframeLoaderDidCreatePlugIn(const Widget*);
85
86    void setIsPrimarySnapshottedPlugIn(bool);
87    bool partOfSnapshotOverlay(Node*);
88
89    bool needsCheckForSizeChange() const { return m_needsCheckForSizeChange; }
90    void setNeedsCheckForSizeChange() { m_needsCheckForSizeChange = true; }
91    void checkSizeChangeForSnapshotting();
92
93    enum SnapshotDecision {
94        SnapshotNotYetDecided,
95        NeverSnapshot,
96        Snapshotted,
97        MaySnapshotWhenResized,
98        MaySnapshotWhenContentIsSet
99    };
100    SnapshotDecision snapshotDecision() const { return m_snapshotDecision; }
101
102protected:
103    HTMLPlugInImageElement(const QualifiedName& tagName, Document*, bool createdByParser, PreferPlugInsForImagesOption);
104
105    bool isImageType();
106
107    OwnPtr<HTMLImageLoader> m_imageLoader;
108    String m_serviceType;
109    String m_url;
110    KURL m_loadedUrl;
111
112    static void updateWidgetCallback(Node*, unsigned = 0);
113    virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
114    virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
115
116    bool allowedToLoadFrameURL(const String& url);
117    bool wouldLoadAsNetscapePlugin(const String& url, const String& serviceType);
118
119    virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE;
120
121    virtual void documentWillSuspendForPageCache() OVERRIDE;
122    virtual void documentDidResumeFromPageCache() OVERRIDE;
123
124    virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
125
126    virtual bool isRestartedPlugin() const OVERRIDE { return m_isRestartedPlugin; }
127
128private:
129    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
130    virtual bool willRecalcStyle(StyleChange) OVERRIDE;
131
132    void didAddUserAgentShadowRoot(ShadowRoot*) OVERRIDE;
133
134    virtual void finishParsingChildren() OVERRIDE;
135
136    void updateWidgetIfNecessary();
137
138    virtual void updateSnapshot(PassRefPtr<Image>) OVERRIDE;
139    virtual void dispatchPendingMouseClick() OVERRIDE;
140    void simulatedMouseClickTimerFired(DeferrableOneShotTimer<HTMLPlugInImageElement>*);
141
142    void swapRendererTimerFired(Timer<HTMLPlugInImageElement>*);
143
144    void restartSimilarPlugIns();
145
146    virtual bool isPlugInImageElement() const OVERRIDE { return true; }
147
148    void removeSnapshotTimerFired(Timer<HTMLPlugInImageElement>*);
149
150    virtual void defaultEventHandler(Event*) OVERRIDE;
151
152    bool m_needsWidgetUpdate;
153    bool m_shouldPreferPlugInsForImages;
154    bool m_needsDocumentActivationCallbacks;
155    RefPtr<RenderStyle> m_customStyleForPageCache;
156    RefPtr<MouseEvent> m_pendingClickEventFromSnapshot;
157    DeferrableOneShotTimer<HTMLPlugInImageElement> m_simulatedMouseClickTimer;
158    Timer<HTMLPlugInImageElement> m_swapRendererTimer;
159    Timer<HTMLPlugInImageElement> m_removeSnapshotTimer;
160    RefPtr<Image> m_snapshotImage;
161    bool m_createdDuringUserGesture;
162    bool m_isRestartedPlugin;
163    bool m_needsCheckForSizeChange;
164    bool m_plugInWasCreated;
165    bool m_deferredPromotionToPrimaryPlugIn;
166    IntSize m_sizeWhenSnapshotted;
167    SnapshotDecision m_snapshotDecision;
168};
169
170inline HTMLPlugInImageElement* toHTMLPlugInImageElement(Node* node)
171{
172    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isPluginElement());
173    HTMLPlugInElement* plugInElement = static_cast<HTMLPlugInElement*>(node);
174    ASSERT_WITH_SECURITY_IMPLICATION(plugInElement->isPlugInImageElement());
175    return static_cast<HTMLPlugInImageElement*>(plugInElement);
176}
177
178inline const HTMLPlugInImageElement* toHTMLPlugInImageElement(const Node* node)
179{
180    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isPluginElement());
181    const HTMLPlugInElement* plugInElement = static_cast<const HTMLPlugInElement*>(node);
182    ASSERT_WITH_SECURITY_IMPLICATION(plugInElement->isPlugInImageElement());
183    return static_cast<const HTMLPlugInImageElement*>(plugInElement);
184}
185
186// This will catch anyone doing an unnecessary cast.
187void toHTMLPlugInImageElement(const HTMLPlugInImageElement*);
188
189} // namespace WebCore
190
191#endif // HTMLPlugInImageElement_h
192