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