1/*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
4 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef PluginView_h
29#define PluginView_h
30
31#include "FrameLoadRequest.h"
32#include "IntRect.h"
33#include "MediaCanStartListener.h"
34#include "PluginViewBase.h"
35#include "ResourceRequest.h"
36#include "Timer.h"
37#include <wtf/HashMap.h>
38#include <wtf/HashSet.h>
39#include <wtf/OwnPtr.h>
40#include <wtf/PassRefPtr.h>
41#include <wtf/RefPtr.h>
42#include <wtf/Vector.h>
43#include <wtf/text/CString.h>
44
45#if ENABLE(NETSCAPE_PLUGIN_API)
46#include "PluginStream.h"
47#include "npruntime_internal.h"
48#endif
49
50#if OS(WINDOWS) && PLATFORM(GTK)
51typedef struct HWND__* HWND;
52typedef HWND PlatformPluginWidget;
53#else
54typedef PlatformWidget PlatformPluginWidget;
55#endif
56#if PLATFORM(GTK)
57typedef struct _GtkSocket GtkSocket;
58#endif
59
60#if PLATFORM(X11)
61typedef unsigned long Window;
62typedef struct _XDisplay Display;
63#endif
64
65namespace JSC {
66    namespace Bindings {
67        class Instance;
68    }
69}
70
71namespace WebCore {
72    class Frame;
73    class FrameView;
74    class Image;
75    class HTMLPlugInElement;
76    class KeyboardEvent;
77    class MouseEvent;
78    class URL;
79#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
80    class PluginMessageThrottlerWin;
81#endif
82    class PluginPackage;
83    class PluginRequest;
84    class PluginStream;
85    class ResourceError;
86    class ResourceResponse;
87    class WheelEvent;
88
89    enum PluginStatus {
90        PluginStatusCanNotFindPlugin,
91        PluginStatusCanNotLoadPlugin,
92        PluginStatusLoadedSuccessfully
93    };
94
95    class PluginRequest {
96        WTF_MAKE_NONCOPYABLE(PluginRequest); WTF_MAKE_FAST_ALLOCATED;
97    public:
98        PluginRequest(const FrameLoadRequest& frameLoadRequest, bool sendNotification, void* notifyData, bool shouldAllowPopups)
99            : m_frameLoadRequest(frameLoadRequest)
100            , m_notifyData(notifyData)
101            , m_sendNotification(sendNotification)
102            , m_shouldAllowPopups(shouldAllowPopups) { }
103    public:
104        const FrameLoadRequest& frameLoadRequest() const { return m_frameLoadRequest; }
105        void* notifyData() const { return m_notifyData; }
106        bool sendNotification() const { return m_sendNotification; }
107        bool shouldAllowPopups() const { return m_shouldAllowPopups; }
108    private:
109        FrameLoadRequest m_frameLoadRequest;
110        void* m_notifyData;
111        bool m_sendNotification;
112        bool m_shouldAllowPopups;
113    };
114
115    class PluginManualLoader {
116    public:
117        virtual ~PluginManualLoader() {}
118        virtual void didReceiveResponse(const ResourceResponse&) = 0;
119        virtual void didReceiveData(const char*, int) = 0;
120        virtual void didFinishLoading() = 0;
121        virtual void didFail(const ResourceError&) = 0;
122    };
123
124    class PluginView : public PluginViewBase
125#if ENABLE(NETSCAPE_PLUGIN_API)
126                     , private PluginStreamClient
127#endif
128                     , public PluginManualLoader
129                     , private MediaCanStartListener {
130    public:
131        static PassRefPtr<PluginView> create(Frame* parentFrame, const IntSize&, HTMLPlugInElement*, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
132        virtual ~PluginView();
133
134        PluginPackage* plugin() const { return m_plugin.get(); }
135#if ENABLE(NETSCAPE_PLUGIN_API)
136        NPP instance() const { return m_instance; }
137#endif
138
139        void setNPWindowRect(const IntRect&);
140        static PluginView* currentPluginView();
141
142#if ENABLE(NETSCAPE_PLUGIN_API)
143        NPObject* npObject();
144#endif
145        PassRefPtr<JSC::Bindings::Instance> bindingInstance();
146
147        PluginStatus status() const { return m_status; }
148
149#if ENABLE(NETSCAPE_PLUGIN_API)
150        // NPN functions
151        NPError getURLNotify(const char* url, const char* target, void* notifyData);
152        NPError getURL(const char* url, const char* target);
153        NPError postURLNotify(const char* url, const char* target, uint32_t len, const char* but, NPBool file, void* notifyData);
154        NPError postURL(const char* url, const char* target, uint32_t len, const char* but, NPBool file);
155        NPError newStream(NPMIMEType type, const char* target, NPStream** stream);
156        int32_t write(NPStream* stream, int32_t len, void* buffer);
157        NPError destroyStream(NPStream* stream, NPReason reason);
158#endif
159        const char* userAgent();
160#if ENABLE(NETSCAPE_PLUGIN_API)
161        static const char* userAgentStatic();
162#endif
163        void status(const char* message);
164
165#if ENABLE(NETSCAPE_PLUGIN_API)
166        NPError getValue(NPNVariable variable, void* value);
167        static NPError getValueStatic(NPNVariable variable, void* value);
168        NPError setValue(NPPVariable variable, void* value);
169        NPError getValueForURL(NPNURLVariable variable, const char* url, char** value, uint32_t* len);
170        NPError setValueForURL(NPNURLVariable variable, const char* url, const char* value, uint32_t len);
171        NPError getAuthenticationInfo(const char* protocol, const char* host, int32_t port, const char* scheme, const char* realm, char** username, uint32_t* ulen, char** password, uint32_t* plen);
172        void invalidateRect(NPRect*);
173        void invalidateRegion(NPRegion);
174#endif
175        void forceRedraw();
176        void pushPopupsEnabledState(bool state);
177        void popPopupsEnabledState();
178
179        virtual void invalidateRect(const IntRect&);
180
181        bool arePopupsAllowed() const;
182
183        void setJavaScriptPaused(bool);
184
185        void privateBrowsingStateChanged(bool);
186
187        void disconnectStream(PluginStream*);
188        void streamDidFinishLoading(PluginStream* stream) { disconnectStream(stream); }
189
190        // Widget functions
191        virtual void setFrameRect(const IntRect&);
192        virtual void frameRectsChanged();
193        virtual void setFocus(bool);
194        virtual void show();
195        virtual void hide();
196        virtual void paint(GraphicsContext*, const IntRect&);
197        virtual void clipRectChanged() override;
198
199        // This method is used by plugins on all platforms to obtain a clip rect that includes clips set by WebCore,
200        // e.g., in overflow:auto sections.  The clip rects coordinates are in the containing window's coordinate space.
201        // This clip includes any clips that the widget itself sets up for its children.
202        IntRect windowClipRect() const;
203
204        virtual void handleEvent(Event*);
205        virtual void setParent(ScrollView*);
206        virtual void setParentVisible(bool);
207
208        virtual bool isPluginView() const override { return true; }
209
210        Frame* parentFrame() const { return m_parentFrame.get(); }
211
212        void focusPluginElement();
213
214        const String& pluginsPage() const { return m_pluginsPage; }
215        const String& mimeType() const { return m_mimeType; }
216        const URL& url() const { return m_url; }
217
218#if defined(XP_MACOSX) && ENABLE(NETSCAPE_PLUGIN_API)
219        bool popUpContextMenu(NPMenu*);
220#endif
221
222#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
223        static LRESULT CALLBACK PluginViewWndProc(HWND, UINT, WPARAM, LPARAM);
224        LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
225        WNDPROC pluginWndProc() const { return m_pluginWndProc; }
226#endif
227
228        // Used for manual loading
229        void didReceiveResponse(const ResourceResponse&);
230        void didReceiveData(const char*, int);
231        void didFinishLoading();
232        void didFail(const ResourceError&);
233
234        static bool isCallingPlugin();
235
236        bool start();
237
238#if ENABLE(NETSCAPE_PLUGIN_API)
239        static void keepAlive(NPP);
240#endif
241        void keepAlive();
242
243#if PLATFORM(X11)
244        static Display* getPluginDisplay(Frame*);
245        static Window getRootWindow(Frame* parentFrame);
246#endif
247
248    private:
249        PluginView(Frame* parentFrame, const IntSize&, PluginPackage*, HTMLPlugInElement*, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
250
251        void setParameters(const Vector<String>& paramNames, const Vector<String>& paramValues);
252        bool startOrAddToUnstartedList();
253        void init();
254        bool platformStart();
255        void stop();
256        void platformDestroy();
257        static void setCurrentPluginView(PluginView*);
258#if ENABLE(NETSCAPE_PLUGIN_API)
259        NPError load(const FrameLoadRequest&, bool sendNotification, void* notifyData);
260        NPError handlePost(const char* url, const char* target, uint32_t len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders);
261        NPError handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf);
262#endif
263        static void freeStringArray(char** stringArray, int length);
264        void setCallingPlugin(bool) const;
265
266        void invalidateWindowlessPluginRect(const IntRect&);
267
268        virtual void mediaCanStart();
269
270#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
271        void paintWindowedPluginIntoContext(GraphicsContext*, const IntRect&);
272        static HDC WINAPI hookedBeginPaint(HWND, PAINTSTRUCT*);
273        static BOOL WINAPI hookedEndPaint(HWND, const PAINTSTRUCT*);
274#endif
275
276#if ENABLE(NETSCAPE_PLUGIN_API)
277        static bool platformGetValueStatic(NPNVariable variable, void* value, NPError* result);
278        bool platformGetValue(NPNVariable variable, void* value, NPError* result);
279#endif
280
281        RefPtr<Frame> m_parentFrame;
282        RefPtr<PluginPackage> m_plugin;
283        HTMLPlugInElement* m_element;
284        bool m_isStarted;
285        URL m_url;
286        PluginStatus m_status;
287        Vector<IntRect> m_invalidRects;
288
289        void performRequest(PluginRequest*);
290        void scheduleRequest(PassOwnPtr<PluginRequest>);
291        void requestTimerFired(Timer<PluginView>*);
292        void invalidateTimerFired(Timer<PluginView>*);
293        Timer<PluginView> m_requestTimer;
294        Timer<PluginView> m_invalidateTimer;
295
296        void popPopupsStateTimerFired(Timer<PluginView>*);
297        Timer<PluginView> m_popPopupsStateTimer;
298
299        void lifeSupportTimerFired(Timer<PluginView>*);
300        Timer<PluginView> m_lifeSupportTimer;
301
302#if ENABLE(NETSCAPE_PLUGIN_API)
303        bool dispatchNPEvent(NPEvent&);
304#endif
305#if defined(XP_MACOSX) && ENABLE(NETSCAPE_PLUGIN_API)
306        int16_t dispatchNPCocoaEvent(NPCocoaEvent&);
307        bool m_updatedCocoaTextInputRequested;
308        bool m_keyDownSent;
309        uint16_t m_disregardKeyUpCounter;
310#endif
311
312#if defined(XP_MACOSX)
313        void handleWheelEvent(WheelEvent*);
314#endif
315        void updatePluginWidget();
316        void paintMissingPluginIcon(GraphicsContext*, const IntRect&);
317
318        void handleKeyboardEvent(KeyboardEvent*);
319        void handleMouseEvent(MouseEvent*);
320#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
321        void handleFocusInEvent();
322        void handleFocusOutEvent();
323#endif
324
325#if OS(WINDOWS)
326        void paintIntoTransformedContext(HDC);
327        PassRefPtr<Image> snapshot();
328#endif
329
330        int m_mode;
331        int m_paramCount;
332        char** m_paramNames;
333        char** m_paramValues;
334        String m_pluginsPage;
335
336        String m_mimeType;
337        WTF::CString m_userAgent;
338
339#if ENABLE(NETSCAPE_PLUGIN_API)
340        NPP m_instance;
341        NPP_t m_instanceStruct;
342        NPWindow m_npWindow;
343#endif
344
345        Vector<bool, 4> m_popupStateStack;
346
347        HashSet<RefPtr<PluginStream> > m_streams;
348        Vector<OwnPtr<PluginRequest> > m_requests;
349
350        bool m_isWindowed;
351        bool m_isTransparent;
352        bool m_haveInitialized;
353        bool m_isWaitingToStart;
354
355#if defined(XP_UNIX)
356        bool m_needsXEmbed;
357#endif
358
359#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
360        OwnPtr<PluginMessageThrottlerWin> m_messageThrottler;
361        WNDPROC m_pluginWndProc;
362        unsigned m_lastMessage;
363        bool m_isCallingPluginWndProc;
364        HDC m_wmPrintHDC;
365        bool m_haveUpdatedPluginWidget;
366#endif
367
368#if (PLATFORM(GTK) && OS(WINDOWS)) || PLATFORM(EFL)
369        // On Mac OSX and Qt/Windows the plugin does not have its own native widget,
370        // but is using the containing window as its reference for positioning/painting.
371        PlatformPluginWidget m_window;
372public:
373        PlatformPluginWidget platformPluginWidget() const { return m_window; }
374        void setPlatformPluginWidget(PlatformPluginWidget widget) { m_window = widget; }
375#else
376public:
377        void setPlatformPluginWidget(PlatformPluginWidget widget) { setPlatformWidget(widget); }
378        PlatformPluginWidget platformPluginWidget() const { return platformWidget(); }
379#endif
380
381private:
382
383#if defined(XP_UNIX) || PLATFORM(GTK)
384        void setNPWindowIfNeeded();
385#elif defined(XP_MACOSX)
386        NP_CGContext m_npCgContext;
387        CGContextRef m_contextRef;
388
389        void setNPWindowIfNeeded();
390#endif
391
392#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
393        bool m_hasPendingGeometryChange;
394        Pixmap m_drawable;
395        Visual* m_visual;
396        Colormap m_colormap;
397        Display* m_pluginDisplay;
398
399        void initXEvent(XEvent* event);
400#endif
401
402#if PLATFORM(GTK)
403        static gboolean plugRemovedCallback(GtkSocket*, PluginView*);
404        static void plugAddedCallback(GtkSocket*, PluginView*);
405        void updateWidgetAllocationAndClip();
406        bool m_plugAdded;
407        IntRect m_delayedAllocation;
408#endif
409
410        IntRect m_clipRect; // The clip rect to apply to a windowed plug-in
411        IntRect m_windowRect; // Our window rect.
412
413        bool m_loadManually;
414        RefPtr<PluginStream> m_manualStream;
415
416        bool m_isJavaScriptPaused;
417
418        bool m_haveCalledSetWindow;
419
420        static PluginView* s_currentPluginView;
421    };
422
423inline PluginView* toPluginView(Widget* widget)
424{
425    ASSERT(!widget || widget->isPluginView());
426    return static_cast<PluginView*>(widget);
427}
428
429inline const PluginView* toPluginView(const Widget* widget)
430{
431    ASSERT(!widget || widget->isPluginView());
432    return static_cast<const PluginView*>(widget);
433}
434
435// This will catch anyone doing an unnecessary cast.
436void toPluginView(const PluginView*);
437
438} // namespace WebCore
439
440#endif
441