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
fetchInfo()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
setMIMEDescription(const String & mimeDescription)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
staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance,NPNVariable variable,void * value)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
initializeGtk(QLibrary * module=0)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
load()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
NPVersion() const194 uint16_t PluginPackage::NPVersion() const
195 {
196 return NP_VERSION_MINOR;
197 }
198
199 }
200