Remove the Timer parameters from timer callbacks
[WebKit-https.git] / Source / WebKit / mac / Plugins / Hosted / NetscapePluginInstanceProxy.h
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/Identifier.h>
32 #include <JavaScriptCore/VM.h>
33 #include <JavaScriptCore/Strong.h>
34 #include <WebCore/Timer.h>
35 #include <WebKitLegacy/npapi.h>
36 #include <wtf/Deque.h>
37 #include <wtf/Forward.h>
38 #include <wtf/HashMap.h>
39 #include <wtf/PassRefPtr.h>
40 #include <wtf/RefCounted.h>
41 #include <wtf/RetainPtr.h>
42 #include "WebKitPluginHostTypes.h"
43
44 namespace JSC {
45     namespace Bindings {
46         class Instance;
47         class RootObject;
48     }
49     class ArgList;
50 }
51 @class WebHostedNetscapePluginView;
52 @class WebFrame;
53
54 namespace WebKit {
55
56 class HostedNetscapePluginStream;
57 class NetscapePluginHostProxy;
58 class PluginRequest;
59 class ProxyInstance;
60     
61 class NetscapePluginInstanceProxy : public RefCounted<NetscapePluginInstanceProxy> {
62 public:
63     static PassRefPtr<NetscapePluginInstanceProxy> create(NetscapePluginHostProxy*, WebHostedNetscapePluginView *, bool fullFramePlugin);
64     ~NetscapePluginInstanceProxy();
65     
66     uint32_t pluginID() const 
67     {
68         ASSERT(m_pluginID);
69         
70         return m_pluginID;
71     }
72     uint32_t renderContextID() const { ASSERT(fastMallocSize(this)); return m_renderContextID; }
73     void setRenderContextID(uint32_t renderContextID) { m_renderContextID = renderContextID; }
74     
75     RendererType rendererType() const { return m_rendererType; }
76     void setRendererType(RendererType rendererType) { m_rendererType = rendererType; }
77     
78     WebHostedNetscapePluginView *pluginView() const { ASSERT(fastMallocSize(this)); return m_pluginView; }
79     NetscapePluginHostProxy* hostProxy() const { ASSERT(fastMallocSize(this)); return m_pluginHostProxy; }
80     
81     bool cancelStreamLoad(uint32_t streamID, NPReason);
82     void disconnectStream(HostedNetscapePluginStream*);
83     
84     void setManualStream(PassRefPtr<HostedNetscapePluginStream>);
85     HostedNetscapePluginStream* manualStream() const { return m_manualStream.get(); }
86     
87     void pluginHostDied();
88     
89     void resize(NSRect size, NSRect clipRect);
90     void destroy();
91     void focusChanged(bool hasFocus);
92     void windowFocusChanged(bool hasFocus);
93     void windowFrameChanged(NSRect frame);
94
95     void setShouldHostLayersInWindowServer(bool);
96     void layerHostingModeChanged(bool hostsLayersInWindowServer, uint32_t renderContextID);
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     void snapshot(CGContextRef, unsigned width, unsigned height);
106     
107     void startTimers(bool throttleTimers);
108     void stopTimers();
109     
110     void invalidateRect(double x, double y, double width, double height);
111     
112     // NPRuntime
113     bool getWindowNPObject(uint32_t& objectID);
114     bool getPluginElementNPObject(uint32_t& objectID);
115     bool forgetBrowserObjectID(uint32_t objectID); // Will fail if the ID is being sent to plug-in right now (i.e., retain/release calls aren't balanced).
116
117     bool evaluate(uint32_t objectID, const WTF::String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups);
118     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);
119     bool invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
120     bool construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
121     bool enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength);
122     
123     bool getProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t &resultData, mach_msg_type_number_t& resultLength);
124     bool getProperty(uint32_t objectID, unsigned propertyName, data_t &resultData, mach_msg_type_number_t& resultLength);    
125     bool setProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength);
126     bool setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength);
127     bool removeProperty(uint32_t objectID, const JSC::Identifier& propertyName);
128     bool removeProperty(uint32_t objectID, unsigned propertyName);
129     bool hasProperty(uint32_t objectID, const JSC::Identifier& propertyName);
130     bool hasProperty(uint32_t objectID, unsigned propertyName);
131     bool hasMethod(uint32_t objectID, const JSC::Identifier& methodName);
132     
133     void status(const char* message);
134     NPError loadURL(const char* url, const char* target, const char* postData, uint32_t postDataLength, LoadURLFlags, uint32_t& requestID);
135
136     bool getCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t& cookiesData, mach_msg_type_number_t& cookiesLength);
137     bool setCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t cookiesData, mach_msg_type_number_t cookiesLength);
138              
139     bool getProxy(data_t urlData, mach_msg_type_number_t urlLength, data_t& proxyData, mach_msg_type_number_t& proxyLength);
140     bool getAuthenticationInfo(data_t protocolData, data_t hostData, uint32_t port, data_t schemeData, data_t realmData, 
141                                data_t& usernameData, mach_msg_type_number_t& usernameLength, data_t& passwordData, mach_msg_type_number_t& passwordLength);
142     bool convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, 
143                       double& destX, double& destY, NPCoordinateSpace destSpace);
144
145     PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>);
146     RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args);
147     void marshalValue(JSC::ExecState*, JSC::JSValue, data_t& resultData, mach_msg_type_number_t& resultLength);
148     JSC::JSValue demarshalValue(JSC::ExecState*, const char* valueData, mach_msg_type_number_t valueLength);
149
150     // No-op if the value does not contain a local object.
151     void retainLocalObject(JSC::JSValue);
152     void releaseLocalObject(JSC::JSValue);
153
154     void addInstance(ProxyInstance*);
155     void removeInstance(ProxyInstance*);
156     
157     void cleanup();
158     void invalidate();
159     
160     void willCallPluginFunction();
161     void didCallPluginFunction(bool& stopped);
162     bool shouldStop();
163     
164     uint32_t nextRequestID();
165     
166     uint32_t checkIfAllowedToLoadURL(const char* url, const char* target);
167     void cancelCheckIfAllowedToLoadURL(uint32_t checkID);
168     void checkIfAllowedToLoadURLResult(uint32_t checkID, bool allowed);
169
170     void resolveURL(const char* url, const char* target, data_t& resolvedURLData, mach_msg_type_number_t& resolvedURLLength);
171     
172     void didDraw();
173     void privateBrowsingModeDidChange(bool isPrivateBrowsingEnabled);
174     
175     static void setGlobalException(const WTF::String&);
176     static void moveGlobalExceptionToExecState(JSC::ExecState*);
177
178     // Reply structs
179     struct Reply {
180         enum Type {
181             InstantiatePlugin,
182             GetScriptableNPObject,
183             BooleanAndData,
184             Boolean
185         };
186         
187         Reply(Type type) 
188             : m_type(type)
189         {
190         }
191         
192         virtual ~Reply() { }
193     
194         Type m_type;
195     };
196
197     struct InstantiatePluginReply : public Reply {
198         static const int ReplyType = InstantiatePlugin;
199         
200         InstantiatePluginReply(kern_return_t resultCode, uint32_t renderContextID, RendererType rendererType)
201             : Reply(InstantiatePlugin)
202             , m_resultCode(resultCode)
203             , m_renderContextID(renderContextID)
204             , m_rendererType(rendererType)
205         {
206         }
207                  
208         kern_return_t m_resultCode;
209         uint32_t m_renderContextID;
210         RendererType m_rendererType;
211     };
212
213     struct GetScriptableNPObjectReply : public Reply {
214         static const Reply::Type ReplyType = GetScriptableNPObject;
215         
216         GetScriptableNPObjectReply(uint32_t objectID)
217             : Reply(ReplyType)
218             , m_objectID(objectID)
219         {
220         }
221             
222         uint32_t m_objectID;
223     };
224     
225     struct BooleanReply : public Reply {
226         static const Reply::Type ReplyType = Boolean;
227         
228         BooleanReply(boolean_t result)
229             : Reply(ReplyType)
230             , m_result(result)
231         {
232         }
233         
234         boolean_t m_result;
235     };
236
237     struct BooleanAndDataReply : public Reply {
238         static const Reply::Type ReplyType = BooleanAndData;
239         
240         BooleanAndDataReply(boolean_t returnValue, RetainPtr<CFDataRef> result)
241             : Reply(ReplyType)
242             , m_returnValue(returnValue)
243             , m_result(result)
244         {
245         }
246         
247         boolean_t m_returnValue;
248         RetainPtr<CFDataRef> m_result;
249     };
250     
251     void setCurrentReply(uint32_t requestID, std::unique_ptr<Reply> reply)
252     {
253         ASSERT(!m_replies.contains(requestID));
254         m_replies.add(requestID, WTF::move(reply));
255     }
256     
257     template <typename T>
258     std::unique_ptr<T> waitForReply(uint32_t requestID)
259     {
260         Ref<NetscapePluginInstanceProxy> protect(*this); // Plug-in host may crash while we are waiting for reply, releasing all instances to the instance proxy.
261
262         willCallPluginFunction();
263         m_waitingForReply = true;
264
265         auto reply = processRequestsAndWaitForReply(requestID);
266         if (reply)
267             ASSERT(reply->m_type == T::ReplyType);
268         
269         m_waitingForReply = false;
270
271         bool stopped = false;
272         didCallPluginFunction(stopped);
273         if (stopped) {
274             // The instance proxy may have been deleted from didCallPluginFunction(), so a null reply needs to be returned.
275             return nullptr;
276         }
277
278         return std::unique_ptr<T>(static_cast<T*>(reply.release()));
279     }
280     
281     void webFrameDidFinishLoadWithReason(WebFrame*, NPReason);
282
283 private:
284     NetscapePluginInstanceProxy(NetscapePluginHostProxy*, WebHostedNetscapePluginView*, bool fullFramePlugin);
285
286     NPError loadRequest(NSURLRequest*, const char* cTarget, bool currentEventIsUserGesture, uint32_t& streamID);
287     
288     class PluginRequest;
289     void performRequest(PluginRequest*);
290     void evaluateJavaScript(PluginRequest*);
291     
292     void stopAllStreams();
293     std::unique_ptr<Reply> processRequestsAndWaitForReply(uint32_t requestID);
294     
295     NetscapePluginHostProxy* m_pluginHostProxy;
296     WebHostedNetscapePluginView *m_pluginView;
297
298     void requestTimerFired();
299     WebCore::Timer m_requestTimer;
300     Deque<RefPtr<PluginRequest>> m_pluginRequests;
301     
302     HashMap<uint32_t, RefPtr<HostedNetscapePluginStream>> m_streams;
303
304     uint32_t m_currentURLRequestID;
305     
306     uint32_t m_pluginID;
307     uint32_t m_renderContextID;
308     RendererType m_rendererType;
309     
310     bool m_waitingForReply;
311     HashMap<uint32_t, std::unique_ptr<Reply>> m_replies;
312     
313     // NPRuntime
314
315     void addValueToArray(NSMutableArray *, JSC::ExecState* exec, JSC::JSValue value);
316     
317     bool demarshalValueFromArray(JSC::ExecState*, NSArray *array, NSUInteger& index, JSC::JSValue& result);
318     void demarshalValues(JSC::ExecState*, data_t valuesData, mach_msg_type_number_t valuesLength, JSC::MarkedArgumentBuffer& result);
319
320     class LocalObjectMap {
321         WTF_MAKE_NONCOPYABLE(LocalObjectMap);
322     public:
323         LocalObjectMap();
324         ~LocalObjectMap();
325         uint32_t idForObject(JSC::VM&, JSC::JSObject*);
326         void retain(JSC::JSObject*);
327         void release(JSC::JSObject*);
328         void clear();
329         bool forget(uint32_t);
330         bool contains(uint32_t) const;
331         JSC::JSObject* get(uint32_t) const;
332
333     private:
334         HashMap<uint32_t, JSC::Strong<JSC::JSObject>> m_idToJSObjectMap;
335         // The pair consists of object ID and a reference count. One reference belongs to remote plug-in,
336         // and the proxy will add transient references for arguments that are being sent out.
337         HashMap<JSC::JSObject*, std::pair<uint32_t, uint32_t>> m_jsObjectToIDMap;
338         uint32_t m_objectIDCounter;
339     };
340
341     LocalObjectMap m_localObjects;
342
343     typedef HashSet<ProxyInstance*> ProxyInstanceSet;
344     ProxyInstanceSet m_instances;
345
346     uint32_t m_urlCheckCounter;
347     typedef HashMap<uint32_t, RetainPtr<id>> URLCheckMap;
348     URLCheckMap m_urlChecks;
349     
350     unsigned m_pluginFunctionCallDepth;
351     bool m_shouldStopSoon;
352     uint32_t m_currentRequestID;
353
354     // All NPRuntime functions will return false when destroying a plug-in. This is necessary because there may be unhandled messages waiting,
355     // and spinning in processRequests() will unexpectedly execute them from inside destroy(). That's not a good time to execute arbitrary JavaScript,
356     // since both loading and rendering data structures may be in inconsistent state.
357     // This suppresses calls from all plug-ins, even those in different pages, since JS might affect the frame with plug-in that's being stopped.
358     //
359     // FIXME: Plug-ins can execute arbitrary JS from destroy() in same process case, and other browsers also support that.
360     // A better fix may be to make sure that unrelated messages are postponed until after destroy() returns.
361     // Another possible fix may be to send destroy message at a time when internal structures are consistent.
362     //
363     // FIXME: We lack similar message suppression in other cases - resize() is also triggered by layout, so executing arbitrary JS is also problematic.
364     static bool m_inDestroy;
365
366     bool m_pluginIsWaitingForDraw;
367     
368     RefPtr<HostedNetscapePluginStream> m_manualStream;
369
370     typedef HashMap<WebFrame*, RefPtr<PluginRequest>> FrameLoadMap;
371     FrameLoadMap m_pendingFrameLoads;
372 };
373     
374 } // namespace WebKit
375
376 #endif // NetscapePluginInstanceProxy_h
377 #endif // USE(PLUGIN_HOST_PROCESS)