⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netscapepluginhostproxy.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#if USE(PLUGIN_HOST_PROCESS)#import "NetscapePluginHostProxy.h"#import <mach/mach.h>#import <wtf/StdLibExtras.h>#import "HostedNetscapePluginStream.h"#import "NetscapePluginHostManager.h"#import "NetscapePluginInstanceProxy.h"#import "WebFrameInternal.h"#import "WebHostedNetscapePluginView.h"#import "WebKitSystemInterface.h"#import <WebCore/Frame.h>#import <WebCore/IdentifierRep.h>#import <WebCore/ScriptController.h>extern "C" {#import "WebKitPluginHost.h"#import "WebKitPluginClientServer.h"}using namespace std;using namespace JSC;using namespace WebCore;namespace WebKit {class PluginDestroyDeferrer {public:    PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy)        : m_proxy(proxy)    {        m_proxy->willCallPluginFunction();    }        ~PluginDestroyDeferrer()    {        m_proxy->didCallPluginFunction();    }private:    NetscapePluginInstanceProxy* m_proxy;};typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap;static PluginProxyMap& pluginProxyMap(){    DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ());        return pluginProxyMap;}NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN)    : m_clientPort(clientPort)    , m_portSet(MACH_PORT_NULL)    , m_pluginHostPort(pluginHostPort)    , m_isModal(false)    , m_menuBarIsVisible(true)    , m_pluginHostPSN(pluginHostPSN){    pluginProxyMap().add(m_clientPort, this);        // FIXME: We should use libdispatch for this.    CFMachPortContext context = { 0, this, 0, 0, 0 };    m_deadNameNotificationPort.adoptCF(CFMachPortCreate(0, deadNameNotificationCallback, &context, 0));    mach_port_t previous;    mach_port_request_notification(mach_task_self(), pluginHostPort, MACH_NOTIFY_DEAD_NAME, 0,                                    CFMachPortGetPort(m_deadNameNotificationPort.get()), MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);    ASSERT(previous == MACH_PORT_NULL);        RetainPtr<CFRunLoopSourceRef> deathPortSource(AdoptCF, CFMachPortCreateRunLoopSource(0, m_deadNameNotificationPort.get(), 0));        CFRunLoopAddSource(CFRunLoopGetCurrent(), deathPortSource.get(), kCFRunLoopDefaultMode);    #ifdef USE_LIBDISPATCH    // FIXME: Unfortunately we can't use a dispatch source here until <rdar://problem/6393180> has been resolved.    m_clientPortSource = dispatch_source_mig_create(m_clientPort, 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);#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 && static_cast<mach_msg_header_t*>(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME);        static_cast<NetscapePluginHostProxy*>(info)->pluginHostDied();}void NetscapePluginHostProxy::setMenuBarVisible(bool visible){    m_menuBarIsVisible = visible;        [NSMenu setMenuBarVisible:visible];    if (visible) {        // Make ourselves the front app        ProcessSerialNumber psn;        GetCurrentProcess(&psn);        SetFrontProcess(&psn);    }}void NetscapePluginHostProxy::applicationDidBecomeActive(){    SetFrontProcess(&m_pluginHostPSN);}void NetscapePluginHostProxy::beginModal(){    ASSERT(!m_placeholderWindow);    ASSERT(!m_activationObserver);        m_placeholderWindow.adoptNS([[NSWindow 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()];}    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];    [m_placeholderWindow.get() orderOut:nil];    m_placeholderWindow = 0;        // 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(){    if (!m_portSet) {        mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet);        mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet);        mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);    }        char buffer[4096];        mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer);        kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL);        if (kr != KERN_SUCCESS) {        LOG_ERROR("Could not receive mach message, error %x", kr);        return false;    }        if (msg->msgh_local_port == m_clientPort) {        __ReplyUnion__WKWebKitPluginClient_subsystem reply;        mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply);                if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) {            kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);                        if (kr != KERN_SUCCESS) {                LOG_ERROR("Could not send mach message, error %x", kr);                return false;            }        }                return true;    }        if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) {        ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME);        pluginHostDied();        return false;    }        ASSERT_NOT_REACHED();    return false;}} // namespace WebKitusing namespace WebKit;// Helper class for deallocating dataclass DataDeallocator {public:    DataDeallocator(data_t data, mach_msg_type_number_t dataLength)        : m_data(reinterpret_cast<vm_address_t>(data))        , m_dataLength(dataLength)    {    }        ~DataDeallocator()    {        if (!m_data)            return;                vm_deallocate(mach_task_self(), m_data, m_dataLength);    }    private:    vm_address_t m_data;    vm_size_t m_dataLength;};// MiG callbackskern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t textCnt){    DataDeallocator deallocator(text, textCnt);        NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);    if (!hostProxy)        return KERN_FAILURE;        NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);    if (!instanceProxy)        return KERN_FAILURE;        instanceProxy->status(text);    return KERN_SUCCESS;}kern_return_t WKPCLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t url, mach_msg_type_number_t urlLength, data_t target, mach_msg_type_number_t targetLength,                           data_t postData, mach_msg_type_number_t postDataLength, uint32_t flags,                          uint16_t* outResult, uint32_t* outStreamID){    DataDeallocator urlDeallocator(url, urlLength);    DataDeallocator targetDeallocator(target, targetLength);    DataDeallocator postDataDeallocator(postData, postDataLength);    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);    if (!hostProxy)        return KERN_FAILURE;        NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);    if (!instanceProxy)        return KERN_FAILURE;    uint32_t streamID = 0;    NPError result = instanceProxy->loadURL(url, target, postData, postDataLength, static_cast<LoadURLFlags>(flags), streamID);        *outResult = result;    *outStreamID = streamID;    return KERN_SUCCESS;}kern_return_t WKPCCancelLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t streamID, int16_t reason){    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);    if (!hostProxy)        return KERN_FAILURE;        NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);    if (!instanceProxy)        return KERN_FAILURE;        HostedNetscapePluginStream* pluginStream = instanceProxy->pluginStream(streamID);    if (!pluginStream)        return KERN_FAILURE;    pluginStream->cancelLoad(reason);    return KERN_SUCCESS;}kern_return_t WKPCInvalidateRect(mach_port_t clientPort, uint32_t pluginID, double x, double y, double width, double height){    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);    if (!hostProxy)        return KERN_FAILURE;        NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);    if (!instanceProxy)        return KERN_FAILURE;    [instanceProxy->pluginView() setNeedsDisplayInRect:NSMakeRect(x, y, width, height)];        return KERN_SUCCESS;}kern_return_t WKPCGetScriptableNPObjectReply(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID){    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);    if (!hostProxy)        return KERN_FAILURE;        NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);    if (!instanceProxy)        return KERN_FAILURE;    instanceProxy->setCurrentReply(new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID));    return KERN_SUCCESS;}kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, boolean_t result){    NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort);    if (!hostProxy)        return KERN_FAILURE;        NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID);    if (!instanceProxy)        return KERN_FAILURE;        instanceProxy->setCurrentReply(new NetscapePluginInstanceProxy::BooleanReply(result));    return KERN_SUCCESS;}kern_return_t WKPCBooleanAndDataReply(mach_port_t clientPort, uint32_t pluginID, boolean_t returnValue, data_t resultData, mach_msg_type_number_t resultLength){    DataDeallocator deallocator(resultData, resultLength);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -