summaryrefslogtreecommitdiffstats
path: root/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-13 16:23:25 +0100
committerBen Murdoch <benm@google.com>2011-05-16 11:35:02 +0100
commit65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch)
treef478babb801e720de7bfaee23443ffe029f58731 /Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h
parent47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff)
downloadexternal_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h')
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h372
1 files changed, 372 insertions, 0 deletions
diff --git a/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h
new file mode 100644
index 0000000..f784ade
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if USE(PLUGIN_HOST_PROCESS)
+
+#ifndef NetscapePluginInstanceProxy_h
+#define NetscapePluginInstanceProxy_h
+
+#include <JavaScriptCore/Protect.h>
+#include <WebCore/Timer.h>
+#include <WebKit/npapi.h>
+#include <wtf/Deque.h>
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include "WebKitPluginHostTypes.h"
+
+namespace JSC {
+ namespace Bindings {
+ class Instance;
+ class RootObject;
+ }
+ class ArgList;
+}
+@class WebHostedNetscapePluginView;
+@class WebFrame;
+
+namespace WebKit {
+
+class HostedNetscapePluginStream;
+class NetscapePluginHostProxy;
+class PluginRequest;
+class ProxyInstance;
+
+class NetscapePluginInstanceProxy : public RefCounted<NetscapePluginInstanceProxy> {
+public:
+ static PassRefPtr<NetscapePluginInstanceProxy> create(NetscapePluginHostProxy*, WebHostedNetscapePluginView *, bool fullFramePlugin);
+ ~NetscapePluginInstanceProxy();
+
+ uint32_t pluginID() const
+ {
+ ASSERT(m_pluginID);
+
+ return m_pluginID;
+ }
+ uint32_t renderContextID() const { ASSERT(fastMallocSize(this)); return m_renderContextID; }
+ void setRenderContextID(uint32_t renderContextID) { m_renderContextID = renderContextID; }
+
+ RendererType rendererType() const { return m_rendererType; }
+ void setRendererType(RendererType rendererType) { m_rendererType = rendererType; }
+
+ WebHostedNetscapePluginView *pluginView() const { ASSERT(fastMallocSize(this)); return m_pluginView; }
+ NetscapePluginHostProxy* hostProxy() const { ASSERT(fastMallocSize(this)); return m_pluginHostProxy; }
+
+ bool cancelStreamLoad(uint32_t streamID, NPReason);
+ void disconnectStream(HostedNetscapePluginStream*);
+
+ void setManualStream(PassRefPtr<HostedNetscapePluginStream>);
+ HostedNetscapePluginStream* manualStream() const { return m_manualStream.get(); }
+
+ void pluginHostDied();
+
+ void resize(NSRect size, NSRect clipRect);
+ void destroy();
+ void focusChanged(bool hasFocus);
+ void windowFocusChanged(bool hasFocus);
+ void windowFrameChanged(NSRect frame);
+
+ void mouseEvent(NSView *pluginView, NSEvent *, NPCocoaEventType);
+ void keyEvent(NSView *pluginView, NSEvent *, NPCocoaEventType);
+ void insertText(NSString *);
+ bool wheelEvent(NSView *pluginView, NSEvent *);
+ void syntheticKeyDownWithCommandModifier(int keyCode, char character);
+ void flagsChanged(NSEvent *);
+ void print(CGContextRef, unsigned width, unsigned height);
+ void snapshot(CGContextRef, unsigned width, unsigned height);
+
+ void startTimers(bool throttleTimers);
+ void stopTimers();
+
+ void invalidateRect(double x, double y, double width, double height);
+
+ // NPRuntime
+ bool getWindowNPObject(uint32_t& objectID);
+ bool getPluginElementNPObject(uint32_t& objectID);
+ 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).
+
+ bool evaluate(uint32_t objectID, const WTF::String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups);
+ 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);
+ bool invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
+ bool construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength);
+ bool enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength);
+
+ bool getProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t &resultData, mach_msg_type_number_t& resultLength);
+ bool getProperty(uint32_t objectID, unsigned propertyName, data_t &resultData, mach_msg_type_number_t& resultLength);
+ bool setProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength);
+ bool setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength);
+ bool removeProperty(uint32_t objectID, const JSC::Identifier& propertyName);
+ bool removeProperty(uint32_t objectID, unsigned propertyName);
+ bool hasProperty(uint32_t objectID, const JSC::Identifier& propertyName);
+ bool hasProperty(uint32_t objectID, unsigned propertyName);
+ bool hasMethod(uint32_t objectID, const JSC::Identifier& methodName);
+
+ void status(const char* message);
+ NPError loadURL(const char* url, const char* target, const char* postData, uint32_t postDataLength, LoadURLFlags, uint32_t& requestID);
+
+ bool getCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t& cookiesData, mach_msg_type_number_t& cookiesLength);
+ bool setCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t cookiesData, mach_msg_type_number_t cookiesLength);
+
+ bool getProxy(data_t urlData, mach_msg_type_number_t urlLength, data_t& proxyData, mach_msg_type_number_t& proxyLength);
+ bool getAuthenticationInfo(data_t protocolData, data_t hostData, uint32_t port, data_t schemeData, data_t realmData,
+ data_t& usernameData, mach_msg_type_number_t& usernameLength, data_t& passwordData, mach_msg_type_number_t& passwordLength);
+ bool convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
+ double& destX, double& destY, NPCoordinateSpace destSpace);
+
+ PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>);
+ RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args);
+ void marshalValue(JSC::ExecState*, JSC::JSValue, data_t& resultData, mach_msg_type_number_t& resultLength);
+ JSC::JSValue demarshalValue(JSC::ExecState*, const char* valueData, mach_msg_type_number_t valueLength);
+
+ // No-op if the value does not contain a local object.
+ void retainLocalObject(JSC::JSValue);
+ void releaseLocalObject(JSC::JSValue);
+
+ void addInstance(ProxyInstance*);
+ void removeInstance(ProxyInstance*);
+
+ void cleanup();
+ void invalidate();
+
+ void willCallPluginFunction();
+ void didCallPluginFunction(bool& stopped);
+ bool shouldStop();
+
+ uint32_t nextRequestID();
+
+ uint32_t checkIfAllowedToLoadURL(const char* url, const char* target);
+ void cancelCheckIfAllowedToLoadURL(uint32_t checkID);
+ void checkIfAllowedToLoadURLResult(uint32_t checkID, bool allowed);
+
+ void resolveURL(const char* url, const char* target, data_t& resolvedURLData, mach_msg_type_number_t& resolvedURLLength);
+
+ void didDraw();
+ void privateBrowsingModeDidChange(bool isPrivateBrowsingEnabled);
+
+ static void setGlobalException(const WTF::String&);
+ static void moveGlobalExceptionToExecState(JSC::ExecState*);
+
+ // Reply structs
+ struct Reply {
+ enum Type {
+ InstantiatePlugin,
+ GetScriptableNPObject,
+ BooleanAndData,
+ Boolean
+ };
+
+ Reply(Type type)
+ : m_type(type)
+ {
+ }
+
+ virtual ~Reply() { }
+
+ Type m_type;
+ };
+
+ struct InstantiatePluginReply : public Reply {
+ static const int ReplyType = InstantiatePlugin;
+
+ InstantiatePluginReply(kern_return_t resultCode, uint32_t renderContextID, RendererType rendererType)
+ : Reply(InstantiatePlugin)
+ , m_resultCode(resultCode)
+ , m_renderContextID(renderContextID)
+ , m_rendererType(rendererType)
+ {
+ }
+
+ kern_return_t m_resultCode;
+ uint32_t m_renderContextID;
+ RendererType m_rendererType;
+ };
+
+ struct GetScriptableNPObjectReply : public Reply {
+ static const Reply::Type ReplyType = GetScriptableNPObject;
+
+ GetScriptableNPObjectReply(uint32_t objectID)
+ : Reply(ReplyType)
+ , m_objectID(objectID)
+ {
+ }
+
+ uint32_t m_objectID;
+ };
+
+ struct BooleanReply : public Reply {
+ static const Reply::Type ReplyType = Boolean;
+
+ BooleanReply(boolean_t result)
+ : Reply(ReplyType)
+ , m_result(result)
+ {
+ }
+
+ boolean_t m_result;
+ };
+
+ struct BooleanAndDataReply : public Reply {
+ static const Reply::Type ReplyType = BooleanAndData;
+
+ BooleanAndDataReply(boolean_t returnValue, RetainPtr<CFDataRef> result)
+ : Reply(ReplyType)
+ , m_returnValue(returnValue)
+ , m_result(result)
+ {
+ }
+
+ boolean_t m_returnValue;
+ RetainPtr<CFDataRef> m_result;
+ };
+
+ void setCurrentReply(uint32_t requestID, Reply* reply)
+ {
+ ASSERT(!m_replies.contains(requestID));
+ m_replies.set(requestID, reply);
+ }
+
+ template <typename T>
+ std::auto_ptr<T> waitForReply(uint32_t requestID)
+ {
+ RefPtr<NetscapePluginInstanceProxy> protect(this); // Plug-in host may crash while we are waiting for reply, releasing all instances to the instance proxy.
+
+ willCallPluginFunction();
+ m_waitingForReply = true;
+
+ Reply* reply = processRequestsAndWaitForReply(requestID);
+ if (reply)
+ ASSERT(reply->m_type == T::ReplyType);
+
+ m_waitingForReply = false;
+
+ bool stopped = false;
+ didCallPluginFunction(stopped);
+ if (stopped) {
+ // The instance proxy may have been deleted from didCallPluginFunction(), so a null reply needs to be returned.
+ delete static_cast<T*>(reply);
+ return std::auto_ptr<T>();
+ }
+
+ return std::auto_ptr<T>(static_cast<T*>(reply));
+ }
+
+ void webFrameDidFinishLoadWithReason(WebFrame*, NPReason);
+
+private:
+ NetscapePluginInstanceProxy(NetscapePluginHostProxy*, WebHostedNetscapePluginView*, bool fullFramePlugin);
+
+ NPError loadRequest(NSURLRequest*, const char* cTarget, bool currentEventIsUserGesture, uint32_t& streamID);
+
+ class PluginRequest;
+ void performRequest(PluginRequest*);
+ void evaluateJavaScript(PluginRequest*);
+
+ void stopAllStreams();
+ Reply* processRequestsAndWaitForReply(uint32_t requestID);
+
+ NetscapePluginHostProxy* m_pluginHostProxy;
+ WebHostedNetscapePluginView *m_pluginView;
+
+ void requestTimerFired(WebCore::Timer<NetscapePluginInstanceProxy>*);
+ WebCore::Timer<NetscapePluginInstanceProxy> m_requestTimer;
+ Deque<RefPtr<PluginRequest> > m_pluginRequests;
+
+ HashMap<uint32_t, RefPtr<HostedNetscapePluginStream> > m_streams;
+
+ uint32_t m_currentURLRequestID;
+
+ uint32_t m_pluginID;
+ uint32_t m_renderContextID;
+ RendererType m_rendererType;
+
+ bool m_waitingForReply;
+ HashMap<uint32_t, Reply*> m_replies;
+
+ // NPRuntime
+
+ void addValueToArray(NSMutableArray *, JSC::ExecState* exec, JSC::JSValue value);
+
+ bool demarshalValueFromArray(JSC::ExecState*, NSArray *array, NSUInteger& index, JSC::JSValue& result);
+ void demarshalValues(JSC::ExecState*, data_t valuesData, mach_msg_type_number_t valuesLength, JSC::MarkedArgumentBuffer& result);
+
+ class LocalObjectMap : Noncopyable {
+ public:
+ LocalObjectMap();
+ ~LocalObjectMap();
+ uint32_t idForObject(JSC::JSObject*);
+ void retain(JSC::JSObject*);
+ void release(JSC::JSObject*);
+ void clear();
+ bool forget(uint32_t);
+ bool contains(uint32_t) const;
+ JSC::JSObject* get(uint32_t) const;
+
+ private:
+ HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> > m_idToJSObjectMap;
+ // The pair consists of object ID and a reference count. One reference belongs to remote plug-in,
+ // and the proxy will add transient references for arguments that are being sent out.
+ HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> > m_jsObjectToIDMap;
+ uint32_t m_objectIDCounter;
+ };
+
+ LocalObjectMap m_localObjects;
+
+ typedef HashSet<ProxyInstance*> ProxyInstanceSet;
+ ProxyInstanceSet m_instances;
+
+ uint32_t m_urlCheckCounter;
+ typedef HashMap<uint32_t, RetainPtr<id> > URLCheckMap;
+ URLCheckMap m_urlChecks;
+
+ unsigned m_pluginFunctionCallDepth;
+ bool m_shouldStopSoon;
+ uint32_t m_currentRequestID;
+
+ // All NPRuntime functions will return false when destroying a plug-in. This is necessary because there may be unhandled messages waiting,
+ // and spinning in processRequests() will unexpectedly execute them from inside destroy(). That's not a good time to execute arbitrary JavaScript,
+ // since both loading and rendering data structures may be in inconsistent state.
+ // 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.
+ //
+ // FIXME: Plug-ins can execute arbitrary JS from destroy() in same process case, and other browsers also support that.
+ // A better fix may be to make sure that unrelated messages are postponed until after destroy() returns.
+ // Another possible fix may be to send destroy message at a time when internal structures are consistent.
+ //
+ // FIXME: We lack similar message suppression in other cases - resize() is also triggered by layout, so executing arbitrary JS is also problematic.
+ static bool m_inDestroy;
+
+ bool m_pluginIsWaitingForDraw;
+
+ RefPtr<HostedNetscapePluginStream> m_manualStream;
+
+ typedef HashMap<WebFrame*, RefPtr<PluginRequest> > FrameLoadMap;
+ FrameLoadMap m_pendingFrameLoads;
+};
+
+} // namespace WebKit
+
+#endif // NetscapePluginInstanceProxy_h
+#endif // USE(PLUGIN_HOST_PROCESS)