2009-03-26 Anders Carlsson <andersca@apple.com>
[WebKit-https.git] / WebKit / mac / Plugins / Hosted / NetscapePluginHostProxy.mm
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #if USE(PLUGIN_HOST_PROCESS)
27
28 #import "NetscapePluginHostProxy.h"
29
30 #import <mach/mach.h>
31 #import <wtf/StdLibExtras.h>
32
33 #import "HostedNetscapePluginStream.h"
34 #import "NetscapePluginHostManager.h"
35 #import "NetscapePluginInstanceProxy.h"
36 #import "WebFrameInternal.h"
37 #import "WebHostedNetscapePluginView.h"
38 #import "WebKitSystemInterface.h"
39 #import <WebCore/Frame.h>
40 #import <WebCore/IdentifierRep.h>
41 #import <WebCore/ScriptController.h>
42
43 extern "C" {
44 #import "WebKitPluginHost.h"
45 #import "WebKitPluginClientServer.h"
46 }
47
48 using namespace std;
49 using namespace JSC;
50 using namespace WebCore;
51
52 namespace WebKit {
53
54 class PluginDestroyDeferrer {
55 public:
56     PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy)
57         : m_proxy(proxy)
58     {
59         m_proxy->willCallPluginFunction();
60     }
61     
62     ~PluginDestroyDeferrer()
63     {
64         m_proxy->didCallPluginFunction();
65     }
66
67 private:
68     RefPtr<NetscapePluginInstanceProxy> m_proxy;
69 };
70
71 typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap;
72 static PluginProxyMap& pluginProxyMap()
73 {
74     DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ());
75     
76     return pluginProxyMap;
77 }
78
79 NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN)
80     : m_clientPort(clientPort)
81     , m_portSet(MACH_PORT_NULL)
82     , m_pluginHostPort(pluginHostPort)
83     , m_isModal(false)
84     , m_menuBarIsVisible(true)
85     , m_pluginHostPSN(pluginHostPSN)
86 {
87     pluginProxyMap().add(m_clientPort, this);
88     
89     // FIXME: We should use libdispatch for this.
90     CFMachPortContext context = { 0, this, 0, 0, 0 };
91     m_deadNameNotificationPort.adoptCF(CFMachPortCreate(0, deadNameNotificationCallback, &context, 0));
92
93     mach_port_t previous;
94     mach_port_request_notification(mach_task_self(), pluginHostPort, MACH_NOTIFY_DEAD_NAME, 0, 
95                                    CFMachPortGetPort(m_deadNameNotificationPort.get()), MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
96     ASSERT(previous == MACH_PORT_NULL);
97     
98     RetainPtr<CFRunLoopSourceRef> deathPortSource(AdoptCF, CFMachPortCreateRunLoopSource(0, m_deadNameNotificationPort.get(), 0));
99     
100     CFRunLoopAddSource(CFRunLoopGetCurrent(), deathPortSource.get(), kCFRunLoopDefaultMode);
101     
102 #ifdef USE_LIBDISPATCH
103     // FIXME: Unfortunately we can't use a dispatch source here until <rdar://problem/6393180> has been resolved.
104     m_clientPortSource = dispatch_source_mig_create(m_clientPort, WKWebKitPluginClient_subsystem.maxsize, 0, 
105                                                     dispatch_get_main_queue(), WebKitPluginClient_server);
106 #else
107     m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKWebKitPluginClient_subsystem, m_clientPort));
108     CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode);
109     CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSEventTrackingRunLoopMode);
110 #endif
111 }
112
113 NetscapePluginHostProxy::~NetscapePluginHostProxy()
114 {
115     pluginProxyMap().remove(m_clientPort);
116
117     // Free the port set
118     if (m_portSet) {
119         mach_port_extract_member(mach_task_self(), m_clientPort, m_portSet);
120         mach_port_extract_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
121         mach_port_destroy(mach_task_self(), m_portSet);
122     }
123     
124     ASSERT(m_clientPortSource);
125 #ifdef USE_LIBDISPATCH
126     dispatch_release(m_clientPortSource);
127 #else
128     CFRunLoopSourceInvalidate(m_clientPortSource.get());
129     m_clientPortSource = 0;
130 #endif
131 }
132
133 void NetscapePluginHostProxy::pluginHostDied()
134 {
135     PluginInstanceMap instances;    
136     m_instances.swap(instances);
137   
138     PluginInstanceMap::const_iterator end = instances.end();
139     for (PluginInstanceMap::const_iterator it = instances.begin(); it != end; ++it)
140         it->second->pluginHostDied();
141     
142     NetscapePluginHostManager::shared().pluginHostDied(this);
143     
144     // The plug-in crashed while its menu bar was hidden. Make sure to show it.
145     if (!m_menuBarIsVisible)
146         setMenuBarVisible(true);
147
148     // The plug-in crashed while it had a modal dialog up.
149     if (m_isModal)
150         endModal();
151     
152     delete this;
153 }
154     
155 void NetscapePluginHostProxy::addPluginInstance(NetscapePluginInstanceProxy* instance)
156 {
157     ASSERT(!m_instances.contains(instance->pluginID()));
158     
159     m_instances.set(instance->pluginID(), instance);
160 }
161     
162 void NetscapePluginHostProxy::removePluginInstance(NetscapePluginInstanceProxy* instance)
163 {
164     ASSERT(m_instances.get(instance->pluginID()) == instance);
165
166     m_instances.remove(instance->pluginID());
167 }
168
169 NetscapePluginInstanceProxy* NetscapePluginHostProxy::pluginInstance(uint32_t pluginID)
170 {
171     return m_instances.get(pluginID).get();
172 }
173
174 void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
175 {
176     ASSERT(msg && static_cast<mach_msg_header_t*>(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME);
177     
178     static_cast<NetscapePluginHostProxy*>(info)->pluginHostDied();
179 }
180
181 void NetscapePluginHostProxy::setMenuBarVisible(bool visible)
182 {
183     m_menuBarIsVisible = visible;
184     
185     [NSMenu setMenuBarVisible:visible];
186     if (visible) {
187         // Make ourselves the front app
188         ProcessSerialNumber psn;
189         GetCurrentProcess(&psn);
190         SetFrontProcess(&psn);
191     }
192 }
193
194 void NetscapePluginHostProxy::applicationDidBecomeActive()
195 {
196     SetFrontProcess(&m_pluginHostPSN);
197 }
198
199 void NetscapePluginHostProxy::beginModal()
200 {
201     ASSERT(!m_placeholderWindow);
202     ASSERT(!m_activationObserver);
203     
204     m_placeholderWindow.adoptNS([[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
205     
206     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
207                                                                          usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
208     
209     // We need to be able to get the setModal(false) call from the plug-in host.
210     CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
211     
212     [NSApp runModalForWindow:m_placeholderWindow.get()];
213 }
214     
215 void NetscapePluginHostProxy::endModal()
216 {
217     ASSERT(m_placeholderWindow);
218     ASSERT(m_activationObserver);
219     
220     [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
221     m_activationObserver = nil;
222     
223     CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
224     
225     [NSApp stopModal];
226     [m_placeholderWindow.get() orderOut:nil];
227     m_placeholderWindow = 0;
228     
229     // Make ourselves the front process.
230     ProcessSerialNumber psn;
231     GetCurrentProcess(&psn);
232     SetFrontProcess(&psn);            
233 }
234     
235
236 void NetscapePluginHostProxy::setModal(bool modal)
237 {
238     if (modal == m_isModal) 
239         return;
240     
241     m_isModal = modal;
242     
243     if (m_isModal)
244         beginModal();
245     else
246         endModal();
247 }
248     
249 bool NetscapePluginHostProxy::processRequests()
250 {
251     if (!m_portSet) {
252         mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet);
253         mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet);
254         mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
255     }
256     
257     char buffer[4096];
258     
259     mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer);
260     
261     kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL);
262     
263     if (kr != KERN_SUCCESS) {
264         LOG_ERROR("Could not receive mach message, error %x", kr);
265         return false;
266     }
267     
268     if (msg->msgh_local_port == m_clientPort) {
269         __ReplyUnion__WKWebKitPluginClient_subsystem reply;
270         mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply);
271         
272         if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) {
273             kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
274             
275             if (kr != KERN_SUCCESS) {
276                 LOG_ERROR("Could not send mach message, error %x", kr);
277                 return false;
278             }
279         }
280         
281         return true;
282     }
283     
284     if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) {
285         ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME);
286         pluginHostDied();
287         return false;
288     }
289     
290     ASSERT_NOT_REACHED();
291     return false;
292 }
293
294 } // namespace WebKit
295
296 using namespace WebKit;
297
298 // Helper class for deallocating data
299 class DataDeallocator {
300 public:
301     DataDeallocator(data_t data, mach_msg_type_number_t dataLength)
302         : m_data(reinterpret_cast<vm_address_t>(data))
303         , m_dataLength(dataLength)
304     {
305     }
306     
307     ~DataDeallocator()
308     {
309         if (!m_data)
310             return;
311         
312         vm_deallocate(mach_task_self(), m_data, m_dataLength);
313     }
314     
315 private:
316     vm_address_t m_data;
317     vm_size_t m_dataLength;
318 };
319
320 // MiG callbacks
321 kern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t textCnt)
322 {
323     DataDeallocator deallocator(text, textCnt);
324     
325     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
326     if (!hostProxy)
327         return KERN_FAILURE;
328     
329     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
330     if (!instanceProxy)
331         return KERN_FAILURE;
332     
333     instanceProxy->status(text);
334     return KERN_SUCCESS;
335 }
336
337 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, 
338                           data_t postData, mach_msg_type_number_t postDataLength, uint32_t flags,
339                           uint16_t* outResult, uint32_t* outStreamID)
340 {
341     DataDeallocator urlDeallocator(url, urlLength);
342     DataDeallocator targetDeallocator(target, targetLength);
343     DataDeallocator postDataDeallocator(postData, postDataLength);
344
345     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
346     if (!hostProxy)
347         return KERN_FAILURE;
348     
349     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
350     if (!instanceProxy)
351         return KERN_FAILURE;
352
353     uint32_t streamID = 0;
354     NPError result = instanceProxy->loadURL(url, target, postData, postDataLength, static_cast<LoadURLFlags>(flags), streamID);
355     
356     *outResult = result;
357     *outStreamID = streamID;
358     return KERN_SUCCESS;
359 }
360
361 kern_return_t WKPCCancelLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t streamID, int16_t reason)
362 {
363     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
364     if (!hostProxy)
365         return KERN_FAILURE;
366     
367     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
368     if (!instanceProxy)
369         return KERN_FAILURE;
370     
371     HostedNetscapePluginStream* pluginStream = instanceProxy->pluginStream(streamID);
372     if (!pluginStream)
373         return KERN_FAILURE;
374
375     pluginStream->cancelLoad(reason);
376     return KERN_SUCCESS;
377 }
378
379 kern_return_t WKPCInvalidateRect(mach_port_t clientPort, uint32_t pluginID, double x, double y, double width, double height)
380 {
381     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
382     if (!hostProxy)
383         return KERN_FAILURE;
384     
385     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
386     if (!instanceProxy)
387         return KERN_FAILURE;
388
389     instanceProxy->invalidateRect(x, y, width, height);
390     return KERN_SUCCESS;
391 }
392
393 kern_return_t WKPCGetScriptableNPObjectReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
394 {
395     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
396     if (!hostProxy)
397         return KERN_FAILURE;
398     
399     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
400     if (!instanceProxy)
401         return KERN_FAILURE;
402
403     instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID));
404     return KERN_SUCCESS;
405 }
406
407 kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t result)
408 {
409     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
410     if (!hostProxy)
411         return KERN_FAILURE;
412     
413     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
414     if (!instanceProxy)
415         return KERN_FAILURE;
416     
417     instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanReply(result));
418     return KERN_SUCCESS;
419 }
420
421 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)
422 {
423     DataDeallocator deallocator(resultData, resultLength);
424
425     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
426     if (!hostProxy)
427         return KERN_FAILURE;
428     
429     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
430     if (!instanceProxy)
431         return KERN_FAILURE;
432
433     RetainPtr<CFDataRef> result(AdoptCF, CFDataCreate(0, reinterpret_cast<UInt8*>(resultData), resultLength));
434     instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanAndDataReply(returnValue, result));
435     
436     return KERN_SUCCESS;
437 }
438
439 kern_return_t WKPCInstantiatePluginReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, kern_return_t result, uint32_t renderContextID, boolean_t useSoftwareRenderer)
440 {
441     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
442     if (!hostProxy)
443         return KERN_FAILURE;
444     
445     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
446     if (!instanceProxy)
447         return KERN_FAILURE;
448
449     instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::InstantiatePluginReply(result, renderContextID, useSoftwareRenderer));
450     return KERN_SUCCESS;
451 }
452
453 kern_return_t WKPCGetWindowNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
454 {
455     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
456     if (!hostProxy)
457         return KERN_FAILURE;
458     
459     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
460     if (!instanceProxy)
461         return KERN_FAILURE;
462
463     uint32_t objectID;
464     if (!instanceProxy->getWindowNPObject(objectID))
465         return KERN_FAILURE;
466     
467     *outObjectID = objectID;    
468     return KERN_SUCCESS;
469 }
470
471 kern_return_t WKPCGetPluginElementNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
472 {
473     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
474     if (!hostProxy)
475         return KERN_FAILURE;
476     
477     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
478     if (!instanceProxy)
479         return KERN_FAILURE;
480     
481     uint32_t objectID;
482     if (!instanceProxy->getPluginElementNPObject(objectID))
483         return KERN_FAILURE;
484     
485     *outObjectID = objectID;    
486     return KERN_SUCCESS;
487 }
488
489 kern_return_t WKPCReleaseObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID)
490 {
491     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
492     if (!hostProxy)
493         return KERN_FAILURE;
494     
495     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
496     if (!instanceProxy)
497         return KERN_FAILURE;
498
499     instanceProxy->releaseObject(objectID);
500     return KERN_SUCCESS;
501 }
502
503 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)
504 {
505     DataDeallocator deallocator(scriptData, scriptLength);
506
507     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
508     if (!hostProxy)
509         return KERN_FAILURE;
510     
511     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
512     if (!instanceProxy)
513         return KERN_FAILURE;
514
515     PluginDestroyDeferrer deferrer(instanceProxy);
516     
517     String script = String::fromUTF8WithLatin1Fallback(scriptData, scriptLength);
518     
519     data_t resultData = 0;
520     mach_msg_type_number_t resultLength = 0;
521     boolean_t returnValue = instanceProxy->evaluate(objectID, script, resultData, resultLength);
522     
523     _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
524     if (resultData)
525         mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
526         
527     return KERN_SUCCESS;
528 }
529
530 kern_return_t WKPCGetStringIdentifier(mach_port_t clientPort, data_t name, mach_msg_type_number_t nameCnt, uint64_t* identifier)
531 {
532     DataDeallocator deallocator(name, nameCnt);
533
534     COMPILE_ASSERT(sizeof(*identifier) == sizeof(IdentifierRep*), identifier_sizes);
535     
536     *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(name));
537     return KERN_SUCCESS;
538 }
539
540 kern_return_t WKPCGetIntIdentifier(mach_port_t clientPort, int32_t value, uint64_t* identifier)
541 {
542     COMPILE_ASSERT(sizeof(*identifier) == sizeof(NPIdentifier), identifier_sizes);
543     
544     *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(value));
545     return KERN_SUCCESS;
546 }
547
548 static Identifier identifierFromIdentifierRep(IdentifierRep* identifier)
549 {
550     ASSERT(IdentifierRep::isValid(identifier));
551     ASSERT(identifier->isString());
552   
553     const char* str = identifier->string();    
554     return Identifier(JSDOMWindow::commonJSGlobalData(), String::fromUTF8WithLatin1Fallback(str, strlen(str)));
555 }
556
557 kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier,
558                          data_t argumentsData, mach_msg_type_number_t argumentsLength) 
559 {
560     DataDeallocator deallocator(argumentsData, argumentsLength);
561
562     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
563     if (!hostProxy)
564         return KERN_FAILURE;
565     
566     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
567     if (!instanceProxy)
568         return KERN_FAILURE;
569
570     PluginDestroyDeferrer deferrer(instanceProxy);
571     
572     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
573     if (!IdentifierRep::isValid(identifier)) {
574         _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false, 0, 0);
575         return KERN_SUCCESS;
576     }
577
578     Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);
579
580     data_t resultData = 0;
581     mach_msg_type_number_t resultLength = 0;
582     boolean_t returnValue = instanceProxy->invoke(objectID, methodNameIdentifier, argumentsData, argumentsLength, resultData, resultLength);
583     
584     _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
585     if (resultData)
586         mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
587     
588     return KERN_SUCCESS;
589 }
590
591 kern_return_t WKPCInvokeDefault(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID,
592                                 data_t argumentsData, mach_msg_type_number_t argumentsLength)
593 {
594     DataDeallocator deallocator(argumentsData, argumentsLength);
595
596     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
597     if (!hostProxy)
598         return KERN_FAILURE;
599     
600     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
601     if (!instanceProxy)
602         return KERN_FAILURE;
603
604     PluginDestroyDeferrer deferrer(instanceProxy);
605
606     data_t resultData = 0;
607     mach_msg_type_number_t resultLength = 0;
608     boolean_t returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, resultData, resultLength);
609     
610     _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
611     if (resultData)
612         mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
613     
614     return KERN_SUCCESS;
615 }
616
617 kern_return_t WKPCConstruct(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID,
618                             data_t argumentsData, mach_msg_type_number_t argumentsLength, 
619                             boolean_t* returnValue, data_t* resultData, mach_msg_type_number_t* resultLength)
620 {
621     DataDeallocator deallocator(argumentsData, argumentsLength);
622
623     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
624     if (!hostProxy)
625         return KERN_FAILURE;
626     
627     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
628     if (!instanceProxy)
629         return KERN_FAILURE;
630
631     PluginDestroyDeferrer deferrer(instanceProxy);
632
633     *returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength);
634     
635     return KERN_SUCCESS;
636 }
637
638 kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
639 {
640     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
641     if (!hostProxy)
642         return KERN_FAILURE;
643     
644     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
645     if (!instanceProxy)
646         return KERN_FAILURE;
647     
648     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
649     if (!IdentifierRep::isValid(identifier))
650         return KERN_FAILURE;
651     
652     PluginDestroyDeferrer deferrer(instanceProxy);
653
654     data_t resultData = 0;
655     mach_msg_type_number_t resultLength = 0;
656     boolean_t returnValue;
657     
658     if (identifier->isString()) {
659         Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
660         returnValue = instanceProxy->getProperty(objectID, propertyNameIdentifier, resultData, resultLength);
661     } else 
662         returnValue = instanceProxy->setProperty(objectID, identifier->number(), resultData, resultLength);
663     
664     _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
665     if (resultData)
666         mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
667     
668     return KERN_SUCCESS;
669 }
670
671 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)
672 {
673     DataDeallocator deallocator(valueData, valueLength);
674
675     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
676     if (!hostProxy)
677         return KERN_FAILURE;
678     
679     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
680     if (!instanceProxy)
681         return KERN_FAILURE;
682
683     PluginDestroyDeferrer deferrer(instanceProxy);
684
685     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
686     if (!IdentifierRep::isValid(identifier))
687         *returnValue = false;
688     
689     if (identifier->isString()) {
690         Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
691         *returnValue = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength);
692     } else 
693         *returnValue = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength);
694     
695     return KERN_SUCCESS;
696 }
697
698 kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, boolean_t* returnValue)
699 {
700     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
701     if (!hostProxy)
702         return KERN_FAILURE;
703     
704     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
705     if (!instanceProxy)
706         return KERN_FAILURE;
707     
708     PluginDestroyDeferrer deferrer(instanceProxy);
709
710     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
711     if (!IdentifierRep::isValid(identifier))
712         return KERN_FAILURE;
713         
714     if (identifier->isString()) {
715         Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
716         *returnValue = instanceProxy->removeProperty(objectID, propertyNameIdentifier);
717     } else 
718         *returnValue = instanceProxy->removeProperty(objectID, identifier->number());
719     
720     return KERN_SUCCESS;
721 }
722
723 kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
724 {
725     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
726     if (!hostProxy)
727         return KERN_FAILURE;
728     
729     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
730     if (!instanceProxy)
731         return KERN_FAILURE;
732     
733     PluginDestroyDeferrer deferrer(instanceProxy);
734
735     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
736     if (!IdentifierRep::isValid(identifier)) {
737         _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false);
738         return KERN_SUCCESS;
739     }    
740     
741     boolean_t returnValue;
742     if (identifier->isString()) {
743         Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);        
744         returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier);
745     } else 
746         returnValue = instanceProxy->hasProperty(objectID, identifier->number());
747     
748     _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
749     
750     return KERN_SUCCESS;
751 }
752
753 kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
754 {
755     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
756     if (!hostProxy)
757         return KERN_FAILURE;
758     
759     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
760     if (!instanceProxy)
761         return KERN_FAILURE;
762     
763     PluginDestroyDeferrer deferrer(instanceProxy);
764
765     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
766     if (!IdentifierRep::isValid(identifier)) {
767         _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false);
768         return KERN_SUCCESS;
769     }
770     
771     Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);        
772     boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier);
773
774     _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
775
776     return KERN_SUCCESS;
777 }
778
779 kern_return_t WKPCIdentifierInfo(mach_port_t clientPort, uint64_t serverIdentifier, data_t* infoData, mach_msg_type_number_t* infoLength)
780 {
781     IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
782     if (!IdentifierRep::isValid(identifier))
783         return KERN_FAILURE;
784     
785     id info;
786     if (identifier->isString()) {
787         const char* str = identifier->string();
788         info = [NSData dataWithBytesNoCopy:(void*)str length:strlen(str) freeWhenDone:NO];
789     } else 
790         info = [NSNumber numberWithInt:identifier->number()];
791
792     RetainPtr<NSData*> data = [NSPropertyListSerialization dataFromPropertyList:info format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
793     ASSERT(data);
794     
795     *infoLength = [data.get() length];
796     mig_allocate(reinterpret_cast<vm_address_t*>(infoData), *infoLength);
797     
798     memcpy(*infoData, [data.get() bytes], *infoLength);
799     
800     return KERN_SUCCESS;
801 }
802
803 kern_return_t WKPCEnumerate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
804 {
805     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
806     if (!hostProxy)
807         return KERN_FAILURE;
808     
809     NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
810     if (!instanceProxy)
811         return KERN_FAILURE;
812     
813     data_t resultData = 0;
814     mach_msg_type_number_t resultLength = 0;
815     boolean_t returnValue = instanceProxy->enumerate(objectID, resultData, resultLength);
816     
817     _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
818     
819     if (resultData)
820         mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
821     
822     return KERN_SUCCESS;
823 }
824
825 kern_return_t WKPCSetMenuBarVisible(mach_port_t clientPort, boolean_t menuBarVisible)
826 {
827     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
828     if (!hostProxy)
829         return KERN_FAILURE;
830
831     hostProxy->setMenuBarVisible(menuBarVisible);
832     
833     return KERN_SUCCESS;
834 }
835
836 kern_return_t WKPCSetModal(mach_port_t clientPort, boolean_t modal)
837 {
838     NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
839     if (!hostProxy)
840         return KERN_FAILURE;
841     
842     hostProxy->setModal(modal);
843     
844     return KERN_SUCCESS;
845 }
846
847 #endif // USE(PLUGIN_HOST_PROCESS)