Remove all uses of deprecatedCharacters from WebKit2
[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) && ENABLE(NETSCAPE_PLUGIN_API)
28
29 #include "NetscapePluginModule.h"
30
31 #include "PluginProcessProxy.h"
32 #include "NetscapeBrowserFuncs.h"
33 #include <WebCore/FileSystem.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include <wtf/text/StringBuilder.h>
40
41 using namespace WebCore;
42
43 namespace WebKit {
44
45 class StdoutDevNullRedirector {
46 public:
47     StdoutDevNullRedirector();
48     ~StdoutDevNullRedirector();
49
50 private:
51     int m_savedStdout;
52 };
53
54 StdoutDevNullRedirector::StdoutDevNullRedirector()
55     : m_savedStdout(-1)
56 {
57     int newStdout = open("/dev/null", O_WRONLY);
58     if (newStdout == -1)
59         return;
60     m_savedStdout = dup(STDOUT_FILENO);
61     dup2(newStdout, STDOUT_FILENO);
62 }
63
64 StdoutDevNullRedirector::~StdoutDevNullRedirector()
65 {
66     if (m_savedStdout != -1)
67         dup2(m_savedStdout, STDOUT_FILENO);
68 }
69
70
71 void NetscapePluginModule::parseMIMEDescription(const String& mimeDescription, Vector<MimeClassInfo>& result)
72 {
73     ASSERT_ARG(result, result.isEmpty());
74
75     Vector<String> types;
76     mimeDescription.lower().split(UChar(';'), false, types);
77     result.reserveInitialCapacity(types.size());
78
79     size_t mimeInfoCount = 0;
80     for (size_t i = 0; i < types.size(); ++i) {
81         Vector<String> mimeTypeParts;
82         types[i].split(UChar(':'), true, mimeTypeParts);
83         if (mimeTypeParts.size() <= 0)
84             continue;
85
86         result.uncheckedAppend(MimeClassInfo());
87         MimeClassInfo& mimeInfo = result[mimeInfoCount++];
88         mimeInfo.type = mimeTypeParts[0];
89
90         if (mimeTypeParts.size() > 1)
91             mimeTypeParts[1].split(UChar(','), false, mimeInfo.extensions);
92
93         if (mimeTypeParts.size() > 2)
94             mimeInfo.desc = mimeTypeParts[2];
95     }
96 }
97
98 String NetscapePluginModule::buildMIMEDescription(const Vector<MimeClassInfo>& mimeDescription)
99 {
100     StringBuilder builder;
101
102     size_t mimeInfoCount = mimeDescription.size();
103     for (size_t i = 0; i < mimeInfoCount; ++i) {
104         const MimeClassInfo& mimeInfo = mimeDescription[i];
105         builder.append(mimeInfo.type);
106         builder.append(':');
107
108         size_t extensionsCount = mimeInfo.extensions.size();
109         for (size_t j = 0; j < extensionsCount; ++j) {
110             builder.append(mimeInfo.extensions[j]);
111             if (j != extensionsCount - 1)
112                 builder.append(',');
113         }
114         builder.append(':');
115
116         builder.append(mimeInfo.desc);
117         if (i != mimeInfoCount - 1)
118             builder.append(';');
119     }
120
121     return builder.toString();
122 }
123
124 bool NetscapePluginModule::getPluginInfoForLoadedPlugin(RawPluginMetaData& metaData)
125 {
126     ASSERT(m_isInitialized);
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         metaData.name = String::fromUTF8(buffer);
141
142     error = NPP_GetValue(0, NPPVpluginDescriptionString, &buffer);
143     if (error == NPERR_NO_ERROR)
144         metaData.description = String::fromUTF8(buffer);
145
146     String mimeDescription = String::fromUTF8(NP_GetMIMEDescription());
147     if (mimeDescription.isNull())
148         return false;
149
150     metaData.mimeDescription = mimeDescription;
151
152     return true;
153 }
154
155 bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
156 {
157     RawPluginMetaData metaData;
158     if (!PluginProcessProxy::scanPlugin(pluginPath, metaData))
159         return false;
160
161     plugin.path = pluginPath;
162     plugin.info.file = pathGetFileName(pluginPath);
163     plugin.info.name = metaData.name;
164     plugin.info.desc = metaData.description;
165     parseMIMEDescription(metaData.mimeDescription, plugin.info.mimes);
166
167     return true;
168 }
169
170 void NetscapePluginModule::determineQuirks()
171 {
172 #if CPU(X86_64)
173     RawPluginMetaData metaData;
174     if (!getPluginInfoForLoadedPlugin(metaData))
175         return;
176
177     Vector<MimeClassInfo> mimeTypes;
178     parseMIMEDescription(metaData.mimeDescription, mimeTypes);
179     for (size_t i = 0; i < mimeTypes.size(); ++i) {
180         if (mimeTypes[i].type == "application/x-shockwave-flash") {
181             m_pluginQuirks.add(PluginQuirks::IgnoreRightClickInWindowlessMode);
182             break;
183         }
184     }
185 #endif
186 }
187
188 static void writeByte(char byte)
189 {
190     int result;
191     while ((result = fputc(byte, stdout)) == EOF && errno == EINTR) { }
192     ASSERT(result != EOF);
193 }
194
195 static void writeCharacter(UChar character)
196 {
197     writeByte(reinterpret_cast<const char*>(&character)[0]);
198     writeByte(reinterpret_cast<const char*>(&character)[1]);
199 }
200
201 static void writeLine(const String& line)
202 {
203     unsigned length = line.length();
204     for (unsigned i = 0; i < length; ++i) {
205         UChar character = line[i];
206         if (character != '\n')
207             writeCharacter(character);
208     }
209     writeCharacter('\n');
210 }
211
212 bool NetscapePluginModule::scanPlugin(const String& pluginPath)
213 {
214     RawPluginMetaData metaData;
215
216     {
217         // Don't allow the plugin to pollute the standard output.
218         StdoutDevNullRedirector stdOutRedirector;
219
220         // We are loading the plugin here since it does not seem to be a standardized way to
221         // get the needed informations from a UNIX plugin without loading it.
222         RefPtr<NetscapePluginModule> pluginModule = NetscapePluginModule::getOrCreate(pluginPath);
223         if (!pluginModule)
224             return false;
225
226         pluginModule->incrementLoadCount();
227         bool success = pluginModule->getPluginInfoForLoadedPlugin(metaData);
228         pluginModule->decrementLoadCount();
229
230         if (!success)
231             return false;
232     }
233
234     // Write data to standard output for the UI process.
235     writeLine(metaData.name);
236     writeLine(metaData.description);
237     writeLine(metaData.mimeDescription);
238
239     fflush(stdout);
240
241     return true;
242 }
243
244 } // namespace WebKit
245
246 #endif // PLUGIN_ARCHITECTURE(X11) && ENABLE(NETSCAPE_PLUGIN_API)