d2e3ec94ad1a6f7605b039b67325f8a19790cf76
[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 "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
40 using namespace WebCore;
41
42 namespace WebKit {
43
44 static void parseMIMEDescription(const String& mimeDescription, Vector<MimeClassInfo>& result)
45 {
46     ASSERT_ARG(result, result.isEmpty());
47
48     Vector<String> types;
49     mimeDescription.lower().split(UChar(';'), false, types);
50     result.reserveInitialCapacity(types.size());
51
52     size_t mimeInfoCount = 0;
53     for (size_t i = 0; i < types.size(); ++i) {
54         Vector<String> mimeTypeParts;
55         types[i].split(UChar(':'), true, mimeTypeParts);
56         if (mimeTypeParts.size() <= 0)
57             continue;
58
59         result.uncheckedAppend(MimeClassInfo());
60         MimeClassInfo& mimeInfo = result[mimeInfoCount++];
61         mimeInfo.type = mimeTypeParts[0];
62
63         if (mimeTypeParts.size() > 1)
64             mimeTypeParts[1].split(UChar(','), false, mimeInfo.extensions);
65
66         if (mimeTypeParts.size() > 2)
67             mimeInfo.desc = mimeTypeParts[2];
68     }
69 }
70
71 bool NetscapePluginModule::getPluginInfoForLoadedPlugin(RawPluginMetaData& metaData)
72 {
73     ASSERT(m_isInitialized);
74
75     Module* module = m_module.get();
76     NPP_GetValueProcPtr NPP_GetValue = module->functionPointer<NPP_GetValueProcPtr>("NP_GetValue");
77     if (!NPP_GetValue)
78         return false;
79
80     NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription = module->functionPointer<NP_GetMIMEDescriptionFuncPtr>("NP_GetMIMEDescription");
81     if (!NP_GetMIMEDescription)
82         return false;
83
84     char* buffer;
85     NPError error = NPP_GetValue(0, NPPVpluginNameString, &buffer);
86     if (error == NPERR_NO_ERROR)
87         metaData.name = String::fromUTF8(buffer);
88
89     error = NPP_GetValue(0, NPPVpluginDescriptionString, &buffer);
90     if (error == NPERR_NO_ERROR)
91         metaData.description = String::fromUTF8(buffer);
92
93     String mimeDescription = String::fromUTF8(NP_GetMIMEDescription());
94     if (mimeDescription.isNull())
95         return false;
96
97     metaData.mimeDescription = mimeDescription;
98
99     return true;
100 }
101
102 bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
103 {
104     RawPluginMetaData metaData;
105     if (!PluginProcessProxy::scanPlugin(pluginPath, metaData))
106         return false;
107
108     plugin.path = pluginPath;
109     plugin.info.file = pathGetFileName(pluginPath);
110     plugin.info.name = metaData.name;
111     plugin.info.desc = metaData.description;
112     parseMIMEDescription(metaData.mimeDescription, plugin.info.mimes);
113
114     return true;
115 }
116
117 void NetscapePluginModule::determineQuirks()
118 {
119 #if CPU(X86_64)
120     RawPluginMetaData metaData;
121     if (!getPluginInfoForLoadedPlugin(metaData))
122         return;
123
124     Vector<MimeClassInfo> mimeTypes;
125     parseMIMEDescription(metaData.mimeDescription, mimeTypes);
126     for (size_t i = 0; i < mimeTypes.size(); ++i) {
127         if (mimeTypes[i].type == "application/x-shockwave-flash") {
128             m_pluginQuirks.add(PluginQuirks::IgnoreRightClickInWindowlessMode);
129             break;
130         }
131     }
132 #endif
133 }
134
135 static String truncateToSingleLine(const String& string)
136 {
137     ASSERT_ARG(string, !string.is8Bit());
138
139     unsigned oldLength = string.length();
140     UChar* buffer;
141     String stringBuffer(StringImpl::createUninitialized(oldLength + 1, buffer));
142
143     unsigned newLength = 0;
144     for (const UChar* c = string.characters16(); c < string.characters16() + oldLength; ++c) {
145         if (*c != UChar('\n'))
146             buffer[newLength++] = *c;
147     }
148     buffer[newLength++] = UChar('\n');
149
150     if (newLength == oldLength + 1)
151         return stringBuffer;
152     return String(stringBuffer.characters16(), newLength);
153 }
154
155 bool NetscapePluginModule::scanPlugin(const String& pluginPath)
156 {
157     // We are loading the plugin here since it does not seem to be a standardized way to
158     // get the needed informations from a UNIX plugin without loading it.
159     RefPtr<NetscapePluginModule> pluginModule = NetscapePluginModule::getOrCreate(pluginPath);
160     if (!pluginModule)
161         return false;
162
163     pluginModule->incrementLoadCount();
164     RawPluginMetaData metaData;
165     bool success = pluginModule->getPluginInfoForLoadedPlugin(metaData);
166     pluginModule->decrementLoadCount();
167
168     if (!success)
169         return false;
170
171     // Write data to standard output for the UI process.
172     String output[3] = {
173         truncateToSingleLine(metaData.name),
174         truncateToSingleLine(metaData.description),
175         truncateToSingleLine(metaData.mimeDescription)
176     };
177     for (unsigned i = 0; i < 3; ++i) {
178         const String& line = output[i];
179         const char* current = reinterpret_cast<const char*>(line.characters16());
180         const char* end = reinterpret_cast<const char*>(line.characters16()) + (line.length() * sizeof(UChar));
181         while (current < end) {
182             int result;
183             while ((result = fputc(*current, stdout)) == EOF && errno == EINTR) { }
184             ASSERT(result != EOF);
185             ++current;
186         }
187     }
188
189     fflush(stdout);
190
191     return true;
192 }
193
194 } // namespace WebKit
195
196 #endif // PLUGIN_ARCHITECTURE(X11)