1 /* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Collabora Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "PluginPackage.h" 29 30 #include "MIMETypeRegistry.h" 31 #include "npruntime_impl.h" 32 #include "PluginDatabase.h" 33 #include "PluginDebug.h" 34 #include <wtf/text/CString.h> 35 36 namespace WebCore { 37 38 bool PluginPackage::fetchInfo() 39 { 40 if (!load()) 41 return false; 42 43 NPP_GetValueProcPtr gv = (NPP_GetValueProcPtr)m_module->resolve("NP_GetValue"); 44 typedef char *(*NPP_GetMIMEDescriptionProcPtr)(); 45 NPP_GetMIMEDescriptionProcPtr gm = 46 (NPP_GetMIMEDescriptionProcPtr)m_module->resolve("NP_GetMIMEDescription"); 47 if (!gm || !gv) 48 return false; 49 50 char *buf = 0; 51 NPError err = gv(0, NPPVpluginNameString, (void*) &buf); 52 if (err != NPERR_NO_ERROR) 53 return false; 54 55 m_name = buf; 56 err = gv(0, NPPVpluginDescriptionString, (void*) &buf); 57 if (err != NPERR_NO_ERROR) 58 return false; 59 60 m_description = buf; 61 determineModuleVersionFromDescription(); 62 63 String mimeDescription = gm(); 64 setMIMEDescription(mimeDescription); 65 m_infoIsFromCache = false; 66 67 return true; 68 } 69 70 void PluginPackage::setMIMEDescription(const String& mimeDescription) 71 { 72 m_fullMIMEDescription = mimeDescription.lower(); 73 74 Vector<String> types; 75 mimeDescription.lower().split(UChar(';'), false, types); 76 for (unsigned i = 0; i < types.size(); ++i) { 77 Vector<String> mime; 78 types[i].split(UChar(':'), true, mime); 79 if (mime.size() > 0) { 80 Vector<String> exts; 81 if (mime.size() > 1) 82 mime[1].split(UChar(','), false, exts); 83 determineQuirks(mime[0]); 84 m_mimeToExtensions.add(mime[0], exts); 85 if (mime.size() > 2) 86 m_mimeToDescriptions.add(mime[0], mime[2]); 87 } 88 } 89 } 90 91 static NPError staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance, NPNVariable variable, void* value) 92 { 93 if (variable == NPNVToolkit) { 94 *static_cast<uint32_t*>(value) = 2; 95 return NPERR_NO_ERROR; 96 } 97 98 return NPN_GetValue(instance, variable, value); 99 } 100 101 static void initializeGtk(QLibrary* module = 0) 102 { 103 // Ensures missing Gtk initialization in some versions of Adobe's flash player 104 // plugin do not cause crashes. See BR# 40567, 44324, and 44405 for details. 105 if (module) { 106 typedef void *(*gtk_init_ptr)(int*, char***); 107 gtk_init_ptr gtkInit = (gtk_init_ptr)module->resolve("gtk_init"); 108 if (gtkInit) { 109 // Prevent gtk_init() from replacing the X error handlers, since the Gtk 110 // handlers abort when they receive an X error, thus killing the viewer. 111 #ifdef Q_WS_X11 112 int (*old_error_handler)(Display*, XErrorEvent*) = XSetErrorHandler(0); 113 int (*old_io_error_handler)(Display*) = XSetIOErrorHandler(0); 114 #endif 115 gtkInit(0, 0); 116 #ifdef Q_WS_X11 117 XSetErrorHandler(old_error_handler); 118 XSetIOErrorHandler(old_io_error_handler); 119 #endif 120 return; 121 } 122 } 123 124 QLibrary library(QLatin1String("libgtk-x11-2.0.so.0")); 125 if (library.load()) { 126 typedef void *(*gtk_init_check_ptr)(int*, char***); 127 gtk_init_check_ptr gtkInitCheck = (gtk_init_check_ptr)library.resolve("gtk_init_check"); 128 // NOTE: We're using gtk_init_check() since gtk_init() calls exit() on failure. 129 if (gtkInitCheck) 130 (void) gtkInitCheck(0, 0); 131 } 132 } 133 134 bool PluginPackage::load() 135 { 136 if (m_isLoaded) { 137 m_loadCount++; 138 return true; 139 } 140 141 m_module = new QLibrary((QString)m_path); 142 m_module->setLoadHints(QLibrary::ResolveAllSymbolsHint); 143 if (!m_module->load()) { 144 LOG(Plugins, "%s not loaded (%s)", m_path.utf8().data(), 145 m_module->errorString().toLatin1().constData()); 146 return false; 147 } 148 149 m_isLoaded = true; 150 151 NP_InitializeFuncPtr NP_Initialize; 152 NPError npErr; 153 154 NP_Initialize = (NP_InitializeFuncPtr)m_module->resolve("NP_Initialize"); 155 m_NPP_Shutdown = (NPP_ShutdownProcPtr)m_module->resolve("NP_Shutdown"); 156 157 if (!NP_Initialize || !m_NPP_Shutdown) 158 goto abort; 159 160 memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); 161 m_pluginFuncs.size = sizeof(m_pluginFuncs); 162 163 initializeBrowserFuncs(); 164 165 if (m_path.contains("npwrapper.")) { 166 // nspluginwrapper relies on the toolkit value to know if glib is available 167 // It does so in NP_Initialize with a null instance, therefore it is done this way: 168 m_browserFuncs.getvalue = staticPluginQuirkRequiresGtkToolKit_NPN_GetValue; 169 // Workaround Adobe's failure to properly initialize Gtk in some versions 170 // of their flash player plugin. 171 initializeGtk(); 172 } else if (m_path.contains("flashplayer")) { 173 // Workaround Adobe's failure to properly initialize Gtk in some versions 174 // of their flash player plugin. 175 initializeGtk(m_module); 176 } 177 178 #if defined(XP_UNIX) 179 npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs); 180 #else 181 npErr = NP_Initialize(&m_browserFuncs); 182 #endif 183 if (npErr != NPERR_NO_ERROR) 184 goto abort; 185 186 m_loadCount++; 187 return true; 188 189 abort: 190 unloadWithoutShutdown(); 191 return false; 192 } 193 194 uint16_t PluginPackage::NPVersion() const 195 { 196 return NP_VERSION_MINOR; 197 } 198 199 } 200