WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,1188 @@
+/*
+ * 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/IdentifierRep.h>
+#import <WebCore/ScriptController.h>
+#import <string>
+
+extern "C" {
+#import "WebKitPluginHost.h"
+#import "WebKitPluginClientServer.h"
+}
+
+using namespace std;
+using namespace JSC;
+using namespace WebCore;
+
+@interface WebPlaceholderModalWindow : NSWindow 
+@end
+
+@implementation WebPlaceholderModalWindow
+// Prevent NSApp from calling requestUserAttention: when the window is shown 
+// modally, even if the app is inactive. See 6823049.
+- (BOOL)_wantsUserAttention
+{
+    return NO;   
+}
+@end
+
+namespace WebKit {
+
+class PluginDestroyDeferrer {
+public:
+    PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy)
+        : m_proxy(proxy)
+    {
+        m_proxy->willCallPluginFunction();
+    }
+    
+    ~PluginDestroyDeferrer()
+    {
+        m_proxy->didCallPluginFunction();
+    }
+
+private:
+    RefPtr<NetscapePluginInstanceProxy> m_proxy;
+};
+
+typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap;
+static PluginProxyMap& pluginProxyMap()
+{
+    DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ());
+    
+    return pluginProxyMap;
+}
+
+unsigned NetscapePluginHostProxy::s_processingRequests;
+
+NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN, bool shouldCacheMissingPropertiesAndMethods)
+    : m_clientPort(clientPort)
+    , m_portSet(MACH_PORT_NULL)
+    , m_pluginHostPort(pluginHostPort)
+    , m_isModal(false)
+    , m_menuBarIsVisible(true)
+    , m_fullscreenWindowIsShowing(false)
+    , m_pluginHostPSN(pluginHostPSN)
+    , m_shouldCacheMissingPropertiesAndMethods(shouldCacheMissingPropertiesAndMethods)
+{
+    pluginProxyMap().add(m_clientPort, this);
+    
+    // FIXME: We should use libdispatch for this.
+    CFMachPortContext context = { 0, this, 0, 0, 0 };
+    m_deadNameNotificationPort.adoptCF(CFMachPortCreate(0, deadNameNotificationCallback, &context, 0));
+
+    mach_port_t previous;
+    mach_port_request_notification(mach_task_self(), pluginHostPort, MACH_NOTIFY_DEAD_NAME, 0, 
+                                   CFMachPortGetPort(m_deadNameNotificationPort.get()), MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+    ASSERT(previous == MACH_PORT_NULL);
+    
+    RetainPtr<CFRunLoopSourceRef> deathPortSource(AdoptCF, CFMachPortCreateRunLoopSource(0, m_deadNameNotificationPort.get(), 0));
+    
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), deathPortSource.get(), kCFRunLoopDefaultMode);
+    
+    m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKWebKitPluginClient_subsystem, m_clientPort));
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode);
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSEventTrackingRunLoopMode);
+}
+
+NetscapePluginHostProxy::~NetscapePluginHostProxy()
+{
+    pluginProxyMap().remove(m_clientPort);
+
+    // Free the port set
+    if (m_portSet) {
+        mach_port_extract_member(mach_task_self(), m_clientPort, m_portSet);
+        mach_port_extract_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
+        mach_port_destroy(mach_task_self(), m_portSet);
+    }
+    
+    ASSERT(m_clientPortSource);
+    CFRunLoopSourceInvalidate(m_clientPortSource.get());
+    m_clientPortSource = 0;
+}
+
+void NetscapePluginHostProxy::pluginHostDied()
+{
+    PluginInstanceMap instances;    
+    m_instances.swap(instances);
+  
+    PluginInstanceMap::const_iterator end = instances.end();
+    for (PluginInstanceMap::const_iterator it = instances.begin(); it != end; ++it)
+        it->second->pluginHostDied();
+    
+    NetscapePluginHostManager::shared().pluginHostDied(this);
+    
+    // The plug-in crashed while its menu bar was hidden. Make sure to show it.
+    if (!m_menuBarIsVisible)
+        setMenuBarVisible(true);
+
+    // The plug-in crashed while it had a modal dialog up.
+    if (m_isModal)
+        endModal();
+    
+    delete this;
+}
+    
+void NetscapePluginHostProxy::addPluginInstance(NetscapePluginInstanceProxy* instance)
+{
+    ASSERT(!m_instances.contains(instance->pluginID()));
+    
+    m_instances.set(instance->pluginID(), instance);
+}
+    
+void NetscapePluginHostProxy::removePluginInstance(NetscapePluginInstanceProxy* instance)
+{
+    ASSERT(m_instances.get(instance->pluginID()) == instance);
+
+    m_instances.remove(instance->pluginID());
+}
+
+NetscapePluginInstanceProxy* NetscapePluginHostProxy::pluginInstance(uint32_t pluginID)
+{
+    NetscapePluginInstanceProxy* result = m_instances.get(pluginID).get();
+    ASSERT(!result || result->hostProxy() == this);
+    return result;
+}
+
+void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
+{
+    ASSERT(msg);
+    ASSERT(static_cast<mach_msg_header_t*>(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME);
+    
+    static_cast<NetscapePluginHostProxy*>(info)->pluginHostDied();
+}
+
+void NetscapePluginHostProxy::setMenuBarVisible(bool visible)
+{
+    m_menuBarIsVisible = visible;
+
+    [NSMenu setMenuBarVisible:visible];
+}
+
+void NetscapePluginHostProxy::didEnterFullscreen() const
+{
+    SetFrontProcess(&m_pluginHostPSN);
+}
+
+void NetscapePluginHostProxy::didExitFullscreen() const
+{
+    // If the plug-in host is the current application then we should bring ourselves to the front when it exits full-screen mode.
+
+    ProcessSerialNumber frontProcess;
+    GetFrontProcess(&frontProcess);
+    Boolean isSameProcess = 0;
+    SameProcess(&frontProcess, &m_pluginHostPSN, &isSameProcess);
+    if (!isSameProcess)
+        return;
+
+    ProcessSerialNumber currentProcess;
+    GetCurrentProcess(&currentProcess);
+    SetFrontProcess(&currentProcess);
+}
+
+void NetscapePluginHostProxy::setFullscreenWindowIsShowing(bool isShowing)
+{
+    if (m_fullscreenWindowIsShowing == isShowing)
+        return;
+
+    m_fullscreenWindowIsShowing = isShowing;
+    if (m_fullscreenWindowIsShowing)
+        didEnterFullscreen();
+    else
+        didExitFullscreen();
+
+}
+
+void NetscapePluginHostProxy::applicationDidBecomeActive()
+{
+    SetFrontProcess(&m_pluginHostPSN);
+}
+
+void NetscapePluginHostProxy::beginModal()
+{
+    ASSERT(!m_placeholderWindow);
+    ASSERT(!m_activationObserver);
+    
+    m_placeholderWindow.adoptNS([[WebPlaceholderModalWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
+    
+    m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
+                                                                         usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
+    
+    // We need to be able to get the setModal(false) call from the plug-in host.
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
+    
+    [NSApp runModalForWindow:m_placeholderWindow.get()];
+    
+    [m_placeholderWindow.get() orderOut:nil];
+    m_placeholderWindow = 0;
+}
+    
+void NetscapePluginHostProxy::endModal()
+{
+    ASSERT(m_placeholderWindow);
+    ASSERT(m_activationObserver);
+    
+    [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
+    m_activationObserver = nil;
+    
+    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
+    
+    [NSApp stopModal];
+    
+    // Make ourselves the front process.
+    ProcessSerialNumber psn;
+    GetCurrentProcess(&psn);
+    SetFrontProcess(&psn);            
+}
+    
+
+void NetscapePluginHostProxy::setModal(bool modal)
+{
+    if (modal == m_isModal) 
+        return;
+    
+    m_isModal = modal;
+    
+    if (m_isModal)
+        beginModal();
+    else
+        endModal();
+}
+    
+bool NetscapePluginHostProxy::processRequests()
+{
+    s_processingRequests++;
+
+   if (!m_portSet) {
+        mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet);
+        mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet);
+        mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
+    }
+    
+    char buffer[4096];
+    
+    mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer);
+    
+    kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL);
+    
+    if (kr != KERN_SUCCESS) {
+        LOG_ERROR("Could not receive mach message, error %x", kr);
+        s_processingRequests--;
+        return false;
+    }
+    
+    if (msg->msgh_local_port == m_clientPort) {
+        __ReplyUnion__WKWebKitPluginClient_subsystem reply;
+        mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply);
+        
+        if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) {
+            kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+            
+            if (kr != KERN_SUCCESS) {
+                LOG_ERROR("Could not send mach message, error %x", kr);
+                s_processingRequests--;
+                return false;
+            }
+        }
+        
+        s_processingRequests--;
+        return true;
+    }
+    
+    if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) {
+        ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME);
+        pluginHostDied();
+        s_processingRequests--;
+        return false;
+    }
+    
+    ASSERT_NOT_REACHED();
+    s_processingRequests--;
+    return false;
+}
+
+} // namespace WebKit
+
+using namespace WebKit;
+
+// Helper class for deallocating data
+class DataDeallocator {
+public:
+    DataDeallocator(data_t data, mach_msg_type_number_t dataLength)
+        : m_data(reinterpret_cast<vm_address_t>(data))
+        , m_dataLength(dataLength)
+    {
+    }
+    
+    ~DataDeallocator()
+    {
+        if (!m_data)
+            return;
+        
+        vm_deallocate(mach_task_self(), m_data, m_dataLength);
+    }
+    
+private:
+    vm_address_t m_data;
+    vm_size_t m_dataLength;
+};
+
+// MiG callbacks
+kern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t textCnt)
+{
+    DataDeallocator deallocator(text, textCnt);
+    
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    instanceProxy->status(text);
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t url, mach_msg_type_number_t urlLength, data_t target, mach_msg_type_number_t targetLength, 
+                          data_t postData, mach_msg_type_number_t postDataLength, uint32_t flags,
+                          uint16_t* outResult, uint32_t* outStreamID)
+{
+    DataDeallocator urlDeallocator(url, urlLength);
+    DataDeallocator targetDeallocator(target, targetLength);
+    DataDeallocator postDataDeallocator(postData, postDataLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    uint32_t streamID = 0;
+    NPError result = instanceProxy->loadURL(url, target, postData, postDataLength, static_cast<LoadURLFlags>(flags), streamID);
+    
+    *outResult = result;
+    *outStreamID = streamID;
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCCancelLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t streamID, int16_t reason)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    if (!instanceProxy->cancelStreamLoad(streamID, reason))
+        return KERN_FAILURE;
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCInvalidateRect(mach_port_t clientPort, uint32_t pluginID, double x, double y, double width, double height)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_SUCCESS;
+
+    if (!hostProxy->isProcessingRequests()) {
+        if (NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID))
+            instanceProxy->invalidateRect(x, y, width, height);
+        return KERN_SUCCESS;
+    }
+
+    // Defer the work
+    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+        if (NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort)) {
+            if (NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID))
+                instanceProxy->invalidateRect(x, y, width, height);
+        }
+    });
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetScriptableNPObjectReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID));
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t result)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanReply(result));
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCBooleanAndDataReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t returnValue, data_t resultData, mach_msg_type_number_t resultLength)
+{
+    DataDeallocator deallocator(resultData, resultLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    RetainPtr<CFDataRef> result(AdoptCF, CFDataCreate(0, reinterpret_cast<UInt8*>(resultData), resultLength));
+    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanAndDataReply(returnValue, result));
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCInstantiatePluginReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, kern_return_t result, uint32_t renderContextID, uint32_t rendererType)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::InstantiatePluginReply(result, renderContextID, static_cast<RendererType>(rendererType)));
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetWindowNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    uint32_t objectID;
+    if (!instanceProxy->getWindowNPObject(objectID))
+        return KERN_FAILURE;
+    
+    *outObjectID = objectID;    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetPluginElementNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    uint32_t objectID;
+    if (!instanceProxy->getPluginElementNPObject(objectID))
+        return KERN_FAILURE;
+    
+    *outObjectID = objectID;    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCForgetBrowserObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    return instanceProxy->forgetBrowserObjectID(objectID) ? KERN_SUCCESS : KERN_FAILURE;
+}
+
+kern_return_t WKPCEvaluate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, data_t scriptData, mach_msg_type_number_t scriptLength, boolean_t allowPopups)
+{
+    DataDeallocator deallocator(scriptData, scriptLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    PluginDestroyDeferrer deferrer(instanceProxy);
+    
+    String script = String::fromUTF8WithLatin1Fallback(scriptData, scriptLength);
+    
+    data_t resultData = 0;
+    mach_msg_type_number_t resultLength = 0;
+    boolean_t returnValue = instanceProxy->evaluate(objectID, script, resultData, resultLength, allowPopups);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+    if (resultData)
+        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+        
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetStringIdentifier(mach_port_t clientPort, data_t name, mach_msg_type_number_t nameCnt, uint64_t* identifier)
+{
+    DataDeallocator deallocator(name, nameCnt);
+
+    COMPILE_ASSERT(sizeof(*identifier) == sizeof(IdentifierRep*), identifier_sizes);
+    
+    *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(name));
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetIntIdentifier(mach_port_t clientPort, int32_t value, uint64_t* identifier)
+{
+    COMPILE_ASSERT(sizeof(*identifier) == sizeof(NPIdentifier), identifier_sizes);
+    
+    *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(value));
+    return KERN_SUCCESS;
+}
+
+static Identifier identifierFromIdentifierRep(IdentifierRep* identifier)
+{
+    ASSERT(IdentifierRep::isValid(identifier));
+    ASSERT(identifier->isString());
+  
+    const char* str = identifier->string();    
+    return Identifier(JSDOMWindow::commonJSGlobalData(), stringToUString(String::fromUTF8WithLatin1Fallback(str, strlen(str))));
+}
+
+kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier,
+                         data_t argumentsData, mach_msg_type_number_t argumentsLength) 
+{
+    DataDeallocator deallocator(argumentsData, argumentsLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    PluginDestroyDeferrer deferrer(instanceProxy);
+    
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+
+    Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);
+
+    data_t resultData = 0;
+    mach_msg_type_number_t resultLength = 0;
+    boolean_t returnValue = instanceProxy->invoke(objectID, methodNameIdentifier, argumentsData, argumentsLength, resultData, resultLength);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+    if (resultData)
+        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCInvokeDefault(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID,
+                                data_t argumentsData, mach_msg_type_number_t argumentsLength)
+{
+    DataDeallocator deallocator(argumentsData, argumentsLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    data_t resultData = 0;
+    mach_msg_type_number_t resultLength = 0;
+    boolean_t returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, resultData, resultLength);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+    if (resultData)
+        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCConstruct(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID,
+                            data_t argumentsData, mach_msg_type_number_t argumentsLength, 
+                            boolean_t* returnValue, data_t* resultData, mach_msg_type_number_t* resultLength)
+{
+    DataDeallocator deallocator(argumentsData, argumentsLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    *returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+    
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    data_t resultData = 0;
+    mach_msg_type_number_t resultLength = 0;
+    boolean_t returnValue;
+    
+    if (identifier->isString()) {
+        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
+        returnValue = instanceProxy->getProperty(objectID, propertyNameIdentifier, resultData, resultLength);
+    } else 
+        returnValue = instanceProxy->setProperty(objectID, identifier->number(), resultData, resultLength);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+    if (resultData)
+        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier, data_t valueData, mach_msg_type_number_t valueLength)
+{
+    DataDeallocator deallocator(valueData, valueLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+
+    bool result;
+    if (identifier->isString()) {
+        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
+        result = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength);
+    } else 
+        result = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, result);
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+
+    bool result;
+    if (identifier->isString()) {
+        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
+        result = instanceProxy->removeProperty(objectID, propertyNameIdentifier);
+    } else 
+        result = instanceProxy->removeProperty(objectID, identifier->number());
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, result);
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+    
+    boolean_t returnValue;
+    if (identifier->isString()) {
+        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
+        returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier);
+    } else 
+        returnValue = instanceProxy->hasProperty(objectID, identifier->number());
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    PluginDestroyDeferrer deferrer(instanceProxy);
+
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+    
+    Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);        
+    boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCIdentifierInfo(mach_port_t clientPort, uint64_t serverIdentifier, data_t* infoData, mach_msg_type_number_t* infoLength)
+{
+    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
+    if (!IdentifierRep::isValid(identifier))
+        return KERN_FAILURE;
+    
+    id info;
+    if (identifier->isString()) {
+        const char* str = identifier->string();
+        info = [NSData dataWithBytesNoCopy:(void*)str length:strlen(str) freeWhenDone:NO];
+    } else 
+        info = [NSNumber numberWithInt:identifier->number()];
+
+    RetainPtr<NSData*> data = [NSPropertyListSerialization dataFromPropertyList:info format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+    ASSERT(data);
+    
+    *infoLength = [data.get() length];
+    mig_allocate(reinterpret_cast<vm_address_t*>(infoData), *infoLength);
+    
+    memcpy(*infoData, [data.get() bytes], *infoLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCEnumerate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    data_t resultData = 0;
+    mach_msg_type_number_t resultLength = 0;
+    boolean_t returnValue = instanceProxy->enumerate(objectID, resultData, resultLength);
+
+    hostProxy = instanceProxy->hostProxy();
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
+    
+    if (resultData)
+        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetMenuBarVisible(mach_port_t clientPort, boolean_t menuBarVisible)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    hostProxy->setMenuBarVisible(menuBarVisible);
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetFullscreenWindowIsShowing(mach_port_t clientPort, boolean_t fullscreenWindowIsShowing)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    hostProxy->setFullscreenWindowIsShowing(fullscreenWindowIsShowing);
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetModal(mach_port_t clientPort, boolean_t modal)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    if (!hostProxy->isProcessingRequests()) {
+        hostProxy->setModal(modal);
+        return KERN_SUCCESS;
+    }
+
+    // Defer the work
+    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+        if (NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort))
+            hostProxy->setModal(modal);
+    });
+
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetCookies(mach_port_t clientPort, uint32_t pluginID,
+                             data_t urlData, mach_msg_type_number_t urlLength,
+                             boolean_t* returnValue, data_t* cookiesData, mach_msg_type_number_t* cookiesLength)
+{
+    *cookiesData = 0;
+    *cookiesLength = 0;
+    
+    DataDeallocator deallocator(urlData, urlLength);
+    
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    *returnValue = instanceProxy->getCookies(urlData, urlLength, *cookiesData, *cookiesLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetProxy(mach_port_t clientPort, uint32_t pluginID,
+                           data_t urlData, mach_msg_type_number_t urlLength,
+                           boolean_t* returnValue, data_t* proxyData, mach_msg_type_number_t* proxyLength)
+{
+    *proxyData = 0;
+    *proxyLength = 0;
+    
+    DataDeallocator deallocator(urlData, urlLength);
+    
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    *returnValue = instanceProxy->getProxy(urlData, urlLength, *proxyData, *proxyLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCSetCookies(mach_port_t clientPort, uint32_t pluginID,
+                             data_t urlData, mach_msg_type_number_t urlLength,
+                             data_t cookiesData, mach_msg_type_number_t cookiesLength,
+                             boolean_t* returnValue)
+{
+    DataDeallocator urlDeallocator(urlData, urlLength);
+    DataDeallocator cookiesDeallocator(cookiesData, cookiesLength);
+ 
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    *returnValue = instanceProxy->setCookies(urlData, urlLength, cookiesData, cookiesLength);
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCGetAuthenticationInfo(mach_port_t clientPort, uint32_t pluginID,
+                                        data_t protocolData, mach_msg_type_number_t protocolLength,
+                                        data_t hostData, mach_msg_type_number_t hostLength,
+                                        uint32_t port,
+                                        data_t schemeData, mach_msg_type_number_t schemeLength,
+                                        data_t realmData, mach_msg_type_number_t realmLength,
+                                        boolean_t* returnValue,
+                                        data_t* usernameData, mach_msg_type_number_t *usernameLength,
+                                        data_t* passwordData, mach_msg_type_number_t *passwordLength)
+{
+    DataDeallocator protocolDeallocator(protocolData, protocolLength);
+    DataDeallocator hostDeallocator(hostData, hostLength);
+    DataDeallocator schemeDeallocator(schemeData, schemeLength);
+    DataDeallocator realmDeallocator(realmData, realmLength);
+
+    *usernameData = 0;
+    *usernameLength = 0;
+    *passwordData = 0;
+    *passwordLength = 0;
+    
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    *returnValue = instanceProxy->getAuthenticationInfo(protocolData, hostData, port, schemeData, realmData, *usernameData, *usernameLength, *passwordData, *passwordLength);
+    
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCConvertPoint(mach_port_t clientPort, uint32_t pluginID, 
+                               double sourceX, double sourceY, uint32_t sourceSpace, 
+                               uint32_t destSpace, boolean_t *returnValue, double *destX, double *destY)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    *returnValue = instanceProxy->convertPoint(sourceX, sourceY, static_cast<NPCoordinateSpace>(sourceSpace), 
+                                               *destX, *destY, static_cast<NPCoordinateSpace>(destSpace));
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCCheckIfAllowedToLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t urlData, mach_msg_type_number_t urlLength,
+                                          data_t targetData, mach_msg_type_number_t targetLength, uint32_t *checkID)
+{
+    DataDeallocator urlDeallocator(urlData, urlLength);
+    DataDeallocator targetDeallocator(targetData, targetLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    *checkID = instanceProxy->checkIfAllowedToLoadURL(urlData, targetData);
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCCancelCheckIfAllowedToLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t checkID)
+{
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+
+    instanceProxy->cancelCheckIfAllowedToLoadURL(checkID);
+    return KERN_SUCCESS;
+}
+
+kern_return_t WKPCResolveURL(mach_port_t clientPort, uint32_t pluginID, data_t urlData, mach_msg_type_number_t urlLength,
+                             data_t targetData, mach_msg_type_number_t targetLength,
+                             data_t *resolvedURLData, mach_msg_type_number_t *resolvedURLLength)
+{
+    DataDeallocator urlDeallocator(urlData, urlLength);
+    DataDeallocator targetDeallocator(targetData, targetLength);
+    
+    *resolvedURLData = 0;
+    *resolvedURLLength = 0;
+    
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+    
+    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
+    if (!instanceProxy)
+        return KERN_FAILURE;
+    
+    instanceProxy->resolveURL(urlData, targetData, *resolvedURLData, *resolvedURLLength);
+    return KERN_SUCCESS;
+}
+
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+kern_return_t WKPCRunSyncOpenPanel(mach_port_t clientPort, data_t panelData, mach_msg_type_number_t panelDataLength)
+{
+    DataDeallocator panelDataDeallocator(panelData, panelDataLength);
+
+    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
+    if (!hostProxy)
+        return KERN_FAILURE;
+
+    NSOpenPanel *sheet = [NSOpenPanel openPanel];
+    NSDictionary *panelState = [NSPropertyListSerialization propertyListFromData:[NSData dataWithBytes:panelData length:panelDataLength]
+                                                                mutabilityOption:NSPropertyListImmutable
+                                                                          format:NULL
+                                                                errorDescription:nil];
+    
+    [sheet setCanChooseFiles:[[panelState objectForKey:@"canChooseFiles"] boolValue]];
+    [sheet setCanChooseDirectories:[[panelState objectForKey:@"canChooseDirectories"] boolValue]];
+    [sheet setResolvesAliases:[[panelState objectForKey:@"resolvesAliases"] boolValue]];
+    [sheet setAllowsMultipleSelection:[[panelState objectForKey:@"allowsMultipleSelection"] boolValue]];
+    [sheet setCanCreateDirectories:[[panelState objectForKey:@"canCreateDirectories"] boolValue]];
+    [sheet setShowsHiddenFiles:[[panelState objectForKey:@"showsHiddenFiles"] boolValue]];
+    [sheet setExtensionHidden:[[panelState objectForKey:@"isExtensionHidden"] boolValue]];
+    [sheet setCanSelectHiddenExtension:[[panelState objectForKey:@"canSelectHiddenExtension"] boolValue]];
+    [sheet setAllowsOtherFileTypes:[[panelState objectForKey:@"allowsOtherFileTypes"] boolValue]];
+    [sheet setTreatsFilePackagesAsDirectories:[[panelState objectForKey:@"treatsFilePackagesAsDirectories"] boolValue]];
+    [sheet setPrompt:[panelState objectForKey:@"prompt"]];
+    [sheet setNameFieldLabel:[panelState objectForKey:@"nameFieldLabel"]];
+    [sheet setMessage:[panelState objectForKey:@"message"]];
+    [sheet setAllowedFileTypes:[panelState objectForKey:@"allowedFileTypes"]];
+    [sheet setRequiredFileType:[panelState objectForKey:@"requiredFileType"]];    
+    [sheet setTitle:[panelState objectForKey:@"title"]];
+    [sheet runModal];
+
+    NetscapePluginHostProxy* newHostProxy = pluginProxyMap().get(clientPort);
+    if (newHostProxy != hostProxy)
+        return KERN_FAILURE;
+
+    NSDictionary *ret = [NSDictionary dictionaryWithObjectsAndKeys:
+                         [sheet filenames], @"filenames",
+                         WKNoteOpenPanelFiles([sheet filenames]), @"extensions",
+                         nil];
+    
+    RetainPtr<NSData*> data = [NSPropertyListSerialization dataFromPropertyList:ret format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
+    ASSERT(data);
+
+    _WKPHSyncOpenPanelReply(hostProxy->port(), const_cast<char *>(static_cast<const char*>([data.get() bytes])), [data.get() length]);
+    return KERN_SUCCESS;
+}
+#else
+kern_return_t WKPCRunSyncOpenPanel(mach_port_t clientPort, data_t panelData, mach_msg_type_number_t panelDataLength)
+{
+    return KERN_FAILURE;
+}
+#endif // !defined(BUILDING_ON_SNOW_LEOPARD)
+
+kern_return_t WKPCSetException(mach_port_t clientPort, data_t message, mach_msg_type_number_t messageCnt)
+{
+    DataDeallocator deallocator(message, messageCnt);
+
+    string str(message, messageCnt);
+    NetscapePluginInstanceProxy::setGlobalException(str.c_str());
+
+    return KERN_SUCCESS;
+}
+
+#endif // USE(PLUGIN_HOST_PROCESS)