• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 namespace WebCore {
42 
fetchInfo()43 bool 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)
webkitgtkXError(Display * xdisplay,XErrorEvent * error)107 static 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 
moduleMixesGtkSymbols(GModule * module)122 static 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 
load()133 bool 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 
208 abort:
209     unloadWithoutShutdown();
210     return false;
211 }
212 
NPVersion() const213 uint16_t PluginPackage::NPVersion() const
214 {
215     return NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL;
216 }
217 }
218