1/*
2 * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#if USE(PLUGIN_HOST_PROCESS)
27
28#ifndef NetscapePluginInstanceProxy_h
29#define NetscapePluginInstanceProxy_h
30
31#include <JavaScriptCore/Protect.h>
32#include <WebCore/Timer.h>
33#include <WebKit/npapi.h>
34#include <wtf/Deque.h>
35#include <wtf/HashMap.h>
36#include <wtf/PassRefPtr.h>
37#include <wtf/RefCounted.h>
38#include <wtf/RetainPtr.h>
39#include "WebKitPluginHostTypes.h"
40
41namespace WebCore {
42    class String;
43}
44
45namespace JSC {
46    namespace Bindings {
47        class Instance;
48        class RootObject;
49    }
50}
51@class WebHostedNetscapePluginView;
52@class WebFrame;
53
54namespace WebKit {
55
56class HostedNetscapePluginStream;
57class NetscapePluginHostProxy;
58class PluginRequest;
59class ProxyInstance;
60
61class NetscapePluginInstanceProxy : public RefCounted<NetscapePluginInstanceProxy> {
62public:
63    static PassRefPtr<NetscapePluginInstanceProxy> create(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView, bool fullFramePlugin)
64    {
65        return adoptRef(new NetscapePluginInstanceProxy(pluginHostProxy, pluginView, fullFramePlugin));
66    }
67    ~NetscapePluginInstanceProxy();
68
69    uint32_t pluginID() const
70    {
71        ASSERT(m_pluginID);
72
73        return m_pluginID;
74    }
75    uint32_t renderContextID() const { return m_renderContextID; }
76    void setRenderContextID(uint32_t renderContextID) { m_renderContextID = renderContextID; }
77
78    bool useSoftwareRenderer() const { return m_useSoftwareRenderer; }
79    void setUseSoftwareRenderer(bool useSoftwareRenderer) { m_useSoftwareRenderer = useSoftwareRenderer; }
80
81    WebHostedNetscapePluginView *pluginView() const { return m_pluginView; }
82    NetscapePluginHostProxy* hostProxy() const { return m_pluginHostProxy; }
83
84    bool cancelStreamLoad(uint32_t streamID, NPReason);
85    void disconnectStream(HostedNetscapePluginStream*);
86
87    void setManualStream(PassRefPtr<HostedNetscapePluginStream>);
88    HostedNetscapePluginStream* manualStream() const { return m_manualStream.get(); }
89
90    void pluginHostDied();
91
92    void resize(NSRect size, NSRect clipRect, bool sync);
93    void destroy();
94    void focusChanged(bool hasFocus);
95    void windowFocusChanged(bool hasFocus);
96    void windowFrameChanged(NSRect frame);
97
98    void mouseEvent(NSView *pluginView, NSEvent *, NPCocoaEventType);
99    void keyEvent(NSView *pluginView, NSEvent *, NPCocoaEventType);
100    void insertText(NSString *);
101    bool wheelEvent(NSView *pluginView, NSEvent *);
102    void syntheticKeyDownWithCommandModifier(int keyCode, char character);
103    void flagsChanged(NSEvent *);
104    void print(CGContextRef, unsigned width, unsigned height);
105
106    void startTimers(bool throttleTimers);
107    void stopTimers();
108
109    void invalidateRect(double x, double y, double width, double height);
110
111    // NPRuntime
112    bool getWindowNPObject(uint32_t& objectID);
113    bool getPluginElementNPObject(uint32_t& objectID);
114    void releaseObject(uint32_t objectID);
115
116    bool evaluate(uint32_t objectID, const WebCore::String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups);
117    bool invoke(uint32_t objectID, const JSC::Identifier& methodName, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
118    bool invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
119    bool construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
120    bool enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength);
121
122    bool getProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t &resultData, mach_msg_type_number_t& resultLength);
123    bool getProperty(uint32_t objectID, unsigned propertyName, data_t &resultData, mach_msg_type_number_t& resultLength);
124    bool setProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength);
125    bool setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength);
126    bool removeProperty(uint32_t objectID, const JSC::Identifier& propertyName);
127    bool removeProperty(uint32_t objectID, unsigned propertyName);
128    bool hasProperty(uint32_t objectID, const JSC::Identifier& propertyName);
129    bool hasProperty(uint32_t objectID, unsigned propertyName);
130    bool hasMethod(uint32_t objectID, const JSC::Identifier& methodName);
131
132    void status(const char* message);
133    NPError loadURL(const char* url, const char* target, const char* postData, uint32_t postDataLength, LoadURLFlags, uint32_t& requestID);
134
135    bool getCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t& cookiesData, mach_msg_type_number_t& cookiesLength);
136    bool setCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t cookiesData, mach_msg_type_number_t cookiesLength);
137
138    bool getProxy(data_t urlData, mach_msg_type_number_t urlLength, data_t& proxyData, mach_msg_type_number_t& proxyLength);
139    bool getAuthenticationInfo(data_t protocolData, data_t hostData, uint32_t port, data_t schemeData, data_t realmData,
140                               data_t& usernameData, mach_msg_type_number_t& usernameLength, data_t& passwordData, mach_msg_type_number_t& passwordLength);
141    bool convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
142                      double& destX, double& destY, NPCoordinateSpace destSpace);
143
144    PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>);
145    RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args);
146    void marshalValue(JSC::ExecState*, JSC::JSValue value, data_t& resultData, mach_msg_type_number_t& resultLength);
147    JSC::JSValue demarshalValue(JSC::ExecState*, const char* valueData, mach_msg_type_number_t valueLength);
148
149    void addInstance(ProxyInstance*);
150    void removeInstance(ProxyInstance*);
151
152    void cleanup();
153    void invalidate();
154
155    void willCallPluginFunction();
156    void didCallPluginFunction();
157    bool shouldStop();
158
159    uint32_t nextRequestID();
160
161    uint32_t checkIfAllowedToLoadURL(const char* url, const char* target);
162    void cancelCheckIfAllowedToLoadURL(uint32_t checkID);
163    void checkIfAllowedToLoadURLResult(uint32_t checkID, bool allowed);
164
165    void resolveURL(const char* url, const char* target, data_t& resolvedURLData, mach_msg_type_number_t& resolvedURLLength);
166
167    void didDraw();
168    void privateBrowsingModeDidChange(bool isPrivateBrowsingEnabled);
169
170    static void setGlobalException(const WebCore::String&);
171    static void moveGlobalExceptionToExecState(JSC::ExecState*);
172
173    // Reply structs
174    struct Reply {
175        enum Type {
176            InstantiatePlugin,
177            GetScriptableNPObject,
178            BooleanAndData,
179            Boolean
180        };
181
182        Reply(Type type)
183            : m_type(type)
184        {
185        }
186
187        virtual ~Reply() { }
188
189        Type m_type;
190    };
191
192    struct InstantiatePluginReply : public Reply {
193        static const int ReplyType = InstantiatePlugin;
194
195        InstantiatePluginReply(kern_return_t resultCode, uint32_t renderContextID, boolean_t useSoftwareRenderer)
196            : Reply(InstantiatePlugin)
197            , m_resultCode(resultCode)
198            , m_renderContextID(renderContextID)
199            , m_useSoftwareRenderer(useSoftwareRenderer)
200        {
201        }
202
203        kern_return_t m_resultCode;
204        uint32_t m_renderContextID;
205        boolean_t m_useSoftwareRenderer;
206    };
207
208    struct GetScriptableNPObjectReply : public Reply {
209        static const Reply::Type ReplyType = GetScriptableNPObject;
210
211        GetScriptableNPObjectReply(uint32_t objectID)
212            : Reply(ReplyType)
213            , m_objectID(objectID)
214        {
215        }
216
217        uint32_t m_objectID;
218    };
219
220    struct BooleanReply : public Reply {
221        static const Reply::Type ReplyType = Boolean;
222
223        BooleanReply(boolean_t result)
224            : Reply(ReplyType)
225            , m_result(result)
226        {
227        }
228
229        boolean_t m_result;
230    };
231
232    struct BooleanAndDataReply : public Reply {
233        static const Reply::Type ReplyType = BooleanAndData;
234
235        BooleanAndDataReply(boolean_t returnValue, RetainPtr<CFDataRef> result)
236            : Reply(ReplyType)
237            , m_returnValue(returnValue)
238            , m_result(result)
239        {
240        }
241
242        boolean_t m_returnValue;
243        RetainPtr<CFDataRef> m_result;
244    };
245
246    void setCurrentReply(uint32_t requestID, Reply* reply)
247    {
248        ASSERT(!m_replies.contains(requestID));
249        m_replies.set(requestID, reply);
250    }
251
252    template <typename T>
253    std::auto_ptr<T> waitForReply(uint32_t requestID)
254    {
255        willCallPluginFunction();
256
257        m_waitingForReply = true;
258
259        Reply* reply = processRequestsAndWaitForReply(requestID);
260        if (reply)
261            ASSERT(reply->m_type == T::ReplyType);
262
263        m_waitingForReply = false;
264
265        didCallPluginFunction();
266
267        return std::auto_ptr<T>(static_cast<T*>(reply));
268    }
269
270    void webFrameDidFinishLoadWithReason(WebFrame*, NPReason);
271
272private:
273    NetscapePluginInstanceProxy(NetscapePluginHostProxy*, WebHostedNetscapePluginView*, bool fullFramePlugin);
274
275    NPError loadRequest(NSURLRequest*, const char* cTarget, bool currentEventIsUserGesture, uint32_t& streamID);
276
277    class PluginRequest;
278    void performRequest(PluginRequest*);
279    void evaluateJavaScript(PluginRequest*);
280
281    void stopAllStreams();
282    Reply* processRequestsAndWaitForReply(uint32_t requestID);
283
284    NetscapePluginHostProxy* m_pluginHostProxy;
285    WebHostedNetscapePluginView *m_pluginView;
286
287    void requestTimerFired(WebCore::Timer<NetscapePluginInstanceProxy>*);
288    WebCore::Timer<NetscapePluginInstanceProxy> m_requestTimer;
289    Deque<RefPtr<PluginRequest> > m_pluginRequests;
290
291    HashMap<uint32_t, RefPtr<HostedNetscapePluginStream> > m_streams;
292
293    uint32_t m_currentURLRequestID;
294
295    uint32_t m_pluginID;
296    uint32_t m_renderContextID;
297    boolean_t m_useSoftwareRenderer;
298
299    bool m_waitingForReply;
300    HashMap<uint32_t, Reply*> m_replies;
301
302    // NPRuntime
303    uint32_t idForObject(JSC::JSObject*);
304
305    void addValueToArray(NSMutableArray *, JSC::ExecState* exec, JSC::JSValue value);
306
307    bool demarshalValueFromArray(JSC::ExecState*, NSArray *array, NSUInteger& index, JSC::JSValue& result);
308    void demarshalValues(JSC::ExecState*, data_t valuesData, mach_msg_type_number_t valuesLength, JSC::MarkedArgumentBuffer& result);
309
310    uint32_t m_objectIDCounter;
311    typedef HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> > ObjectMap;
312    ObjectMap m_objects;
313
314    typedef HashSet<ProxyInstance*> ProxyInstanceSet;
315    ProxyInstanceSet m_instances;
316
317    uint32_t m_urlCheckCounter;
318    typedef HashMap<uint32_t, RetainPtr<id> > URLCheckMap;
319    URLCheckMap m_urlChecks;
320
321    unsigned m_pluginFunctionCallDepth;
322    bool m_shouldStopSoon;
323    uint32_t m_currentRequestID;
324    bool m_inDestroy;
325    bool m_pluginIsWaitingForDraw;
326
327    RefPtr<HostedNetscapePluginStream> m_manualStream;
328
329    typedef HashMap<WebFrame*, RefPtr<PluginRequest> > FrameLoadMap;
330    FrameLoadMap m_pendingFrameLoads;
331};
332
333} // namespace WebKit
334
335#endif // NetscapePluginInstanceProxy_h
336#endif // USE(PLUGIN_HOST_PROCESS)
337