1/* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Collabora Ltd. All rights reserved. 4 * Copyright (C) 2008 Nuanti Ltd. 5 * Copyright (C) 2008 Novell Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "PluginPackage.h" 31 32#include "GOwnPtrGtk.h" 33#include "GRefPtrGtk.h" 34#include "MIMETypeRegistry.h" 35#include "NotImplemented.h" 36#include "npruntime_impl.h" 37#include "PluginDebug.h" 38#include <gio/gio.h> 39#include <wtf/text/CString.h> 40 41namespace WebCore { 42 43bool PluginPackage::fetchInfo() 44{ 45#if defined(XP_UNIX) 46 if (!load()) 47 return false; 48 49 NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription = 0; 50 NPP_GetValueProcPtr NPP_GetValue = 0; 51 52 g_module_symbol(m_module, "NP_GetMIMEDescription", (void**)&NP_GetMIMEDescription); 53 g_module_symbol(m_module, "NP_GetValue", (void**)&NPP_GetValue); 54 55 if (!NP_GetMIMEDescription || !NPP_GetValue) 56 return false; 57 58 char* buffer = 0; 59 NPError err = NPP_GetValue(0, NPPVpluginNameString, &buffer); 60 if (err == NPERR_NO_ERROR) 61 m_name = buffer; 62 63 buffer = 0; 64 err = NPP_GetValue(0, NPPVpluginDescriptionString, &buffer); 65 if (err == NPERR_NO_ERROR) { 66 m_description = buffer; 67 determineModuleVersionFromDescription(); 68 } 69 70 const gchar* types = NP_GetMIMEDescription(); 71 if (!types) 72 return true; 73 74 gchar** mimeDescs = g_strsplit(types, ";", -1); 75 for (int i = 0; mimeDescs[i] && mimeDescs[i][0]; i++) { 76 GOwnPtr<char> mime(g_utf8_strdown(mimeDescs[i], -1)); 77 gchar** mimeData = g_strsplit(mime.get(), ":", 3); 78 if (g_strv_length(mimeData) < 3) { 79 g_strfreev(mimeData); 80 continue; 81 } 82 83 String description = String::fromUTF8(mimeData[2]); 84 gchar** extensions = g_strsplit(mimeData[1], ",", -1); 85 86 Vector<String> extVector; 87 for (int j = 0; extensions[j]; j++) 88 extVector.append(String::fromUTF8(extensions[j])); 89 90 determineQuirks(mimeData[0]); 91 m_mimeToExtensions.add(mimeData[0], extVector); 92 m_mimeToDescriptions.add(mimeData[0], description); 93 94 g_strfreev(extensions); 95 g_strfreev(mimeData); 96 } 97 g_strfreev(mimeDescs); 98 99 return true; 100#else 101 notImplemented(); 102 return false; 103#endif 104} 105 106#if defined(XP_UNIX) 107static int webkitgtkXError(Display* xdisplay, XErrorEvent* error) 108{ 109 gchar errorMessage[64]; 110 XGetErrorText(xdisplay, error->error_code, errorMessage, 63); 111 g_warning("The program '%s' received an X Window System error.\n" 112 "This probably reflects a bug in the Adobe Flash plugin.\n" 113 "The error was '%s'.\n" 114 " (Details: serial %ld error_code %d request_code %d minor_code %d)\n", 115 g_get_prgname(), errorMessage, 116 error->serial, error->error_code, 117 error->request_code, error->minor_code); 118 return 0; 119} 120#endif 121 122static bool moduleMixesGtkSymbols(GModule* module) 123{ 124 gpointer symbol; 125#ifdef GTK_API_VERSION_2 126 return g_module_symbol(module, "gtk_application_get_type", &symbol); 127#else 128 return g_module_symbol(module, "gtk_object_get_type", &symbol); 129#endif 130} 131 132 133bool PluginPackage::load() 134{ 135 if (m_isLoaded) { 136 m_loadCount++; 137 return true; 138 } 139 140 GOwnPtr<gchar> finalPath(g_strdup(m_path.utf8().data())); 141 while (g_file_test(finalPath.get(), G_FILE_TEST_IS_SYMLINK)) { 142 GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(finalPath.get())); 143 GRefPtr<GFile> dir = adoptGRef(g_file_get_parent(file.get())); 144 GOwnPtr<gchar> linkPath(g_file_read_link(finalPath.get(), 0)); 145 GRefPtr<GFile> resolvedFile = adoptGRef(g_file_resolve_relative_path(dir.get(), linkPath.get())); 146 finalPath.set(g_file_get_path(resolvedFile.get())); 147 } 148 149 // No joke. If there is a netscape component in the path, go back 150 // to the symlink, as flash breaks otherwise. 151 // See http://src.chromium.org/viewvc/chrome/trunk/src/webkit/glue/plugins/plugin_list_posix.cc 152 GOwnPtr<gchar> baseName(g_path_get_basename(finalPath.get())); 153 if (!g_strcmp0(baseName.get(), "libflashplayer.so") 154 && g_strstr_len(finalPath.get(), -1, "/netscape/")) 155 finalPath.set(g_strdup(m_path.utf8().data())); 156 157 m_module = g_module_open(finalPath.get(), G_MODULE_BIND_LOCAL); 158 159 if (!m_module) { 160 LOG(Plugins,"Module Load Failed :%s, Error:%s\n", (m_path.utf8()).data(), g_module_error()); 161 return false; 162 } 163 164 if (moduleMixesGtkSymbols(m_module)) { 165 LOG(Plugins, "Module '%s' mixes GTK+ 2 and GTK+ 3 symbols, ignoring plugin.\n", m_path.utf8().data()); 166 g_module_close(m_module); 167 return false; 168 } 169 170 m_isLoaded = true; 171 172#if defined(XP_UNIX) 173 if (!g_strcmp0(baseName.get(), "libflashplayer.so")) { 174 // Flash plugin can produce X errors that are handled by the GDK X error handler, which 175 // exits the process. Since we don't want to crash due to flash bugs, we install a 176 // custom error handler to show a warning when a X error happens without aborting. 177 XSetErrorHandler(webkitgtkXError); 178 } 179#endif 180 181 NP_InitializeFuncPtr NP_Initialize = 0; 182 m_NPP_Shutdown = 0; 183 184 NPError npErr; 185 186 g_module_symbol(m_module, "NP_Initialize", (void**)&NP_Initialize); 187 g_module_symbol(m_module, "NP_Shutdown", (void**)&m_NPP_Shutdown); 188 189 if (!NP_Initialize || !m_NPP_Shutdown) 190 goto abort; 191 192 memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); 193 m_pluginFuncs.size = sizeof(m_pluginFuncs); 194 195 initializeBrowserFuncs(); 196 197#if defined(XP_UNIX) 198 npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs); 199#else 200 npErr = NP_Initialize(&m_browserFuncs); 201#endif 202 if (npErr != NPERR_NO_ERROR) 203 goto abort; 204 205 m_loadCount++; 206 return true; 207 208abort: 209 unloadWithoutShutdown(); 210 return false; 211} 212 213uint16_t PluginPackage::NPVersion() const 214{ 215 return NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; 216} 217} 218