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 "NetscapePluginModule.h" 28 29#if ENABLE(NETSCAPE_PLUGIN_API) 30 31#include "Module.h" 32#include "NPRuntimeUtilities.h" 33#include "NetscapeBrowserFuncs.h" 34#include <wtf/PassOwnPtr.h> 35#include <wtf/text/CString.h> 36 37namespace WebKit { 38 39static Vector<NetscapePluginModule*>& initializedNetscapePluginModules() 40{ 41 DEFINE_STATIC_LOCAL(Vector<NetscapePluginModule*>, initializedNetscapePluginModules, ()); 42 return initializedNetscapePluginModules; 43} 44 45NetscapePluginModule::NetscapePluginModule(const String& pluginPath) 46 : m_pluginPath(pluginPath) 47 , m_isInitialized(false) 48 , m_loadCount(0) 49 , m_shutdownProcPtr(0) 50 , m_pluginFuncs() 51{ 52} 53 54NetscapePluginModule::~NetscapePluginModule() 55{ 56 ASSERT(initializedNetscapePluginModules().find(this) == notFound); 57} 58 59Vector<String> NetscapePluginModule::sitesWithData() 60{ 61 Vector<String> sites; 62 63 incrementLoadCount(); 64 tryGetSitesWithData(sites); 65 decrementLoadCount(); 66 67 return sites; 68} 69 70bool NetscapePluginModule::clearSiteData(const String& site, uint64_t flags, uint64_t maxAge) 71{ 72 incrementLoadCount(); 73 bool result = tryClearSiteData(site, flags, maxAge); 74 decrementLoadCount(); 75 76 return result; 77} 78 79bool NetscapePluginModule::tryGetSitesWithData(Vector<String>& sites) 80{ 81 if (!m_isInitialized) 82 return false; 83 84 // Check if the plug-in supports NPP_GetSitesWithData. 85 if (!m_pluginFuncs.getsiteswithdata) 86 return false; 87 88 char** siteArray = m_pluginFuncs.getsiteswithdata(); 89 90 // There were no sites with data. 91 if (!siteArray) 92 return true; 93 94 for (int i = 0; siteArray[i]; ++i) { 95 char* site = siteArray[i]; 96 97 String siteString = String::fromUTF8(site); 98 if (!siteString.isNull()) 99 sites.append(siteString); 100 101 npnMemFree(site); 102 } 103 104 npnMemFree(siteArray); 105 return true; 106} 107 108bool NetscapePluginModule::tryClearSiteData(const String& site, uint64_t flags, uint64_t maxAge) 109{ 110 if (!m_isInitialized) 111 return false; 112 113 // Check if the plug-in supports NPP_ClearSiteData. 114 if (!m_pluginFuncs.clearsitedata) 115 return false; 116 117 CString siteString; 118 if (!site.isNull()) 119 siteString = site.utf8(); 120 121 return m_pluginFuncs.clearsitedata(siteString.data(), flags, maxAge) == NPERR_NO_ERROR; 122} 123 124void NetscapePluginModule::shutdown() 125{ 126 ASSERT(m_isInitialized); 127 128 m_shutdownProcPtr(); 129 130 m_isInitialized = false; 131 132 size_t pluginModuleIndex = initializedNetscapePluginModules().find(this); 133 ASSERT(pluginModuleIndex != notFound); 134 135 initializedNetscapePluginModules().remove(pluginModuleIndex); 136} 137 138PassRefPtr<NetscapePluginModule> NetscapePluginModule::getOrCreate(const String& pluginPath) 139{ 140 // First, see if we already have a module with this plug-in path. 141 for (size_t i = 0; i < initializedNetscapePluginModules().size(); ++i) { 142 NetscapePluginModule* pluginModule = initializedNetscapePluginModules()[i]; 143 144 if (pluginModule->m_pluginPath == pluginPath) 145 return pluginModule; 146 } 147 148 RefPtr<NetscapePluginModule> pluginModule(adoptRef(new NetscapePluginModule(pluginPath))); 149 150 // Try to load and initialize the plug-in module. 151 if (!pluginModule->load()) 152 return 0; 153 154 return pluginModule.release(); 155} 156 157void NetscapePluginModule::incrementLoadCount() 158{ 159 if (!m_loadCount) { 160 // Load the plug-in module if necessary. 161 load(); 162 } 163 164 m_loadCount++; 165} 166 167void NetscapePluginModule::decrementLoadCount() 168{ 169 ASSERT(m_loadCount > 0); 170 m_loadCount--; 171 172 if (!m_loadCount) { 173 shutdown(); 174 unload(); 175 } 176} 177 178bool NetscapePluginModule::load() 179{ 180 if (m_isInitialized) { 181 ASSERT(initializedNetscapePluginModules().find(this) != notFound); 182 return true; 183 } 184 185 if (!tryLoad()) { 186 unload(); 187 return false; 188 } 189 190 m_isInitialized = true; 191 192 ASSERT(initializedNetscapePluginModules().find(this) == notFound); 193 initializedNetscapePluginModules().append(this); 194 195 determineQuirks(); 196 197 return true; 198} 199 200bool NetscapePluginModule::tryLoad() 201{ 202 m_module = adoptPtr(new Module(m_pluginPath)); 203 if (!m_module->load()) 204 return false; 205 206 NP_InitializeFuncPtr initializeFuncPtr = m_module->functionPointer<NP_InitializeFuncPtr>("NP_Initialize"); 207 if (!initializeFuncPtr) 208 return false; 209 210#if !PLUGIN_ARCHITECTURE(X11) 211 NP_GetEntryPointsFuncPtr getEntryPointsFuncPtr = m_module->functionPointer<NP_GetEntryPointsFuncPtr>("NP_GetEntryPoints"); 212 if (!getEntryPointsFuncPtr) 213 return false; 214#endif 215 216 m_shutdownProcPtr = m_module->functionPointer<NPP_ShutdownProcPtr>("NP_Shutdown"); 217 if (!m_shutdownProcPtr) 218 return false; 219 220 m_pluginFuncs.size = sizeof(NPPluginFuncs); 221 m_pluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; 222 223 // On Mac, NP_Initialize must be called first, then NP_GetEntryPoints. On Windows, the order is 224 // reversed. Failing to follow this order results in crashes (e.g., in Silverlight on Mac and 225 // in Flash and QuickTime on Windows). 226#if PLUGIN_ARCHITECTURE(MAC) 227#ifndef NP_NO_CARBON 228 229#if COMPILER(CLANG) 230#pragma clang diagnostic push 231#pragma clang diagnostic ignored "-Wdeprecated-declarations" 232#endif 233 234 // Plugins (at least QT) require that you call UseResFile on the resource file before loading it. 235 ResFileRefNum currentResourceFile = CurResFile(); 236 237 ResFileRefNum pluginResourceFile = m_module->bundleResourceMap(); 238 UseResFile(pluginResourceFile); 239 240#endif 241 bool result = initializeFuncPtr(netscapeBrowserFuncs()) == NPERR_NO_ERROR && getEntryPointsFuncPtr(&m_pluginFuncs) == NPERR_NO_ERROR; 242 243#ifndef NP_NO_CARBON 244 // Restore the resource file. 245 UseResFile(currentResourceFile); 246 247#if COMPILER(CLANG) 248#pragma clang diagnostic pop 249#endif 250 251#endif 252 253 return result; 254#elif PLUGIN_ARCHITECTURE(WIN) 255 if (getEntryPointsFuncPtr(&m_pluginFuncs) != NPERR_NO_ERROR || initializeFuncPtr(netscapeBrowserFuncs()) != NPERR_NO_ERROR) 256 return false; 257#elif PLUGIN_ARCHITECTURE(X11) 258 if (initializeFuncPtr(netscapeBrowserFuncs(), &m_pluginFuncs) != NPERR_NO_ERROR) 259 return false; 260#endif 261 262 return true; 263} 264 265void NetscapePluginModule::unload() 266{ 267 ASSERT(!m_isInitialized); 268 269 m_module = nullptr; 270} 271 272} // namespace WebKit 273 274#endif // ENABLE(NETSCAPE_PLUGIN_API) 275