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