diff options
author | Cary Clark <> | 2009-03-24 21:14:25 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-24 21:14:25 -0700 |
commit | 5ec837f49e9c57d4394ce64b853fd86269c8b340 (patch) | |
tree | de89879b3a2cb0d713abc3c1fac766cb17706245 /WebKit/mac | |
parent | 02ba42cb469e2f0e26216fe434dbb912cf48d248 (diff) | |
download | external_webkit-5ec837f49e9c57d4394ce64b853fd86269c8b340.zip external_webkit-5ec837f49e9c57d4394ce64b853fd86269c8b340.tar.gz external_webkit-5ec837f49e9c57d4394ce64b853fd86269c8b340.tar.bz2 |
Automated import from //branches/master/...@141953,141953
Diffstat (limited to 'WebKit/mac')
26 files changed, 3839 insertions, 8 deletions
diff --git a/WebKit/mac/ForwardingHeaders/kjs/SavedBuiltins.h b/WebKit/mac/ForwardingHeaders/kjs/SavedBuiltins.h deleted file mode 100644 index e380807..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/SavedBuiltins.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/SavedBuiltins.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/collector.h b/WebKit/mac/ForwardingHeaders/kjs/collector.h deleted file mode 100644 index b8ef5a1..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/collector.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/collector.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/dtoa.h b/WebKit/mac/ForwardingHeaders/kjs/dtoa.h deleted file mode 100644 index 4646cf1..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/dtoa.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/dtoa.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/identifier.h b/WebKit/mac/ForwardingHeaders/kjs/identifier.h deleted file mode 100644 index 2471c99..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/identifier.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/identifier.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/interpreter.h b/WebKit/mac/ForwardingHeaders/kjs/interpreter.h deleted file mode 100644 index 08c2be3..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/interpreter.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/interpreter.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/lookup.h b/WebKit/mac/ForwardingHeaders/kjs/lookup.h deleted file mode 100644 index 5e2ffa0..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/lookup.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/lookup.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/operations.h b/WebKit/mac/ForwardingHeaders/kjs/operations.h deleted file mode 100644 index eb80f49..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/operations.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/operations.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/protect.h b/WebKit/mac/ForwardingHeaders/kjs/protect.h deleted file mode 100644 index e4e0499..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/protect.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/protect.h> diff --git a/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h new file mode 100644 index 0000000..539372c --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h @@ -0,0 +1,97 @@ +/* + * 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)); + } + + 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 start(); + void stop(); + + void cancelLoad(NPReason reason); + +private: + NSError *errorForReason(NPReason) const; + void cancelLoad(NSError *); + + HostedNetscapePluginStream(NetscapePluginInstanceProxy*, uint32_t streamID, NSURLRequest *); + + void startStream(NSURL *, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers); + + NSError *pluginCancelledConnectionError() const; + + // NetscapePlugInStreamLoaderClient methods. + void didReceiveResponse(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceResponse&); + void didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError&); + 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/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm new file mode 100644 index 0000000..68e25ab --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm @@ -0,0 +1,248 @@ +/* + * 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 "HostedNetscapePluginStream.h" + +#import "NetscapePluginHostProxy.h" +#import "NetscapePluginInstanceProxy.h" +#import <WebCore/DocumentLoader.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoader.h> +#import "WebHostedNetscapePluginView.h" +#import "WebFrameInternal.h" +#import "WebKitErrorsPrivate.h" +#import "WebNSURLExtras.h" +#import "WebNSURLRequestExtras.h" +#import "WebKitPluginHost.h" +#import "WebKitSystemInterface.h" + +using namespace WebCore; + +namespace WebKit { + +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 (core([instance->pluginView() webFrame])->loader()->shouldHideReferrer([request URL], core([instance->pluginView() webFrame])->loader()->outgoingReferrer())) + [m_request.get() _web_setHTTPReferrer:nil]; +} + +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); +} + +static NPReason 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) +{ + _WKPHStreamDidFail(m_instance->hostProxy()->port(), m_instance->pluginID(), m_streamID, reasonForError(error)); +} + +bool HostedNetscapePluginStream::wantsAllStreams() const +{ + // FIXME: Implement. + return false; +} + +void HostedNetscapePluginStream::start() +{ + ASSERT(m_request); + ASSERT(!m_frameLoader); + ASSERT(!m_loader); + + m_loader = NetscapePlugInStreamLoader::create(core([m_instance->pluginView() webFrame]), this); + m_loader->setShouldBufferData(false); + + m_loader->documentLoader()->addPlugInStreamLoader(m_loader.get()); + m_loader->load(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(); + ASSERT(documentLoader); + + if (documentLoader->isLoadingMainResource()) + documentLoader->cancelMainResourceLoad(error); + return; + } + + if (!m_loader->isDone()) + m_loader->cancel(error); + 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] 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) + diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h new file mode 100644 index 0000000..8e539f3 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h @@ -0,0 +1,70 @@ +/* + * 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 <wtf/HashMap.h> +#import <wtf/PassRefPtr.h> + +@class WebHostedNetscapePluginView; +@class WebNetscapePluginPackage; + +namespace WebKit { + +class NetscapePluginInstanceProxy; +class NetscapePluginHostProxy; + +class NetscapePluginHostManager { +public: + static NetscapePluginHostManager& shared(); + + PassRefPtr<NetscapePluginInstanceProxy> instantiatePlugin(WebNetscapePluginPackage *, WebHostedNetscapePluginView *, NSString *mimeType, NSArray *attributeKeys, NSArray *attributeValues, NSString *userAgent, NSURL *sourceURL); + + void pluginHostDied(NetscapePluginHostProxy*); + +private: + NetscapePluginHostProxy* hostForPackage(WebNetscapePluginPackage *); + + NetscapePluginHostManager(); + ~NetscapePluginHostManager(); + + bool spawnPluginHost(WebNetscapePluginPackage *, mach_port_t clientPort, mach_port_t& pluginHostPort); + + 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<WebNetscapePluginPackage*, NetscapePluginHostProxy*> PluginHostMap; + PluginHostMap m_pluginHosts; +}; + +} // namespace WebKit + +#endif // NetscapePluginHostManager_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm new file mode 100644 index 0000000..9cedc42 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm @@ -0,0 +1,234 @@ +/* + * 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 "NetscapePluginHostManager.h" + +#import "NetscapePluginHostProxy.h" +#import "NetscapePluginInstanceProxy.h" +#import "WebKitSystemInterface.h" +#import "WebNetscapePluginPackage.h" +#import <mach/mach_port.h> +#import <servers/bootstrap.h> +#import <wtf/Assertions.h> +#import <wtf/RetainPtr.h> +#import <wtf/StdLibExtras.h> + +extern "C" { +#import "WebKitPluginAgent.h" +#import "WebKitPluginHost.h" +} + +using namespace std; + +namespace WebKit { + +NetscapePluginHostManager& NetscapePluginHostManager::shared() +{ + DEFINE_STATIC_LOCAL(NetscapePluginHostManager, pluginHostManager, ()); + + return pluginHostManager; +} + +static const NSString *pluginHostAppName = @"WebKitPluginHost.app"; + +NetscapePluginHostManager::NetscapePluginHostManager() + : m_pluginVendorPort(MACH_PORT_NULL) +{ +} + +NetscapePluginHostManager::~NetscapePluginHostManager() +{ +} + +NetscapePluginHostProxy* NetscapePluginHostManager::hostForPackage(WebNetscapePluginPackage *package) +{ + pair<PluginHostMap::iterator, bool> result = m_pluginHosts.add(package, 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) + return 0; + + mach_port_t pluginHostPort; + if (!spawnPluginHost(package, clientPort, pluginHostPort)) { + mach_port_destroy(mach_task_self(), clientPort); + return 0; + } + + NetscapePluginHostProxy* hostProxy = new NetscapePluginHostProxy(clientPort, pluginHostPort); + + CFRetain(package); + result.first->second = hostProxy; + + return hostProxy; +} + +bool NetscapePluginHostManager::spawnPluginHost(WebNetscapePluginPackage *package, mach_port_t clientPort, mach_port_t& pluginHostPort) +{ + 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]; + + NSDictionary *launchProperties = [[NSDictionary alloc] initWithObjectsAndKeys: + pluginHostAppExecutablePath, @"pluginHostPath", + [NSNumber numberWithInt:[package pluginHostArchitecture]], @"cpuType", + 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 != 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; + } + + NSDictionary *hostProperties = [[NSDictionary alloc] initWithObjectsAndKeys: + [package path], @"bundlePath", + nil]; + + data = [NSPropertyListSerialization dataFromPropertyList:hostProperties format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil]; + ASSERT(data); + + [hostProperties release]; + + kr = _WKPHCheckInWithPluginHost(pluginHostPort, (uint8_t*)[data bytes], [data length], clientPort, renderServerPort); + + 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(WebNetscapePluginPackage *pluginPackage, WebHostedNetscapePluginView *pluginView, NSString *mimeType, NSArray *attributeKeys, NSArray *attributeValues, NSString *userAgent, NSURL *sourceURL) +{ + NetscapePluginHostProxy* hostProxy = hostForPackage(pluginPackage); + 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"]; + + NSData *data = [NSPropertyListSerialization dataFromPropertyList:properties.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil]; + ASSERT(data); + + RefPtr<NetscapePluginInstanceProxy> instance = NetscapePluginInstanceProxy::create(hostProxy, pluginView); + kern_return_t kr = _WKPHInstantiatePlugin(hostProxy->port(), (uint8_t*)[data bytes], [data length], instance->pluginID()); + if (kr == MACH_SEND_INVALID_DEST) { + // The plug-in host must have died, but we haven't received the death notification yet. + pluginHostDied(hostProxy); + + // Try to spawn it again. + hostProxy = hostForPackage(pluginPackage); + + kr = _WKPHInstantiatePlugin(hostProxy->port(), (uint8_t*)[data bytes], [data length], instance->pluginID()); + } + + auto_ptr<NetscapePluginInstanceProxy::InstantiatePluginReply> reply = instance->waitForReply<NetscapePluginInstanceProxy::InstantiatePluginReply>(); + if (!reply.get()) + return 0; + + if (reply->m_resultCode != KERN_SUCCESS) + return 0; + + instance->setRenderContextID(reply->m_renderContextID); + instance->setUseSoftwareRenderer(reply->m_useSoftwareRenderer); + + return instance.release(); +} + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h new file mode 100644 index 0000000..c597eec --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h @@ -0,0 +1,82 @@ +/* + * 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> + +namespace WebKit { + +class NetscapePluginInstanceProxy; + +class NetscapePluginHostProxy { +public: + NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort); + + mach_port_t port() const { return m_pluginHostPort; } + mach_port_t clientPort() const { return m_clientPort; } + + void addPluginInstance(NetscapePluginInstanceProxy*); + void removePluginInstance(NetscapePluginInstanceProxy*); + + NetscapePluginInstanceProxy* pluginInstance(uint32_t pluginID); + + void setMenuBarVisible(bool); + void setModal(bool); + +private: + ~NetscapePluginHostProxy(); + void pluginHostDied(); + + static void deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info); + + typedef HashMap<uint32_t, RefPtr<NetscapePluginInstanceProxy> > PluginInstanceMap; + PluginInstanceMap m_instances; + + mach_port_t m_clientPort; +#ifdef USE_LIBDISPATCH + dispatch_source_t m_clientPortSource; +#else + RetainPtr<CFRunLoopSourceRef> m_clientPortSource; +#endif + mach_port_t m_pluginHostPort; + RetainPtr<CFMachPortRef> m_deadNameNotificationPort; + + RetainPtr<NSWindow *> m_placeholderWindow; + unsigned m_modalCount; + + bool m_menuBarIsVisible; +}; + +} // namespace WebKit + +#endif // NetscapePluginHostProxy_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm new file mode 100644 index 0000000..14af429 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm @@ -0,0 +1,635 @@ +/* + * 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 "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/ScriptController.h> +#import <WebCore/npruntime_impl.h> + +extern "C" { +#import "WebKitPluginHost.h" +#import "WebKitPluginClientServer.h" +} + +using namespace std; +using namespace JSC; +using namespace WebCore; + +namespace WebKit { + +static String fromUTF8WithLatin1Fallback(const char* data, int length = -1) +{ + if (length == -1) + length = strlen(data); + + String result = String::fromUTF8(data, length); + + if (result.isNull()) + result = String(data, length); + + return result; +} + +typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap; +static PluginProxyMap& pluginProxyMap() +{ + DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ()); + + return pluginProxyMap; +} + +NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort) + : m_clientPort(clientPort) + , m_pluginHostPort(pluginHostPort) + , m_modalCount(0) + , m_menuBarIsVisible(true) +{ + 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); + +#ifdef USE_LIBDISPATCH + // FIXME: Unfortunately we can't use a dispatch source here until <rdar://problem/6393180> has been resolved. + m_clientPortSource = dispatch_source_mig_create(m_clientPort, WKPCWebKitPluginClient_subsystem.maxsize, 0, + dispatch_get_main_queue(), WebKitPluginClient_server); +#else + m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKPCWebKitPluginClient_subsystem, m_clientPort)); + CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode); +#endif +} + +NetscapePluginHostProxy::~NetscapePluginHostProxy() +{ + pluginProxyMap().remove(m_clientPort); + + ASSERT(m_clientPortSource); +#ifdef USE_LIBDISPATCH + dispatch_release(m_clientPortSource); +#else + CFRunLoopSourceInvalidate(m_clientPortSource.get()); + m_clientPortSource = 0; +#endif +} + +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_modalCount) { + m_modalCount = 1; + + setModal(false); + } + + 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) +{ + return m_instances.get(pluginID).get(); +} + +void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) +{ + ASSERT(msg && 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]; + if (visible) { + // Make ourselves the front app + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcess(&psn); + } +} + +void NetscapePluginHostProxy::setModal(bool modal) +{ + if (modal) { + if (!m_modalCount++) { + ASSERT(!m_placeholderWindow); + + m_placeholderWindow.adoptNS([[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]); + + // 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()]; + } + } else { + if (!--m_modalCount) { + ASSERT(m_placeholderWindow); + + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode); + + [NSApp stopModal]; + [m_placeholderWindow.get() orderOut:nil]; + m_placeholderWindow = 0; + + // Make ourselves the front process. + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcess(&psn); + } + } +} + +} // namespace WebKit + +using namespace WebKit; + +// MiG callbacks +kern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t 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) +{ + 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; + + HostedNetscapePluginStream* pluginStream = instanceProxy->pluginStream(streamID); + if (!pluginStream) + return KERN_FAILURE; + + pluginStream->cancelLoad(reason); + 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_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + [instanceProxy->pluginView() setNeedsDisplayInRect:NSMakeRect(x, y, width, height)]; + + return KERN_SUCCESS; +} + +kern_return_t WKPCGetScriptableNPObjectReply(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; + + instanceProxy->setCurrentReply(new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID)); + return KERN_SUCCESS; +} + +kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, 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(new NetscapePluginInstanceProxy::BooleanReply(result)); + return KERN_SUCCESS; +} + +kern_return_t WKPCBooleanAndDataReply(mach_port_t clientPort, uint32_t pluginID, boolean_t returnValue, data_t resultData, mach_msg_type_number_t resultLength) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + RetainPtr<CFDataRef> result = CFDataCreate(0, reinterpret_cast<UInt8*>(resultData), resultLength); + instanceProxy->setCurrentReply(new NetscapePluginInstanceProxy::BooleanAndDataReply(returnValue, result)); + + return KERN_SUCCESS; +} + +kern_return_t WKPCInstantiatePluginReply(mach_port_t clientPort, uint32_t pluginID, kern_return_t result, uint32_t renderContextID, boolean_t useSoftwareRenderer) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->setCurrentReply(new NetscapePluginInstanceProxy::InstantiatePluginReply(result, renderContextID, useSoftwareRenderer)); + 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 WKPCReleaseObject(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; + + instanceProxy->releaseObject(objectID); + return KERN_SUCCESS; +} + +kern_return_t WKPCEvaluate(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, data_t scriptData, mach_msg_type_number_t scriptLength) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + String script = fromUTF8WithLatin1Fallback(scriptData, scriptLength); + + data_t resultData; + mach_msg_type_number_t resultLength; + + boolean_t returnValue = instanceProxy->evaluate(objectID, script, resultData, resultLength); + + _WKPHEvaluateReply(hostProxy->port(), instanceProxy->pluginID(), returnValue, resultData, resultLength); + 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) +{ + COMPILE_ASSERT(sizeof(*identifier) == sizeof(NPIdentifier), identifier_sizes); + + *identifier = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(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>(_NPN_GetIntIdentifier(value)); + return KERN_SUCCESS; +} + +static Identifier identifierFromServerIdentifier(uint64_t serverIdentifier) +{ + NPIdentifier identifier = reinterpret_cast<NPIdentifier>(serverIdentifier); + ASSERT(_NPN_IdentifierIsString(identifier)); + + String s = fromUTF8WithLatin1Fallback(_NPN_UTF8FromIdentifier(identifier)); + + return Identifier(JSDOMWindow::commonJSGlobalData(), s); +} + +kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t identifier, + data_t argumentsData, mach_msg_type_number_t argumentsLength) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + Identifier methodNameIdentifier = identifierFromServerIdentifier(identifier); + + data_t resultData; + mach_msg_type_number_t resultLength; + + boolean_t returnValue = instanceProxy->invoke(objectID, methodNameIdentifier, argumentsData, argumentsLength, resultData, resultLength); + + _WKPHEvaluateReply(hostProxy->port(), instanceProxy->pluginID(), returnValue, resultData, resultLength); + 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 objectID, + data_t argumentsData, mach_msg_type_number_t argumentsLength, + boolean_t*returnValue, data_t* resultData, mach_msg_type_number_t* resultLength) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + *returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, *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) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + *returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t identifier, boolean_t*returnValue, data_t* resultData, mach_msg_type_number_t* resultLength) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + NPIdentifier npIdentifier = reinterpret_cast<NPIdentifier>(identifier); + if (_NPN_IdentifierIsString(npIdentifier)) { + const NPUTF8* propertyName = _NPN_UTF8FromIdentifier(npIdentifier); + String propertyNameString = fromUTF8WithLatin1Fallback(propertyName); + + Identifier propertyNameIdentifier = identifierFromServerIdentifier(identifier); + *returnValue = instanceProxy->getProperty(objectID, propertyNameIdentifier, *resultData, *resultLength); + } else + *returnValue = instanceProxy->setProperty(objectID, _NPN_IntFromIdentifier(npIdentifier), *resultData, *resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t identifier, data_t valueData, mach_msg_type_number_t valueLength, boolean_t*returnValue) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + NPIdentifier npIdentifier = reinterpret_cast<NPIdentifier>(identifier); + if (_NPN_IdentifierIsString(npIdentifier)) { + const NPUTF8* propertyName = _NPN_UTF8FromIdentifier(npIdentifier); + String propertyNameString = fromUTF8WithLatin1Fallback(propertyName); + + Identifier propertyNameIdentifier = identifierFromServerIdentifier(identifier); + *returnValue = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength); + } else + *returnValue = instanceProxy->setProperty(objectID, _NPN_IntFromIdentifier(npIdentifier), valueData, valueLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t identifier, boolean_t*returnValue) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + NPIdentifier npIdentifier = reinterpret_cast<NPIdentifier>(identifier); + if (_NPN_IdentifierIsString(npIdentifier)) { + const NPUTF8* propertyName = _NPN_UTF8FromIdentifier(npIdentifier); + String propertyNameString = fromUTF8WithLatin1Fallback(propertyName); + + Identifier propertyNameIdentifier = identifierFromServerIdentifier(identifier); + *returnValue = instanceProxy->removeProperty(objectID, propertyNameIdentifier); + } else + *returnValue = instanceProxy->removeProperty(objectID, _NPN_IntFromIdentifier(npIdentifier)); + + return KERN_SUCCESS; +} + +kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t identifier, boolean_t*returnValue) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + NPIdentifier npIdentifier = reinterpret_cast<NPIdentifier>(identifier); + if (_NPN_IdentifierIsString(npIdentifier)) { + const NPUTF8* propertyName = _NPN_UTF8FromIdentifier(npIdentifier); + String propertyNameString = fromUTF8WithLatin1Fallback(propertyName); + + Identifier propertyNameIdentifier = identifierFromServerIdentifier(identifier); + *returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier); + } else + *returnValue = instanceProxy->hasProperty(objectID, _NPN_IntFromIdentifier(npIdentifier)); + + return KERN_SUCCESS; +} + +kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t identifier, boolean_t*returnValue) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + Identifier methodNameIdentifier = identifierFromServerIdentifier(identifier); + *returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier); + + return KERN_SUCCESS; +} + +kern_return_t WKPCIdentifierInfo(mach_port_t clientPort, uint64_t serverIdentifier, data_t* infoData, mach_msg_type_number_t* infoLength) +{ + NPIdentifier identifier = reinterpret_cast<NPIdentifier>(serverIdentifier); + + id info; + if (_NPN_IdentifierIsString(identifier)) { + char* s = _NPN_UTF8FromIdentifier(identifier); + info = [NSData dataWithBytesNoCopy:s length:strlen(s) freeWhenDone:NO]; + } else + info = [NSNumber numberWithInt:_NPN_IntFromIdentifier(identifier)]; + + 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 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 WKPCSetModal(mach_port_t clientPort, boolean_t modal) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + hostProxy->setModal(modal); + + return KERN_SUCCESS; +} + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h new file mode 100644 index 0000000..343aa41 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h @@ -0,0 +1,254 @@ +/* + * 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 NetscapePluginInstanceProxy_h +#define NetscapePluginInstanceProxy_h + +#include <JavaScriptCore/Protect.h> +#include <WebCore/Timer.h> +#include <WebKit/npapi.h> +#include <wtf/Deque.h> +#include <wtf/HashMap.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RetainPtr.h> +#include "WebKitPluginHostTypes.h" + +namespace WebCore { + class String; +} + +namespace JSC { + namespace Bindings { + class Instance; + class RootObject; + } +} +@class WebHostedNetscapePluginView; + +namespace WebKit { + +class HostedNetscapePluginStream; +class NetscapePluginHostProxy; + +class NetscapePluginInstanceProxy : public RefCounted<NetscapePluginInstanceProxy> { +public: + static PassRefPtr<NetscapePluginInstanceProxy> create(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView) + { + return adoptRef(new NetscapePluginInstanceProxy(pluginHostProxy, pluginView)); + } + ~NetscapePluginInstanceProxy(); + + uint32_t pluginID() const { return m_pluginID; } + uint32_t renderContextID() const { return m_renderContextID; } + void setRenderContextID(uint32_t renderContextID) { m_renderContextID = renderContextID; } + + bool useSoftwareRenderer() const { return m_useSoftwareRenderer; } + void setUseSoftwareRenderer(bool useSoftwareRenderer) { m_useSoftwareRenderer = useSoftwareRenderer; } + + WebHostedNetscapePluginView *pluginView() const { return m_pluginView; } + NetscapePluginHostProxy* hostProxy() const { return m_pluginHostProxy; } + + HostedNetscapePluginStream *pluginStream(uint32_t streamID); + void disconnectStream(HostedNetscapePluginStream*); + + 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 startTimers(bool throttleTimers); + void stopTimers(); + + // NPRuntime + bool getWindowNPObject(uint32_t& objectID); + void releaseObject(uint32_t objectID); + + bool evaluate(uint32_t objectID, const WebCore::String& script, data_t& resultData, mach_msg_type_number_t& resultLength); + 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 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); + + PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>); + RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args); + void marshalValue(JSC::ExecState*, JSC::JSValuePtr value, data_t& resultData, mach_msg_type_number_t& resultLength); + JSC::JSValuePtr demarshalValue(JSC::ExecState*, const char* valueData, mach_msg_type_number_t valueLength); + + // 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, boolean_t useSoftwareRenderer) + : Reply(InstantiatePlugin) + , m_resultCode(resultCode) + , m_renderContextID(renderContextID) + , m_useSoftwareRenderer(useSoftwareRenderer) + { + } + + kern_return_t m_resultCode; + uint32_t m_renderContextID; + boolean_t m_useSoftwareRenderer; + }; + + 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(Reply* reply) + { + ASSERT(!m_currentReply.get()); + m_currentReply = std::auto_ptr<Reply>(reply); + } + + template <typename T> + std::auto_ptr<T> waitForReply() + { + m_waitingForReply = true; + + processRequestsAndWaitForReply(); + + if (m_currentReply.get()) + ASSERT(m_currentReply->m_type == T::ReplyType); + + m_waitingForReply = false; + return std::auto_ptr<T>(static_cast<T*>(m_currentReply.release())); + } + +private: + NetscapePluginInstanceProxy(NetscapePluginHostProxy*, WebHostedNetscapePluginView *); + + NPError loadRequest(NSURLRequest *, const char* cTarget, bool currentEventIsUserGesture, uint32_t& streamID); + + class PluginRequest; + void performRequest(PluginRequest*); + void evaluateJavaScript(PluginRequest*); + + void stopAllStreams(); + void processRequestsAndWaitForReply(); + + NetscapePluginHostProxy* m_pluginHostProxy; + WebHostedNetscapePluginView *m_pluginView; + + void requestTimerFired(WebCore::Timer<NetscapePluginInstanceProxy>*); + WebCore::Timer<NetscapePluginInstanceProxy> m_requestTimer; + Deque<PluginRequest*> m_pluginRequests; + + HashMap<uint32_t, RefPtr<HostedNetscapePluginStream> > m_streams; + + uint32_t m_currentRequestID; + + uint32_t m_pluginID; + uint32_t m_renderContextID; + boolean_t m_useSoftwareRenderer; + + bool m_waitingForReply; + std::auto_ptr<Reply> m_currentReply; + + // NPRuntime + uint32_t idForObject(JSC::JSObject*); + + void addValueToArray(NSMutableArray *, JSC::ExecState* exec, JSC::JSValuePtr value); + + bool demarshalValueFromArray(JSC::ExecState*, NSArray *array, NSUInteger& index, JSC::JSValuePtr& result); + void demarshalValues(JSC::ExecState*, data_t valuesData, mach_msg_type_number_t valuesLength, JSC::ArgList& result); + + uint32_t m_objectIDCounter; + typedef HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> > ObjectMap; + ObjectMap m_objects; +}; + +} // namespace WebKit + +#endif // NetscapePluginInstanceProxy_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm new file mode 100644 index 0000000..6d0df52 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm @@ -0,0 +1,946 @@ +/* + * 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 "NetscapePluginInstanceProxy.h" + +#import "HostedNetscapePluginStream.h" +#import "NetscapePluginHostProxy.h" +#import "ProxyInstance.h" +#import "WebDataSourceInternal.h" +#import "WebFrameInternal.h" +#import "WebHostedNetscapePluginView.h" +#import "WebNSDataExtras.h" +#import "WebNSURLExtras.h" +#import "WebKitNSStringExtras.h" +#import "WebPluginRequest.h" +#import "WebViewInternal.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" + +#import <mach/mach.h> +#import <WebCore/DocumentLoader.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoader.h> +#import <WebCore/FrameTree.h> +#import <WebCore/runtime_object.h> +#import <WebCore/ScriptController.h> +#import <WebCore/ScriptValue.h> +#include <runtime/JSLock.h> +#import <utility> + +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: + PluginRequest(uint32_t requestID, NSURLRequest *request, NSString *frameName, bool didStartFromUserGesture) + : m_requestID(requestID) + , m_request(request) + , m_frameName(frameName) + , m_didStartFromUserGesture(didStartFromUserGesture) + { + } + + uint32_t requestID() const { return m_requestID; } + NSURLRequest *request() const { return m_request.get(); } + NSString *frameName() const { return m_frameName.get(); } + bool didStartFromUserGesture() const { return m_didStartFromUserGesture; } + +private: + uint32_t m_requestID; + RetainPtr<NSURLRequest *> m_request; + RetainPtr<NSString *> m_frameName; + bool m_didStartFromUserGesture; +}; + +static uint32_t pluginIDCounter; + +NetscapePluginInstanceProxy::NetscapePluginInstanceProxy(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView) + : m_pluginHostProxy(pluginHostProxy) + , m_pluginView(pluginView) + , m_requestTimer(this, &NetscapePluginInstanceProxy::requestTimerFired) + , m_currentRequestID(0) + , m_renderContextID(0) + , m_useSoftwareRenderer(false) + , m_waitingForReply(false) + , m_objectIDCounter(0) +{ + ASSERT(m_pluginView); + + // Assign a plug-in ID. + do { + m_pluginID = ++pluginIDCounter; + } while (pluginHostProxy->pluginInstance(m_pluginID) || !m_pluginID); + + pluginHostProxy->addPluginInstance(this); +} + +NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy() +{ + ASSERT(!m_pluginHostProxy); +} + +void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect) +{ + _WKPHResizePluginInstance(m_pluginHostProxy->port(), m_pluginID, size.origin.x, size.origin.y, size.size.width, size.size.height); +} + +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::destroy() +{ + stopAllStreams(); + + _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID); + + // 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_objects.clear(); + + m_pluginHostProxy->removePluginInstance(this); + m_pluginHostProxy = 0; +} + +HostedNetscapePluginStream *NetscapePluginInstanceProxy::pluginStream(uint32_t streamID) +{ + return m_streams.get(streamID).get(); +} + +void NetscapePluginInstanceProxy::disconnectStream(HostedNetscapePluginStream* stream) +{ + m_streams.remove(stream->streamID()); +} + +void NetscapePluginInstanceProxy::pluginHostDied() +{ + stopAllStreams(); + + m_pluginHostProxy = 0; + + [m_pluginView pluginHostDied]; + m_pluginView = nil; +} + +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, + // FIXME: Is it always correct to pass the rect of the first screen here? + 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, + // FIXME: Is it always correct to pass the rect of the first screen here? + 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]); +} + +void NetscapePluginInstanceProxy::stopTimers() +{ + _WKPHPluginInstanceStopTimers(m_pluginHostProxy->port(), m_pluginID); +} + +void NetscapePluginInstanceProxy::status(const char* message) +{ + RetainPtr<CFStringRef> status(AdoptCF, CFStringCreateWithCString(NULL, 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. + 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 & CurrentEventIsUserGesture, streamID); +} + +void NetscapePluginInstanceProxy::performRequest(PluginRequest* pluginRequest) +{ + 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) + 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]; +} + +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->didStartFromUserGesture()]; + + // 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()); + + 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()); + + PluginRequest* request = m_pluginRequests.first(); + m_pluginRequests.removeFirst(); + + if (!m_pluginRequests.isEmpty()) + m_requestTimer.startOneShot(0); + + performRequest(request); + delete request; +} + +NPError NetscapePluginInstanceProxy::loadRequest(NSURLRequest *request, const char* cTarget, bool currentEventIsUserGesture, 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. + if ([[m_pluginView dataSource] _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 ([[m_pluginView dataSource] _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 (!FrameLoader::canLoad(URL, String(), core([m_pluginView webFrame])->document())) + return NPERR_GENERIC_ERROR; + } + + // FIXME: Handle wraparound + requestID = ++m_currentRequestID; + + 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; + } + + PluginRequest* pluginRequest = new PluginRequest(requestID, request, target, currentEventIsUserGesture); + m_pluginRequests.append(pluginRequest); + m_requestTimer.startOneShot(0); + } else { + RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, requestID, request); + + m_streams.add(requestID, stream); + stream->start(); + } + + return NPERR_NO_ERROR; +} + +void NetscapePluginInstanceProxy::processRequestsAndWaitForReply() +{ + while (!m_currentReply.get()) { + kern_return_t kr = mach_msg_server_once(WebKitPluginClient_server, WKPCWebKitPluginClient_subsystem.maxsize + MAX_TRAILER_SIZE, m_pluginHostProxy->clientPort(), 0); + if (kr != KERN_SUCCESS) { + m_currentReply.reset(); + break; + } + } +} + +uint32_t NetscapePluginInstanceProxy::idForObject(JSObject* object) +{ + uint32_t objectID = 0; + + // Assign an object ID. + do { + objectID = ++m_objectIDCounter; + } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_objects.contains(objectID)); + + m_objects.set(objectID, object); + + return objectID; +} + +// NPRuntime support +bool NetscapePluginInstanceProxy::getWindowNPObject(uint32_t& objectID) +{ + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + if (!frame->script()->isEnabled()) + objectID = 0; + else + objectID = idForObject(frame->script()->windowShell()->window()); + + return true; +} + +void NetscapePluginInstanceProxy::releaseObject(uint32_t objectID) +{ + m_objects.remove(objectID); +} + +bool NetscapePluginInstanceProxy::evaluate(uint32_t objectID, const String& script, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + resultData = 0; + resultLength = 0; + + if (!m_objects.contains(objectID)) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSValuePtr value = frame->loader()->executeScript(script).jsValue(); + + marshalValue(exec, value, 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; + + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr function = object->get(exec, methodName); + CallData callData; + CallType callType = function.getCallData(callData); + if (callType == CallTypeNone) + return false; + + ArgList argList; + demarshalValues(exec, argumentsData, argumentsLength, argList); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + globalObject->startTimeoutCheck(); + JSValuePtr value = call(exec, function, callType, callData, object, argList); + globalObject->stopTimeoutCheck(); + + 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) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + CallData callData; + CallType callType = object->getCallData(callData); + if (callType == CallTypeNone) + return false; + + ArgList argList; + demarshalValues(exec, argumentsData, argumentsLength, argList); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + globalObject->startTimeoutCheck(); + JSValuePtr value = call(exec, object, callType, callData, object, argList); + globalObject->stopTimeoutCheck(); + + 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) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + ConstructData constructData; + ConstructType constructType = object->getConstructData(constructData); + if (constructType == ConstructTypeNone) + return false; + + ArgList argList; + demarshalValues(exec, argumentsData, argumentsLength, argList); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + globalObject->startTimeoutCheck(); + JSValuePtr value = JSC::construct(exec, object, constructType, constructData, argList); + globalObject->stopTimeoutCheck(); + + 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) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr 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_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr 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) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + JSValuePtr 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) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + JSValuePtr value = demarshalValue(exec, valueData, valueLength); + object->put(exec, propertyName, value); + + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, const Identifier& propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + if (!object->hasProperty(exec, propertyName)) { + exec->clearException(); + return false; + } + + JSLock lock(false); + object->deleteProperty(exec, propertyName); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, unsigned propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + if (!object->hasProperty(exec, propertyName)) { + exec->clearException(); + return false; + } + + JSLock lock(false); + object->deleteProperty(exec, propertyName); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, const Identifier& propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + bool result = object->hasProperty(exec, propertyName); + exec->clearException(); + + return result; +} + +bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, unsigned propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + bool result = object->hasProperty(exec, propertyName); + exec->clearException(); + + return result; +} + +bool NetscapePluginInstanceProxy::hasMethod(uint32_t objectID, const Identifier& methodName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr func = object->get(exec, methodName); + exec->clearException(); + return !func.isUndefined(); +} + +void NetscapePluginInstanceProxy::addValueToArray(NSMutableArray *array, ExecState* exec, JSValuePtr value) +{ + JSLock lock(false); + + if (value.isString()) { + [array addObject:[NSNumber numberWithInt:StringValueType]]; + [array addObject:String(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() == &RuntimeObjectImp::s_info) { + // FIXME: Handle ProxyInstance objects. + ASSERT_NOT_REACHED(); + } else { + [array addObject:[NSNumber numberWithInt:JSObjectValueType]]; + [array addObject:[NSNumber numberWithInt:idForObject(object)]]; + } + } else + [array addObject:[NSNumber numberWithInt:VoidValueType]]; +} + +void NetscapePluginInstanceProxy::marshalValue(ExecState* exec, JSValuePtr 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(exec, 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, JSValuePtr& 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(exec, [[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_objects.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()->isEnabled()) + 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; + } +} + +JSValuePtr 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; + JSValuePtr 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, ArgList& 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; + JSValuePtr value; + while (demarshalValueFromArray(exec, array.get(), position, value)) + result.append(value); +} + +PassRefPtr<Instance> NetscapePluginInstanceProxy::createBindingsInstance(PassRefPtr<RootObject> rootObject) +{ + if (_WKPHGetScriptableNPObject(m_pluginHostProxy->port(), m_pluginID) != KERN_SUCCESS) + return 0; + + auto_ptr<GetScriptableNPObjectReply> reply = waitForReply<GetScriptableNPObjectReply>(); + if (!reply.get()) + return 0; + + if (!reply->m_objectID) + return 0; + + return ProxyInstance::create(rootObject, this, reply->m_objectID); +} + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/ProxyInstance.h b/WebKit/mac/Plugins/Hosted/ProxyInstance.h new file mode 100644 index 0000000..014e388 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/ProxyInstance.h @@ -0,0 +1,86 @@ +/* + * 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 ProxyInstance_h +#define ProxyInstance_h + +#include <WebCore/runtime.h> +#include <WebCore/runtime_root.h> +#include <wtf/OwnPtr.h> +#include "WebKitPluginHostTypes.h" + +namespace WebKit { + +class ProxyClass; +class NetscapePluginInstanceProxy; + +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::JSValuePtr fieldValue(JSC::ExecState*, const JSC::Bindings::Field*) const; + void setFieldValue(JSC::ExecState*, const JSC::Bindings::Field*, JSC::JSValuePtr) const; + +private: + ProxyInstance(PassRefPtr<JSC::Bindings::RootObject>, NetscapePluginInstanceProxy*, uint32_t objectID); + + virtual JSC::Bindings::Class *getClass() const; + + virtual JSC::JSValuePtr invokeMethod(JSC::ExecState*, const JSC::Bindings::MethodList&, const JSC::ArgList& args); + + virtual bool supportsInvokeDefaultMethod() const; + virtual JSC::JSValuePtr invokeDefaultMethod(JSC::ExecState*, const JSC::ArgList&); + + virtual bool supportsConstruct() const; + virtual JSC::JSValuePtr invokeConstruct(JSC::ExecState*, const JSC::ArgList&); + + virtual JSC::JSValuePtr defaultValue(JSC::ExecState*, JSC::PreferredPrimitiveType) const; + virtual JSC::JSValuePtr valueOf(JSC::ExecState*) const; + + JSC::JSValuePtr stringValue(JSC::ExecState*) const; + JSC::JSValuePtr numberValue(JSC::ExecState*) const; + JSC::JSValuePtr booleanValue() const; + + JSC::JSValuePtr invoke(JSC::ExecState*, InvokeType, uint64_t identifier, const JSC::ArgList& args); + + 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/WebKit/mac/Plugins/Hosted/ProxyInstance.mm b/WebKit/mac/Plugins/Hosted/ProxyInstance.mm new file mode 100644 index 0000000..8d6aaee --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/ProxyInstance.mm @@ -0,0 +1,310 @@ +/* + * 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 "ProxyInstance.h" + +#import "NetscapePluginHostProxy.h" +#import "NetscapePluginInstanceProxy.h" +#import <WebCore/npruntime_impl.h> + +extern "C" { +#import "WebKitPluginHost.h" +} + +using namespace JSC; +using namespace JSC::Bindings; +using namespace std; + +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 JSValuePtr valueFromInstance(ExecState*, const Instance*) const; + virtual void setValueToInstance(ExecState*, const Instance*, JSValuePtr) const; + + uint64_t m_serverIdentifier; +}; + +JSValuePtr 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, JSValuePtr 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) +{ +} + +ProxyInstance::~ProxyInstance() +{ + deleteAllValues(m_fields); + deleteAllValues(m_methods); + + _WKPHNPObjectRelease(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), m_objectID); +} + +JSC::Bindings::Class *ProxyInstance::getClass() const +{ + return proxyClass(); +} + +JSValuePtr ProxyInstance::invoke(JSC::ExecState* exec, InvokeType type, uint64_t identifier, const JSC::ArgList& args) +{ + RetainPtr<NSData*> arguments(m_instanceProxy->marshalValues(exec, args)); + + if (_WKPHNPObjectInvoke(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), m_objectID, + type, identifier, (char*)[arguments.get() bytes], [arguments.get() length]) != KERN_SUCCESS) + return jsUndefined(); + + auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(); + if (!reply.get() || !reply->m_returnValue) + return jsUndefined(); + + return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get())); +} + +JSValuePtr ProxyInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const ArgList& args) +{ + ASSERT(methodList.size() == 1); + + ProxyMethod* method = static_cast<ProxyMethod*>(methodList[0]); + + return invoke(exec, Invoke, method->serverIdentifier(), args); +} + +bool ProxyInstance::supportsInvokeDefaultMethod() const +{ + if (_WKPHNPObjectHasInvokeDefaultMethod(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), + m_objectID) != KERN_SUCCESS) + return false; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(); + if (reply.get() && reply->m_result) + return true; + + return false; +} + +JSValuePtr ProxyInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args) +{ + return invoke(exec, InvokeDefault, 0, args); +} + +bool ProxyInstance::supportsConstruct() const +{ + if (_WKPHNPObjectHasConstructMethod(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), + m_objectID) != KERN_SUCCESS) + return false; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(); + if (reply.get() && reply->m_result) + return true; + + return false; +} + +JSValuePtr ProxyInstance::invokeConstruct(ExecState* exec, const ArgList& args) +{ + return invoke(exec, Construct, 0, args); +} + +JSValuePtr ProxyInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const +{ + if (hint == PreferString) + return stringValue(exec); + if (hint == PreferNumber) + return numberValue(exec); + return valueOf(exec); +} + +JSValuePtr ProxyInstance::stringValue(ExecState* exec) const +{ + // FIXME: Implement something sensible. + return jsString(exec, ""); +} + +JSValuePtr ProxyInstance::numberValue(ExecState* exec) const +{ + // FIXME: Implement something sensible. + return jsNumber(exec, 0); +} + +JSValuePtr ProxyInstance::booleanValue() const +{ + // FIXME: Implement something sensible. + return jsBoolean(false); +} + +JSValuePtr ProxyInstance::valueOf(ExecState* exec) const +{ + return stringValue(exec); +} + +MethodList ProxyInstance::methodsNamed(const Identifier& identifier) +{ + if (Method* method = m_methods.get(identifier.ustring().rep())) { + MethodList methodList; + methodList.append(method); + return methodList; + } + + uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii())); + if (_WKPHNPObjectHasMethod(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), + m_objectID, methodName) != KERN_SUCCESS) + return MethodList(); + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(); + if (reply.get() && reply->m_result) { + Method* method = new ProxyMethod(methodName); + + m_methods.set(identifier.ustring().rep(), method); + + MethodList methodList; + methodList.append(method); + return methodList; + } + + return MethodList(); +} + +Field* ProxyInstance::fieldNamed(const Identifier& identifier) +{ + if (Field* field = m_fields.get(identifier.ustring().rep())) + return field; + + uint64_t propertyName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii())); + if (_WKPHNPObjectHasProperty(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), + m_objectID, propertyName) != KERN_SUCCESS) + return 0; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(); + if (reply.get() && reply->m_result) { + Field* field = new ProxyField(propertyName); + + m_fields.set(identifier.ustring().rep(), field); + + return field; + } + + return 0; +} + +JSC::JSValuePtr ProxyInstance::fieldValue(ExecState* exec, const Field* field) const +{ + uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier(); + + if (_WKPHNPObjectGetProperty(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), + m_objectID, serverIdentifier) != KERN_SUCCESS) + return jsUndefined(); + + auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(); + 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, JSValuePtr value) const +{ + uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier(); + + data_t valueData; + mach_msg_type_number_t valueLength; + + m_instanceProxy->marshalValue(exec, value, valueData, valueLength); + kern_return_t kr = _WKPHNPObjectSetProperty(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), + m_objectID, serverIdentifier, valueData, valueLength); + mig_deallocate(reinterpret_cast<vm_address_t>(valueData), valueLength); + if (kr != KERN_SUCCESS) + return; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(); +} + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) + diff --git a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h new file mode 100644 index 0000000..14b0dc1 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h @@ -0,0 +1,63 @@ +/* + * 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 NetscapePluginInstanceProxy; +} + +@interface WebHostedNetscapePluginView : WebBaseNetscapePluginView +{ + RetainPtr<NSArray> _attributeKeys; + RetainPtr<NSArray> _attributeValues; + + RetainPtr<CALayer> _pluginLayer; + WKSoftwareCARendererRef _softwareRenderer; + + RefPtr<WebKit::NetscapePluginInstanceProxy> _proxy; + BOOL _pluginHostDied; +} + +- (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 + DOMElement:(DOMElement *)anElement; + +- (void)pluginHostDied; +@end + +#endif // USE(PLUGIN_HOST_PROCESS) + diff --git a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm new file mode 100644 index 0000000..f30c2cb --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm @@ -0,0 +1,299 @@ +/* + * 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 "WebHostedNetscapePluginView.h" + +#import "NetscapePluginInstanceProxy.h" +#import "NetscapePluginHostManager.h" +#import "NetscapePluginHostProxy.h" +#import "WebView.h" +#import "WebViewInternal.h" +#import "WebUIDelegate.h" + +#import <CoreFoundation/CoreFoundation.h> +#import <WebCore/runtime.h> +#import <WebCore/runtime_root.h> +#import <WebCore/WebCoreObjCExtras.h> +#import <runtime/InitializeThreading.h> +#import <wtf/Assertions.h> + +using namespace WebKit; + +extern "C" { +#include "WebKitPluginClientServer.h" +#include "WebKitPluginHost.h" +} + +@implementation WebHostedNetscapePluginView + ++ (void)initialize +{ + JSC::initializeThreading(); +#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 + DOMElement:(DOMElement *)element +{ + self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually DOMElement: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 && !_attributeValues); + + _attributeKeys.adoptNS([keys copy]); + _attributeValues.adoptNS([values copy]); +} + +- (BOOL)createPlugin +{ + ASSERT(!_proxy); + + NSString *userAgent = [[self webView] userAgentForURL:_baseURL.get()]; + + _proxy = NetscapePluginHostManager::shared().instantiatePlugin(_pluginPackage.get(), self, _MIMEType.get(), _attributeKeys.get(), _attributeValues.get(), userAgent, _sourceURL.get()); + if (!_proxy) + return NO; + + if (_proxy->useSoftwareRenderer()) + _softwareRenderer = WKSoftwareCARendererCreate(_proxy->renderContextID()); + else { + _pluginLayer = WKMakeRenderLayer(_proxy->renderContextID()); + self.wantsLayer = YES; + } + + // Update the window frame. + _proxy->windowFrameChanged([[self window] frame]); + + return YES; +} + +- (void)setLayer:(CALayer *)newLayer +{ + [super setLayer:newLayer]; + + if (_pluginLayer) + [newLayer addSublayer:_pluginLayer.get()]; +} + +- (void)loadStream +{ +} + +- (void)updateAndSetWindow +{ + if (!_proxy) + return; + + // Use AppKit to convert view coordinates to NSWindow coordinates. + NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil]; + NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil]; + + // 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); + visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow); + + _proxy->resize(boundsInWindow, visibleRectInWindow); +} + +- (void)windowFocusChanged:(BOOL)hasFocus +{ + if (_proxy) + _proxy->windowFocusChanged(hasFocus); +} + +- (BOOL)shouldStop +{ + return YES; +} + +- (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 *theWindow = [self window]; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:) + name:NSWindowDidMoveNotification object:theWindow]; + [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:) + name:NSWindowDidResizeNotification object:theWindow]; +} + +- (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)mouseEntered:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseEntered); +} + +- (void)mouseExited:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseExited); +} + +- (void)keyDown:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->keyEvent(self, event, NPCocoaEventKeyDown); +} + +- (void)keyUp:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->keyEvent(self, event, NPCocoaEventKeyUp); +} + +- (void)pluginHostDied +{ + _pluginHostDied = YES; + + _pluginLayer = nil; + _proxy = 0; + + // No need for us to be layer backed anymore + self.wantsLayer = NO; + + [self setNeedsDisplay:YES]; +} + + +- (void)drawRect:(NSRect)rect +{ + if (_proxy) { + if (_softwareRenderer) + WKSoftwareCARendererRender(_softwareRenderer, (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort], NSRectToCGRect(rect)); + return; + } + + if (_pluginHostDied) { + // Fill the area with a nice red color for now. + [[NSColor redColor] set]; + NSRectFill(rect); + } +} + +- (PassRefPtr<JSC::Bindings::Instance>)createPluginBindingsInstance:(PassRefPtr<JSC::Bindings::RootObject>)rootObject +{ + if (!_proxy) + return 0; + + return _proxy->createBindingsInstance(rootObject); +} + +@end + +#endif diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs new file mode 100644 index 0000000..0f332b6 --- /dev/null +++ b/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/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs new file mode 100644 index 0000000..c802b3d --- /dev/null +++ b/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/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs new file mode 100644 index 0000000..1aab38d --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs @@ -0,0 +1,166 @@ +/* + * 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 WKPC; +userprefix _WKPC; + +simpleroutine StatusText(clientPort :mach_port_t; + pluginID :uint32_t; + text :data_t); + +routine LoadURL(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 CancelLoadURL(clientPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + reason :int16_t); + +simpleroutine InvalidateRect(clientPort :mach_port_t; + pluginID :uint32_t; + x :double; + y :double; + width :double; + height :double); + +// NPRuntime + +routine GetStringIdentifier(clientPort :mach_port_t; + name :data_t; + out identifier :uint64_t); + +routine GetIntIdentifier(clientPort :mach_port_t; + value :int32_t; + out identifier: uint64_t); + +routine GetWindowNPObject(clientPort :mach_port_t; + pluginID :uint32_t; + out objectID :uint32_t); + +routine ReleaseObject(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +simpleroutine Evaluate(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + script :data_t); + +simpleroutine Invoke(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + methodNameIdentifier :uint64_t; + arguments :data_t); + +routine InvokeDefault(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + arguments :data_t; + out returnValue :boolean_t; + out result :data_t, dealloc); + +routine Construct(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + arguments :data_t; + out returnValue :boolean_t; + out result :data_t, dealloc); + +routine GetProperty(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t; + out returnValue :boolean_t; + out result :data_t, dealloc); + +routine SetProperty(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t; + value :data_t; + out returnValue :boolean_t); + +routine RemoveProperty(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t; + out returnValue :boolean_t); + +routine HasProperty(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t; + out returnValue :boolean_t); + +routine HasMethod(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + methodNameIdentifier :uint64_t; + out returnValue :boolean_t); + +routine IdentifierInfo(clientPort :mach_port_t; + identifier :uint64_t; + out info :data_t, dealloc); + +// Misc + +simpleroutine SetMenuBarVisible(clientPort :mach_port_t; + visible :boolean_t); + +simpleroutine SetModal(clientPort :mach_port_t; + modal :boolean_t); + +// Replies +simpleroutine InstantiatePluginReply(clientPort :mach_port_t; + pluginID :uint32_t; + result :kern_return_t; + renderContextID :uint32_t; + useSoftwareRenderer :boolean_t); + +simpleroutine GetScriptableNPObjectReply(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +simpleroutine BooleanReply(clientPort :mach_port_t; + pluginID :uint32_t; + result :boolean_t); + +simpleroutine BooleanAndDataReply(clientPort :mach_port_t; + pluginID :uint32_t; + returnValue :boolean_t; + result :data_t); + + diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs new file mode 100644 index 0000000..4fe96f9 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs @@ -0,0 +1,172 @@ +/* + * 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 WKPH; +userprefix _WKPH; + +routine CheckInWithPluginHost(pluginHostPort :mach_port_t; + options :plist_bytes_t; + clientPort :mach_port_make_send_t; + renderPort :mach_port_copy_send_t); + +simpleroutine InstantiatePlugin(pluginHostPort :mach_port_t; + options :plist_bytes_t; + pluginID :uint32_t); + +simpleroutine ResizePluginInstance(pluginHostPort :mach_port_t; + pluginID :uint32_t; + x :double; + y :double; + width :double; + height :double); +simpleroutine PluginInstanceFocusChanged(pluginHostPort :mach_port_t; + pluginID :uint32_t; + hasFocus :boolean_t); +simpleroutine PluginInstanceWindowFocusChanged(pluginHostPort :mach_port_t; + pluginID :uint32_t; + hasFocus :boolean_t); +simpleroutine PluginInstanceWindowFrameChanged(pluginHostPort :mach_port_t; + pluginID :uint32_t; + x :double; + y :double; + width :double; + height :double; + maxScreenY :double); + +simpleroutine PluginInstanceMouseEvent(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 PluginInstanceKeyboardEvent(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); + +simpleroutine PluginInstanceStartTimers(pluginHostPort :mach_port_t; + pluginID :uint32_t; + throttleTimers :boolean_t); +simpleroutine PluginInstanceStopTimers(pluginHostPort :mach_port_t; + pluginID :uint32_t); + +simpleroutine DestroyPluginInstance(pluginHostPort :mach_port_t; + pluginID :uint32_t); + + +// Streams +simpleroutine StartStream(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 StreamDidReceiveData(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + data :data_t); + +simpleroutine StreamDidFinishLoading(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t); + +simpleroutine StreamDidFail(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + reason :int16_t); + +// NPRuntime + +simpleroutine GetScriptableNPObject(pluginHostPort :mach_port_t; + pluginID :uint32_t); + +simpleroutine NPObjectHasProperty(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyName :uint64_t); + +simpleroutine NPObjectHasMethod(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + methodName :uint64_t); + +simpleroutine NPObjectInvoke(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + invokeType :uint32_t; + methodName :uint64_t; + arguments :data_t); + +simpleroutine NPObjectHasInvokeDefaultMethod(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +simpleroutine NPObjectHasConstructMethod(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +simpleroutine NPObjectGetProperty(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyName :uint64_t); + +simpleroutine NPObjectSetProperty(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyName :uint64_t; + value :data_t); + +simpleroutine NPObjectRelease(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +// Replies + +simpleroutine EvaluateReply(pluginHostPort :mach_port_t; + pluginID :uint32_t; + returnValue :boolean_t; + result :data_t); diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs new file mode 100644 index 0000000..ee53520 --- /dev/null +++ b/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/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h new file mode 100644 index 0000000..a5efde9 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h @@ -0,0 +1,61 @@ +/* + * 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, + CurrentEventIsUserGesture = 1 << 3, +}; + +enum InvokeType { + Invoke, + InvokeDefault, + Construct +}; + +enum ValueType { + VoidValueType, + NullValueType, + BoolValueType, + DoubleValueType, + StringValueType, + JSObjectValueType, + NPObjectValueType +}; + +#endif // WebKitPluginHostTypes_h |