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