summaryrefslogtreecommitdiffstats
path: root/Source/WebKit/mac/Plugins/Hosted
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
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')
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h106
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm276
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h75
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm321
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h106
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm1134
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h372
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm1684
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/ProxyInstance.h106
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/ProxyInstance.mm458
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.h53
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.mm55
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h67
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm535
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs45
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs38
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs238
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs247
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs33
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h67
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h46
-rw-r--r--Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m161
22 files changed, 6223 insertions, 0 deletions
diff --git a/Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h b/Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h
new file mode 100644
index 0000000..34cea32
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 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 HostedNetscapePluginStream_h
+#define HostedNetscapePluginStream_h
+
+#include <WebCore/NetscapePlugInStreamLoader.h>
+#include <WebKit/npapi.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+ class FrameLoader;
+ class NetscapePlugInStreamLoader;
+}
+
+namespace WebKit {
+
+class NetscapePluginInstanceProxy;
+
+class HostedNetscapePluginStream : public RefCounted<HostedNetscapePluginStream>
+ , private WebCore::NetscapePlugInStreamLoaderClient {
+public:
+ static PassRefPtr<HostedNetscapePluginStream> create(NetscapePluginInstanceProxy* instance, uint32_t streamID, NSURLRequest *request)
+ {
+ return adoptRef(new HostedNetscapePluginStream(instance, streamID, request));
+ }
+ static PassRefPtr<HostedNetscapePluginStream> create(NetscapePluginInstanceProxy* instance, WebCore::FrameLoader* frameLoader)
+ {
+ return adoptRef(new HostedNetscapePluginStream(instance, frameLoader));
+ }
+
+ ~HostedNetscapePluginStream();
+
+ uint32_t streamID() const { return m_streamID; }
+
+ void startStreamWithResponse(NSURLResponse *response);
+ void didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char* bytes, int length);
+ void didFinishLoading(WebCore::NetscapePlugInStreamLoader*);
+ void didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError&);
+
+ void start();
+ void stop();
+
+ void cancelLoad(NPReason reason);
+
+ static NPReason reasonForError(NSError* error);
+
+private:
+ NSError *errorForReason(NPReason) const;
+ void cancelLoad(NSError *);
+
+ HostedNetscapePluginStream(NetscapePluginInstanceProxy*, uint32_t streamID, NSURLRequest *);
+ HostedNetscapePluginStream(NetscapePluginInstanceProxy*, WebCore::FrameLoader*);
+
+ void startStream(NSURL *, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers);
+
+ NSError *pluginCancelledConnectionError() const;
+
+ // NetscapePlugInStreamLoaderClient methods.
+ void didReceiveResponse(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceResponse&);
+ bool wantsAllStreams() const;
+
+ RefPtr<NetscapePluginInstanceProxy> m_instance;
+ uint32_t m_streamID;
+ bool m_isTerminated;
+ RetainPtr<NSMutableURLRequest> m_request;
+
+ RetainPtr<NSURL> m_requestURL;
+ RetainPtr<NSURL> m_responseURL;
+ RetainPtr<NSString> m_mimeType;
+
+ WebCore::FrameLoader* m_frameLoader;
+ RefPtr<WebCore::NetscapePlugInStreamLoader> m_loader;
+};
+
+}
+
+#endif // HostedNetscapePluginStream_h
+#endif // USE(PLUGIN_HOST_PROCESS)
diff --git a/Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm b/Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm
new file mode 100644
index 0000000..8ac1389
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2008 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) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "HostedNetscapePluginStream.h"
+
+#import "NetscapePluginHostProxy.h"
+#import "NetscapePluginInstanceProxy.h"
+#import "WebFrameInternal.h"
+#import "WebHostedNetscapePluginView.h"
+#import "WebKitErrorsPrivate.h"
+#import "WebKitPluginHost.h"
+#import "WebKitSystemInterface.h"
+#import "WebNSURLExtras.h"
+#import "WebNSURLRequestExtras.h"
+#import <WebCore/DocumentLoader.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/ResourceLoadScheduler.h>
+#import <WebCore/SecurityOrigin.h>
+#import <WebCore/WebCoreURLResponse.h>
+#import <wtf/RefCountedLeakCounter.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter hostedNetscapePluginStreamCounter("HostedNetscapePluginStream");
+#endif
+
+HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, uint32_t streamID, NSURLRequest *request)
+ : m_instance(instance)
+ , m_streamID(streamID)
+ , m_isTerminated(false)
+ , m_request(AdoptNS, [request mutableCopy])
+ , m_requestURL([request URL])
+ , m_frameLoader(0)
+{
+ if (SecurityOrigin::shouldHideReferrer([request URL], core([instance->pluginView() webFrame])->loader()->outgoingReferrer()))
+ [m_request.get() _web_setHTTPReferrer:nil];
+
+#ifndef NDEBUG
+ hostedNetscapePluginStreamCounter.increment();
+#endif
+}
+
+HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, WebCore::FrameLoader* frameLoader)
+ : m_instance(instance)
+ , m_streamID(1)
+ , m_isTerminated(false)
+ , m_frameLoader(frameLoader)
+{
+#ifndef NDEBUG
+ hostedNetscapePluginStreamCounter.increment();
+#endif
+}
+
+HostedNetscapePluginStream::~HostedNetscapePluginStream()
+{
+#ifndef NDEBUG
+ hostedNetscapePluginStreamCounter.decrement();
+#endif
+}
+
+void HostedNetscapePluginStream::startStreamWithResponse(NSURLResponse *response)
+{
+ didReceiveResponse(0, response);
+}
+
+void HostedNetscapePluginStream::startStream(NSURL *responseURL, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers)
+{
+ m_responseURL = responseURL;
+ m_mimeType = mimeType;
+
+ char* mimeTypeUTF8 = const_cast<char*>([mimeType UTF8String]);
+ int mimeTypeUTF8Length = mimeTypeUTF8 ? strlen (mimeTypeUTF8) + 1 : 0;
+
+ const char *url = [responseURL _web_URLCString];
+ int urlLength = url ? strlen(url) + 1 : 0;
+
+ _WKPHStartStream(m_instance->hostProxy()->port(),
+ m_instance->pluginID(),
+ m_streamID,
+ const_cast<char*>(url), urlLength,
+ expectedContentLength,
+ [lastModifiedDate timeIntervalSince1970],
+ mimeTypeUTF8, mimeTypeUTF8Length,
+ const_cast<char*>(reinterpret_cast<const char*>([headers bytes])), [headers length]);
+}
+
+void HostedNetscapePluginStream::didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char* bytes, int length)
+{
+ _WKPHStreamDidReceiveData(m_instance->hostProxy()->port(),
+ m_instance->pluginID(),
+ m_streamID,
+ const_cast<char*>(bytes), length);
+}
+
+void HostedNetscapePluginStream::didFinishLoading(WebCore::NetscapePlugInStreamLoader*)
+{
+ _WKPHStreamDidFinishLoading(m_instance->hostProxy()->port(),
+ m_instance->pluginID(),
+ m_streamID);
+ m_instance->disconnectStream(this);
+}
+
+void HostedNetscapePluginStream::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& response)
+{
+ NSURLResponse *r = response.nsURLResponse();
+
+ NSMutableData *theHeaders = nil;
+ long long expectedContentLength = [r expectedContentLength];
+
+ if ([r isKindOfClass:[NSHTTPURLResponse class]]) {
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)r;
+ theHeaders = [NSMutableData dataWithCapacity:1024];
+
+ // FIXME: it would be nice to be able to get the raw HTTP header block.
+ // This includes the HTTP version, the real status text,
+ // all headers in their original order and including duplicates,
+ // and all original bytes verbatim, rather than sent through Unicode translation.
+ // Unfortunately NSHTTPURLResponse doesn't provide access at that low a level.
+
+ [theHeaders appendBytes:"HTTP " length:5];
+ char statusStr[10];
+ long statusCode = [httpResponse statusCode];
+ snprintf(statusStr, sizeof(statusStr), "%ld", statusCode);
+ [theHeaders appendBytes:statusStr length:strlen(statusStr)];
+ [theHeaders appendBytes:" OK\n" length:4];
+
+ // HACK: pass the headers through as UTF-8.
+ // This is not the intended behavior; we're supposed to pass original bytes verbatim.
+ // But we don't have the original bytes, we have NSStrings built by the URL loading system.
+ // It hopefully shouldn't matter, since RFC2616/RFC822 require ASCII-only headers,
+ // but surely someone out there is using non-ASCII characters, and hopefully UTF-8 is adequate here.
+ // It seems better than NSASCIIStringEncoding, which will lose information if non-ASCII is used.
+
+ NSDictionary *headerDict = [httpResponse allHeaderFields];
+ NSArray *keys = [[headerDict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
+ NSEnumerator *i = [keys objectEnumerator];
+ NSString *k;
+ while ((k = [i nextObject]) != nil) {
+ NSString *v = [headerDict objectForKey:k];
+ [theHeaders appendData:[k dataUsingEncoding:NSUTF8StringEncoding]];
+ [theHeaders appendBytes:": " length:2];
+ [theHeaders appendData:[v dataUsingEncoding:NSUTF8StringEncoding]];
+ [theHeaders appendBytes:"\n" length:1];
+ }
+
+ // If the content is encoded (most likely compressed), then don't send its length to the plugin,
+ // which is only interested in the decoded length, not yet known at the moment.
+ // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic.
+ NSString *contentEncoding = (NSString *)[[(NSHTTPURLResponse *)r allHeaderFields] objectForKey:@"Content-Encoding"];
+ if (contentEncoding && ![contentEncoding isEqualToString:@"identity"])
+ expectedContentLength = -1;
+
+ [theHeaders appendBytes:"\0" length:1];
+ }
+
+ startStream([r URL], expectedContentLength, WKGetNSURLResponseLastModifiedDate(r), [r MIMEType], theHeaders);
+}
+
+NPReason HostedNetscapePluginStream::reasonForError(NSError *error)
+{
+ if (!error)
+ return NPRES_DONE;
+
+ if ([[error domain] isEqualToString:NSURLErrorDomain] && [error code] == NSURLErrorCancelled)
+ return NPRES_USER_BREAK;
+
+ return NPRES_NETWORK_ERR;
+}
+
+void HostedNetscapePluginStream::didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError& error)
+{
+ if (NetscapePluginHostProxy* hostProxy = m_instance->hostProxy())
+ _WKPHStreamDidFail(hostProxy->port(), m_instance->pluginID(), m_streamID, reasonForError(error));
+ m_instance->disconnectStream(this);
+}
+
+bool HostedNetscapePluginStream::wantsAllStreams() const
+{
+ // FIXME: Implement.
+ return false;
+}
+
+void HostedNetscapePluginStream::start()
+{
+ ASSERT(m_request);
+ ASSERT(!m_frameLoader);
+ ASSERT(!m_loader);
+
+ m_loader = resourceLoadScheduler()->schedulePluginStreamLoad(core([m_instance->pluginView() webFrame]), this, m_request.get());
+}
+
+void HostedNetscapePluginStream::stop()
+{
+ ASSERT(!m_frameLoader);
+
+ if (!m_loader->isDone())
+ m_loader->cancel(m_loader->cancelledError());
+}
+
+void HostedNetscapePluginStream::cancelLoad(NPReason reason)
+{
+ cancelLoad(errorForReason(reason));
+}
+
+void HostedNetscapePluginStream::cancelLoad(NSError *error)
+{
+ if (m_frameLoader) {
+ ASSERT(!m_loader);
+
+ DocumentLoader* documentLoader = m_frameLoader->activeDocumentLoader();
+ if (documentLoader && documentLoader->isLoadingMainResource())
+ documentLoader->cancelMainResourceLoad(error);
+ return;
+ }
+
+ if (!m_loader->isDone()) {
+ // Cancelling the load will disconnect the stream so there's no need to do it explicitly.
+ m_loader->cancel(error);
+ } else
+ m_instance->disconnectStream(this);
+}
+
+NSError *HostedNetscapePluginStream::pluginCancelledConnectionError() const
+{
+ return [[[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInCancelledConnection
+ contentURL:m_responseURL ? m_responseURL.get() : m_requestURL.get()
+ pluginPageURL:nil
+ pluginName:[[m_instance->pluginView() pluginPackage] pluginInfo].name
+ MIMEType:m_mimeType.get()] autorelease];
+}
+
+NSError *HostedNetscapePluginStream::errorForReason(NPReason reason) const
+{
+ if (reason == NPRES_DONE)
+ return nil;
+
+ if (reason == NPRES_USER_BREAK)
+ return [NSError _webKitErrorWithDomain:NSURLErrorDomain
+ code:NSURLErrorCancelled
+ URL:m_responseURL ? m_responseURL.get() : m_requestURL.get()];
+
+ return pluginCancelledConnectionError();
+}
+
+} // namespace WebKit
+
+#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
+
diff --git a/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h
new file mode 100644
index 0000000..4e59456
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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 NetscapePluginHostManager_h
+#define NetscapePluginHostManager_h
+
+#import <WebCore/PlatformString.h>
+#import <wtf/HashMap.h>
+#import <wtf/PassRefPtr.h>
+#import <wtf/text/StringHash.h>
+
+@class WebHostedNetscapePluginView;
+
+namespace WebKit {
+
+class NetscapePluginInstanceProxy;
+class NetscapePluginHostProxy;
+
+class NetscapePluginHostManager {
+public:
+ static NetscapePluginHostManager& shared();
+
+ PassRefPtr<NetscapePluginInstanceProxy> instantiatePlugin(const WTF::String& pluginPath, cpu_type_t pluginArchitecture, const WTF::String& bundleIdentifier, WebHostedNetscapePluginView *, NSString *mimeType, NSArray *attributeKeys, NSArray *attributeValues, NSString *userAgent, NSURL *sourceURL, bool fullFrame, bool isPrivateBrowsingEnabled, bool isAcceleratedCompositingEnabled);
+
+ void pluginHostDied(NetscapePluginHostProxy*);
+
+ static void createPropertyListFile(const WTF::String& pluginPath, cpu_type_t pluginArchitecture);
+
+ void didCreateWindow();
+
+private:
+ NetscapePluginHostProxy* hostForPlugin(const WTF::String& pluginPath, cpu_type_t pluginArchitecture, const WTF::String& bundleIdentifier);
+
+ NetscapePluginHostManager();
+ ~NetscapePluginHostManager();
+
+ bool spawnPluginHost(const WTF::String& pluginPath, cpu_type_t pluginArchitecture, mach_port_t clientPort, mach_port_t& pluginHostPort, ProcessSerialNumber& pluginHostPSN);
+
+ bool initializeVendorPort();
+
+ mach_port_t m_pluginVendorPort;
+
+ // FIXME: This should really be a HashMap of RetainPtrs, but that doesn't work right now.
+ typedef HashMap<WTF::String, NetscapePluginHostProxy*> PluginHostMap;
+ PluginHostMap m_pluginHosts;
+};
+
+} // namespace WebKit
+
+#endif // NetscapePluginHostManager_h
+#endif // USE(PLUGIN_HOST_PROCESS)
diff --git a/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm
new file mode 100644
index 0000000..d8cd081
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2008 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) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "NetscapePluginHostManager.h"
+
+#import "NetscapePluginHostProxy.h"
+#import "NetscapePluginInstanceProxy.h"
+#import "WebLocalizableStrings.h"
+#import "WebKitSystemInterface.h"
+#import "WebNetscapePluginPackage.h"
+#import <mach/mach_port.h>
+#import <servers/bootstrap.h>
+#import <spawn.h>
+#import <wtf/Assertions.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/StdLibExtras.h>
+
+extern "C" {
+#import "WebKitPluginAgent.h"
+#import "WebKitPluginHost.h"
+}
+
+using namespace std;
+using namespace WebCore;
+
+namespace WebKit {
+
+NetscapePluginHostManager& NetscapePluginHostManager::shared()
+{
+ DEFINE_STATIC_LOCAL(NetscapePluginHostManager, pluginHostManager, ());
+
+ return pluginHostManager;
+}
+
+static NSString * const pluginHostAppName = @"WebKitPluginHost.app";
+
+NetscapePluginHostManager::NetscapePluginHostManager()
+ : m_pluginVendorPort(MACH_PORT_NULL)
+{
+}
+
+NetscapePluginHostManager::~NetscapePluginHostManager()
+{
+}
+
+NetscapePluginHostProxy* NetscapePluginHostManager::hostForPlugin(const WTF::String& pluginPath, cpu_type_t pluginArchitecture, const String& bundleIdentifier)
+{
+ pair<PluginHostMap::iterator, bool> result = m_pluginHosts.add(pluginPath, 0);
+
+ // The package was already in the map, just return it.
+ if (!result.second)
+ return result.first->second;
+
+ mach_port_t clientPort;
+ if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort) != KERN_SUCCESS) {
+ m_pluginHosts.remove(result.first);
+ return 0;
+ }
+
+ mach_port_t pluginHostPort;
+ ProcessSerialNumber pluginHostPSN;
+ if (!spawnPluginHost(pluginPath, pluginArchitecture, clientPort, pluginHostPort, pluginHostPSN)) {
+ mach_port_destroy(mach_task_self(), clientPort);
+ m_pluginHosts.remove(result.first);
+ return 0;
+ }
+
+ // Since Flash NPObjects add methods dynamically, we don't want to cache when a property/method doesn't exist
+ // on an object because it could be added later.
+ bool shouldCacheMissingPropertiesAndMethods = bundleIdentifier != "com.macromedia.Flash Player.plugin";
+
+ NetscapePluginHostProxy* hostProxy = new NetscapePluginHostProxy(clientPort, pluginHostPort, pluginHostPSN, shouldCacheMissingPropertiesAndMethods);
+
+ result.first->second = hostProxy;
+
+ return hostProxy;
+}
+
+bool NetscapePluginHostManager::spawnPluginHost(const String& pluginPath, cpu_type_t pluginArchitecture, mach_port_t clientPort, mach_port_t& pluginHostPort, ProcessSerialNumber& pluginHostPSN)
+{
+ if (m_pluginVendorPort == MACH_PORT_NULL) {
+ if (!initializeVendorPort())
+ return false;
+ }
+
+ mach_port_t renderServerPort = WKInitializeRenderServer();
+ if (renderServerPort == MACH_PORT_NULL)
+ return false;
+
+ NSString *pluginHostAppPath = [[NSBundle bundleWithIdentifier:@"com.apple.WebKit"] pathForAuxiliaryExecutable:pluginHostAppName];
+ NSString *pluginHostAppExecutablePath = [[NSBundle bundleWithPath:pluginHostAppPath] executablePath];
+
+ RetainPtr<CFStringRef> localization(AdoptCF, WKCopyCFLocalizationPreferredName(NULL));
+
+ NSDictionary *launchProperties = [[NSDictionary alloc] initWithObjectsAndKeys:
+ pluginHostAppExecutablePath, @"pluginHostPath",
+ [NSNumber numberWithInt:pluginArchitecture], @"cpuType",
+ localization.get(), @"localization",
+ nil];
+
+ NSData *data = [NSPropertyListSerialization dataFromPropertyList:launchProperties format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+ ASSERT(data);
+
+ [launchProperties release];
+
+ kern_return_t kr = _WKPASpawnPluginHost(m_pluginVendorPort, reinterpret_cast<uint8_t*>(const_cast<void*>([data bytes])), [data length], &pluginHostPort);
+
+ if (kr == MACH_SEND_INVALID_DEST) {
+ // The plug-in vendor port has gone away for some reason. Try to reinitialize it.
+ m_pluginVendorPort = MACH_PORT_NULL;
+ if (!initializeVendorPort())
+ return false;
+
+ // And spawn the plug-in host again.
+ kr = _WKPASpawnPluginHost(m_pluginVendorPort, reinterpret_cast<uint8_t*>(const_cast<void*>([data bytes])), [data length], &pluginHostPort);
+ }
+
+ if (kr != KERN_SUCCESS) {
+ // FIXME: Check for invalid dest and try to re-spawn the plug-in agent.
+ LOG_ERROR("Failed to spawn plug-in host, error %x", kr);
+ return false;
+ }
+
+ NSString *visibleName = [NSString stringWithFormat:UI_STRING("%@ (%@ Internet plug-in)",
+ "visible name of the plug-in host process. The first argument is the plug-in name "
+ "and the second argument is the application name."),
+ [[(NSString*)pluginPath lastPathComponent] stringByDeletingPathExtension], [[NSProcessInfo processInfo] processName]];
+
+ NSDictionary *hostProperties = [[NSDictionary alloc] initWithObjectsAndKeys:
+ visibleName, @"visibleName",
+ (NSString *)pluginPath, @"bundlePath",
+ nil];
+
+ data = [NSPropertyListSerialization dataFromPropertyList:hostProperties format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
+ ASSERT(data);
+
+ [hostProperties release];
+
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+
+ kr = _WKPHCheckInWithPluginHost(pluginHostPort, (uint8_t*)[data bytes], [data length], clientPort, psn.highLongOfPSN, psn.lowLongOfPSN, renderServerPort,
+ &pluginHostPSN.highLongOfPSN, &pluginHostPSN.lowLongOfPSN);
+
+ if (kr != KERN_SUCCESS) {
+ mach_port_deallocate(mach_task_self(), pluginHostPort);
+ LOG_ERROR("Failed to check in with plug-in host, error %x", kr);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool NetscapePluginHostManager::initializeVendorPort()
+{
+ ASSERT(m_pluginVendorPort == MACH_PORT_NULL);
+
+ // Get the plug-in agent port.
+ mach_port_t pluginAgentPort;
+ if (bootstrap_look_up(bootstrap_port, "com.apple.WebKit.PluginAgent", &pluginAgentPort) != KERN_SUCCESS) {
+ LOG_ERROR("Failed to look up the plug-in agent port");
+ return false;
+ }
+
+ NSData *appNameData = [[[NSProcessInfo processInfo] processName] dataUsingEncoding:NSUTF8StringEncoding];
+
+ // Tell the plug-in agent that we exist.
+ if (_WKPACheckInApplication(pluginAgentPort, (uint8_t*)[appNameData bytes], [appNameData length], &m_pluginVendorPort) != KERN_SUCCESS)
+ return false;
+
+ // FIXME: Should we add a notification for when the vendor port dies?
+
+ return true;
+}
+
+void NetscapePluginHostManager::pluginHostDied(NetscapePluginHostProxy* pluginHost)
+{
+ PluginHostMap::iterator end = m_pluginHosts.end();
+
+ // This has O(n) complexity but the number of active plug-in hosts is very small so it shouldn't matter.
+ for (PluginHostMap::iterator it = m_pluginHosts.begin(); it != end; ++it) {
+ if (it->second == pluginHost) {
+ m_pluginHosts.remove(it);
+ return;
+ }
+ }
+}
+
+PassRefPtr<NetscapePluginInstanceProxy> NetscapePluginHostManager::instantiatePlugin(const String& pluginPath, cpu_type_t pluginArchitecture, const String& bundleIdentifier, WebHostedNetscapePluginView *pluginView, NSString *mimeType, NSArray *attributeKeys, NSArray *attributeValues, NSString *userAgent, NSURL *sourceURL, bool fullFrame, bool isPrivateBrowsingEnabled, bool isAcceleratedCompositingEnabled)
+{
+ NetscapePluginHostProxy* hostProxy = hostForPlugin(pluginPath, pluginArchitecture, bundleIdentifier);
+ if (!hostProxy)
+ return 0;
+
+ RetainPtr<NSMutableDictionary> properties(AdoptNS, [[NSMutableDictionary alloc] init]);
+
+ if (mimeType)
+ [properties.get() setObject:mimeType forKey:@"mimeType"];
+
+ ASSERT_ARG(userAgent, userAgent);
+ [properties.get() setObject:userAgent forKey:@"userAgent"];
+
+ ASSERT_ARG(attributeKeys, attributeKeys);
+ [properties.get() setObject:attributeKeys forKey:@"attributeKeys"];
+
+ ASSERT_ARG(attributeValues, attributeValues);
+ [properties.get() setObject:attributeValues forKey:@"attributeValues"];
+
+ if (sourceURL)
+ [properties.get() setObject:[sourceURL absoluteString] forKey:@"sourceURL"];
+
+ [properties.get() setObject:[NSNumber numberWithBool:fullFrame] forKey:@"fullFrame"];
+ [properties.get() setObject:[NSNumber numberWithBool:isPrivateBrowsingEnabled] forKey:@"privateBrowsingEnabled"];
+ [properties.get() setObject:[NSNumber numberWithBool:isAcceleratedCompositingEnabled] forKey:@"acceleratedCompositingEnabled"];
+
+ NSData *data = [NSPropertyListSerialization dataFromPropertyList:properties.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
+ ASSERT(data);
+
+ RefPtr<NetscapePluginInstanceProxy> instance = NetscapePluginInstanceProxy::create(hostProxy, pluginView, fullFrame);
+ uint32_t requestID = instance->nextRequestID();
+ kern_return_t kr = _WKPHInstantiatePlugin(hostProxy->port(), requestID, (uint8_t*)[data bytes], [data length], instance->pluginID());
+ if (kr == MACH_SEND_INVALID_DEST) {
+ // Invalidate the instance.
+ instance->invalidate();
+
+ // The plug-in host must have died, but we haven't received the death notification yet.
+ pluginHostDied(hostProxy);
+
+ // Try to spawn it again.
+ hostProxy = hostForPlugin(pluginPath, pluginArchitecture, bundleIdentifier);
+
+ // Create a new instance.
+ instance = NetscapePluginInstanceProxy::create(hostProxy, pluginView, fullFrame);
+ requestID = instance->nextRequestID();
+ kr = _WKPHInstantiatePlugin(hostProxy->port(), requestID, (uint8_t*)[data bytes], [data length], instance->pluginID());
+ }
+
+ auto_ptr<NetscapePluginInstanceProxy::InstantiatePluginReply> reply = instance->waitForReply<NetscapePluginInstanceProxy::InstantiatePluginReply>(requestID);
+ if (!reply.get() || reply->m_resultCode != KERN_SUCCESS) {
+ instance->cleanup();
+ return 0;
+ }
+
+ instance->setRenderContextID(reply->m_renderContextID);
+ instance->setRendererType(reply->m_rendererType);
+
+ return instance.release();
+}
+
+void NetscapePluginHostManager::createPropertyListFile(const String& pluginPath, cpu_type_t pluginArchitecture)
+{
+ NSString *pluginHostAppPath = [[NSBundle bundleWithIdentifier:@"com.apple.WebKit"] pathForAuxiliaryExecutable:pluginHostAppName];
+ NSString *pluginHostAppExecutablePath = [[NSBundle bundleWithPath:pluginHostAppPath] executablePath];
+ NSString *bundlePath = pluginPath;
+
+ pid_t pid;
+ posix_spawnattr_t attr;
+ posix_spawnattr_init(&attr);
+
+ // Set the architecture.
+ size_t ocount = 0;
+ int cpuTypes[] = { pluginArchitecture };
+ posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &ocount);
+
+ // Spawn the plug-in host and tell it to call the registration function.
+ const char* args[] = { [pluginHostAppExecutablePath fileSystemRepresentation], "-createPluginMIMETypesPreferences", [bundlePath fileSystemRepresentation], 0 };
+
+ int result = posix_spawn(&pid, args[0], 0, &attr, const_cast<char* const*>(args), 0);
+ posix_spawnattr_destroy(&attr);
+
+ if (!result && pid > 0) {
+ // Wait for the process to finish.
+ while (waitpid(pid, 0, 0) == -1) { }
+ }
+}
+
+void NetscapePluginHostManager::didCreateWindow()
+{
+ // See if any of our hosts are in full-screen mode.
+ PluginHostMap::iterator end = m_pluginHosts.end();
+ for (PluginHostMap::iterator it = m_pluginHosts.begin(); it != end; ++it) {
+ NetscapePluginHostProxy* hostProxy = it->second;
+
+ if (!hostProxy->isMenuBarVisible()) {
+ // Make ourselves the front process.
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+ SetFrontProcess(&psn);
+ return;
+ }
+ }
+}
+
+} // namespace WebKit
+
+#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h
new file mode 100644
index 0000000..20db5d2
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 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 NetscapePluginHostProxy_h
+#define NetscapePluginHostProxy_h
+
+#include <dispatch/dispatch.h>
+#include <wtf/HashMap.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/PassRefPtr.h>
+
+@class WebPlaceholderModalWindow;
+
+namespace WebKit {
+
+class NetscapePluginInstanceProxy;
+
+class NetscapePluginHostProxy {
+public:
+ NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN, bool shouldCacheMissingPropertiesAndMethods);
+
+ mach_port_t port() const { ASSERT(fastMallocSize(this)); return m_pluginHostPort; }
+ mach_port_t clientPort() const { ASSERT(fastMallocSize(this)); return m_clientPort; }
+
+ void addPluginInstance(NetscapePluginInstanceProxy*);
+ void removePluginInstance(NetscapePluginInstanceProxy*);
+
+ NetscapePluginInstanceProxy* pluginInstance(uint32_t pluginID);
+
+ bool isMenuBarVisible() const { return m_menuBarIsVisible; }
+ void setMenuBarVisible(bool);
+
+ bool isFullscreenWindowShowing() const { return m_fullscreenWindowIsShowing; }
+ void setFullscreenWindowIsShowing(bool);
+
+ void setModal(bool);
+
+ void applicationDidBecomeActive();
+
+ bool processRequests();
+ static bool isProcessingRequests() { return s_processingRequests; }
+
+ bool shouldCacheMissingPropertiesAndMethods() const { return m_shouldCacheMissingPropertiesAndMethods; }
+
+private:
+ ~NetscapePluginHostProxy();
+ void pluginHostDied();
+
+ void beginModal();
+ void endModal();
+
+ void didEnterFullscreen() const;
+ void didExitFullscreen() const;
+
+ static void deadNameNotificationCallback(CFMachPortRef, void *msg, CFIndex size, void *info);
+
+ typedef HashMap<uint32_t, RefPtr<NetscapePluginInstanceProxy> > PluginInstanceMap;
+ PluginInstanceMap m_instances;
+
+ mach_port_t m_clientPort;
+ mach_port_t m_portSet;
+
+ RetainPtr<CFRunLoopSourceRef> m_clientPortSource;
+ mach_port_t m_pluginHostPort;
+ RetainPtr<CFMachPortRef> m_deadNameNotificationPort;
+
+ RetainPtr<id> m_activationObserver;
+ RetainPtr<WebPlaceholderModalWindow *> m_placeholderWindow;
+ unsigned m_isModal;
+ bool m_menuBarIsVisible;
+ bool m_fullscreenWindowIsShowing;
+ const ProcessSerialNumber m_pluginHostPSN;
+
+ static unsigned s_processingRequests;
+
+ bool m_shouldCacheMissingPropertiesAndMethods;
+};
+
+} // namespace WebKit
+
+#endif // NetscapePluginHostProxy_h
+#endif // USE(PLUGIN_HOST_PROCESS)
diff --git a/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm
new file mode 100644
index 0000000..4506f03
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm
@@ -0,0 +1,1134 @@
+/*
+ * Copyright (C) 2008 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) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "NetscapePluginHostProxy.h"
+
+#import <mach/mach.h>
+#import <wtf/StdLibExtras.h>
+
+#import "HostedNetscapePluginStream.h"
+#import "NetscapePluginHostManager.h"
+#import "NetscapePluginInstanceProxy.h"
+#import "WebFrameInternal.h"
+#import "WebHostedNetscapePluginView.h"
+#import "WebKitSystemInterface.h"
+#import <WebCore/Frame.h>
+#import <WebCore/IdentifierRep.h>
+#import <WebCore/ScriptController.h>
+#import <string>
+
+extern "C" {
+#import "WebKitPluginHost.h"
+#import "WebKitPluginClientServer.h"
+}
+
+using namespace std;
+using namespace JSC;
+using namespace WebCore;
+
+@interface WebPlaceholderModalWindow : NSWindow
+@end
+
+@implementation WebPlaceholderModalWindow
+// Prevent NSApp from calling requestUserAttention: when the window is shown
+// modally, even if the app is inactive. See 6823049.
+- (BOOL)_wantsUserAttention
+{
+ return NO;
+}
+@end
+
+namespace WebKit {
+
+class PluginDestroyDeferrer {
+public:
+ PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy)
+ : m_proxy(proxy)
+ {
+ m_proxy->willCallPluginFunction();
+ }
+
+ ~PluginDestroyDeferrer()
+ {
+ bool stopped;
+ m_proxy->didCallPluginFunction(stopped);
+ }
+
+private:
+ RefPtr<NetscapePluginInstanceProxy> m_proxy;
+};
+
+typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap;
+static PluginProxyMap& pluginProxyMap()
+{
+ DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ());
+
+ return pluginProxyMap;
+}
+
+unsigned NetscapePluginHostProxy::s_processingRequests;
+
+NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN, bool shouldCacheMissingPropertiesAndMethods)
+ : m_clientPort(clientPort)
+ , m_portSet(MACH_PORT_NULL)
+ , m_pluginHostPort(pluginHostPort)
+ , m_isModal(false)
+ , m_menuBarIsVisible(true)
+ , m_fullscreenWindowIsShowing(false)
+ , m_pluginHostPSN(pluginHostPSN)
+ , m_shouldCacheMissingPropertiesAndMethods(shouldCacheMissingPropertiesAndMethods)
+{
+ pluginProxyMap().add(m_clientPort, this);
+
+ // FIXME: We should use libdispatch for this.
+ CFMachPortContext context = { 0, this, 0, 0, 0 };
+ m_deadNameNotificationPort.adoptCF(CFMachPortCreate(0, deadNameNotificationCallback, &context, 0));
+
+ mach_port_t previous;
+ mach_port_request_notification(mach_task_self(), pluginHostPort, MACH_NOTIFY_DEAD_NAME, 0,
+ CFMachPortGetPort(m_deadNameNotificationPort.get()), MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+ ASSERT(previous == MACH_PORT_NULL);
+
+ RetainPtr<CFRunLoopSourceRef> deathPortSource(AdoptCF, CFMachPortCreateRunLoopSource(0, m_deadNameNotificationPort.get(), 0));
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), deathPortSource.get(), kCFRunLoopDefaultMode);
+
+ m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKWebKitPluginClient_subsystem, m_clientPort));
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSEventTrackingRunLoopMode);
+}
+
+NetscapePluginHostProxy::~NetscapePluginHostProxy()
+{
+ pluginProxyMap().remove(m_clientPort);
+
+ // Free the port set
+ if (m_portSet) {
+ mach_port_extract_member(mach_task_self(), m_clientPort, m_portSet);
+ mach_port_extract_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
+ mach_port_destroy(mach_task_self(), m_portSet);
+ }
+
+ ASSERT(m_clientPortSource);
+ CFRunLoopSourceInvalidate(m_clientPortSource.get());
+ m_clientPortSource = 0;
+}
+
+void NetscapePluginHostProxy::pluginHostDied()
+{
+ PluginInstanceMap instances;
+ m_instances.swap(instances);
+
+ PluginInstanceMap::const_iterator end = instances.end();
+ for (PluginInstanceMap::const_iterator it = instances.begin(); it != end; ++it)
+ it->second->pluginHostDied();
+
+ NetscapePluginHostManager::shared().pluginHostDied(this);
+
+ // The plug-in crashed while its menu bar was hidden. Make sure to show it.
+ if (!m_menuBarIsVisible)
+ setMenuBarVisible(true);
+
+ // The plug-in crashed while it had a modal dialog up.
+ if (m_isModal)
+ endModal();
+
+ delete this;
+}
+
+void NetscapePluginHostProxy::addPluginInstance(NetscapePluginInstanceProxy* instance)
+{
+ ASSERT(!m_instances.contains(instance->pluginID()));
+
+ m_instances.set(instance->pluginID(), instance);
+}
+
+void NetscapePluginHostProxy::removePluginInstance(NetscapePluginInstanceProxy* instance)
+{
+ ASSERT(m_instances.get(instance->pluginID()) == instance);
+
+ m_instances.remove(instance->pluginID());
+}
+
+NetscapePluginInstanceProxy* NetscapePluginHostProxy::pluginInstance(uint32_t pluginID)
+{
+ NetscapePluginInstanceProxy* result = m_instances.get(pluginID).get();
+ ASSERT(!result || result->hostProxy() == this);
+ return result;
+}
+
+void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
+{
+ ASSERT(msg);
+ ASSERT(static_cast<mach_msg_header_t*>(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME);
+
+ static_cast<NetscapePluginHostProxy*>(info)->pluginHostDied();
+}
+
+void NetscapePluginHostProxy::setMenuBarVisible(bool visible)
+{
+ m_menuBarIsVisible = visible;
+
+ [NSMenu setMenuBarVisible:visible];
+}
+
+void NetscapePluginHostProxy::didEnterFullscreen() const
+{
+ SetFrontProcess(&m_pluginHostPSN);
+}
+
+void NetscapePluginHostProxy::didExitFullscreen() const
+{
+ // If the plug-in host is the current application then we should bring ourselves to the front when it exits full-screen mode.
+
+ ProcessSerialNumber frontProcess;
+ GetFrontProcess(&frontProcess);
+ Boolean isSameProcess = 0;
+ SameProcess(&frontProcess, &m_pluginHostPSN, &isSameProcess);
+ if (!isSameProcess)
+ return;
+
+ ProcessSerialNumber currentProcess;
+ GetCurrentProcess(&currentProcess);
+ SetFrontProcess(&currentProcess);
+}
+
+void NetscapePluginHostProxy::setFullscreenWindowIsShowing(bool isShowing)
+{
+ if (m_fullscreenWindowIsShowing == isShowing)
+ return;
+
+ m_fullscreenWindowIsShowing = isShowing;
+ if (m_fullscreenWindowIsShowing)
+ didEnterFullscreen();
+ else
+ didExitFullscreen();
+
+}
+
+void NetscapePluginHostProxy::applicationDidBecomeActive()
+{
+ SetFrontProcess(&m_pluginHostPSN);
+}
+
+void NetscapePluginHostProxy::beginModal()
+{
+ ASSERT(!m_placeholderWindow);
+ ASSERT(!m_activationObserver);
+
+ m_placeholderWindow.adoptNS([[WebPlaceholderModalWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
+
+ m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
+ usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
+
+ // We need to be able to get the setModal(false) call from the plug-in host.
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
+
+ [NSApp runModalForWindow:m_placeholderWindow.get()];
+
+ [m_placeholderWindow.get() orderOut:nil];
+ m_placeholderWindow = 0;
+}
+
+void NetscapePluginHostProxy::endModal()
+{
+ ASSERT(m_placeholderWindow);
+ ASSERT(m_activationObserver);
+
+ [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
+ m_activationObserver = nil;
+
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
+
+ [NSApp stopModal];
+
+ // Make ourselves the front process.
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+ SetFrontProcess(&psn);
+}
+
+
+void NetscapePluginHostProxy::setModal(bool modal)
+{
+ if (modal == m_isModal)
+ return;
+
+ m_isModal = modal;
+
+ if (m_isModal)
+ beginModal();
+ else
+ endModal();
+}
+
+bool NetscapePluginHostProxy::processRequests()
+{
+ s_processingRequests++;
+
+ if (!m_portSet) {
+ mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet);
+ mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet);
+ mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
+ }
+
+ char buffer[4096];
+
+ mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer);
+
+ kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL);
+
+ if (kr != KERN_SUCCESS) {
+ LOG_ERROR("Could not receive mach message, error %x", kr);
+ s_processingRequests--;
+ return false;
+ }
+
+ if (msg->msgh_local_port == m_clientPort) {
+ __ReplyUnion__WKWebKitPluginClient_subsystem reply;
+ mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply);
+
+ if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) {
+ kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+
+ if (kr != KERN_SUCCESS) {
+ LOG_ERROR("Could not send mach message, error %x", kr);
+ s_processingRequests--;
+ return false;
+ }
+ }
+
+ s_processingRequests--;
+ return true;
+ }
+
+ if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) {
+ ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME);
+ pluginHostDied();
+ s_processingRequests--;
+ return false;
+ }
+
+ ASSERT_NOT_REACHED();
+ s_processingRequests--;
+ return false;
+}
+
+} // namespace WebKit
+
+using namespace WebKit;
+
+// Helper class for deallocating data
+class DataDeallocator {
+public:
+ DataDeallocator(data_t data, mach_msg_type_number_t dataLength)
+ : m_data(reinterpret_cast<vm_address_t>(data))
+ , m_dataLength(dataLength)
+ {
+ }
+
+ ~DataDeallocator()
+ {
+ if (!m_data)
+ return;
+
+ vm_deallocate(mach_task_self(), m_data, m_dataLength);
+ }
+
+private:
+ vm_address_t m_data;
+ vm_size_t m_dataLength;
+};
+
+// MiG callbacks
+kern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t textCnt)
+{
+ DataDeallocator deallocator(text, textCnt);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ instanceProxy->status(text);
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t url, mach_msg_type_number_t urlLength, data_t target, mach_msg_type_number_t targetLength,
+ data_t postData, mach_msg_type_number_t postDataLength, uint32_t flags,
+ uint16_t* outResult, uint32_t* outStreamID)
+{
+ DataDeallocator urlDeallocator(url, urlLength);
+ DataDeallocator targetDeallocator(target, targetLength);
+ DataDeallocator postDataDeallocator(postData, postDataLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ uint32_t streamID = 0;
+ NPError result = instanceProxy->loadURL(url, target, postData, postDataLength, static_cast<LoadURLFlags>(flags), streamID);
+
+ *outResult = result;
+ *outStreamID = streamID;
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCCancelLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t streamID, int16_t reason)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ if (!instanceProxy->cancelStreamLoad(streamID, reason))
+ return KERN_FAILURE;
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCInvalidateRect(mach_port_t clientPort, uint32_t pluginID, double x, double y, double width, double height)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_SUCCESS;
+
+ if (!hostProxy->isProcessingRequests()) {
+ if (NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID))
+ instanceProxy->invalidateRect(x, y, width, height);
+ return KERN_SUCCESS;
+ }
+
+ // Defer the work
+ CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+ if (NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort)) {
+ if (NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID))
+ instanceProxy->invalidateRect(x, y, width, height);
+ }
+ });
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetScriptableNPObjectReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID));
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t result)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanReply(result));
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCBooleanAndDataReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t returnValue, data_t resultData, mach_msg_type_number_t resultLength)
+{
+ DataDeallocator deallocator(resultData, resultLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ RetainPtr<CFDataRef> result(AdoptCF, CFDataCreate(0, reinterpret_cast<UInt8*>(resultData), resultLength));
+ instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanAndDataReply(returnValue, result));
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCInstantiatePluginReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, kern_return_t result, uint32_t renderContextID, uint32_t rendererType)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::InstantiatePluginReply(result, renderContextID, static_cast<RendererType>(rendererType)));
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetWindowNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ uint32_t objectID;
+ if (!instanceProxy->getWindowNPObject(objectID))
+ return KERN_FAILURE;
+
+ *outObjectID = objectID;
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetPluginElementNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ uint32_t objectID;
+ if (!instanceProxy->getPluginElementNPObject(objectID))
+ return KERN_FAILURE;
+
+ *outObjectID = objectID;
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCForgetBrowserObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ return instanceProxy->forgetBrowserObjectID(objectID) ? KERN_SUCCESS : KERN_FAILURE;
+}
+
+kern_return_t WKPCEvaluate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, data_t scriptData, mach_msg_type_number_t scriptLength, boolean_t allowPopups)
+{
+ DataDeallocator deallocator(scriptData, scriptLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ String script = String::fromUTF8WithLatin1Fallback(scriptData, scriptLength);
+
+ data_t resultData = 0;
+ mach_msg_type_number_t resultLength = 0;
+ boolean_t returnValue = instanceProxy->evaluate(objectID, script, resultData, resultLength, allowPopups);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+ if (resultData)
+ mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetStringIdentifier(mach_port_t clientPort, data_t name, mach_msg_type_number_t nameCnt, uint64_t* identifier)
+{
+ DataDeallocator deallocator(name, nameCnt);
+
+ COMPILE_ASSERT(sizeof(*identifier) == sizeof(IdentifierRep*), identifier_sizes);
+
+ *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(name));
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetIntIdentifier(mach_port_t clientPort, int32_t value, uint64_t* identifier)
+{
+ COMPILE_ASSERT(sizeof(*identifier) == sizeof(NPIdentifier), identifier_sizes);
+
+ *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(value));
+ return KERN_SUCCESS;
+}
+
+static Identifier identifierFromIdentifierRep(IdentifierRep* identifier)
+{
+ ASSERT(IdentifierRep::isValid(identifier));
+ ASSERT(identifier->isString());
+
+ const char* str = identifier->string();
+ return Identifier(JSDOMWindow::commonJSGlobalData(), stringToUString(String::fromUTF8WithLatin1Fallback(str, strlen(str))));
+}
+
+kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier,
+ data_t argumentsData, mach_msg_type_number_t argumentsLength)
+{
+ DataDeallocator deallocator(argumentsData, argumentsLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);
+
+ data_t resultData = 0;
+ mach_msg_type_number_t resultLength = 0;
+ boolean_t returnValue = instanceProxy->invoke(objectID, methodNameIdentifier, argumentsData, argumentsLength, resultData, resultLength);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+ if (resultData)
+ mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCInvokeDefault(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID,
+ data_t argumentsData, mach_msg_type_number_t argumentsLength)
+{
+ DataDeallocator deallocator(argumentsData, argumentsLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ data_t resultData = 0;
+ mach_msg_type_number_t resultLength = 0;
+ boolean_t returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, resultData, resultLength);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+ if (resultData)
+ mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCConstruct(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID,
+ data_t argumentsData, mach_msg_type_number_t argumentsLength,
+ boolean_t* returnValue, data_t* resultData, mach_msg_type_number_t* resultLength)
+{
+ DataDeallocator deallocator(argumentsData, argumentsLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ *returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ data_t resultData = 0;
+ mach_msg_type_number_t resultLength = 0;
+ boolean_t returnValue;
+
+ if (identifier->isString()) {
+ Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
+ returnValue = instanceProxy->getProperty(objectID, propertyNameIdentifier, resultData, resultLength);
+ } else
+ returnValue = instanceProxy->setProperty(objectID, identifier->number(), resultData, resultLength);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+ if (resultData)
+ mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier, data_t valueData, mach_msg_type_number_t valueLength)
+{
+ DataDeallocator deallocator(valueData, valueLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ bool result;
+ if (identifier->isString()) {
+ Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
+ result = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength);
+ } else
+ result = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, result);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ bool result;
+ if (identifier->isString()) {
+ Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
+ result = instanceProxy->removeProperty(objectID, propertyNameIdentifier);
+ } else
+ result = instanceProxy->removeProperty(objectID, identifier->number());
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, result);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ boolean_t returnValue;
+ if (identifier->isString()) {
+ Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
+ returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier);
+ } else
+ returnValue = instanceProxy->hasProperty(objectID, identifier->number());
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);
+ boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCIdentifierInfo(mach_port_t clientPort, uint64_t serverIdentifier, data_t* infoData, mach_msg_type_number_t* infoLength)
+{
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+ if (!IdentifierRep::isValid(identifier))
+ return KERN_FAILURE;
+
+ id info;
+ if (identifier->isString()) {
+ const char* str = identifier->string();
+ info = [NSData dataWithBytesNoCopy:(void*)str length:strlen(str) freeWhenDone:NO];
+ } else
+ info = [NSNumber numberWithInt:identifier->number()];
+
+ RetainPtr<NSData*> data = [NSPropertyListSerialization dataFromPropertyList:info format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+ ASSERT(data);
+
+ *infoLength = [data.get() length];
+ mig_allocate(reinterpret_cast<vm_address_t*>(infoData), *infoLength);
+
+ memcpy(*infoData, [data.get() bytes], *infoLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCEnumerate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ data_t resultData = 0;
+ mach_msg_type_number_t resultLength = 0;
+ boolean_t returnValue = instanceProxy->enumerate(objectID, resultData, resultLength);
+
+ hostProxy = instanceProxy->hostProxy();
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+
+ if (resultData)
+ mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetMenuBarVisible(mach_port_t clientPort, boolean_t menuBarVisible)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ hostProxy->setMenuBarVisible(menuBarVisible);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetFullscreenWindowIsShowing(mach_port_t clientPort, boolean_t fullscreenWindowIsShowing)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ hostProxy->setFullscreenWindowIsShowing(fullscreenWindowIsShowing);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetModal(mach_port_t clientPort, boolean_t modal)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ if (!hostProxy->isProcessingRequests()) {
+ hostProxy->setModal(modal);
+ return KERN_SUCCESS;
+ }
+
+ // Defer the work
+ CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+ if (NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort))
+ hostProxy->setModal(modal);
+ });
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetCookies(mach_port_t clientPort, uint32_t pluginID,
+ data_t urlData, mach_msg_type_number_t urlLength,
+ boolean_t* returnValue, data_t* cookiesData, mach_msg_type_number_t* cookiesLength)
+{
+ *cookiesData = 0;
+ *cookiesLength = 0;
+
+ DataDeallocator deallocator(urlData, urlLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ *returnValue = instanceProxy->getCookies(urlData, urlLength, *cookiesData, *cookiesLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetProxy(mach_port_t clientPort, uint32_t pluginID,
+ data_t urlData, mach_msg_type_number_t urlLength,
+ boolean_t* returnValue, data_t* proxyData, mach_msg_type_number_t* proxyLength)
+{
+ *proxyData = 0;
+ *proxyLength = 0;
+
+ DataDeallocator deallocator(urlData, urlLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ *returnValue = instanceProxy->getProxy(urlData, urlLength, *proxyData, *proxyLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetCookies(mach_port_t clientPort, uint32_t pluginID,
+ data_t urlData, mach_msg_type_number_t urlLength,
+ data_t cookiesData, mach_msg_type_number_t cookiesLength,
+ boolean_t* returnValue)
+{
+ DataDeallocator urlDeallocator(urlData, urlLength);
+ DataDeallocator cookiesDeallocator(cookiesData, cookiesLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ *returnValue = instanceProxy->setCookies(urlData, urlLength, cookiesData, cookiesLength);
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetAuthenticationInfo(mach_port_t clientPort, uint32_t pluginID,
+ data_t protocolData, mach_msg_type_number_t protocolLength,
+ data_t hostData, mach_msg_type_number_t hostLength,
+ uint32_t port,
+ data_t schemeData, mach_msg_type_number_t schemeLength,
+ data_t realmData, mach_msg_type_number_t realmLength,
+ boolean_t* returnValue,
+ data_t* usernameData, mach_msg_type_number_t *usernameLength,
+ data_t* passwordData, mach_msg_type_number_t *passwordLength)
+{
+ DataDeallocator protocolDeallocator(protocolData, protocolLength);
+ DataDeallocator hostDeallocator(hostData, hostLength);
+ DataDeallocator schemeDeallocator(schemeData, schemeLength);
+ DataDeallocator realmDeallocator(realmData, realmLength);
+
+ *usernameData = 0;
+ *usernameLength = 0;
+ *passwordData = 0;
+ *passwordLength = 0;
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ *returnValue = instanceProxy->getAuthenticationInfo(protocolData, hostData, port, schemeData, realmData, *usernameData, *usernameLength, *passwordData, *passwordLength);
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCConvertPoint(mach_port_t clientPort, uint32_t pluginID,
+ double sourceX, double sourceY, uint32_t sourceSpace,
+ uint32_t destSpace, boolean_t *returnValue, double *destX, double *destY)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ *returnValue = instanceProxy->convertPoint(sourceX, sourceY, static_cast<NPCoordinateSpace>(sourceSpace),
+ *destX, *destY, static_cast<NPCoordinateSpace>(destSpace));
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCCheckIfAllowedToLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t urlData, mach_msg_type_number_t urlLength,
+ data_t targetData, mach_msg_type_number_t targetLength, uint32_t *checkID)
+{
+ DataDeallocator urlDeallocator(urlData, urlLength);
+ DataDeallocator targetDeallocator(targetData, targetLength);
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ *checkID = instanceProxy->checkIfAllowedToLoadURL(urlData, targetData);
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCCancelCheckIfAllowedToLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t checkID)
+{
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ instanceProxy->cancelCheckIfAllowedToLoadURL(checkID);
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCResolveURL(mach_port_t clientPort, uint32_t pluginID, data_t urlData, mach_msg_type_number_t urlLength,
+ data_t targetData, mach_msg_type_number_t targetLength,
+ data_t *resolvedURLData, mach_msg_type_number_t *resolvedURLLength)
+{
+ DataDeallocator urlDeallocator(urlData, urlLength);
+ DataDeallocator targetDeallocator(targetData, targetLength);
+
+ *resolvedURLData = 0;
+ *resolvedURLLength = 0;
+
+ NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+ if (!hostProxy)
+ return KERN_FAILURE;
+
+ NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+ if (!instanceProxy)
+ return KERN_FAILURE;
+
+ instanceProxy->resolveURL(urlData, targetData, *resolvedURLData, *resolvedURLLength);
+ return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetException(mach_port_t clientPort, data_t message, mach_msg_type_number_t messageCnt)
+{
+ DataDeallocator deallocator(message, messageCnt);
+
+ string str(message, messageCnt);
+ NetscapePluginInstanceProxy::setGlobalException(str.c_str());
+
+ return KERN_SUCCESS;
+}
+
+#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
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)
diff --git a/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm
new file mode 100644
index 0000000..ecaa0d6
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm
@@ -0,0 +1,1684 @@
+/*
+ * 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) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "NetscapePluginInstanceProxy.h"
+
+#import "HostedNetscapePluginStream.h"
+#import "NetscapePluginHostProxy.h"
+#import "ProxyInstance.h"
+#import "ProxyRuntimeObject.h"
+#import "WebDataSourceInternal.h"
+#import "WebFrameInternal.h"
+#import "WebHostedNetscapePluginView.h"
+#import "WebKitNSStringExtras.h"
+#import "WebNSDataExtras.h"
+#import "WebNSURLExtras.h"
+#import "WebPluginRequest.h"
+#import "WebUIDelegate.h"
+#import "WebUIDelegatePrivate.h"
+#import "WebViewInternal.h"
+#import <JavaScriptCore/Error.h>
+#import <JavaScriptCore/JSLock.h>
+#import <JavaScriptCore/PropertyNameArray.h>
+#import <WebCore/CookieJar.h>
+#import <WebCore/DocumentLoader.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/FrameTree.h>
+#import <WebCore/KURL.h>
+#import <WebCore/ProxyServer.h>
+#import <WebCore/SecurityOrigin.h>
+#import <WebCore/ScriptController.h>
+#import <WebCore/ScriptValue.h>
+#import <WebCore/StringSourceProvider.h>
+#import <WebCore/npruntime_impl.h>
+#import <WebCore/runtime_object.h>
+#import <WebKitSystemInterface.h>
+#import <mach/mach.h>
+#import <utility>
+#import <wtf/RefCountedLeakCounter.h>
+#import <wtf/text/CString.h>
+
+extern "C" {
+#import "WebKitPluginClientServer.h"
+#import "WebKitPluginHost.h"
+}
+
+using namespace JSC;
+using namespace JSC::Bindings;
+using namespace std;
+using namespace WebCore;
+
+namespace WebKit {
+
+class NetscapePluginInstanceProxy::PluginRequest : public RefCounted<NetscapePluginInstanceProxy::PluginRequest> {
+public:
+ static PassRefPtr<PluginRequest> create(uint32_t requestID, NSURLRequest* request, NSString* frameName, bool allowPopups)
+ {
+ return adoptRef(new PluginRequest(requestID, request, frameName, allowPopups));
+ }
+
+ uint32_t requestID() const { return m_requestID; }
+ NSURLRequest* request() const { return m_request.get(); }
+ NSString* frameName() const { return m_frameName.get(); }
+ bool allowPopups() const { return m_allowPopups; }
+
+private:
+ PluginRequest(uint32_t requestID, NSURLRequest* request, NSString* frameName, bool allowPopups)
+ : m_requestID(requestID)
+ , m_request(request)
+ , m_frameName(frameName)
+ , m_allowPopups(allowPopups)
+ {
+ }
+
+ uint32_t m_requestID;
+ RetainPtr<NSURLRequest*> m_request;
+ RetainPtr<NSString*> m_frameName;
+ bool m_allowPopups;
+};
+
+NetscapePluginInstanceProxy::LocalObjectMap::LocalObjectMap()
+ : m_objectIDCounter(0)
+{
+}
+
+NetscapePluginInstanceProxy::LocalObjectMap::~LocalObjectMap()
+{
+}
+
+inline bool NetscapePluginInstanceProxy::LocalObjectMap::contains(uint32_t objectID) const
+{
+ return m_idToJSObjectMap.contains(objectID);
+}
+
+inline JSC::JSObject* NetscapePluginInstanceProxy::LocalObjectMap::get(uint32_t objectID) const
+{
+ if (objectID == HashTraits<uint32_t>::emptyValue() || HashTraits<uint32_t>::isDeletedValue(objectID))
+ return 0;
+
+ return m_idToJSObjectMap.get(objectID);
+}
+
+uint32_t NetscapePluginInstanceProxy::LocalObjectMap::idForObject(JSObject* object)
+{
+ // This method creates objects with refcount of 1, but doesn't increase refcount when returning
+ // found objects. This extra count accounts for the main "reference" kept by plugin process.
+
+ // To avoid excessive IPC, plugin process doesn't send each NPObject release/retain call to
+ // Safari. It only sends one when the last reference is removed, and it can destroy the proxy
+ // NPObject.
+
+ // However, the browser may be sending the same object out to plug-in as a function call
+ // argument at the same time - neither side can know what the other one is doing. So,
+ // is to make PCForgetBrowserObject call return a boolean result, making it possible for
+ // the browser to make plugin host keep the proxy with zero refcount for a little longer.
+
+ uint32_t objectID = 0;
+
+ HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
+ if (iter != m_jsObjectToIDMap.end())
+ return iter->second.first;
+
+ do {
+ objectID = ++m_objectIDCounter;
+ } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_idToJSObjectMap.contains(objectID));
+
+ m_idToJSObjectMap.set(objectID, object);
+ m_jsObjectToIDMap.set(object, make_pair<uint32_t, uint32_t>(objectID, 1));
+
+ return objectID;
+}
+
+void NetscapePluginInstanceProxy::LocalObjectMap::retain(JSC::JSObject* object)
+{
+ HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
+ ASSERT(iter != m_jsObjectToIDMap.end());
+
+ iter->second.second = iter->second.second + 1;
+}
+
+void NetscapePluginInstanceProxy::LocalObjectMap::release(JSC::JSObject* object)
+{
+ HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
+ ASSERT(iter != m_jsObjectToIDMap.end());
+
+ ASSERT(iter->second.second > 0);
+ iter->second.second = iter->second.second - 1;
+ if (!iter->second.second) {
+ m_idToJSObjectMap.remove(iter->second.first);
+ m_jsObjectToIDMap.remove(iter);
+ }
+}
+
+void NetscapePluginInstanceProxy::LocalObjectMap::clear()
+{
+ m_idToJSObjectMap.clear();
+ m_jsObjectToIDMap.clear();
+}
+
+bool NetscapePluginInstanceProxy::LocalObjectMap::forget(uint32_t objectID)
+{
+ if (objectID == HashTraits<uint32_t>::emptyValue() || HashTraits<uint32_t>::isDeletedValue(objectID)) {
+ LOG_ERROR("NetscapePluginInstanceProxy::LocalObjectMap::forget: local object id %u is not valid.", objectID);
+ return true;
+ }
+
+ HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> >::iterator iter = m_idToJSObjectMap.find(objectID);
+ if (iter == m_idToJSObjectMap.end()) {
+ LOG_ERROR("NetscapePluginInstanceProxy::LocalObjectMap::forget: local object %u doesn't exist.", objectID);
+ return true;
+ }
+
+ HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator rIter = m_jsObjectToIDMap.find(iter->second.get());
+
+ // If the object is being sent to plug-in right now, then it's not the time to forget.
+ if (rIter->second.second != 1)
+ return false;
+
+ m_jsObjectToIDMap.remove(rIter);
+ m_idToJSObjectMap.remove(iter);
+ return true;
+}
+
+static uint32_t pluginIDCounter;
+
+bool NetscapePluginInstanceProxy::m_inDestroy;
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter netscapePluginInstanceProxyCounter("NetscapePluginInstanceProxy");
+#endif
+
+NetscapePluginInstanceProxy::NetscapePluginInstanceProxy(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView, bool fullFramePlugin)
+ : m_pluginHostProxy(pluginHostProxy)
+ , m_pluginView(pluginView)
+ , m_requestTimer(this, &NetscapePluginInstanceProxy::requestTimerFired)
+ , m_currentURLRequestID(0)
+ , m_renderContextID(0)
+ , m_rendererType(UseSoftwareRenderer)
+ , m_waitingForReply(false)
+ , m_urlCheckCounter(0)
+ , m_pluginFunctionCallDepth(0)
+ , m_shouldStopSoon(false)
+ , m_currentRequestID(0)
+ , m_pluginIsWaitingForDraw(false)
+{
+ ASSERT(m_pluginView);
+
+ if (fullFramePlugin) {
+ // For full frame plug-ins, the first requestID will always be the one for the already
+ // open stream.
+ ++m_currentURLRequestID;
+ }
+
+ // Assign a plug-in ID.
+ do {
+ m_pluginID = ++pluginIDCounter;
+ } while (pluginHostProxy->pluginInstance(m_pluginID) || !m_pluginID);
+
+#ifndef NDEBUG
+ netscapePluginInstanceProxyCounter.increment();
+#endif
+}
+
+PassRefPtr<NetscapePluginInstanceProxy> NetscapePluginInstanceProxy::create(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView, bool fullFramePlugin)
+{
+ RefPtr<NetscapePluginInstanceProxy> proxy = adoptRef(new NetscapePluginInstanceProxy(pluginHostProxy, pluginView, fullFramePlugin));
+ pluginHostProxy->addPluginInstance(proxy.get());
+ return proxy.release();
+}
+
+NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy()
+{
+ ASSERT(!m_pluginHostProxy);
+
+ m_pluginID = 0;
+ deleteAllValues(m_replies);
+
+#ifndef NDEBUG
+ netscapePluginInstanceProxyCounter.decrement();
+#endif
+}
+
+void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect)
+{
+ uint32_t requestID = 0;
+
+ requestID = nextRequestID();
+
+ _WKPHResizePluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID,
+ size.origin.x, size.origin.y, size.size.width, size.size.height,
+ clipRect.origin.x, clipRect.origin.y, clipRect.size.width, clipRect.size.height);
+
+ waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+}
+
+void NetscapePluginInstanceProxy::stopAllStreams()
+{
+ Vector<RefPtr<HostedNetscapePluginStream> > streamsCopy;
+ copyValuesToVector(m_streams, streamsCopy);
+ for (size_t i = 0; i < streamsCopy.size(); i++)
+ streamsCopy[i]->stop();
+}
+
+void NetscapePluginInstanceProxy::cleanup()
+{
+ stopAllStreams();
+
+ m_requestTimer.stop();
+
+ // Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to
+ // to go away when the next garbage collection takes place.
+ m_localObjects.clear();
+
+ if (Frame* frame = core([m_pluginView webFrame]))
+ frame->script()->cleanupScriptObjectsForPlugin(m_pluginView);
+
+ ProxyInstanceSet instances;
+ instances.swap(m_instances);
+
+ // Invalidate all proxy instances.
+ ProxyInstanceSet::const_iterator end = instances.end();
+ for (ProxyInstanceSet::const_iterator it = instances.begin(); it != end; ++it)
+ (*it)->invalidate();
+
+ m_pluginView = nil;
+ m_manualStream = 0;
+}
+
+void NetscapePluginInstanceProxy::invalidate()
+{
+ // If the plug-in host has died, the proxy will be null.
+ if (!m_pluginHostProxy)
+ return;
+
+ m_pluginHostProxy->removePluginInstance(this);
+ m_pluginHostProxy = 0;
+}
+
+void NetscapePluginInstanceProxy::destroy()
+{
+ uint32_t requestID = nextRequestID();
+
+ ASSERT(!m_inDestroy);
+ m_inDestroy = true;
+
+ FrameLoadMap::iterator end = m_pendingFrameLoads.end();
+ for (FrameLoadMap::iterator it = m_pendingFrameLoads.begin(); it != end; ++it)
+ [(it->first) _setInternalLoadDelegate:nil];
+
+ _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID);
+
+ // If the plug-in host crashes while we're waiting for a reply, the last reference to the instance proxy
+ // will go away. Prevent this by protecting it here.
+ RefPtr<NetscapePluginInstanceProxy> protect(this);
+
+ // We don't care about the reply here - we just want to block until the plug-in instance has been torn down.
+ waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+
+ m_inDestroy = false;
+
+ cleanup();
+ invalidate();
+}
+
+void NetscapePluginInstanceProxy::setManualStream(PassRefPtr<HostedNetscapePluginStream> manualStream)
+{
+ ASSERT(!m_manualStream);
+
+ m_manualStream = manualStream;
+}
+
+bool NetscapePluginInstanceProxy::cancelStreamLoad(uint32_t streamID, NPReason reason)
+{
+ HostedNetscapePluginStream* stream = 0;
+
+ if (m_manualStream && streamID == 1)
+ stream = m_manualStream.get();
+ else
+ stream = m_streams.get(streamID).get();
+
+ if (!stream)
+ return false;
+
+ stream->cancelLoad(reason);
+ return true;
+}
+
+void NetscapePluginInstanceProxy::disconnectStream(HostedNetscapePluginStream* stream)
+{
+ if (stream == m_manualStream) {
+ m_manualStream = 0;
+ return;
+ }
+
+ ASSERT(m_streams.get(stream->streamID()) == stream);
+ m_streams.remove(stream->streamID());
+}
+
+void NetscapePluginInstanceProxy::pluginHostDied()
+{
+ m_pluginHostProxy = 0;
+
+ [m_pluginView pluginHostDied];
+
+ cleanup();
+}
+
+void NetscapePluginInstanceProxy::focusChanged(bool hasFocus)
+{
+ _WKPHPluginInstanceFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus);
+}
+
+void NetscapePluginInstanceProxy::windowFocusChanged(bool hasFocus)
+{
+ _WKPHPluginInstanceWindowFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus);
+}
+
+void NetscapePluginInstanceProxy::windowFrameChanged(NSRect frame)
+{
+ _WKPHPluginInstanceWindowFrameChanged(m_pluginHostProxy->port(), m_pluginID, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height,
+ NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]));
+}
+
+void NetscapePluginInstanceProxy::startTimers(bool throttleTimers)
+{
+ _WKPHPluginInstanceStartTimers(m_pluginHostProxy->port(), m_pluginID, throttleTimers);
+}
+
+void NetscapePluginInstanceProxy::mouseEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type)
+{
+ NSPoint screenPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
+ NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil];
+
+ int clickCount;
+ if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited)
+ clickCount = 0;
+ else
+ clickCount = [event clickCount];
+
+
+ _WKPHPluginInstanceMouseEvent(m_pluginHostProxy->port(), m_pluginID,
+ [event timestamp],
+ type, [event modifierFlags],
+ pluginPoint.x, pluginPoint.y,
+ screenPoint.x, screenPoint.y,
+ NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]),
+ [event buttonNumber], clickCount,
+ [event deltaX], [event deltaY], [event deltaZ]);
+}
+
+void NetscapePluginInstanceProxy::keyEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type)
+{
+ NSData *charactersData = [[event characters] dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *charactersIgnoringModifiersData = [[event charactersIgnoringModifiers] dataUsingEncoding:NSUTF8StringEncoding];
+
+ _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID,
+ [event timestamp],
+ type, [event modifierFlags],
+ const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length],
+ const_cast<char*>(reinterpret_cast<const char*>([charactersIgnoringModifiersData bytes])), [charactersIgnoringModifiersData length],
+ [event isARepeat], [event keyCode], WKGetNSEventKeyChar(event));
+}
+
+void NetscapePluginInstanceProxy::syntheticKeyDownWithCommandModifier(int keyCode, char character)
+{
+ NSData *charactersData = [NSData dataWithBytes:&character length:1];
+
+ _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID,
+ [NSDate timeIntervalSinceReferenceDate],
+ NPCocoaEventKeyDown, NSCommandKeyMask,
+ const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length],
+ const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length],
+ false, keyCode, character);
+}
+
+void NetscapePluginInstanceProxy::flagsChanged(NSEvent *event)
+{
+ _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID,
+ [event timestamp], NPCocoaEventFlagsChanged,
+ [event modifierFlags], 0, 0, 0, 0, false, [event keyCode], 0);
+}
+
+void NetscapePluginInstanceProxy::insertText(NSString *text)
+{
+ NSData *textData = [text dataUsingEncoding:NSUTF8StringEncoding];
+
+ _WKPHPluginInstanceInsertText(m_pluginHostProxy->port(), m_pluginID,
+ const_cast<char*>(reinterpret_cast<const char*>([textData bytes])), [textData length]);
+}
+
+bool NetscapePluginInstanceProxy::wheelEvent(NSView *pluginView, NSEvent *event)
+{
+ NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil];
+
+ uint32_t requestID = nextRequestID();
+ _WKPHPluginInstanceWheelEvent(m_pluginHostProxy->port(), m_pluginID, requestID,
+ [event timestamp], [event modifierFlags],
+ pluginPoint.x, pluginPoint.y, [event buttonNumber],
+ [event deltaX], [event deltaY], [event deltaZ]);
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+ if (!reply.get() || !reply->m_result)
+ return false;
+
+ return true;
+}
+
+void NetscapePluginInstanceProxy::print(CGContextRef context, unsigned width, unsigned height)
+{
+ uint32_t requestID = nextRequestID();
+ _WKPHPluginInstancePrint(m_pluginHostProxy->port(), m_pluginID, requestID, width, height);
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
+ if (!reply.get() || !reply->m_returnValue)
+ return;
+
+ RetainPtr<CGDataProvider> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(reply->m_result.get()));
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGImageRef> image(AdoptCF, CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaFirst, dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+
+ // Flip the context and draw the image.
+ CGContextSaveGState(context);
+ CGContextTranslateCTM(context, 0.0, height);
+ CGContextScaleCTM(context, 1.0, -1.0);
+
+ CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get());
+
+ CGContextRestoreGState(context);
+}
+
+void NetscapePluginInstanceProxy::snapshot(CGContextRef context, unsigned width, unsigned height)
+{
+ uint32_t requestID = nextRequestID();
+ _WKPHPluginInstanceSnapshot(m_pluginHostProxy->port(), m_pluginID, requestID, width, height);
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
+ if (!reply.get() || !reply->m_returnValue)
+ return;
+
+ RetainPtr<CGDataProvider> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(reply->m_result.get()));
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGImageRef> image(AdoptCF, CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+
+ CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get());
+}
+
+void NetscapePluginInstanceProxy::stopTimers()
+{
+ _WKPHPluginInstanceStopTimers(m_pluginHostProxy->port(), m_pluginID);
+}
+
+void NetscapePluginInstanceProxy::status(const char* message)
+{
+ RetainPtr<CFStringRef> status(AdoptCF, CFStringCreateWithCString(0, message ? message : "", kCFStringEncodingUTF8));
+ if (!status)
+ return;
+
+ WebView *wv = [m_pluginView webView];
+ [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status.get()];
+}
+
+NPError NetscapePluginInstanceProxy::loadURL(const char* url, const char* target, const char* postData, uint32_t postLen, LoadURLFlags flags, uint32_t& streamID)
+{
+ if (!url)
+ return NPERR_INVALID_PARAM;
+
+ NSMutableURLRequest *request = [m_pluginView requestWithURLCString:url];
+
+ if (flags & IsPost) {
+ NSData *httpBody = nil;
+
+ if (flags & PostDataIsFile) {
+ // If we're posting a file, buf is either a file URL or a path to the file.
+ if (!postData)
+ return NPERR_INVALID_PARAM;
+ RetainPtr<CFStringRef> bufString(AdoptCF, CFStringCreateWithCString(kCFAllocatorDefault, postData, kCFStringEncodingWindowsLatin1));
+ if (!bufString)
+ return NPERR_INVALID_PARAM;
+
+ NSURL *fileURL = [NSURL _web_URLWithDataAsString:(NSString *)bufString.get()];
+ NSString *path;
+ if ([fileURL isFileURL])
+ path = [fileURL path];
+ else
+ path = (NSString *)bufString.get();
+ httpBody = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]];
+ if (!httpBody)
+ return NPERR_FILE_NOT_FOUND;
+ } else
+ httpBody = [NSData dataWithBytes:postData length:postLen];
+
+ if (![httpBody length])
+ return NPERR_INVALID_PARAM;
+
+ [request setHTTPMethod:@"POST"];
+
+ if (flags & AllowHeadersInPostData) {
+ if ([httpBody _web_startsWithBlankLine])
+ httpBody = [httpBody subdataWithRange:NSMakeRange(1, [httpBody length] - 1)];
+ else {
+ NSInteger location = [httpBody _web_locationAfterFirstBlankLine];
+ if (location != NSNotFound) {
+ // If the blank line is somewhere in the middle of postData, everything before is the header.
+ NSData *headerData = [httpBody subdataWithRange:NSMakeRange(0, location)];
+ NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields];
+ unsigned dataLength = [httpBody length] - location;
+
+ // Sometimes plugins like to set Content-Length themselves when they post,
+ // but CFNetwork does not like that. So we will remove the header
+ // and instead truncate the data to the requested length.
+ NSString *contentLength = [header objectForKey:@"Content-Length"];
+
+ if (contentLength)
+ dataLength = min(static_cast<unsigned>([contentLength intValue]), dataLength);
+ [header removeObjectForKey:@"Content-Length"];
+
+ if ([header count] > 0)
+ [request setAllHTTPHeaderFields:header];
+
+ // Everything after the blank line is the actual content of the POST.
+ httpBody = [httpBody subdataWithRange:NSMakeRange(location, dataLength)];
+ }
+ }
+ }
+
+ if (![httpBody length])
+ return NPERR_INVALID_PARAM;
+
+ // Plug-ins expect to receive uncached data when doing a POST (3347134).
+ [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
+ [request setHTTPBody:httpBody];
+ }
+
+ return loadRequest(request, target, flags & AllowPopups, streamID);
+}
+
+void NetscapePluginInstanceProxy::performRequest(PluginRequest* pluginRequest)
+{
+ ASSERT(m_pluginView);
+
+ NSURLRequest *request = pluginRequest->request();
+ NSString *frameName = pluginRequest->frameName();
+ WebFrame *frame = nil;
+
+ NSURL *URL = [request URL];
+ NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
+
+ ASSERT(frameName || JSString);
+ if (frameName) {
+ // FIXME - need to get rid of this window creation which
+ // bypasses normal targeted link handling
+ frame = kit(core([m_pluginView webFrame])->loader()->findFrameForNavigation(frameName));
+ if (!frame) {
+ WebView *currentWebView = [m_pluginView webView];
+ NSDictionary *features = [[NSDictionary alloc] init];
+ WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView
+ createWebViewWithRequest:nil
+ windowFeatures:features];
+ [features release];
+
+ if (!newWebView) {
+ _WKPHLoadURLNotify(m_pluginHostProxy->port(), m_pluginID, pluginRequest->requestID(), NPERR_GENERIC_ERROR);
+ return;
+ }
+
+ frame = [newWebView mainFrame];
+ core(frame)->tree()->setName(frameName);
+ [[newWebView _UIDelegateForwarder] webViewShow:newWebView];
+ }
+ }
+
+ if (JSString) {
+ ASSERT(!frame || [m_pluginView webFrame] == frame);
+ evaluateJavaScript(pluginRequest);
+ } else {
+ [frame loadRequest:request];
+
+ // Check if another plug-in view or even this view is waiting for the frame to load.
+ // If it is, tell it that the load was cancelled because it will be anyway.
+ WebHostedNetscapePluginView *view = [frame _internalLoadDelegate];
+ if (view != nil) {
+ ASSERT([view isKindOfClass:[WebHostedNetscapePluginView class]]);
+ [view webFrame:frame didFinishLoadWithReason:NPRES_USER_BREAK];
+ }
+ m_pendingFrameLoads.set(frame, pluginRequest);
+ [frame _setInternalLoadDelegate:m_pluginView];
+ }
+
+}
+
+void NetscapePluginInstanceProxy::webFrameDidFinishLoadWithReason(WebFrame* webFrame, NPReason reason)
+{
+ FrameLoadMap::iterator it = m_pendingFrameLoads.find(webFrame);
+ ASSERT(it != m_pendingFrameLoads.end());
+
+ PluginRequest* pluginRequest = it->second.get();
+ _WKPHLoadURLNotify(m_pluginHostProxy->port(), m_pluginID, pluginRequest->requestID(), reason);
+
+ m_pendingFrameLoads.remove(it);
+
+ [webFrame _setInternalLoadDelegate:nil];
+}
+
+void NetscapePluginInstanceProxy::evaluateJavaScript(PluginRequest* pluginRequest)
+{
+ NSURL *URL = [pluginRequest->request() URL];
+ NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
+ ASSERT(JSString);
+
+ NSString *result = [[m_pluginView webFrame] _stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:pluginRequest->allowPopups()];
+
+ // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop.
+ if (!m_pluginHostProxy)
+ return;
+
+ if (pluginRequest->frameName() != nil)
+ return;
+
+ if ([result length] > 0) {
+ // Don't call NPP_NewStream and other stream methods if there is no JS result to deliver. This is what Mozilla does.
+ NSData *JSData = [result dataUsingEncoding:NSUTF8StringEncoding];
+
+ RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, pluginRequest->requestID(), pluginRequest->request());
+ m_streams.add(stream->streamID(), stream);
+
+ RetainPtr<NSURLResponse> response(AdoptNS, [[NSURLResponse alloc] initWithURL:URL
+ MIMEType:@"text/plain"
+ expectedContentLength:[JSData length]
+ textEncodingName:nil]);
+ stream->startStreamWithResponse(response.get());
+ stream->didReceiveData(0, static_cast<const char*>([JSData bytes]), [JSData length]);
+ stream->didFinishLoading(0);
+ }
+}
+
+void NetscapePluginInstanceProxy::requestTimerFired(Timer<NetscapePluginInstanceProxy>*)
+{
+ ASSERT(!m_pluginRequests.isEmpty());
+ ASSERT(m_pluginView);
+
+ RefPtr<PluginRequest> request = m_pluginRequests.first();
+ m_pluginRequests.removeFirst();
+
+ if (!m_pluginRequests.isEmpty())
+ m_requestTimer.startOneShot(0);
+
+ performRequest(request.get());
+}
+
+NPError NetscapePluginInstanceProxy::loadRequest(NSURLRequest *request, const char* cTarget, bool allowPopups, uint32_t& requestID)
+{
+ NSURL *URL = [request URL];
+
+ if (!URL)
+ return NPERR_INVALID_URL;
+
+ // Don't allow requests to be loaded when the document loader is stopping all loaders.
+ DocumentLoader* documentLoader = [[m_pluginView dataSource] _documentLoader];
+ if (!documentLoader || documentLoader->isStopping())
+ return NPERR_GENERIC_ERROR;
+
+ NSString *target = nil;
+ if (cTarget) {
+ // Find the frame given the target string.
+ target = [NSString stringWithCString:cTarget encoding:NSISOLatin1StringEncoding];
+ }
+ WebFrame *frame = [m_pluginView webFrame];
+
+ // don't let a plugin start any loads if it is no longer part of a document that is being
+ // displayed unless the loads are in the same frame as the plugin.
+ if (documentLoader != core([m_pluginView webFrame])->loader()->activeDocumentLoader() &&
+ (!cTarget || [frame findFrameNamed:target] != frame)) {
+ return NPERR_GENERIC_ERROR;
+ }
+
+ NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
+ if (JSString != nil) {
+ if (![[[m_pluginView webView] preferences] isJavaScriptEnabled]) {
+ // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does.
+ return NPERR_GENERIC_ERROR;
+ }
+ } else {
+ if (!core([m_pluginView webFrame])->document()->securityOrigin()->canDisplay(URL))
+ return NPERR_GENERIC_ERROR;
+ }
+
+ // FIXME: Handle wraparound
+ requestID = ++m_currentURLRequestID;
+
+ if (cTarget || JSString) {
+ // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't
+ // want to potentially kill the plug-in inside of its URL request.
+
+ if (JSString && target && [frame findFrameNamed:target] != frame) {
+ // For security reasons, only allow JS requests to be made on the frame that contains the plug-in.
+ return NPERR_INVALID_PARAM;
+ }
+
+ RefPtr<PluginRequest> pluginRequest = PluginRequest::create(requestID, request, target, allowPopups);
+ m_pluginRequests.append(pluginRequest.release());
+ m_requestTimer.startOneShot(0);
+ } else {
+ RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, requestID, request);
+
+ ASSERT(!m_streams.contains(requestID));
+ m_streams.add(requestID, stream);
+ stream->start();
+ }
+
+ return NPERR_NO_ERROR;
+}
+
+NetscapePluginInstanceProxy::Reply* NetscapePluginInstanceProxy::processRequestsAndWaitForReply(uint32_t requestID)
+{
+ Reply* reply = 0;
+
+ ASSERT(m_pluginHostProxy);
+ while (!(reply = m_replies.take(requestID))) {
+ if (!m_pluginHostProxy->processRequests())
+ return 0;
+
+ // The host proxy can be destroyed while executing a nested processRequests() call, in which case it's normal
+ // to get a success result, but be unable to keep looping.
+ if (!m_pluginHostProxy)
+ return 0;
+ }
+
+ ASSERT(reply);
+ return reply;
+}
+
+// NPRuntime support
+bool NetscapePluginInstanceProxy::getWindowNPObject(uint32_t& objectID)
+{
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
+ objectID = 0;
+ else
+ objectID = m_localObjects.idForObject(frame->script()->windowShell(pluginWorld())->window());
+
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::getPluginElementNPObject(uint32_t& objectID)
+{
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ if (JSObject* object = frame->script()->jsObjectForPluginElement([m_pluginView element]))
+ objectID = m_localObjects.idForObject(object);
+ else
+ objectID = 0;
+
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::forgetBrowserObjectID(uint32_t objectID)
+{
+ return m_localObjects.forget(objectID);
+}
+
+bool NetscapePluginInstanceProxy::evaluate(uint32_t objectID, const String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups)
+{
+ resultData = 0;
+ resultLength = 0;
+
+ if (m_inDestroy)
+ return false;
+
+ if (!m_localObjects.contains(objectID)) {
+ LOG_ERROR("NetscapePluginInstanceProxy::evaluate: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(pluginWorld());
+ ExecState* exec = globalObject->globalExec();
+
+ bool oldAllowPopups = frame->script()->allowPopupsFromPlugin();
+ frame->script()->setAllowPopupsFromPlugin(allowPopups);
+
+ globalObject->globalData().timeoutChecker.start();
+ Completion completion = JSC::evaluate(exec, globalObject->globalScopeChain(), makeSource(script));
+ globalObject->globalData().timeoutChecker.stop();
+ ComplType type = completion.complType();
+
+ frame->script()->setAllowPopupsFromPlugin(oldAllowPopups);
+
+ JSValue result;
+ if (type == Normal)
+ result = completion.value();
+
+ if (!result)
+ result = jsUndefined();
+
+ marshalValue(exec, result, resultData, resultLength);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::invoke(uint32_t objectID, const Identifier& methodName, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ resultData = 0;
+ resultLength = 0;
+
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::invoke: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue function = object->get(exec, methodName);
+ CallData callData;
+ CallType callType = getCallData(function, callData);
+ if (callType == CallTypeNone)
+ return false;
+
+ MarkedArgumentBuffer argList;
+ demarshalValues(exec, argumentsData, argumentsLength, argList);
+
+ ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(pluginWorld());
+ globalObject->globalData().timeoutChecker.start();
+ JSValue value = call(exec, function, callType, callData, object, argList);
+ globalObject->globalData().timeoutChecker.stop();
+
+ marshalValue(exec, value, resultData, resultLength);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::invokeDefault: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ CallData callData;
+ CallType callType = object->getCallData(callData);
+ if (callType == CallTypeNone)
+ return false;
+
+ MarkedArgumentBuffer argList;
+ demarshalValues(exec, argumentsData, argumentsLength, argList);
+
+ ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(pluginWorld());
+ globalObject->globalData().timeoutChecker.start();
+ JSValue value = call(exec, object, callType, callData, object, argList);
+ globalObject->globalData().timeoutChecker.stop();
+
+ marshalValue(exec, value, resultData, resultLength);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::construct: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+
+ ConstructData constructData;
+ ConstructType constructType = object->getConstructData(constructData);
+ if (constructType == ConstructTypeNone)
+ return false;
+
+ MarkedArgumentBuffer argList;
+ demarshalValues(exec, argumentsData, argumentsLength, argList);
+
+ ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(pluginWorld());
+ globalObject->globalData().timeoutChecker.start();
+ JSValue value = JSC::construct(exec, object, constructType, constructData, argList);
+ globalObject->globalData().timeoutChecker.stop();
+
+ marshalValue(exec, value, resultData, resultLength);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, const Identifier& propertyName, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::getProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue value = object->get(exec, propertyName);
+
+ marshalValue(exec, value, resultData, resultLength);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, unsigned propertyName, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::getProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue value = object->get(exec, propertyName);
+
+ marshalValue(exec, value, resultData, resultLength);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, const Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::setProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+
+ JSValue value = demarshalValue(exec, valueData, valueLength);
+ PutPropertySlot slot;
+ object->put(exec, propertyName, value, slot);
+
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::setProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+
+ JSValue value = demarshalValue(exec, valueData, valueLength);
+ object->put(exec, propertyName, value);
+
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, const Identifier& propertyName)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::removeProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ if (!object->hasProperty(exec, propertyName)) {
+ exec->clearException();
+ return false;
+ }
+
+ JSLock lock(SilenceAssertionsOnly);
+ object->deleteProperty(exec, propertyName);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, unsigned propertyName)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::removeProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ if (!object->hasProperty(exec, propertyName)) {
+ exec->clearException();
+ return false;
+ }
+
+ JSLock lock(SilenceAssertionsOnly);
+ object->deleteProperty(exec, propertyName);
+ exec->clearException();
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, const Identifier& propertyName)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::hasProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ bool result = object->hasProperty(exec, propertyName);
+ exec->clearException();
+
+ return result;
+}
+
+bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, unsigned propertyName)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::hasProperty: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ bool result = object->hasProperty(exec, propertyName);
+ exec->clearException();
+
+ return result;
+}
+
+bool NetscapePluginInstanceProxy::hasMethod(uint32_t objectID, const Identifier& methodName)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::hasMethod: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue func = object->get(exec, methodName);
+ exec->clearException();
+ return !func.isUndefined();
+}
+
+bool NetscapePluginInstanceProxy::enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ if (m_inDestroy)
+ return false;
+
+ JSObject* object = m_localObjects.get(objectID);
+ if (!object) {
+ LOG_ERROR("NetscapePluginInstanceProxy::enumerate: local object %u doesn't exist.", objectID);
+ return false;
+ }
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+
+ PropertyNameArray propertyNames(exec);
+ object->getPropertyNames(exec, propertyNames);
+
+ RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]);
+ for (unsigned i = 0; i < propertyNames.size(); i++) {
+ uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(propertyNames[i].ustring().utf8().data()));
+
+ [array.get() addObject:[NSNumber numberWithLongLong:methodName]];
+ }
+
+ NSData *data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+ ASSERT(data);
+
+ resultLength = [data length];
+ mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength);
+
+ memcpy(resultData, [data bytes], resultLength);
+
+ exec->clearException();
+
+ return true;
+}
+
+void NetscapePluginInstanceProxy::addValueToArray(NSMutableArray *array, ExecState* exec, JSValue value)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ if (value.isString()) {
+ [array addObject:[NSNumber numberWithInt:StringValueType]];
+ [array addObject:ustringToString(value.toString(exec))];
+ } else if (value.isNumber()) {
+ [array addObject:[NSNumber numberWithInt:DoubleValueType]];
+ [array addObject:[NSNumber numberWithDouble:value.toNumber(exec)]];
+ } else if (value.isBoolean()) {
+ [array addObject:[NSNumber numberWithInt:BoolValueType]];
+ [array addObject:[NSNumber numberWithBool:value.toBoolean(exec)]];
+ } else if (value.isNull())
+ [array addObject:[NSNumber numberWithInt:NullValueType]];
+ else if (value.isObject()) {
+ JSObject* object = asObject(value);
+ if (object->classInfo() == &ProxyRuntimeObject::s_info) {
+ ProxyRuntimeObject* runtimeObject = static_cast<ProxyRuntimeObject*>(object);
+ if (ProxyInstance* instance = runtimeObject->getInternalProxyInstance()) {
+ [array addObject:[NSNumber numberWithInt:NPObjectValueType]];
+ [array addObject:[NSNumber numberWithInt:instance->objectID()]];
+ }
+ } else {
+ [array addObject:[NSNumber numberWithInt:JSObjectValueType]];
+ [array addObject:[NSNumber numberWithInt:m_localObjects.idForObject(object)]];
+ }
+ } else
+ [array addObject:[NSNumber numberWithInt:VoidValueType]];
+}
+
+void NetscapePluginInstanceProxy::marshalValue(ExecState* exec, JSValue value, data_t& resultData, mach_msg_type_number_t& resultLength)
+{
+ RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]);
+
+ addValueToArray(array.get(), exec, value);
+
+ RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+ ASSERT(data);
+
+ resultLength = [data.get() length];
+ mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength);
+
+ memcpy(resultData, [data.get() bytes], resultLength);
+}
+
+RetainPtr<NSData *> NetscapePluginInstanceProxy::marshalValues(ExecState* exec, const ArgList& args)
+{
+ RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]);
+
+ for (unsigned i = 0; i < args.size(); i++)
+ addValueToArray(array.get(), exec, args.at(i));
+
+ RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+ ASSERT(data);
+
+ return data;
+}
+
+bool NetscapePluginInstanceProxy::demarshalValueFromArray(ExecState* exec, NSArray *array, NSUInteger& index, JSValue& result)
+{
+ if (index == [array count])
+ return false;
+
+ int type = [[array objectAtIndex:index++] intValue];
+ switch (type) {
+ case VoidValueType:
+ result = jsUndefined();
+ return true;
+ case NullValueType:
+ result = jsNull();
+ return true;
+ case BoolValueType:
+ result = jsBoolean([[array objectAtIndex:index++] boolValue]);
+ return true;
+ case DoubleValueType:
+ result = jsNumber([[array objectAtIndex:index++] doubleValue]);
+ return true;
+ case StringValueType: {
+ NSString *string = [array objectAtIndex:index++];
+
+ result = jsString(exec, String(string));
+ return true;
+ }
+ case JSObjectValueType: {
+ uint32_t objectID = [[array objectAtIndex:index++] intValue];
+
+ result = m_localObjects.get(objectID);
+ ASSERT(result);
+ return true;
+ }
+ case NPObjectValueType: {
+ uint32_t objectID = [[array objectAtIndex:index++] intValue];
+
+ Frame* frame = core([m_pluginView webFrame]);
+ if (!frame)
+ return false;
+
+ if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
+ return false;
+
+ RefPtr<RootObject> rootObject = frame->script()->createRootObject(m_pluginView);
+ if (!rootObject)
+ return false;
+
+ result = ProxyInstance::create(rootObject.release(), this, objectID)->createRuntimeObject(exec);
+ return true;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+}
+
+JSValue NetscapePluginInstanceProxy::demarshalValue(ExecState* exec, const char* valueData, mach_msg_type_number_t valueLength)
+{
+ RetainPtr<NSData*> data(AdoptNS, [[NSData alloc] initWithBytesNoCopy:(void*)valueData length:valueLength freeWhenDone:NO]);
+
+ RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get()
+ mutabilityOption:NSPropertyListImmutable
+ format:0
+ errorDescription:0];
+ NSUInteger position = 0;
+ JSValue value;
+ bool result = demarshalValueFromArray(exec, array.get(), position, value);
+ ASSERT_UNUSED(result, result);
+
+ return value;
+}
+
+void NetscapePluginInstanceProxy::demarshalValues(ExecState* exec, data_t valuesData, mach_msg_type_number_t valuesLength, MarkedArgumentBuffer& result)
+{
+ RetainPtr<NSData*> data(AdoptNS, [[NSData alloc] initWithBytesNoCopy:valuesData length:valuesLength freeWhenDone:NO]);
+
+ RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get()
+ mutabilityOption:NSPropertyListImmutable
+ format:0
+ errorDescription:0];
+ NSUInteger position = 0;
+ JSValue value;
+ while (demarshalValueFromArray(exec, array.get(), position, value))
+ result.append(value);
+}
+
+void NetscapePluginInstanceProxy::retainLocalObject(JSC::JSValue value)
+{
+ if (!value.isObject() || value.inherits(&ProxyRuntimeObject::s_info))
+ return;
+
+ m_localObjects.retain(asObject(value));
+}
+
+void NetscapePluginInstanceProxy::releaseLocalObject(JSC::JSValue value)
+{
+ if (!value.isObject() || value.inherits(&ProxyRuntimeObject::s_info))
+ return;
+
+ m_localObjects.release(asObject(value));
+}
+
+PassRefPtr<Instance> NetscapePluginInstanceProxy::createBindingsInstance(PassRefPtr<RootObject> rootObject)
+{
+ uint32_t requestID = nextRequestID();
+
+ if (_WKPHGetScriptableNPObject(m_pluginHostProxy->port(), m_pluginID, requestID) != KERN_SUCCESS)
+ return 0;
+
+ auto_ptr<GetScriptableNPObjectReply> reply = waitForReply<GetScriptableNPObjectReply>(requestID);
+ if (!reply.get())
+ return 0;
+
+ if (!reply->m_objectID)
+ return 0;
+
+ // Since the reply was non-null, "this" is still a valid pointer.
+ return ProxyInstance::create(rootObject, this, reply->m_objectID);
+}
+
+void NetscapePluginInstanceProxy::addInstance(ProxyInstance* instance)
+{
+ ASSERT(!m_instances.contains(instance));
+
+ m_instances.add(instance);
+}
+
+void NetscapePluginInstanceProxy::removeInstance(ProxyInstance* instance)
+{
+ ASSERT(m_instances.contains(instance));
+
+ m_instances.remove(instance);
+}
+
+void NetscapePluginInstanceProxy::willCallPluginFunction()
+{
+ m_pluginFunctionCallDepth++;
+}
+
+void NetscapePluginInstanceProxy::didCallPluginFunction(bool& stopped)
+{
+ ASSERT(m_pluginFunctionCallDepth > 0);
+ m_pluginFunctionCallDepth--;
+
+ // If -stop was called while we were calling into a plug-in function, and we're no longer
+ // inside a plug-in function, stop now.
+ if (!m_pluginFunctionCallDepth && m_shouldStopSoon) {
+ m_shouldStopSoon = false;
+ [m_pluginView stop];
+ stopped = true;
+ }
+}
+
+bool NetscapePluginInstanceProxy::shouldStop()
+{
+ if (m_pluginFunctionCallDepth) {
+ m_shouldStopSoon = true;
+ return false;
+ }
+
+ return true;
+}
+
+uint32_t NetscapePluginInstanceProxy::nextRequestID()
+{
+ uint32_t requestID = ++m_currentRequestID;
+
+ // We don't want to return the HashMap empty/deleted "special keys"
+ if (requestID == 0 || requestID == static_cast<uint32_t>(-1))
+ return nextRequestID();
+
+ return requestID;
+}
+
+void NetscapePluginInstanceProxy::invalidateRect(double x, double y, double width, double height)
+{
+ ASSERT(m_pluginView);
+
+ m_pluginIsWaitingForDraw = true;
+ [m_pluginView invalidatePluginContentRect:NSMakeRect(x, y, width, height)];
+}
+
+void NetscapePluginInstanceProxy::didDraw()
+{
+ if (!m_pluginIsWaitingForDraw)
+ return;
+
+ m_pluginIsWaitingForDraw = false;
+ _WKPHPluginInstanceDidDraw(m_pluginHostProxy->port(), m_pluginID);
+}
+
+bool NetscapePluginInstanceProxy::getCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t& cookiesData, mach_msg_type_number_t& cookiesLength)
+{
+ ASSERT(m_pluginView);
+
+ NSURL *url = [m_pluginView URLWithCString:urlData];
+ if (!url)
+ return false;
+
+ if (Frame* frame = core([m_pluginView webFrame])) {
+ String cookieString = cookies(frame->document(), url);
+ WTF::CString cookieStringUTF8 = cookieString.utf8();
+ if (cookieStringUTF8.isNull())
+ return false;
+
+ cookiesLength = cookieStringUTF8.length();
+ mig_allocate(reinterpret_cast<vm_address_t*>(&cookiesData), cookiesLength);
+ memcpy(cookiesData, cookieStringUTF8.data(), cookiesLength);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool NetscapePluginInstanceProxy::setCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t cookiesData, mach_msg_type_number_t cookiesLength)
+{
+ ASSERT(m_pluginView);
+
+ NSURL *url = [m_pluginView URLWithCString:urlData];
+ if (!url)
+ return false;
+
+ if (Frame* frame = core([m_pluginView webFrame])) {
+ String cookieString = String::fromUTF8(cookiesData, cookiesLength);
+ if (!cookieString)
+ return false;
+
+ WebCore::setCookies(frame->document(), url, cookieString);
+ return true;
+ }
+
+ return false;
+}
+
+bool NetscapePluginInstanceProxy::getProxy(data_t urlData, mach_msg_type_number_t urlLength, data_t& proxyData, mach_msg_type_number_t& proxyLength)
+{
+ ASSERT(m_pluginView);
+
+ NSURL *url = [m_pluginView URLWithCString:urlData];
+ if (!url)
+ return false;
+
+ Vector<ProxyServer> proxyServers = proxyServersForURL(url, 0);
+ WTF::CString proxyStringUTF8 = toString(proxyServers).utf8();
+
+ proxyLength = proxyStringUTF8.length();
+ mig_allocate(reinterpret_cast<vm_address_t*>(&proxyData), proxyLength);
+ memcpy(proxyData, proxyStringUTF8.data(), proxyLength);
+
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::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)
+{
+ WTF::CString username;
+ WTF::CString password;
+
+ if (!WebKit::getAuthenticationInfo(protocolData, hostData, port, schemeData, realmData, username, password))
+ return false;
+
+ usernameLength = username.length();
+ mig_allocate(reinterpret_cast<vm_address_t*>(&usernameData), usernameLength);
+ memcpy(usernameData, username.data(), usernameLength);
+
+ passwordLength = password.length();
+ mig_allocate(reinterpret_cast<vm_address_t*>(&passwordData), passwordLength);
+ memcpy(passwordData, password.data(), passwordLength);
+
+ return true;
+}
+
+bool NetscapePluginInstanceProxy::convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
+ double& destX, double& destY, NPCoordinateSpace destSpace)
+{
+ ASSERT(m_pluginView);
+
+ return [m_pluginView convertFromX:sourceX andY:sourceY space:sourceSpace toX:&destX andY:&destY space:destSpace];
+}
+
+uint32_t NetscapePluginInstanceProxy::checkIfAllowedToLoadURL(const char* url, const char* target)
+{
+ uint32_t checkID;
+
+ // Assign a check ID
+ do {
+ checkID = ++m_urlCheckCounter;
+ } while (m_urlChecks.contains(checkID) || !m_urlCheckCounter);
+
+ NSString *frameName = target ? [NSString stringWithCString:target encoding:NSISOLatin1StringEncoding] : nil;
+
+ NSNumber *contextInfo = [[NSNumber alloc] initWithUnsignedInt:checkID];
+ WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:[m_pluginView requestWithURLCString:url]
+ target:frameName
+ resultObject:m_pluginView
+ selector:@selector(_containerCheckResult:contextInfo:)
+ controller:m_pluginView
+ contextInfo:contextInfo];
+
+ [contextInfo release];
+ m_urlChecks.set(checkID, check);
+ [check start];
+
+ return checkID;
+}
+
+void NetscapePluginInstanceProxy::cancelCheckIfAllowedToLoadURL(uint32_t checkID)
+{
+ URLCheckMap::iterator it = m_urlChecks.find(checkID);
+ if (it == m_urlChecks.end())
+ return;
+
+ WebPluginContainerCheck *check = it->second.get();
+ [check cancel];
+ m_urlChecks.remove(it);
+}
+
+void NetscapePluginInstanceProxy::checkIfAllowedToLoadURLResult(uint32_t checkID, bool allowed)
+{
+ _WKPHCheckIfAllowedToLoadURLResult(m_pluginHostProxy->port(), m_pluginID, checkID, allowed);
+}
+
+void NetscapePluginInstanceProxy::resolveURL(const char* url, const char* target, data_t& resolvedURLData, mach_msg_type_number_t& resolvedURLLength)
+{
+ ASSERT(m_pluginView);
+
+ WTF::CString resolvedURL = [m_pluginView resolvedURLStringForURL:url target:target];
+
+ resolvedURLLength = resolvedURL.length();
+ mig_allocate(reinterpret_cast<vm_address_t*>(&resolvedURLData), resolvedURLLength);
+ memcpy(resolvedURLData, resolvedURL.data(), resolvedURLLength);
+}
+
+void NetscapePluginInstanceProxy::privateBrowsingModeDidChange(bool isPrivateBrowsingEnabled)
+{
+ _WKPHPluginInstancePrivateBrowsingModeDidChange(m_pluginHostProxy->port(), m_pluginID, isPrivateBrowsingEnabled);
+}
+
+static String& globalExceptionString()
+{
+ DEFINE_STATIC_LOCAL(String, exceptionString, ());
+ return exceptionString;
+}
+
+void NetscapePluginInstanceProxy::setGlobalException(const String& exception)
+{
+ globalExceptionString() = exception;
+}
+
+void NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(ExecState* exec)
+{
+ if (globalExceptionString().isNull())
+ return;
+
+ {
+ JSLock lock(SilenceAssertionsOnly);
+ throwError(exec, createError(exec, stringToUString(globalExceptionString())));
+ }
+
+ globalExceptionString() = String();
+}
+
+} // namespace WebKit
+
+#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebKit/mac/Plugins/Hosted/ProxyInstance.h b/Source/WebKit/mac/Plugins/Hosted/ProxyInstance.h
new file mode 100644
index 0000000..b72e49a
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/ProxyInstance.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 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 ProxyInstance_h
+#define ProxyInstance_h
+
+#import "NetscapePluginInstanceProxy.h"
+#import "WebKitPluginHostTypes.h"
+#import <WebCore/Bridge.h>
+#import <WebCore/runtime_root.h>
+#import <wtf/OwnPtr.h>
+
+namespace WebKit {
+
+class ProxyClass;
+
+class ProxyInstance : public JSC::Bindings::Instance {
+public:
+ static PassRefPtr<ProxyInstance> create(PassRefPtr<JSC::Bindings::RootObject> rootObject, NetscapePluginInstanceProxy* instanceProxy, uint32_t objectID)
+ {
+ return adoptRef(new ProxyInstance(rootObject, instanceProxy, objectID));
+ }
+ ~ProxyInstance();
+
+ JSC::Bindings::MethodList methodsNamed(const JSC::Identifier&);
+ JSC::Bindings::Field* fieldNamed(const JSC::Identifier&);
+
+ JSC::JSValue fieldValue(JSC::ExecState*, const JSC::Bindings::Field*) const;
+ void setFieldValue(JSC::ExecState*, const JSC::Bindings::Field*, JSC::JSValue) const;
+
+ void invalidate();
+
+ uint32_t objectID() const { return m_objectID; }
+
+private:
+ ProxyInstance(PassRefPtr<JSC::Bindings::RootObject>, NetscapePluginInstanceProxy*, uint32_t objectID);
+
+ virtual JSC::Bindings::RuntimeObject* newRuntimeObject(JSC::ExecState*);
+
+ virtual JSC::Bindings::Class* getClass() const;
+
+ virtual JSC::JSValue getMethod(JSC::ExecState* exec, const JSC::Identifier& propertyName);
+ virtual JSC::JSValue invokeMethod(JSC::ExecState*, JSC::RuntimeMethod*);
+
+ virtual bool supportsInvokeDefaultMethod() const;
+ virtual JSC::JSValue invokeDefaultMethod(JSC::ExecState*);
+
+ virtual bool supportsConstruct() const;
+ virtual JSC::JSValue invokeConstruct(JSC::ExecState*, const JSC::ArgList&);
+
+ virtual JSC::JSValue defaultValue(JSC::ExecState*, JSC::PreferredPrimitiveType) const;
+ virtual JSC::JSValue valueOf(JSC::ExecState*) const;
+
+ virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+
+ JSC::JSValue stringValue(JSC::ExecState*) const;
+ JSC::JSValue numberValue(JSC::ExecState*) const;
+ JSC::JSValue booleanValue() const;
+
+ JSC::JSValue invoke(JSC::ExecState*, InvokeType, uint64_t identifier, const JSC::ArgList&);
+
+ template <typename T>
+ std::auto_ptr<T> waitForReply(uint32_t requestID) const {
+ std::auto_ptr<T> reply = m_instanceProxy->waitForReply<T>(requestID);
+
+ // If the instance proxy was invalidated, just return a null reply.
+ if (!m_instanceProxy)
+ return std::auto_ptr<T>();
+
+ return reply;
+ }
+
+ NetscapePluginInstanceProxy* m_instanceProxy;
+ uint32_t m_objectID;
+ JSC::Bindings::FieldMap m_fields;
+ JSC::Bindings::MethodMap m_methods;
+};
+
+}
+
+#endif // ProxyInstance_h
+#endif // USE(PLUGIN_HOST_PROCESS)
diff --git a/Source/WebKit/mac/Plugins/Hosted/ProxyInstance.mm b/Source/WebKit/mac/Plugins/Hosted/ProxyInstance.mm
new file mode 100644
index 0000000..927a008
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/ProxyInstance.mm
@@ -0,0 +1,458 @@
+/*
+ * 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) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "ProxyInstance.h"
+
+#import "NetscapePluginHostProxy.h"
+#import "ProxyRuntimeObject.h"
+#import <WebCore/IdentifierRep.h>
+#import <WebCore/JSDOMWindow.h>
+#import <WebCore/npruntime_impl.h>
+#import <WebCore/runtime_method.h>
+#import <runtime/Error.h>
+#import <runtime/PropertyNameArray.h>
+
+extern "C" {
+#import "WebKitPluginHost.h"
+}
+
+using namespace JSC;
+using namespace JSC::Bindings;
+using namespace std;
+using namespace WebCore;
+
+namespace WebKit {
+
+class ProxyClass : public JSC::Bindings::Class {
+private:
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+ virtual Field* fieldNamed(const Identifier&, Instance*) const;
+};
+
+MethodList ProxyClass::methodsNamed(const Identifier& identifier, Instance* instance) const
+{
+ return static_cast<ProxyInstance*>(instance)->methodsNamed(identifier);
+}
+
+Field* ProxyClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+ return static_cast<ProxyInstance*>(instance)->fieldNamed(identifier);
+}
+
+static ProxyClass* proxyClass()
+{
+ DEFINE_STATIC_LOCAL(ProxyClass, proxyClass, ());
+ return &proxyClass;
+}
+
+class ProxyField : public JSC::Bindings::Field {
+public:
+ ProxyField(uint64_t serverIdentifier)
+ : m_serverIdentifier(serverIdentifier)
+ {
+ }
+
+ uint64_t serverIdentifier() const { return m_serverIdentifier; }
+
+private:
+ virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
+
+ uint64_t m_serverIdentifier;
+};
+
+JSValue ProxyField::valueFromInstance(ExecState* exec, const Instance* instance) const
+{
+ return static_cast<const ProxyInstance*>(instance)->fieldValue(exec, this);
+}
+
+void ProxyField::setValueToInstance(ExecState* exec, const Instance* instance, JSValue value) const
+{
+ static_cast<const ProxyInstance*>(instance)->setFieldValue(exec, this, value);
+}
+
+class ProxyMethod : public JSC::Bindings::Method {
+public:
+ ProxyMethod(uint64_t serverIdentifier)
+ : m_serverIdentifier(serverIdentifier)
+ {
+ }
+
+ uint64_t serverIdentifier() const { return m_serverIdentifier; }
+
+private:
+ virtual int numParameters() const { return 0; }
+
+ uint64_t m_serverIdentifier;
+};
+
+ProxyInstance::ProxyInstance(PassRefPtr<RootObject> rootObject, NetscapePluginInstanceProxy* instanceProxy, uint32_t objectID)
+ : Instance(rootObject)
+ , m_instanceProxy(instanceProxy)
+ , m_objectID(objectID)
+{
+ m_instanceProxy->addInstance(this);
+}
+
+ProxyInstance::~ProxyInstance()
+{
+ deleteAllValues(m_fields);
+ deleteAllValues(m_methods);
+
+ if (!m_instanceProxy)
+ return;
+
+ m_instanceProxy->removeInstance(this);
+
+ invalidate();
+}
+
+RuntimeObject* ProxyInstance::newRuntimeObject(ExecState* exec)
+{
+ return new (exec) ProxyRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+JSC::Bindings::Class* ProxyInstance::getClass() const
+{
+ return proxyClass();
+}
+
+JSValue ProxyInstance::invoke(JSC::ExecState* exec, InvokeType type, uint64_t identifier, const ArgList& args)
+{
+ if (!m_instanceProxy)
+ return jsUndefined();
+
+ RetainPtr<NSData*> arguments(m_instanceProxy->marshalValues(exec, args));
+
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ for (unsigned i = 0; i < args.size(); i++)
+ m_instanceProxy->retainLocalObject(args.at(i));
+
+ if (_WKPHNPObjectInvoke(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID,
+ type, identifier, (char*)[arguments.get() bytes], [arguments.get() length]) != KERN_SUCCESS) {
+ if (m_instanceProxy) {
+ for (unsigned i = 0; i < args.size(); i++)
+ m_instanceProxy->releaseLocalObject(args.at(i));
+ }
+ return jsUndefined();
+ }
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
+ NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
+
+ if (m_instanceProxy) {
+ for (unsigned i = 0; i < args.size(); i++)
+ m_instanceProxy->releaseLocalObject(args.at(i));
+ }
+
+ if (!reply.get() || !reply->m_returnValue)
+ return jsUndefined();
+
+ return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get()));
+}
+
+class ProxyRuntimeMethod : public RuntimeMethod {
+public:
+ ProxyRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
+ : RuntimeMethod(exec, globalObject, name, list)
+ {
+ }
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static const ClassInfo s_info;
+};
+
+const ClassInfo ProxyRuntimeMethod::s_info = { "ProxyRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };
+
+JSValue ProxyInstance::getMethod(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ MethodList methodList = getClass()->methodsNamed(propertyName, this);
+ return new (exec) ProxyRuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue ProxyInstance::invokeMethod(ExecState* exec, JSC::RuntimeMethod* runtimeMethod)
+{
+ if (!asObject(runtimeMethod)->inherits(&ProxyRuntimeMethod::s_info))
+ return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));
+
+ const MethodList& methodList = *runtimeMethod->methods();
+
+ ASSERT(methodList.size() == 1);
+
+ ProxyMethod* method = static_cast<ProxyMethod*>(methodList[0]);
+
+ return invoke(exec, Invoke, method->serverIdentifier(), ArgList(exec));
+}
+
+bool ProxyInstance::supportsInvokeDefaultMethod() const
+{
+ if (!m_instanceProxy)
+ return false;
+
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ if (_WKPHNPObjectHasInvokeDefaultMethod(m_instanceProxy->hostProxy()->port(),
+ m_instanceProxy->pluginID(), requestID,
+ m_objectID) != KERN_SUCCESS)
+ return false;
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+ if (reply.get() && reply->m_result)
+ return true;
+
+ return false;
+}
+
+JSValue ProxyInstance::invokeDefaultMethod(ExecState* exec)
+{
+ return invoke(exec, InvokeDefault, 0, ArgList(exec));
+}
+
+bool ProxyInstance::supportsConstruct() const
+{
+ if (!m_instanceProxy)
+ return false;
+
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ if (_WKPHNPObjectHasConstructMethod(m_instanceProxy->hostProxy()->port(),
+ m_instanceProxy->pluginID(), requestID,
+ m_objectID) != KERN_SUCCESS)
+ return false;
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+ if (reply.get() && reply->m_result)
+ return true;
+
+ return false;
+}
+
+JSValue ProxyInstance::invokeConstruct(ExecState* exec, const ArgList& args)
+{
+ return invoke(exec, Construct, 0, args);
+}
+
+JSValue ProxyInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue ProxyInstance::stringValue(ExecState* exec) const
+{
+ // FIXME: Implement something sensible.
+ return jsEmptyString(exec);
+}
+
+JSValue ProxyInstance::numberValue(ExecState*) const
+{
+ // FIXME: Implement something sensible.
+ return jsNumber(0);
+}
+
+JSValue ProxyInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible.
+ return jsBoolean(false);
+}
+
+JSValue ProxyInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+void ProxyInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
+{
+ if (!m_instanceProxy)
+ return;
+
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ if (_WKPHNPObjectEnumerate(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID) != KERN_SUCCESS)
+ return;
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
+ NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
+ if (!reply.get() || !reply->m_returnValue)
+ return;
+
+ RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:(NSData *)reply->m_result.get()
+ mutabilityOption:NSPropertyListImmutable
+ format:0
+ errorDescription:0];
+
+ for (NSNumber *number in array.get()) {
+ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>([number longLongValue]);
+ if (!IdentifierRep::isValid(identifier))
+ continue;
+
+ if (identifier->isString()) {
+ const char* str = identifier->string();
+ nameArray.add(Identifier(JSDOMWindow::commonJSGlobalData(), stringToUString(String::fromUTF8WithLatin1Fallback(str, strlen(str)))));
+ } else
+ nameArray.add(Identifier::from(exec, identifier->number()));
+ }
+}
+
+MethodList ProxyInstance::methodsNamed(const Identifier& identifier)
+{
+ if (!m_instanceProxy)
+ return MethodList();
+
+ // If we already have an entry in the map, use it.
+ MethodMap::iterator existingMapEntry = m_methods.find(identifier.impl());
+ if (existingMapEntry != m_methods.end()) {
+ MethodList methodList;
+ if (existingMapEntry->second)
+ methodList.append(existingMapEntry->second);
+ return methodList;
+ }
+
+ uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii().data()));
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ if (_WKPHNPObjectHasMethod(m_instanceProxy->hostProxy()->port(),
+ m_instanceProxy->pluginID(), requestID,
+ m_objectID, methodName) != KERN_SUCCESS)
+ return MethodList();
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+ if (!reply.get())
+ return MethodList();
+
+ if (!reply->m_result && !m_instanceProxy->hostProxy()->shouldCacheMissingPropertiesAndMethods())
+ return MethodList();
+
+ // Add a new entry to the map unless an entry was added while we were in waitForReply.
+ pair<MethodMap::iterator, bool> mapAddResult = m_methods.add(identifier.impl(), 0);
+ if (mapAddResult.second && reply->m_result)
+ mapAddResult.first->second = new ProxyMethod(methodName);
+
+ MethodList methodList;
+ if (mapAddResult.first->second)
+ methodList.append(mapAddResult.first->second);
+ return methodList;
+}
+
+Field* ProxyInstance::fieldNamed(const Identifier& identifier)
+{
+ if (!m_instanceProxy)
+ return 0;
+
+ // If we already have an entry in the map, use it.
+ FieldMap::iterator existingMapEntry = m_fields.find(identifier.impl());
+ if (existingMapEntry != m_fields.end())
+ return existingMapEntry->second;
+
+ uint64_t propertyName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii().data()));
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ if (_WKPHNPObjectHasProperty(m_instanceProxy->hostProxy()->port(),
+ m_instanceProxy->pluginID(), requestID,
+ m_objectID, propertyName) != KERN_SUCCESS)
+ return 0;
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+ if (!reply.get())
+ return 0;
+
+ if (!reply->m_result && !m_instanceProxy->hostProxy()->shouldCacheMissingPropertiesAndMethods())
+ return 0;
+
+ // Add a new entry to the map unless an entry was added while we were in waitForReply.
+ pair<FieldMap::iterator, bool> mapAddResult = m_fields.add(identifier.impl(), 0);
+ if (mapAddResult.second && reply->m_result)
+ mapAddResult.first->second = new ProxyField(propertyName);
+ return mapAddResult.first->second;
+}
+
+JSC::JSValue ProxyInstance::fieldValue(ExecState* exec, const Field* field) const
+{
+ if (!m_instanceProxy)
+ return jsUndefined();
+
+ uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier();
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ if (_WKPHNPObjectGetProperty(m_instanceProxy->hostProxy()->port(),
+ m_instanceProxy->pluginID(), requestID,
+ m_objectID, serverIdentifier) != KERN_SUCCESS)
+ return jsUndefined();
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
+ NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
+ if (!reply.get() || !reply->m_returnValue)
+ return jsUndefined();
+
+ return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get()));
+}
+
+void ProxyInstance::setFieldValue(ExecState* exec, const Field* field, JSValue value) const
+{
+ if (!m_instanceProxy)
+ return;
+
+ uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier();
+ uint32_t requestID = m_instanceProxy->nextRequestID();
+
+ data_t valueData;
+ mach_msg_type_number_t valueLength;
+
+ m_instanceProxy->marshalValue(exec, value, valueData, valueLength);
+ m_instanceProxy->retainLocalObject(value);
+ kern_return_t kr = _WKPHNPObjectSetProperty(m_instanceProxy->hostProxy()->port(),
+ m_instanceProxy->pluginID(), requestID,
+ m_objectID, serverIdentifier, valueData, valueLength);
+ mig_deallocate(reinterpret_cast<vm_address_t>(valueData), valueLength);
+ if (m_instanceProxy)
+ m_instanceProxy->releaseLocalObject(value);
+ if (kr != KERN_SUCCESS)
+ return;
+
+ auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
+ NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
+}
+
+void ProxyInstance::invalidate()
+{
+ ASSERT(m_instanceProxy);
+
+ if (NetscapePluginHostProxy* hostProxy = m_instanceProxy->hostProxy())
+ _WKPHNPObjectRelease(hostProxy->port(),
+ m_instanceProxy->pluginID(), m_objectID);
+ m_instanceProxy = 0;
+}
+
+} // namespace WebKit
+
+#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
+
diff --git a/Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.h b/Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.h
new file mode 100644
index 0000000..81d9b42
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 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 COMPUTER, 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 ProxyRuntimeObject_h
+#define ProxyRuntimeObject_h
+
+#include <WebCore/runtime_object.h>
+
+namespace WebKit {
+
+class ProxyInstance;
+
+class ProxyRuntimeObject : public JSC::Bindings::RuntimeObject {
+public:
+ ProxyRuntimeObject(JSC::ExecState*, JSC::JSGlobalObject*, PassRefPtr<ProxyInstance>);
+ virtual ~ProxyRuntimeObject();
+
+ ProxyInstance* getInternalProxyInstance() const;
+
+ static const JSC::ClassInfo s_info;
+
+private:
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.mm b/Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.mm
new file mode 100644
index 0000000..96855b3
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/ProxyRuntimeObject.mm
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 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 COMPUTER, 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)
+
+#include "ProxyInstance.h"
+#include "ProxyRuntimeObject.h"
+
+using namespace JSC;
+
+namespace WebKit {
+
+
+const ClassInfo ProxyRuntimeObject::s_info = { "ProxyRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+ProxyRuntimeObject::ProxyRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<ProxyInstance> instance)
+ : RuntimeObject(exec, globalObject, instance)
+{
+}
+
+ProxyRuntimeObject::~ProxyRuntimeObject()
+{
+}
+
+ProxyInstance* ProxyRuntimeObject::getInternalProxyInstance() const
+{
+ return static_cast<ProxyInstance*>(getInternalInstance());
+}
+
+
+}
+
+#endif
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h b/Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h
new file mode 100644
index 0000000..1eb164d
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 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)
+
+#import "WebBaseNetscapePluginView.h"
+#import "WebKitSystemInterface.h"
+
+#import <wtf/RefPtr.h>
+
+namespace WebKit {
+ class HostedNetscapePluginStream;
+ class NetscapePluginInstanceProxy;
+}
+
+@interface WebHostedNetscapePluginView : WebBaseNetscapePluginView<WebPluginManualLoader, WebPluginContainerCheckController>
+{
+ RetainPtr<NSArray> _attributeKeys;
+ RetainPtr<NSArray> _attributeValues;
+
+ RetainPtr<CALayer> _pluginLayer;
+ WKSoftwareCARendererRef _softwareRenderer;
+
+ NSSize _previousSize;
+ RefPtr<WebKit::NetscapePluginInstanceProxy> _proxy;
+}
+
+- (id)initWithFrame:(NSRect)r
+ pluginPackage:(WebNetscapePluginPackage *)thePluginPackage
+ URL:(NSURL *)URL
+ baseURL:(NSURL *)baseURL
+ MIMEType:(NSString *)MIME
+ attributeKeys:(NSArray *)keys
+ attributeValues:(NSArray *)values
+ loadManually:(BOOL)loadManually
+ element:(PassRefPtr<WebCore::HTMLPlugInElement>)element;
+
+- (void)pluginHostDied;
+- (CALayer *)pluginLayer;
+- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithReason:(NPReason)reason;
+
+@end
+
+#endif // USE(PLUGIN_HOST_PROCESS)
+
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm b/Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm
new file mode 100644
index 0000000..5593050
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2008 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) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "WebHostedNetscapePluginView.h"
+
+#import "HostedNetscapePluginStream.h"
+#import "NetscapePluginInstanceProxy.h"
+#import "NetscapePluginHostManager.h"
+#import "NetscapePluginHostProxy.h"
+#import "WebTextInputWindowController.h"
+#import "WebFrameInternal.h"
+#import "WebView.h"
+#import "WebViewInternal.h"
+#import "WebUIDelegate.h"
+
+#import <CoreFoundation/CoreFoundation.h>
+#import <WebCore/Bridge.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameLoaderTypes.h>
+#import <WebCore/FrameView.h>
+#import <WebCore/HTMLPlugInElement.h>
+#import <WebCore/RenderEmbeddedObject.h>
+#import <WebCore/WebCoreObjCExtras.h>
+#import <WebCore/runtime_root.h>
+#import <runtime/InitializeThreading.h>
+#import <wtf/Assertions.h>
+#import <wtf/Threading.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+extern "C" {
+#include "WebKitPluginClientServer.h"
+#include "WebKitPluginHost.h"
+}
+
+@implementation WebHostedNetscapePluginView
+
++ (void)initialize
+{
+ JSC::initializeThreading();
+ WTF::initializeMainThreadToProcessMainThread();
+#ifndef BUILDING_ON_TIGER
+ WebCoreObjCFinalizeOnMainThread(self);
+#endif
+ WKSendUserChangeNotifications();
+}
+
+- (id)initWithFrame:(NSRect)frame
+ pluginPackage:(WebNetscapePluginPackage *)pluginPackage
+ URL:(NSURL *)URL
+ baseURL:(NSURL *)baseURL
+ MIMEType:(NSString *)MIME
+ attributeKeys:(NSArray *)keys
+ attributeValues:(NSArray *)values
+ loadManually:(BOOL)loadManually
+ element:(PassRefPtr<WebCore::HTMLPlugInElement>)element
+{
+ self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually element:element];
+ if (!self)
+ return nil;
+
+ return self;
+}
+
+- (void)handleMouseMoved:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->mouseEvent(self, event, NPCocoaEventMouseMoved);
+}
+
+- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values
+{
+ ASSERT(!_attributeKeys);
+ ASSERT(!_attributeValues);
+
+ _attributeKeys.adoptNS([keys copy]);
+ _attributeValues.adoptNS([values copy]);
+}
+
+- (BOOL)createPlugin
+{
+ ASSERT(!_proxy);
+
+ NSString *userAgent = [[self webView] userAgentForURL:_baseURL.get()];
+ BOOL accleratedCompositingEnabled = false;
+#if USE(ACCELERATED_COMPOSITING)
+ accleratedCompositingEnabled = [[[self webView] preferences] acceleratedCompositingEnabled];
+#endif
+
+ _proxy = NetscapePluginHostManager::shared().instantiatePlugin([_pluginPackage.get() path], [_pluginPackage.get() pluginHostArchitecture], [_pluginPackage.get() bundleIdentifier], self, _MIMEType.get(), _attributeKeys.get(), _attributeValues.get(), userAgent, _sourceURL.get(),
+ _mode == NP_FULL, _isPrivateBrowsingEnabled, accleratedCompositingEnabled);
+ if (!_proxy)
+ return NO;
+
+ if (_proxy->rendererType() == UseSoftwareRenderer)
+ _softwareRenderer = WKSoftwareCARendererCreate(_proxy->renderContextID());
+ else {
+ _pluginLayer = WKMakeRenderLayer(_proxy->renderContextID());
+
+ if (accleratedCompositingEnabled && _proxy->rendererType() == UseAcceleratedCompositing) {
+ // FIXME: This code can be shared between WebHostedNetscapePluginView and WebNetscapePluginView.
+#ifndef BUILDING_ON_LEOPARD
+ // Since this layer isn't going to be inserted into a view, we need to create another layer and flip its geometry
+ // in order to get the coordinate system right.
+ RetainPtr<CALayer> realPluginLayer(AdoptNS, _pluginLayer.releaseRef());
+
+ _pluginLayer.adoptNS([[CALayer alloc] init]);
+ _pluginLayer.get().bounds = realPluginLayer.get().bounds;
+ _pluginLayer.get().geometryFlipped = YES;
+
+ realPluginLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+ [_pluginLayer.get() addSublayer:realPluginLayer.get()];
+#endif
+
+ // Eagerly enter compositing mode, since we know we'll need it. This avoids firing setNeedsStyleRecalc()
+ // for iframes that contain composited plugins at bad times. https://bugs.webkit.org/show_bug.cgi?id=39033
+ core([self webFrame])->view()->enterCompositingMode();
+ [self element]->setNeedsStyleRecalc(SyntheticStyleChange);
+ } else
+ self.wantsLayer = YES;
+ }
+
+ // Update the window frame.
+ _proxy->windowFrameChanged([[self window] frame]);
+
+ return YES;
+}
+
+// FIXME: This method is an ideal candidate to move up to the base class
+- (CALayer *)pluginLayer
+{
+ return _pluginLayer.get();
+}
+
+- (void)setLayer:(CALayer *)newLayer
+{
+ // FIXME: This should use the same implementation as WebNetscapePluginView (and move to the base class).
+ [super setLayer:newLayer];
+
+ if (_pluginLayer)
+ [newLayer addSublayer:_pluginLayer.get()];
+}
+
+- (void)privateBrowsingModeDidChange
+{
+ if (_proxy)
+ _proxy->privateBrowsingModeDidChange(_isPrivateBrowsingEnabled);
+}
+
+- (void)loadStream
+{
+}
+
+- (void)updateAndSetWindow
+{
+ if (!_proxy)
+ return;
+
+ // The base coordinates of a window and it's contentView happen to be the equal at a userSpaceScaleFactor
+ // of 1. For non-1.0 scale factors this assumption is false.
+ NSView *windowContentView = [[self window] contentView];
+ NSRect boundsInWindow = [self convertRect:[self bounds] toView:windowContentView];
+
+ NSRect visibleRectInWindow;
+
+ // Core Animation plug-ins need to be updated (with a 0,0,0,0 clipRect) when
+ // moved to a background tab. We don't do this for Core Graphics plug-ins as
+ // older versions of Flash have historical WebKit-specific code that isn't
+ // compatible with this behavior.
+ BOOL shouldClipOutPlugin = _pluginLayer && [self shouldClipOutPlugin];
+ if (!shouldClipOutPlugin)
+ visibleRectInWindow = [self actualVisibleRectInWindow];
+ else
+ visibleRectInWindow = NSZeroRect;
+
+ // Flip Y to convert NSWindow coordinates to top-left-based window coordinates.
+ float borderViewHeight = [[self currentWindow] frame].size.height;
+ boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow);
+
+ if (!shouldClipOutPlugin)
+ visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow);
+
+ _previousSize = boundsInWindow.size;
+
+ _proxy->resize(boundsInWindow, visibleRectInWindow);
+
+ CGRect layerBounds = NSRectToCGRect(boundsInWindow);
+ CGRect bounds = NSRectToCGRect([self bounds]);
+ CGRect frame = NSRectToCGRect([self frame]);
+
+ // We're not scaled, or in a subframe
+ CATransform3D scaleTransform = CATransform3DIdentity;
+ if (CGSizeEqualToSize(bounds.size, frame.size)) {
+ // We're in a subframe. Backing store is boundsInWindow.size.
+ if (boundsInWindow.size.width && boundsInWindow.size.height)
+ scaleTransform = CATransform3DMakeScale(frame.size.width / boundsInWindow.size.width, frame.size.height / boundsInWindow.size.height, 1);
+ } else {
+ // We're in the main frame with scaling. Need to mimic the frame/bounds scaling on Widgets.
+ if (frame.size.width && frame.size.height)
+ scaleTransform = CATransform3DMakeScale(bounds.size.width / frame.size.width, bounds.size.height / frame.size.height, 1);
+ }
+
+ _pluginLayer.get().sublayerTransform = scaleTransform;
+}
+
+- (void)windowFocusChanged:(BOOL)hasFocus
+{
+ if (_proxy)
+ _proxy->windowFocusChanged(hasFocus);
+}
+
+- (BOOL)shouldStop
+{
+ if (!_proxy)
+ return YES;
+
+ return _proxy->shouldStop();
+}
+
+- (void)destroyPlugin
+{
+ if (_proxy) {
+ if (_softwareRenderer) {
+ WKSoftwareCARendererDestroy(_softwareRenderer);
+ _softwareRenderer = 0;
+ }
+
+ _proxy->destroy();
+ _proxy = 0;
+ }
+
+ _pluginLayer = 0;
+}
+
+- (void)startTimers
+{
+ if (_proxy)
+ _proxy->startTimers(_isCompletelyObscured);
+}
+
+- (void)stopTimers
+{
+ if (_proxy)
+ _proxy->stopTimers();
+}
+
+- (void)focusChanged
+{
+ if (_proxy)
+ _proxy->focusChanged(_hasFocus);
+}
+
+- (void)windowFrameDidChange:(NSNotification *)notification
+{
+ if (_proxy && [self window])
+ _proxy->windowFrameChanged([[self window] frame]);
+}
+
+- (void)addWindowObservers
+{
+ [super addWindowObservers];
+
+ ASSERT([self window]);
+
+ NSWindow *window = [self window];
+
+ NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+ [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:)
+ name:NSWindowDidMoveNotification object:window];
+ [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:)
+ name:NSWindowDidResizeNotification object:window];
+
+ if (_proxy)
+ _proxy->windowFrameChanged([window frame]);
+ [self updateAndSetWindow];
+}
+
+- (void)removeWindowObservers
+{
+ [super removeWindowObservers];
+
+ NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+ [notificationCenter removeObserver:self name:NSWindowDidMoveNotification object:nil];
+ [notificationCenter removeObserver:self name:NSWindowDidResizeNotification object:nil];
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->mouseEvent(self, event, NPCocoaEventMouseDown);
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->mouseEvent(self, event, NPCocoaEventMouseUp);
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->mouseEvent(self, event, NPCocoaEventMouseDragged);
+}
+
+- (void)handleMouseEntered:(NSEvent *)event
+{
+ // Set cursor to arrow. Plugins often handle cursor internally, but those that don't will just get this default one.
+ [[NSCursor arrowCursor] set];
+
+ if (_isStarted && _proxy)
+ _proxy->mouseEvent(self, event, NPCocoaEventMouseEntered);
+}
+
+- (void)handleMouseExited:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->mouseEvent(self, event, NPCocoaEventMouseExited);
+
+ // Set cursor back to arrow cursor. Because NSCursor doesn't know about changes that the plugin made, we could get confused about what we think the
+ // current cursor is otherwise. Therefore we have no choice but to unconditionally reset the cursor when the mouse exits the plugin.
+ // FIXME: This should be job of plugin host, see <rdar://problem/7654434>.
+ [[NSCursor arrowCursor] set];
+}
+
+- (void)scrollWheel:(NSEvent *)event
+{
+ bool processedEvent = false;
+
+ if (_isStarted && _proxy)
+ processedEvent = _proxy->wheelEvent(self, event);
+
+ if (!processedEvent)
+ [super scrollWheel:event];
+}
+
+- (NSTextInputContext *)inputContext
+{
+ return [[WebTextInputWindowController sharedTextInputWindowController] inputContext];
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+ if (!_isStarted || !_proxy)
+ return;
+
+ NSString *string = nil;
+ if ([[WebTextInputWindowController sharedTextInputWindowController] interpretKeyEvent:event string:&string]) {
+ if (string)
+ _proxy->insertText(string);
+ return;
+ }
+
+ _proxy->keyEvent(self, event, NPCocoaEventKeyDown);
+}
+
+- (void)keyUp:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->keyEvent(self, event, NPCocoaEventKeyUp);
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+ if (_isStarted && _proxy)
+ _proxy->flagsChanged(event);
+}
+
+- (void)sendModifierEventWithKeyCode:(int)keyCode character:(char)character
+{
+ if (_isStarted && _proxy)
+ _proxy->syntheticKeyDownWithCommandModifier(keyCode, character);
+}
+
+- (void)pluginHostDied
+{
+ if (_element->renderer() && _element->renderer()->isEmbeddedObject()) {
+ // FIXME: The renderer could also be a RenderApplet, we should handle that.
+ RenderEmbeddedObject* renderer = toRenderEmbeddedObject(_element->renderer());
+ renderer->setShowsCrashedPluginIndicator();
+ }
+
+ _pluginLayer = nil;
+ _proxy = 0;
+
+ // No need for us to be layer backed anymore
+ self.wantsLayer = NO;
+
+ [self invalidatePluginContentRect:[self bounds]];
+}
+
+- (void)visibleRectDidChange
+{
+ [super visibleRectDidChange];
+ WKSyncSurfaceToView(self);
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ if (_cachedSnapshot) {
+ NSRect sourceRect = { NSZeroPoint, [_cachedSnapshot.get() size] };
+ [_cachedSnapshot.get() drawInRect:[self bounds] fromRect:sourceRect operation:NSCompositeSourceOver fraction:1];
+ return;
+ }
+
+ if (_proxy) {
+ if (_softwareRenderer) {
+ if ([NSGraphicsContext currentContextDrawingToScreen]) {
+ WKSoftwareCARendererRender(_softwareRenderer, (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort], NSRectToCGRect(rect));
+ _proxy->didDraw();
+ } else
+ _proxy->print(reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]), [self bounds].size.width, [self bounds].size.height);
+ } else if (_snapshotting && [self supportsSnapshotting]) {
+ _proxy->snapshot(reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]), [self bounds].size.width, [self bounds].size.height);
+ }
+
+ return;
+ }
+}
+
+- (PassRefPtr<JSC::Bindings::Instance>)createPluginBindingsInstance:(PassRefPtr<JSC::Bindings::RootObject>)rootObject
+{
+ if (!_proxy)
+ return 0;
+
+ return _proxy->createBindingsInstance(rootObject);
+}
+
+- (void)pluginView:(NSView *)pluginView receivedResponse:(NSURLResponse *)response
+{
+ ASSERT(_loadManually);
+ if (!_proxy)
+ return;
+
+ ASSERT(!_proxy->manualStream());
+
+ _proxy->setManualStream(HostedNetscapePluginStream::create(_proxy.get(), core([self webFrame])->loader()));
+ _proxy->manualStream()->startStreamWithResponse(response);
+}
+
+- (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data
+{
+ ASSERT(_loadManually);
+ if (!_proxy)
+ return;
+
+ if (HostedNetscapePluginStream* manualStream = _proxy->manualStream())
+ manualStream->didReceiveData(0, static_cast<const char*>([data bytes]), [data length]);
+}
+
+- (void)pluginView:(NSView *)pluginView receivedError:(NSError *)error
+{
+ ASSERT(_loadManually);
+ if (!_proxy)
+ return;
+
+ if (HostedNetscapePluginStream* manualStream = _proxy->manualStream())
+ manualStream->didFail(0, error);
+}
+
+- (void)pluginViewFinishedLoading:(NSView *)pluginView
+{
+ ASSERT(_loadManually);
+ if (!_proxy)
+ return;
+
+ if (HostedNetscapePluginStream* manualStream = _proxy->manualStream())
+ manualStream->didFinishLoading(0);
+}
+
+- (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)webPluginContainerCheck
+{
+ ASSERT([webPluginContainerCheck isKindOfClass:[WebPluginContainerCheck class]]);
+
+ id contextInfo = [webPluginContainerCheck contextInfo];
+ ASSERT([contextInfo isKindOfClass:[NSNumber class]]);
+
+ if (!_proxy)
+ return;
+
+ uint32_t checkID = [(NSNumber *)contextInfo unsignedIntValue];
+ _proxy->cancelCheckIfAllowedToLoadURL(checkID);
+}
+
+- (void)_containerCheckResult:(PolicyAction)policy contextInfo:(id)contextInfo
+{
+ ASSERT([contextInfo isKindOfClass:[NSNumber class]]);
+ if (!_proxy)
+ return;
+
+ uint32_t checkID = [(NSNumber *)contextInfo unsignedIntValue];
+ _proxy->checkIfAllowedToLoadURLResult(checkID, (policy == PolicyUse));
+}
+
+- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithReason:(NPReason)reason
+{
+ if (_isStarted && _proxy)
+ _proxy->webFrameDidFinishLoadWithReason(webFrame, reason);
+}
+
+- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithError:(NSError *)error
+{
+ NPReason reason = NPRES_DONE;
+ if (error)
+ reason = HostedNetscapePluginStream::reasonForError(error);
+ [self webFrame:webFrame didFinishLoadWithReason:reason];
+}
+
+@end
+
+#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs
new file mode 100644
index 0000000..0f332b6
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <WebKit/WebKitPluginHostTypes.defs>
+
+subsystem WebKitPluginAgent 100;
+
+serverprefix WKPA;
+userprefix _WKPA;
+
+routine CheckInApplication(serverPort :mach_port_t;
+ ServerAuditToken token :audit_token_t;
+ applicationName :application_name_t;
+ out pluginVendorPort :mach_port_make_send_t);
+
+routine SpawnPluginHost(pluginVendorPort :mach_port_t;
+ sreplyport _replyPort :mach_port_make_send_once_t;
+ options :plist_bytes_t;
+ out pluginHostPort: mach_port_move_send_t);
+
+routine CheckInPluginHost(serverPort :mach_port_t;
+ pluginHostPort :mach_port_move_send_t;
+ ServerAuditToken token :audit_token_t);
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs
new file mode 100644
index 0000000..c802b3d
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <WebKit/WebKitPluginHostTypes.defs>
+
+subsystem WebKitPluginAgentReply 200;
+
+serverprefix WKPA;
+userprefix _WKPA;
+
+skip; // CheckInApplication
+
+simpleroutine SpawnPluginHostReply(_replyPort :mach_port_move_send_once_t;
+ in pluginHostPort: mach_port_move_send_t);
+
+skip; // CheckInPluginHost
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs
new file mode 100644
index 0000000..15fc5fa
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <WebKit/WebKitPluginHostTypes.defs>
+
+// FIXME: Come up with a better name.
+subsystem WebKitPluginClient 300;
+
+serverprefix WK;
+userprefix _WK;
+
+simpleroutine PCStatusText(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ text :data_t);
+
+routine PCLoadURL(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ url :data_t;
+ target :data_t;
+ postData :data_t;
+ flags: uint32_t;
+ out resultCode :uint16_t;
+ out requestID :uint32_t);
+
+simpleroutine PCCancelLoadURL(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ streamID :uint32_t;
+ reason :int16_t);
+
+simpleroutine PCInvalidateRect(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ x :double;
+ y :double;
+ width :double;
+ height :double);
+
+routine PCGetCookies(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ url :data_t;
+ out returnValue :boolean_t;
+ out cookies :data_t, dealloc);
+
+routine PCSetCookies(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ url :data_t;
+ cookies :data_t;
+ out returnValue :boolean_t);
+
+routine PCGetProxy(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ url :data_t;
+ out returnValue :boolean_t;
+ out proxy :data_t, dealloc);
+
+routine PCGetAuthenticationInfo(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ protocol :data_t;
+ host :data_t;
+ port :uint32_t;
+ scheme :data_t;
+ realm :data_t;
+ out returnValue :boolean_t;
+ out username :data_t, dealloc;
+ out password :data_t, dealloc);
+
+routine PCConvertPoint(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ sourceX :double;
+ sourceY :double;
+ sourceSpace :uint32_t;
+ destSpace :uint32_t;
+ out returnValue :boolean_t;
+ out destX :double;
+ out destY :double);
+
+// NPRuntime
+
+routine PCGetStringIdentifier(clientPort :mach_port_t;
+ name :data_t;
+ out identifier :uint64_t);
+
+routine PCGetIntIdentifier(clientPort :mach_port_t;
+ value :int32_t;
+ out identifier: uint64_t);
+
+routine PCGetWindowNPObject(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ out objectID :uint32_t);
+routine PCGetPluginElementNPObject(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ out objectID :uint32_t);
+
+routine PCForgetBrowserObject(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ objectID :uint32_t);
+
+simpleroutine PCEvaluate(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ script :data_t;
+ allowPopups :boolean_t);
+
+simpleroutine PCInvoke(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ methodNameIdentifier :uint64_t;
+ arguments :data_t);
+
+simpleroutine PCInvokeDefault(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ arguments :data_t);
+
+routine PCConstruct(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ objectID :uint32_t;
+ arguments :data_t;
+ out returnValue :boolean_t;
+ out result :data_t, dealloc);
+
+simpleroutine PCGetProperty(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyNameIdentifier :uint64_t);
+
+simpleroutine PCSetProperty(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyNameIdentifier :uint64_t;
+ value :data_t);
+
+simpleroutine PCRemoveProperty(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyNameIdentifier :uint64_t);
+
+simpleroutine PCHasProperty(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyNameIdentifier :uint64_t);
+
+simpleroutine PCHasMethod(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ methodNameIdentifier :uint64_t);
+
+routine PCIdentifierInfo(clientPort :mach_port_t;
+ identifier :uint64_t;
+ out info :data_t, dealloc);
+
+simpleroutine PCEnumerate(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t);
+
+// Misc
+
+simpleroutine PCSetMenuBarVisible(clientPort :mach_port_t;
+ visible :boolean_t);
+
+simpleroutine PCSetModal(clientPort :mach_port_t;
+ modal :boolean_t);
+
+routine PCCheckIfAllowedToLoadURL(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ url :data_t;
+ target :data_t;
+ out checkID :uint32_t);
+
+simpleroutine PCCancelCheckIfAllowedToLoadURL(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ checkID :uint32_t);
+
+routine PCResolveURL(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ url :data_t;
+ target :data_t;
+ out resolvedURL :data_t, dealloc);
+
+// Replies
+simpleroutine PCInstantiatePluginReply(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ result :kern_return_t;
+ renderContextID :uint32_t;
+ rendererType :uint32_t);
+
+simpleroutine PCGetScriptableNPObjectReply(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t);
+
+simpleroutine PCBooleanReply(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ result :boolean_t);
+
+simpleroutine PCBooleanAndDataReply(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ returnValue :boolean_t;
+ result :data_t);
+
+simpleroutine PCSetFullscreenWindowIsShowing(clientPort :mach_port_t;
+ isShowing :boolean_t);
+
+simpleroutine PCSetException(clientPort :mach_port_t;
+ message :data_t);
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs
new file mode 100644
index 0000000..fa808ac
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <WebKit/WebKitPluginHostTypes.defs>
+
+subsystem WebKitPluginHost 300;
+
+serverprefix WK;
+userprefix _WK;
+
+routine PHCheckInWithPluginHost(pluginHostPort :mach_port_t;
+ options :plist_bytes_t;
+ clientPort :mach_port_make_send_t;
+ clientPSNHigh :uint32_t;
+ clientPSNLow :uint32_t;
+ renderPort :mach_port_copy_send_t;
+ out pluginHostPSNHigh :uint32_t;
+ out pluginHostPSNLow :uint32_t);
+
+simpleroutine PHInstantiatePlugin(pluginHostPort :mach_port_t;
+ requestID :uint32_t;
+ options :plist_bytes_t;
+ pluginID :uint32_t);
+
+simpleroutine PHResizePluginInstance(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ pluginX :double;
+ pluginY :double;
+ pluginWidth :double;
+ pluginHeight :double;
+ clipX :double;
+ clipY :double;
+ clipWidth :double;
+ clipHeight :double);
+
+simpleroutine PHPluginInstanceFocusChanged(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ hasFocus :boolean_t);
+simpleroutine PHPluginInstanceWindowFocusChanged(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ hasFocus :boolean_t);
+simpleroutine PHPluginInstanceWindowFrameChanged(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ x :double;
+ y :double;
+ width :double;
+ height :double;
+ maxScreenY :double);
+
+simpleroutine PHPluginInstanceMouseEvent(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ timestamp :double;
+ eventType :uint32_t;
+ modifierFlags :uint32_t;
+ pluginX :double;
+ pluginY :double;
+ screenX :double;
+ screenY :double;
+ maxScreenY :double;
+ buttonNumber :int32_t;
+ clickCount :int32_t;
+ deltaX :double;
+ deltaY :double;
+ deltaZ: double);
+
+simpleroutine PHPluginInstanceKeyboardEvent(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ timestamp :double;
+ eventType :uint32_t;
+ modifierFlags :uint32_t;
+ characters :data_t;
+ charactersIgnoringModifiers :data_t;
+ isARepeat :boolean_t;
+ keyCode :uint16_t;
+ keyChar :uint8_t);
+
+simpleroutine PHPluginInstanceWheelEvent(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ timestamp :double;
+ modifierFlags :uint32_t;
+ pluginX :double;
+ pluginY :double;
+ buttonNumber :int32_t;
+ deltaX :double;
+ deltaY :double;
+ deltaZ: double);
+
+simpleroutine PHPluginInstanceInsertText(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ text :data_t);
+
+simpleroutine PHPluginInstanceStartTimers(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ throttleTimers :boolean_t);
+simpleroutine PHPluginInstanceStopTimers(pluginHostPort :mach_port_t;
+ pluginID :uint32_t);
+
+simpleroutine PHPluginInstancePrint(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ width :uint32_t;
+ height :uint32_t);
+
+simpleroutine PHDestroyPluginInstance(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t);
+
+simpleroutine PHCheckIfAllowedToLoadURLResult(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ checkID :uint32_t;
+ result :boolean_t);
+
+// Streams
+simpleroutine PHStartStream(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ streamID :uint32_t;
+ responseURL :data_t;
+ expectedContentLength :int64_t;
+ lastModifiedTimeInterval :double;
+ mimeType :data_t;
+ headers :data_t);
+
+simpleroutine PHStreamDidReceiveData(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ streamID :uint32_t;
+ data :data_t);
+
+simpleroutine PHStreamDidFinishLoading(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ streamID :uint32_t);
+
+simpleroutine PHStreamDidFail(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ streamID :uint32_t;
+ reason :int16_t);
+
+simpleroutine PHLoadURLNotify(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ reason :int16_t);
+
+// NPRuntime
+
+simpleroutine PHGetScriptableNPObject(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t);
+
+simpleroutine PHNPObjectHasProperty(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyName :uint64_t);
+
+simpleroutine PHNPObjectHasMethod(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ methodName :uint64_t);
+
+simpleroutine PHNPObjectInvoke(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ invokeType :uint32_t;
+ methodName :uint64_t;
+ arguments :data_t);
+
+simpleroutine PHNPObjectHasInvokeDefaultMethod(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t);
+
+simpleroutine PHNPObjectHasConstructMethod(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t);
+
+simpleroutine PHNPObjectGetProperty(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyName :uint64_t);
+
+simpleroutine PHNPObjectSetProperty(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t;
+ propertyName :uint64_t;
+ value :data_t);
+
+simpleroutine PHNPObjectRelease(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ objectID :uint32_t);
+
+simpleroutine PHNPObjectEnumerate(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ objectID :uint32_t);
+
+// Replies
+
+simpleroutine PHBooleanReply(clientPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ result :boolean_t);
+
+simpleroutine PHBooleanAndDataReply(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ returnValue :boolean_t;
+ result :data_t);
+
+simpleroutine PHPluginInstanceDidDraw(pluginHostPort :mach_port_t;
+ pluginID :uint32_t);
+simpleroutine PHPluginInstancePrivateBrowsingModeDidChange(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ privateBrowsingEnabled :boolean_t);
+
+simpleroutine PHPluginInstanceSnapshot(pluginHostPort :mach_port_t;
+ pluginID :uint32_t;
+ requestID :uint32_t;
+ width :uint32_t;
+ height :uint32_t);
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs
new file mode 100644
index 0000000..ee53520
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import <WebKit/WebKitPluginHostTypes.h>;
+
+type plist_bytes_t = ^array [] of uint8_t;
+type application_name_t = ^array [] of uint8_t;
+type data_t = ^array [] of char;
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h
new file mode 100644
index 0000000..0bac2bc
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef WebKitPluginHostTypes_h
+#define WebKitPluginHostTypes_h
+
+typedef uint8_t* plist_bytes_t;
+typedef uint8_t* application_name_t;
+
+typedef char* data_t;
+
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
+enum LoadURLFlags {
+ IsPost = 1 << 0,
+ PostDataIsFile = 1 << 1,
+ AllowHeadersInPostData = 1 << 2,
+ AllowPopups = 1 << 3,
+};
+
+enum InvokeType {
+ Invoke,
+ InvokeDefault,
+ Construct
+};
+
+enum ValueType {
+ VoidValueType,
+ NullValueType,
+ BoolValueType,
+ DoubleValueType,
+ StringValueType,
+ JSObjectValueType,
+ NPObjectValueType
+};
+
+enum RendererType {
+ UseAcceleratedCompositing,
+ UseSoftwareRenderer,
+ UseLayerBackedView
+};
+
+#endif // WebKitPluginHostTypes_h
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h b/Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h
new file mode 100644
index 0000000..9f036ee
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 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 WebTextInputWindowController_h
+#define WebTextInputWindowController_h
+
+@class WebTextInputPanel;
+
+@interface WebTextInputWindowController : NSObject {
+ WebTextInputPanel *_panel;
+}
+
++ (WebTextInputWindowController *)sharedTextInputWindowController;
+
+- (NSTextInputContext *)inputContext;
+- (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string;
+
+@end
+
+#endif // WebTextInputWindowController_h
+
+#endif // USE(PLUGIN_HOST_PROCESS)
diff --git a/Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m b/Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m
new file mode 100644
index 0000000..c168e6e
--- /dev/null
+++ b/Source/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2009 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)
+
+#import "WebTextInputWindowController.h"
+
+#import <WebKitSystemInterface.h>
+
+@interface WebTextInputPanel : NSPanel {
+ NSTextView *_inputTextView;
+}
+
+- (NSTextInputContext *)_inputContext;
+- (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string;
+
+@end
+
+#define inputWindowHeight 20
+
+@implementation WebTextInputPanel
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ [_inputTextView release];
+
+ [super dealloc];
+}
+
+- (id)init
+{
+ self = [super initWithContentRect:NSZeroRect styleMask:WKGetInputPanelWindowStyle() backing:NSBackingStoreBuffered defer:YES];
+ if (!self)
+ return nil;
+
+ // Set the frame size.
+ NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
+ NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, inputWindowHeight);
+
+ [self setFrame:frame display:NO];
+
+ _inputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
+ _inputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
+
+ NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
+ scrollView.documentView = _inputTextView;
+ self.contentView = scrollView;
+ [scrollView release];
+
+ [self setFloatingPanel:YES];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(_keyboardInputSourceChanged:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+
+ return self;
+}
+
+- (void)_keyboardInputSourceChanged:(NSNotification *)notification
+{
+ [_inputTextView setString:@""];
+ [self orderOut:nil];
+}
+
+- (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string
+{
+ BOOL hadMarkedText = [_inputTextView hasMarkedText];
+
+ *string = nil;
+
+ if (![[_inputTextView inputContext] handleEvent:event])
+ return NO;
+
+ if ([_inputTextView hasMarkedText]) {
+ // Don't show the input method window for dead keys
+ if ([[event characters] length] > 0)
+ [self orderFront:nil];
+
+ return YES;
+ }
+
+ if (hadMarkedText) {
+ [self orderOut:nil];
+
+ NSString *text = [[_inputTextView textStorage] string];
+ if ([text length] > 0)
+ *string = [[text copy] autorelease];
+ }
+
+ [_inputTextView setString:@""];
+ return hadMarkedText;
+}
+
+- (NSTextInputContext *)_inputContext
+{
+ return [_inputTextView inputContext];
+}
+
+@end
+
+@implementation WebTextInputWindowController
+
++ (WebTextInputWindowController *)sharedTextInputWindowController
+{
+ static WebTextInputWindowController *textInputWindowController;
+ if (!textInputWindowController)
+ textInputWindowController = [[WebTextInputWindowController alloc] init];
+
+ return textInputWindowController;
+}
+
+- (id)init
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _panel = [[WebTextInputPanel alloc] init];
+
+ return self;
+}
+
+- (NSTextInputContext *)inputContext
+{
+ return [_panel _inputContext];
+}
+
+- (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string
+{
+ return [_panel _interpretKeyEvent:event string:string];
+}
+
+@end
+
+#endif // USE(PLUGIN_HOST_PROCESS)
+