• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
43extern "C" {
44#import "WebKitPluginHost.h"
45#import "WebKitPluginClientServer.h"
46}
47
48using namespace std;
49using namespace JSC;
50using namespace WebCore;
51
52@interface WebPlaceholderModalWindow : NSWindow
53@end
54
55@implementation WebPlaceholderModalWindow
56// Prevent NSApp from calling requestUserAttention: when the window is shown
57// modally, even if the app is inactive. See 6823049.
58- (BOOL)_wantsUserAttention
59{
60    return NO;
61}
62@end
63
64namespace WebKit {
65
66class PluginDestroyDeferrer {
67public:
68    PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy)
69        : m_proxy(proxy)
70    {
71        m_proxy->willCallPluginFunction();
72    }
73
74    ~PluginDestroyDeferrer()
75    {
76        m_proxy->didCallPluginFunction();
77    }
78
79private:
80    RefPtr<NetscapePluginInstanceProxy> m_proxy;
81};
82
83typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap;
84static PluginProxyMap& pluginProxyMap()
85{
86    DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ());
87
88    return pluginProxyMap;
89}
90
91NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN, bool shouldCacheMissingPropertiesAndMethods)
92    : m_clientPort(clientPort)
93    , m_portSet(MACH_PORT_NULL)
94    , m_pluginHostPort(pluginHostPort)
95    , m_isModal(false)
96    , m_menuBarIsVisible(true)
97    , m_pluginHostPSN(pluginHostPSN)
98    , m_processingRequests(0)
99    , m_shouldCacheMissingPropertiesAndMethods(shouldCacheMissingPropertiesAndMethods)
100{
101    pluginProxyMap().add(m_clientPort, this);
102
103    // FIXME: We should use libdispatch for this.
104    CFMachPortContext context = { 0, this, 0, 0, 0 };
105    m_deadNameNotificationPort.adoptCF(CFMachPortCreate(0, deadNameNotificationCallback, &context, 0));
106
107    mach_port_t previous;
108    mach_port_request_notification(mach_task_self(), pluginHostPort, MACH_NOTIFY_DEAD_NAME, 0,
109                                   CFMachPortGetPort(m_deadNameNotificationPort.get()), MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
110    ASSERT(previous == MACH_PORT_NULL);
111
112    RetainPtr<CFRunLoopSourceRef> deathPortSource(AdoptCF, CFMachPortCreateRunLoopSource(0, m_deadNameNotificationPort.get(), 0));
113
114    CFRunLoopAddSource(CFRunLoopGetCurrent(), deathPortSource.get(), kCFRunLoopDefaultMode);
115
116#ifdef USE_LIBDISPATCH
117    // FIXME: Unfortunately we can't use a dispatch source here until <rdar://problem/6393180> has been resolved.
118    m_clientPortSource = dispatch_source_mig_create(m_clientPort, WKWebKitPluginClient_subsystem.maxsize, 0,
119                                                    dispatch_get_main_queue(), WebKitPluginClient_server);
120#else
121    m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKWebKitPluginClient_subsystem, m_clientPort));
122    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode);
123    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSEventTrackingRunLoopMode);
124#endif
125}
126
127NetscapePluginHostProxy::~NetscapePluginHostProxy()
128{
129    pluginProxyMap().remove(m_clientPort);
130
131    // Free the port set
132    if (m_portSet) {
133        mach_port_extract_member(mach_task_self(), m_clientPort, m_portSet);
134        mach_port_extract_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
135        mach_port_destroy(mach_task_self(), m_portSet);
136    }
137
138    ASSERT(m_clientPortSource);
139#ifdef USE_LIBDISPATCH
140    dispatch_release(m_clientPortSource);
141#else
142    CFRunLoopSourceInvalidate(m_clientPortSource.get());
143    m_clientPortSource = 0;
144#endif
145}
146
147void NetscapePluginHostProxy::pluginHostDied()
148{
149    PluginInstanceMap instances;
150    m_instances.swap(instances);
151
152    PluginInstanceMap::const_iterator end = instances.end();
153    for (PluginInstanceMap::const_iterator it = instances.begin(); it != end; ++it)
154        it->second->pluginHostDied();
155
156    NetscapePluginHostManager::shared().pluginHostDied(this);
157
158    // The plug-in crashed while its menu bar was hidden. Make sure to show it.
159    if (!m_menuBarIsVisible)
160        setMenuBarVisible(true);
161
162    // The plug-in crashed while it had a modal dialog up.
163    if (m_isModal)
164        endModal();
165
166    delete this;
167}
168
169void NetscapePluginHostProxy::addPluginInstance(NetscapePluginInstanceProxy* instance)
170{
171    ASSERT(!m_instances.contains(instance->pluginID()));
172
173    m_instances.set(instance->pluginID(), instance);
174}
175
176void NetscapePluginHostProxy::removePluginInstance(NetscapePluginInstanceProxy* instance)
177{
178    ASSERT(m_instances.get(instance->pluginID()) == instance);
179
180    m_instances.remove(instance->pluginID());
181}
182
183NetscapePluginInstanceProxy* NetscapePluginHostProxy::pluginInstance(uint32_t pluginID)
184{
185    return m_instances.get(pluginID).get();
186}
187
188void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
189{
190    ASSERT(msg && static_cast<mach_msg_header_t*>(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME);
191
192    static_cast<NetscapePluginHostProxy*>(info)->pluginHostDied();
193}
194
195void NetscapePluginHostProxy::setMenuBarVisible(bool visible)
196{
197    m_menuBarIsVisible = visible;
198
199    [NSMenu setMenuBarVisible:visible];
200    if (visible) {
201        // Make ourselves the front app
202        ProcessSerialNumber psn;
203        GetCurrentProcess(&psn);
204        SetFrontProcess(&psn);
205    }
206}
207
208void NetscapePluginHostProxy::applicationDidBecomeActive()
209{
210    SetFrontProcess(&m_pluginHostPSN);
211}
212
213void NetscapePluginHostProxy::beginModal()
214{
215    ASSERT(!m_placeholderWindow);
216    ASSERT(!m_activationObserver);
217
218    m_placeholderWindow.adoptNS([[WebPlaceholderModalWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
219
220    m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
221                                                                         usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
222
223    // We need to be able to get the setModal(false) call from the plug-in host.
224    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
225
226    [NSApp runModalForWindow:m_placeholderWindow.get()];
227
228    [m_placeholderWindow.get() orderOut:nil];
229    m_placeholderWindow = 0;
230}
231
232void NetscapePluginHostProxy::endModal()
233{
234    ASSERT(m_placeholderWindow);
235    ASSERT(m_activationObserver);
236
237    [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
238    m_activationObserver = nil;
239
240    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode);
241
242    [NSApp stopModal];
243
244    // Make ourselves the front process.
245    ProcessSerialNumber psn;
246    GetCurrentProcess(&psn);
247    SetFrontProcess(&psn);
248}
249
250
251void NetscapePluginHostProxy::setModal(bool modal)
252{
253    if (modal == m_isModal)
254        return;
255
256    m_isModal = modal;
257
258    if (m_isModal)
259        beginModal();
260    else
261        endModal();
262}
263
264bool NetscapePluginHostProxy::processRequests()
265{
266    m_processingRequests++;
267
268   if (!m_portSet) {
269        mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet);
270        mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet);
271        mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
272    }
273
274    char buffer[4096];
275
276    mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer);
277
278    kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL);
279
280    if (kr != KERN_SUCCESS) {
281        LOG_ERROR("Could not receive mach message, error %x", kr);
282        m_processingRequests--;
283        return false;
284    }
285
286    if (msg->msgh_local_port == m_clientPort) {
287        __ReplyUnion__WKWebKitPluginClient_subsystem reply;
288        mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply);
289
290        if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) {
291            kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
292
293            if (kr != KERN_SUCCESS) {
294                LOG_ERROR("Could not send mach message, error %x", kr);
295                m_processingRequests--;
296                return false;
297            }
298        }
299
300        m_processingRequests--;
301        return true;
302    }
303
304    if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) {
305        ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME);
306        pluginHostDied();
307        m_processingRequests--;
308        return false;
309    }
310
311    ASSERT_NOT_REACHED();
312    m_processingRequests--;
313    return false;
314}
315
316} // namespace WebKit
317
318using namespace WebKit;
319
320// Helper class for deallocating data
321class DataDeallocator {
322public:
323    DataDeallocator(data_t data, mach_msg_type_number_t dataLength)
324        : m_data(reinterpret_cast<vm_address_t>(data))
325        , m_dataLength(dataLength)
326    {
327    }
328
329    ~DataDeallocator()
330    {
331        if (!m_data)
332            return;
333
334        vm_deallocate(mach_task_self(), m_data, m_dataLength);
335    }
336
337private:
338    vm_address_t m_data;
339    vm_size_t m_dataLength;
340};
341
342// MiG callbacks
343kern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t textCnt)
344{
345    DataDeallocator deallocator(text, textCnt);
346
347    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
348    if (!hostProxy)
349        return KERN_FAILURE;
350
351    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
352    if (!instanceProxy)
353        return KERN_FAILURE;
354
355    instanceProxy->status(text);
356    return KERN_SUCCESS;
357}
358
359kern_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,
360                          data_t postData, mach_msg_type_number_t postDataLength, uint32_t flags,
361                          uint16_t* outResult, uint32_t* outStreamID)
362{
363    DataDeallocator urlDeallocator(url, urlLength);
364    DataDeallocator targetDeallocator(target, targetLength);
365    DataDeallocator postDataDeallocator(postData, postDataLength);
366
367    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
368    if (!hostProxy)
369        return KERN_FAILURE;
370
371    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
372    if (!instanceProxy)
373        return KERN_FAILURE;
374
375    uint32_t streamID = 0;
376    NPError result = instanceProxy->loadURL(url, target, postData, postDataLength, static_cast<LoadURLFlags>(flags), streamID);
377
378    *outResult = result;
379    *outStreamID = streamID;
380    return KERN_SUCCESS;
381}
382
383kern_return_t WKPCCancelLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t streamID, int16_t reason)
384{
385    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
386    if (!hostProxy)
387        return KERN_FAILURE;
388
389    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
390    if (!instanceProxy)
391        return KERN_FAILURE;
392
393    if (!instanceProxy->cancelStreamLoad(streamID, reason))
394        return KERN_FAILURE;
395
396    return KERN_SUCCESS;
397}
398
399kern_return_t WKPCInvalidateRect(mach_port_t clientPort, uint32_t pluginID, double x, double y, double width, double height)
400{
401    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
402    if (!hostProxy)
403        return KERN_SUCCESS;
404
405    if (!hostProxy->isProcessingRequests()) {
406        if (NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID))
407            instanceProxy->invalidateRect(x, y, width, height);
408        return KERN_SUCCESS;
409    }
410
411    // Defer the work
412    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
413        if (NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort)) {
414            if (NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID))
415                instanceProxy->invalidateRect(x, y, width, height);
416        }
417    });
418
419    return KERN_SUCCESS;
420}
421
422kern_return_t WKPCGetScriptableNPObjectReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
423{
424    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
425    if (!hostProxy)
426        return KERN_FAILURE;
427
428    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
429    if (!instanceProxy)
430        return KERN_FAILURE;
431
432    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID));
433    return KERN_SUCCESS;
434}
435
436kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t result)
437{
438    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
439    if (!hostProxy)
440        return KERN_FAILURE;
441
442    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
443    if (!instanceProxy)
444        return KERN_FAILURE;
445
446    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanReply(result));
447    return KERN_SUCCESS;
448}
449
450kern_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)
451{
452    DataDeallocator deallocator(resultData, resultLength);
453
454    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
455    if (!hostProxy)
456        return KERN_FAILURE;
457
458    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
459    if (!instanceProxy)
460        return KERN_FAILURE;
461
462    RetainPtr<CFDataRef> result(AdoptCF, CFDataCreate(0, reinterpret_cast<UInt8*>(resultData), resultLength));
463    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanAndDataReply(returnValue, result));
464
465    return KERN_SUCCESS;
466}
467
468kern_return_t WKPCInstantiatePluginReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, kern_return_t result, uint32_t renderContextID, boolean_t useSoftwareRenderer)
469{
470    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
471    if (!hostProxy)
472        return KERN_FAILURE;
473
474    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
475    if (!instanceProxy)
476        return KERN_FAILURE;
477
478    instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::InstantiatePluginReply(result, renderContextID, useSoftwareRenderer));
479    return KERN_SUCCESS;
480}
481
482kern_return_t WKPCGetWindowNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
483{
484    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
485    if (!hostProxy)
486        return KERN_FAILURE;
487
488    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
489    if (!instanceProxy)
490        return KERN_FAILURE;
491
492    uint32_t objectID;
493    if (!instanceProxy->getWindowNPObject(objectID))
494        return KERN_FAILURE;
495
496    *outObjectID = objectID;
497    return KERN_SUCCESS;
498}
499
500kern_return_t WKPCGetPluginElementNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID)
501{
502    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
503    if (!hostProxy)
504        return KERN_FAILURE;
505
506    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
507    if (!instanceProxy)
508        return KERN_FAILURE;
509
510    uint32_t objectID;
511    if (!instanceProxy->getPluginElementNPObject(objectID))
512        return KERN_FAILURE;
513
514    *outObjectID = objectID;
515    return KERN_SUCCESS;
516}
517
518kern_return_t WKPCReleaseObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID)
519{
520    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
521    if (!hostProxy)
522        return KERN_FAILURE;
523
524    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
525    if (!instanceProxy)
526        return KERN_FAILURE;
527
528    instanceProxy->releaseObject(objectID);
529    return KERN_SUCCESS;
530}
531
532kern_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)
533{
534    DataDeallocator deallocator(scriptData, scriptLength);
535
536    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
537    if (!hostProxy)
538        return KERN_FAILURE;
539
540    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
541    if (!instanceProxy) {
542        _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0);
543        return KERN_SUCCESS;
544    }
545
546    PluginDestroyDeferrer deferrer(instanceProxy);
547
548    String script = String::fromUTF8WithLatin1Fallback(scriptData, scriptLength);
549
550    data_t resultData = 0;
551    mach_msg_type_number_t resultLength = 0;
552    boolean_t returnValue = instanceProxy->evaluate(objectID, script, resultData, resultLength, allowPopups);
553
554    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
555    if (resultData)
556        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
557
558    return KERN_SUCCESS;
559}
560
561kern_return_t WKPCGetStringIdentifier(mach_port_t clientPort, data_t name, mach_msg_type_number_t nameCnt, uint64_t* identifier)
562{
563    DataDeallocator deallocator(name, nameCnt);
564
565    COMPILE_ASSERT(sizeof(*identifier) == sizeof(IdentifierRep*), identifier_sizes);
566
567    *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(name));
568    return KERN_SUCCESS;
569}
570
571kern_return_t WKPCGetIntIdentifier(mach_port_t clientPort, int32_t value, uint64_t* identifier)
572{
573    COMPILE_ASSERT(sizeof(*identifier) == sizeof(NPIdentifier), identifier_sizes);
574
575    *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(value));
576    return KERN_SUCCESS;
577}
578
579static Identifier identifierFromIdentifierRep(IdentifierRep* identifier)
580{
581    ASSERT(IdentifierRep::isValid(identifier));
582    ASSERT(identifier->isString());
583
584    const char* str = identifier->string();
585    return Identifier(JSDOMWindow::commonJSGlobalData(), String::fromUTF8WithLatin1Fallback(str, strlen(str)));
586}
587
588kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier,
589                         data_t argumentsData, mach_msg_type_number_t argumentsLength)
590{
591    DataDeallocator deallocator(argumentsData, argumentsLength);
592
593    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
594    if (!hostProxy)
595        return KERN_FAILURE;
596
597    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
598    if (!instanceProxy) {
599        _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0);
600        return KERN_SUCCESS;
601    }
602
603    PluginDestroyDeferrer deferrer(instanceProxy);
604
605    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
606    if (!IdentifierRep::isValid(identifier)) {
607        _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false, 0, 0);
608        return KERN_SUCCESS;
609    }
610
611    Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);
612
613    data_t resultData = 0;
614    mach_msg_type_number_t resultLength = 0;
615    boolean_t returnValue = instanceProxy->invoke(objectID, methodNameIdentifier, argumentsData, argumentsLength, resultData, resultLength);
616
617    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
618    if (resultData)
619        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
620
621    return KERN_SUCCESS;
622}
623
624kern_return_t WKPCInvokeDefault(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID,
625                                data_t argumentsData, mach_msg_type_number_t argumentsLength)
626{
627    DataDeallocator deallocator(argumentsData, argumentsLength);
628
629    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
630    if (!hostProxy)
631        return KERN_FAILURE;
632
633    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
634    if (!instanceProxy) {
635        _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0);
636        return KERN_SUCCESS;
637    }
638
639    PluginDestroyDeferrer deferrer(instanceProxy);
640
641    data_t resultData = 0;
642    mach_msg_type_number_t resultLength = 0;
643    boolean_t returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, resultData, resultLength);
644
645    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
646    if (resultData)
647        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
648
649    return KERN_SUCCESS;
650}
651
652kern_return_t WKPCConstruct(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID,
653                            data_t argumentsData, mach_msg_type_number_t argumentsLength,
654                            boolean_t* returnValue, data_t* resultData, mach_msg_type_number_t* resultLength)
655{
656    DataDeallocator deallocator(argumentsData, argumentsLength);
657
658    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
659    if (!hostProxy)
660        return KERN_FAILURE;
661
662    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
663    if (!instanceProxy)
664        return KERN_FAILURE;
665
666    PluginDestroyDeferrer deferrer(instanceProxy);
667
668    *returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength);
669
670    return KERN_SUCCESS;
671}
672
673kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
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        _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0);
682        return KERN_SUCCESS;
683    }
684
685    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
686    if (!IdentifierRep::isValid(identifier)) {
687        _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0);
688        return KERN_SUCCESS;
689    }
690
691    PluginDestroyDeferrer deferrer(instanceProxy);
692
693    data_t resultData = 0;
694    mach_msg_type_number_t resultLength = 0;
695    boolean_t returnValue;
696
697    if (identifier->isString()) {
698        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
699        returnValue = instanceProxy->getProperty(objectID, propertyNameIdentifier, resultData, resultLength);
700    } else
701        returnValue = instanceProxy->setProperty(objectID, identifier->number(), resultData, resultLength);
702
703    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
704    if (resultData)
705        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
706
707    return KERN_SUCCESS;
708}
709
710kern_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)
711{
712    DataDeallocator deallocator(valueData, valueLength);
713
714    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
715    if (!hostProxy)
716        return KERN_FAILURE;
717
718    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
719    if (!instanceProxy)
720        return KERN_FAILURE;
721
722    PluginDestroyDeferrer deferrer(instanceProxy);
723
724    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
725    if (!IdentifierRep::isValid(identifier))
726        *returnValue = false;
727
728    if (identifier->isString()) {
729        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
730        *returnValue = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength);
731    } else
732        *returnValue = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength);
733
734    return KERN_SUCCESS;
735}
736
737kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, boolean_t* returnValue)
738{
739    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
740    if (!hostProxy)
741        return KERN_FAILURE;
742
743    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
744    if (!instanceProxy)
745        return KERN_FAILURE;
746
747    PluginDestroyDeferrer deferrer(instanceProxy);
748
749    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
750    if (!IdentifierRep::isValid(identifier))
751        return KERN_FAILURE;
752
753    if (identifier->isString()) {
754        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
755        *returnValue = instanceProxy->removeProperty(objectID, propertyNameIdentifier);
756    } else
757        *returnValue = instanceProxy->removeProperty(objectID, identifier->number());
758
759    return KERN_SUCCESS;
760}
761
762kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
763{
764    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
765    if (!hostProxy)
766        return KERN_FAILURE;
767
768    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
769    if (!instanceProxy) {
770        _WKPHBooleanReply(hostProxy->port(), pluginID, requestID, false);
771        return KERN_SUCCESS;
772    }
773
774    PluginDestroyDeferrer deferrer(instanceProxy);
775
776    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
777    if (!IdentifierRep::isValid(identifier)) {
778        _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false);
779        return KERN_SUCCESS;
780    }
781
782    boolean_t returnValue;
783    if (identifier->isString()) {
784        Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier);
785        returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier);
786    } else
787        returnValue = instanceProxy->hasProperty(objectID, identifier->number());
788
789    _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
790
791    return KERN_SUCCESS;
792}
793
794kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier)
795{
796    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
797    if (!hostProxy)
798        return KERN_FAILURE;
799
800    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
801    if (!instanceProxy) {
802        _WKPHBooleanReply(hostProxy->port(), pluginID, requestID, false);
803        return KERN_SUCCESS;
804    }
805
806    PluginDestroyDeferrer deferrer(instanceProxy);
807
808    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
809    if (!IdentifierRep::isValid(identifier)) {
810        _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false);
811        return KERN_SUCCESS;
812    }
813
814    Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier);
815    boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier);
816
817    _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue);
818
819    return KERN_SUCCESS;
820}
821
822kern_return_t WKPCIdentifierInfo(mach_port_t clientPort, uint64_t serverIdentifier, data_t* infoData, mach_msg_type_number_t* infoLength)
823{
824    IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
825    if (!IdentifierRep::isValid(identifier))
826        return KERN_FAILURE;
827
828    id info;
829    if (identifier->isString()) {
830        const char* str = identifier->string();
831        info = [NSData dataWithBytesNoCopy:(void*)str length:strlen(str) freeWhenDone:NO];
832    } else
833        info = [NSNumber numberWithInt:identifier->number()];
834
835    RetainPtr<NSData*> data = [NSPropertyListSerialization dataFromPropertyList:info format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
836    ASSERT(data);
837
838    *infoLength = [data.get() length];
839    mig_allocate(reinterpret_cast<vm_address_t*>(infoData), *infoLength);
840
841    memcpy(*infoData, [data.get() bytes], *infoLength);
842
843    return KERN_SUCCESS;
844}
845
846kern_return_t WKPCEnumerate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID)
847{
848    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
849    if (!hostProxy)
850        return KERN_FAILURE;
851
852    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
853    if (!instanceProxy) {
854        _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0);
855        return KERN_SUCCESS;
856    }
857
858    data_t resultData = 0;
859    mach_msg_type_number_t resultLength = 0;
860    boolean_t returnValue = instanceProxy->enumerate(objectID, resultData, resultLength);
861
862    _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength);
863
864    if (resultData)
865        mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength);
866
867    return KERN_SUCCESS;
868}
869
870kern_return_t WKPCSetMenuBarVisible(mach_port_t clientPort, boolean_t menuBarVisible)
871{
872    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
873    if (!hostProxy)
874        return KERN_FAILURE;
875
876    hostProxy->setMenuBarVisible(menuBarVisible);
877
878    return KERN_SUCCESS;
879}
880
881kern_return_t WKPCSetModal(mach_port_t clientPort, boolean_t modal)
882{
883    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
884    if (!hostProxy)
885        return KERN_FAILURE;
886
887    hostProxy->setModal(modal);
888
889    return KERN_SUCCESS;
890}
891
892kern_return_t WKPCGetCookies(mach_port_t clientPort, uint32_t pluginID,
893                             data_t urlData, mach_msg_type_number_t urlLength,
894                             boolean_t* returnValue, data_t* cookiesData, mach_msg_type_number_t* cookiesLength)
895{
896    *cookiesData = 0;
897    *cookiesLength = 0;
898
899    DataDeallocator deallocator(urlData, urlLength);
900
901    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
902    if (!hostProxy)
903        return KERN_FAILURE;
904
905    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
906    if (!instanceProxy)
907        return KERN_FAILURE;
908
909    *returnValue = instanceProxy->getCookies(urlData, urlLength, *cookiesData, *cookiesLength);
910
911    return KERN_SUCCESS;
912}
913
914kern_return_t WKPCGetProxy(mach_port_t clientPort, uint32_t pluginID,
915                           data_t urlData, mach_msg_type_number_t urlLength,
916                           boolean_t* returnValue, data_t* proxyData, mach_msg_type_number_t* proxyLength)
917{
918    *proxyData = 0;
919    *proxyLength = 0;
920
921    DataDeallocator deallocator(urlData, urlLength);
922
923    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
924    if (!hostProxy)
925        return KERN_FAILURE;
926
927    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
928    if (!instanceProxy)
929        return KERN_FAILURE;
930
931    *returnValue = instanceProxy->getProxy(urlData, urlLength, *proxyData, *proxyLength);
932
933    return KERN_SUCCESS;
934}
935
936kern_return_t WKPCSetCookies(mach_port_t clientPort, uint32_t pluginID,
937                             data_t urlData, mach_msg_type_number_t urlLength,
938                             data_t cookiesData, mach_msg_type_number_t cookiesLength,
939                             boolean_t* returnValue)
940{
941    DataDeallocator urlDeallocator(urlData, urlLength);
942    DataDeallocator cookiesDeallocator(cookiesData, cookiesLength);
943
944    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
945    if (!hostProxy)
946        return KERN_FAILURE;
947
948    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
949    if (!instanceProxy)
950        return KERN_FAILURE;
951
952    *returnValue = instanceProxy->setCookies(urlData, urlLength, cookiesData, cookiesLength);
953    return KERN_SUCCESS;
954}
955
956kern_return_t WKPCGetAuthenticationInfo(mach_port_t clientPort, uint32_t pluginID,
957                                        data_t protocolData, mach_msg_type_number_t protocolLength,
958                                        data_t hostData, mach_msg_type_number_t hostLength,
959                                        uint32_t port,
960                                        data_t schemeData, mach_msg_type_number_t schemeLength,
961                                        data_t realmData, mach_msg_type_number_t realmLength,
962                                        boolean_t* returnValue,
963                                        data_t* usernameData, mach_msg_type_number_t *usernameLength,
964                                        data_t* passwordData, mach_msg_type_number_t *passwordLength)
965{
966    DataDeallocator protocolDeallocator(protocolData, protocolLength);
967    DataDeallocator hostDeallocator(hostData, hostLength);
968    DataDeallocator schemeDeallocator(schemeData, schemeLength);
969    DataDeallocator realmDeallocator(realmData, realmLength);
970
971    *usernameData = 0;
972    *usernameLength = 0;
973    *passwordData = 0;
974    *passwordLength = 0;
975
976    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
977    if (!hostProxy)
978        return KERN_FAILURE;
979
980    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
981    if (!instanceProxy)
982        return KERN_FAILURE;
983
984    *returnValue = instanceProxy->getAuthenticationInfo(protocolData, hostData, port, schemeData, realmData, *usernameData, *usernameLength, *passwordData, *passwordLength);
985
986    return KERN_SUCCESS;
987}
988
989kern_return_t WKPCConvertPoint(mach_port_t clientPort, uint32_t pluginID,
990                               double sourceX, double sourceY, uint32_t sourceSpace,
991                               uint32_t destSpace, boolean_t *returnValue, double *destX, double *destY)
992{
993    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
994    if (!hostProxy)
995        return KERN_FAILURE;
996
997    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
998    if (!instanceProxy)
999        return KERN_FAILURE;
1000
1001    *returnValue = instanceProxy->convertPoint(sourceX, sourceY, static_cast<NPCoordinateSpace>(sourceSpace),
1002                                               *destX, *destY, static_cast<NPCoordinateSpace>(destSpace));
1003    return KERN_SUCCESS;
1004}
1005
1006kern_return_t WKPCCheckIfAllowedToLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t urlData, mach_msg_type_number_t urlLength,
1007                                          data_t targetData, mach_msg_type_number_t targetLength, uint32_t *checkID)
1008{
1009    DataDeallocator urlDeallocator(urlData, urlLength);
1010    DataDeallocator targetDeallocator(targetData, targetLength);
1011
1012    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
1013    if (!hostProxy)
1014        return KERN_FAILURE;
1015
1016    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
1017    if (!instanceProxy)
1018        return KERN_FAILURE;
1019
1020    *checkID = instanceProxy->checkIfAllowedToLoadURL(urlData, targetData);
1021    return KERN_SUCCESS;
1022}
1023
1024kern_return_t WKPCCancelCheckIfAllowedToLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t checkID)
1025{
1026    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
1027    if (!hostProxy)
1028        return KERN_FAILURE;
1029
1030    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
1031    if (!instanceProxy)
1032        return KERN_FAILURE;
1033
1034    instanceProxy->cancelCheckIfAllowedToLoadURL(checkID);
1035    return KERN_SUCCESS;
1036}
1037
1038kern_return_t WKPCResolveURL(mach_port_t clientPort, uint32_t pluginID, data_t urlData, mach_msg_type_number_t urlLength,
1039                             data_t targetData, mach_msg_type_number_t targetLength,
1040                             data_t *resolvedURLData, mach_msg_type_number_t *resolvedURLLength)
1041{
1042    DataDeallocator urlDeallocator(urlData, urlLength);
1043    DataDeallocator targetDeallocator(targetData, targetLength);
1044
1045    *resolvedURLData = 0;
1046    *resolvedURLLength = 0;
1047
1048    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);
1049    if (!hostProxy)
1050        return KERN_FAILURE;
1051
1052    NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);
1053    if (!instanceProxy)
1054        return KERN_FAILURE;
1055
1056    instanceProxy->resolveURL(urlData, targetData, *resolvedURLData, *resolvedURLLength);
1057    return KERN_SUCCESS;
1058}
1059
1060#endif // USE(PLUGIN_HOST_PROCESS)
1061