Home | History | Annotate | Download | only in PluginProcess
      1 /*
      2  * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "PluginProcess.h"
     28 
     29 #if ENABLE(PLUGIN_PROCESS)
     30 
     31 #include "ArgumentCoders.h"
     32 #include "NetscapePluginModule.h"
     33 #include "PluginProcessProxyMessages.h"
     34 #include "PluginProcessCreationParameters.h"
     35 #include "WebProcessConnection.h"
     36 
     37 #if PLATFORM(MAC)
     38 #include "MachPort.h"
     39 #endif
     40 
     41 namespace WebKit {
     42 
     43 static const double shutdownTimeout = 15.0;
     44 
     45 PluginProcess& PluginProcess::shared()
     46 {
     47     DEFINE_STATIC_LOCAL(PluginProcess, pluginProcess, ());
     48     return pluginProcess;
     49 }
     50 
     51 PluginProcess::PluginProcess()
     52     : ChildProcess(shutdownTimeout)
     53 #if PLATFORM(MAC)
     54     , m_compositingRenderServerPort(MACH_PORT_NULL)
     55 #endif
     56 {
     57 }
     58 
     59 PluginProcess::~PluginProcess()
     60 {
     61 }
     62 
     63 void PluginProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop)
     64 {
     65     ASSERT(!m_connection);
     66 
     67     m_connection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop);
     68     m_connection->setDidCloseOnConnectionWorkQueueCallback(didCloseOnConnectionWorkQueue);
     69     m_connection->open();
     70 }
     71 
     72 void PluginProcess::removeWebProcessConnection(WebProcessConnection* webProcessConnection)
     73 {
     74     size_t vectorIndex = m_webProcessConnections.find(webProcessConnection);
     75     ASSERT(vectorIndex != notFound);
     76 
     77     m_webProcessConnections.remove(vectorIndex);
     78 
     79     if (m_webProcessConnections.isEmpty() && m_pluginModule) {
     80         // Decrement the load count. This is balanced by a call to incrementLoadCount in createWebProcessConnection.
     81         m_pluginModule->decrementLoadCount();
     82     }
     83 
     84     enableTermination();
     85 }
     86 
     87 NetscapePluginModule* PluginProcess::netscapePluginModule()
     88 {
     89     if (!m_pluginModule) {
     90         ASSERT(!m_pluginPath.isNull());
     91         m_pluginModule = NetscapePluginModule::getOrCreate(m_pluginPath);
     92 
     93 #if PLATFORM(MAC)
     94         if (m_pluginModule) {
     95             if (m_pluginModule->pluginQuirks().contains(PluginQuirks::PrognameShouldBeWebKitPluginHost))
     96                 setprogname("WebKitPluginHost");
     97         }
     98 #endif
     99     }
    100 
    101     return m_pluginModule.get();
    102 }
    103 
    104 bool PluginProcess::shouldTerminate()
    105 {
    106     ASSERT(m_webProcessConnections.isEmpty());
    107 
    108     return true;
    109 }
    110 
    111 void PluginProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
    112 {
    113     didReceivePluginProcessMessage(connection, messageID, arguments);
    114 }
    115 
    116 void PluginProcess::didClose(CoreIPC::Connection*)
    117 {
    118     // The UI process has crashed, just go ahead and quit.
    119     // FIXME: If the plug-in is spinning in the main loop, we'll never get this message.
    120     RunLoop::current()->stop();
    121 }
    122 
    123 void PluginProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
    124 {
    125 }
    126 
    127 void PluginProcess::syncMessageSendTimedOut(CoreIPC::Connection*)
    128 {
    129 }
    130 
    131 void PluginProcess::initializePluginProcess(const PluginProcessCreationParameters& parameters)
    132 {
    133     ASSERT(!m_pluginModule);
    134 
    135     m_pluginPath = parameters.pluginPath;
    136 
    137     platformInitialize(parameters);
    138 }
    139 
    140 void PluginProcess::createWebProcessConnection()
    141 {
    142     bool didHaveAnyWebProcessConnections = !m_webProcessConnections.isEmpty();
    143 
    144 #if PLATFORM(MAC)
    145     // Create the listening port.
    146     mach_port_t listeningPort;
    147     mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
    148 
    149     // Create a listening connection.
    150     RefPtr<WebProcessConnection> connection = WebProcessConnection::create(listeningPort);
    151     m_webProcessConnections.append(connection.release());
    152 
    153     CoreIPC::MachPort clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
    154     m_connection->send(Messages::PluginProcessProxy::DidCreateWebProcessConnection(clientPort), 0);
    155 #else
    156     // FIXME: Implement.
    157     ASSERT_NOT_REACHED();
    158 #endif
    159 
    160     if (NetscapePluginModule* module = netscapePluginModule()) {
    161         if (!didHaveAnyWebProcessConnections) {
    162             // Increment the load count. This is matched by a call to decrementLoadCount in removeWebProcessConnection.
    163             // We do this so that the plug-in module's NP_Shutdown won't be called until right before exiting.
    164             module->incrementLoadCount();
    165         }
    166     }
    167 
    168     disableTermination();
    169 }
    170 
    171 void PluginProcess::getSitesWithData(uint64_t callbackID)
    172 {
    173     LocalTerminationDisabler terminationDisabler(*this);
    174 
    175     Vector<String> sites;
    176     if (NetscapePluginModule* module = netscapePluginModule())
    177         sites = module->sitesWithData();
    178 
    179     m_connection->send(Messages::PluginProcessProxy::DidGetSitesWithData(sites, callbackID), 0);
    180 }
    181 
    182 void PluginProcess::clearSiteData(const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
    183 {
    184     LocalTerminationDisabler terminationDisabler(*this);
    185 
    186     if (NetscapePluginModule* module = netscapePluginModule()) {
    187         if (sites.isEmpty()) {
    188             // Clear everything.
    189             module->clearSiteData(String(), flags, maxAgeInSeconds);
    190         } else {
    191             for (size_t i = 0; i < sites.size(); ++i)
    192                 module->clearSiteData(sites[i], flags, maxAgeInSeconds);
    193         }
    194     }
    195 
    196     m_connection->send(Messages::PluginProcessProxy::DidClearSiteData(callbackID), 0);
    197 }
    198 
    199 } // namespace WebKit
    200 
    201 #endif // ENABLE(PLUGIN_PROCESS)
    202 
    203