/* * 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 #import #import "HostedNetscapePluginStream.h" #import "NetscapePluginHostManager.h" #import "NetscapePluginInstanceProxy.h" #import "WebFrameInternal.h" #import "WebHostedNetscapePluginView.h" #import "WebKitSystemInterface.h" #import #import #import 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 m_proxy; }; typedef HashMap PluginProxyMap; static PluginProxyMap& pluginProxyMap() { DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ()); return pluginProxyMap; } 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_processingRequests(0) , 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 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 has been resolved. m_clientPortSource = dispatch_source_mig_create(m_clientPort, WKWebKitPluginClient_subsystem.maxsize, 0, dispatch_get_main_queue(), WebKitPluginClient_server); #else m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKWebKitPluginClient_subsystem, m_clientPort)); CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode); CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSEventTrackingRunLoopMode); #endif } 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); #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_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) { return m_instances.get(pluginID).get(); } void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) { ASSERT(msg); ASSERT(static_cast(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME); static_cast(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(¤tProcess); SetFrontProcess(¤tProcess); } 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() { m_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(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); m_processingRequests--; return false; } if (msg->msgh_local_port == m_clientPort) { __ReplyUnion__WKWebKitPluginClient_subsystem reply; mach_msg_header_t* replyHeader = reinterpret_cast(&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); m_processingRequests--; return false; } } m_processingRequests--; return true; } if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) { ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME); pluginHostDied(); m_processingRequests--; return false; } ASSERT_NOT_REACHED(); m_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(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(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 result(AdoptCF, CFDataCreate(0, reinterpret_cast(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, 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(requestID, 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 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 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 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) { _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); return KERN_SUCCESS; } 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); _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); if (resultData) mig_deallocate(reinterpret_cast(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(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(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(), 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) { _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); return KERN_SUCCESS; } PluginDestroyDeferrer deferrer(instanceProxy); IdentifierRep* identifier = reinterpret_cast(serverIdentifier); if (!IdentifierRep::isValid(identifier)) { _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false, 0, 0); return KERN_SUCCESS; } 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); _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); if (resultData) mig_deallocate(reinterpret_cast(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) { _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); return KERN_SUCCESS; } PluginDestroyDeferrer deferrer(instanceProxy); data_t resultData = 0; mach_msg_type_number_t resultLength = 0; boolean_t returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, resultData, resultLength); _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); if (resultData) mig_deallocate(reinterpret_cast(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) { _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); return KERN_SUCCESS; } IdentifierRep* identifier = reinterpret_cast(serverIdentifier); if (!IdentifierRep::isValid(identifier)) { _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); return KERN_SUCCESS; } 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); _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); if (resultData) mig_deallocate(reinterpret_cast(resultData), resultLength); return KERN_SUCCESS; } kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, data_t valueData, mach_msg_type_number_t valueLength, boolean_t* returnValue) { 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(serverIdentifier); if (!IdentifierRep::isValid(identifier)) *returnValue = false; if (identifier->isString()) { Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); *returnValue = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength); } else *returnValue = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength); return KERN_SUCCESS; } kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, boolean_t* returnValue) { 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(serverIdentifier); if (!IdentifierRep::isValid(identifier)) return KERN_FAILURE; if (identifier->isString()) { Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); *returnValue = instanceProxy->removeProperty(objectID, propertyNameIdentifier); } else *returnValue = instanceProxy->removeProperty(objectID, identifier->number()); 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) { _WKPHBooleanReply(hostProxy->port(), pluginID, requestID, false); return KERN_SUCCESS; } PluginDestroyDeferrer deferrer(instanceProxy); IdentifierRep* identifier = reinterpret_cast(serverIdentifier); if (!IdentifierRep::isValid(identifier)) { _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false); return KERN_SUCCESS; } boolean_t returnValue; if (identifier->isString()) { Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier); } else returnValue = instanceProxy->hasProperty(objectID, identifier->number()); _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) { _WKPHBooleanReply(hostProxy->port(), pluginID, requestID, false); return KERN_SUCCESS; } PluginDestroyDeferrer deferrer(instanceProxy); IdentifierRep* identifier = reinterpret_cast(serverIdentifier); if (!IdentifierRep::isValid(identifier)) { _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false); return KERN_SUCCESS; } Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier); boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier); _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(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 data = [NSPropertyListSerialization dataFromPropertyList:info format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; ASSERT(data); *infoLength = [data.get() length]; mig_allocate(reinterpret_cast(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) { _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); return KERN_SUCCESS; } data_t resultData = 0; mach_msg_type_number_t resultLength = 0; boolean_t returnValue = instanceProxy->enumerate(objectID, resultData, resultLength); _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); if (resultData) mig_deallocate(reinterpret_cast(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; 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(sourceSpace), *destX, *destY, static_cast(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]; NSDictionary *ret = [NSDictionary dictionaryWithObjectsAndKeys: [sheet filenames], @"filenames", WKNoteOpenPanelFiles([sheet filenames]), @"extensions", nil]; RetainPtr data = [NSPropertyListSerialization dataFromPropertyList:ret format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; ASSERT(data); _WKPHSyncOpenPanelReply(hostProxy->port(), const_cast(static_cast([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) #endif // USE(PLUGIN_HOST_PROCESS)