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