[GTK] The process freezes when you right click on windowless Flash
[WebKit-https.git] / Source / WebKit2 / Shared / Plugins / Netscape / x11 / NetscapePluginModuleX11.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #if PLUGIN_ARCHITECTURE(X11)
28
29 #include "NetscapePluginModule.h"
30
31 #include "NetscapeBrowserFuncs.h"
32 #include <WebCore/FileSystem.h>
33
34 #if PLATFORM(QT)
35 #include <QLibrary>
36 #endif
37
38 #include <fcntl.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42
43 using namespace WebCore;
44
45 namespace WebKit {
46
47 class StdoutDevNullRedirector {
48 public:
49     StdoutDevNullRedirector();
50     ~StdoutDevNullRedirector();
51
52 private:
53     int m_savedStdout;
54 };
55
56 StdoutDevNullRedirector::StdoutDevNullRedirector()
57     : m_savedStdout(-1)
58 {
59     int newStdout = open("/dev/null", O_WRONLY);
60     if (newStdout == -1)
61         return;
62     m_savedStdout = dup(STDOUT_FILENO);
63     dup2(newStdout, STDOUT_FILENO);
64 }
65
66 StdoutDevNullRedirector::~StdoutDevNullRedirector()
67 {
68     if (m_savedStdout != -1)
69         dup2(m_savedStdout, STDOUT_FILENO);
70 }
71
72 #if PLATFORM(QT)
73 static void initializeGTK()
74 {
75     QLibrary library(QLatin1String("libgtk-x11-2.0.so.0"));
76     if (library.load()) {
77         typedef void *(*gtk_init_check_ptr)(int*, char***);
78         gtk_init_check_ptr gtkInitCheck = reinterpret_cast<gtk_init_check_ptr>(library.resolve("gtk_init_check"));
79         // NOTE: We're using gtk_init_check() since gtk_init() calls exit() on failure.
80         if (gtkInitCheck)
81             (void) gtkInitCheck(0, 0);
82     }
83 }
84 #endif
85
86 void NetscapePluginModule::applyX11QuirksBeforeLoad()
87 {
88 #if PLATFORM(QT)
89     if (m_pluginPath.contains("npwrapper") || m_pluginPath.contains("flashplayer")) {
90         initializeGTK();
91         m_pluginQuirks.add(PluginQuirks::RequiresGTKToolKit);
92     }
93 #endif
94 }
95
96 void NetscapePluginModule::setMIMEDescription(const String& mimeDescription, PluginModuleInfo& plugin)
97 {
98     Vector<String> types;
99     mimeDescription.lower().split(UChar(';'), false, types);
100     plugin.info.mimes.reserveCapacity(types.size());
101
102     size_t mimeInfoCount = 0;
103     for (size_t i = 0; i < types.size(); ++i) {
104         Vector<String> mimeTypeParts;
105         types[i].split(UChar(':'), true, mimeTypeParts);
106         if (mimeTypeParts.size() <= 0)
107             continue;
108
109         plugin.info.mimes.uncheckedAppend(MimeClassInfo());
110         MimeClassInfo& mimeInfo = plugin.info.mimes[mimeInfoCount++];
111         mimeInfo.type = mimeTypeParts[0];
112
113         if (mimeTypeParts.size() > 1)
114             mimeTypeParts[1].split(UChar(','), false, mimeInfo.extensions);
115
116         if (mimeTypeParts.size() > 2)
117             mimeInfo.desc = mimeTypeParts[2];
118     }
119 }
120
121 bool NetscapePluginModule::getPluginInfoForLoadedPlugin(PluginModuleInfo& plugin)
122 {
123     ASSERT(m_isInitialized);
124
125     plugin.path = m_pluginPath;
126     plugin.info.file = pathGetFileName(m_pluginPath);
127
128     Module* module = m_module.get();
129     NPP_GetValueProcPtr NPP_GetValue = module->functionPointer<NPP_GetValueProcPtr>("NP_GetValue");
130     if (!NPP_GetValue)
131         return false;
132
133     NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription = module->functionPointer<NP_GetMIMEDescriptionFuncPtr>("NP_GetMIMEDescription");
134     if (!NP_GetMIMEDescription)
135         return false;
136
137     char* buffer;
138     NPError error = NPP_GetValue(0, NPPVpluginNameString, &buffer);
139     if (error == NPERR_NO_ERROR)
140         plugin.info.name = buffer;
141
142     error = NPP_GetValue(0, NPPVpluginDescriptionString, &buffer);
143     if (error == NPERR_NO_ERROR)
144         plugin.info.desc = buffer;
145
146     const char* mimeDescription = NP_GetMIMEDescription();
147     if (!mimeDescription)
148         return false;
149
150     setMIMEDescription(mimeDescription, plugin);
151
152     return true;
153 }
154 bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
155 {
156     // Tempararily suppress stdout in this function as plugins will be loaded and shutdown and debug info
157     // is leaked to layout test output.
158     StdoutDevNullRedirector stdoutDevNullRedirector;
159
160     // We are loading the plugin here since it does not seem to be a standardized way to
161     // get the needed informations from a UNIX plugin without loading it.
162     RefPtr<NetscapePluginModule> pluginModule = NetscapePluginModule::getOrCreate(pluginPath);
163     if (!pluginModule)
164         return false;
165
166     pluginModule->incrementLoadCount();
167     bool returnValue = pluginModule->getPluginInfoForLoadedPlugin(plugin);
168     pluginModule->decrementLoadCount();
169
170     return returnValue;
171 }
172
173 void NetscapePluginModule::determineQuirks()
174 {
175 #if CPU(X86_64)
176     PluginModuleInfo plugin;
177     if (!getPluginInfoForLoadedPlugin(plugin))
178         return;
179
180     Vector<MimeClassInfo> mimeTypes = plugin.info.mimes;
181     for (size_t i = 0; i < mimeTypes.size(); ++i) {
182         if (mimeTypes[i].type == "application/x-shockwave-flash") {
183             m_pluginQuirks.add(PluginQuirks::IgnoreRightClickInWindowlessMode);
184             break;
185         }
186     }
187 #endif
188 }
189
190 } // namespace WebKit
191
192 #endif // PLUGIN_ARCHITECTURE(X11)