• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "PluginDatabase.h"
29 
30 #include "Frame.h"
31 #include "KURL.h"
32 #include "PluginPackage.h"
33 #include <windows.h>
34 #include <shlwapi.h>
35 
36 #if COMPILER(MINGW)
37 #define _countof(x) (sizeof(x)/sizeof(x[0]))
38 #endif
39 
40 namespace WebCore {
41 
addPluginPathsFromRegistry(HKEY rootKey,HashSet<String> & paths)42 static inline void addPluginPathsFromRegistry(HKEY rootKey, HashSet<String>& paths)
43 {
44     HKEY key;
45     HRESULT result = RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key);
46 
47     if (result != ERROR_SUCCESS)
48         return;
49 
50     wchar_t name[128];
51     FILETIME lastModified;
52 
53     // Enumerate subkeys
54     for (int i = 0;; i++) {
55         DWORD nameLen = _countof(name);
56         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
57 
58         if (result != ERROR_SUCCESS)
59             break;
60 
61         WCHAR pathStr[_MAX_PATH];
62         DWORD pathStrSize = sizeof(pathStr);
63         DWORD type;
64 
65         result = SHGetValue(key, name, TEXT("Path"), &type, (LPBYTE)pathStr, &pathStrSize);
66         if (result != ERROR_SUCCESS || type != REG_SZ)
67             continue;
68 
69         paths.add(String(pathStr, pathStrSize / sizeof(WCHAR) - 1));
70     }
71 
72     RegCloseKey(key);
73 }
74 
getPluginPathsInDirectories(HashSet<String> & paths) const75 void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const
76 {
77     // FIXME: This should be a case insensitive set.
78     HashSet<String> uniqueFilenames;
79 
80     HANDLE hFind = INVALID_HANDLE_VALUE;
81     WIN32_FIND_DATAW findFileData;
82 
83     String oldWMPPluginPath;
84     String newWMPPluginPath;
85 
86     Vector<String>::const_iterator end = m_pluginDirectories.end();
87     for (Vector<String>::const_iterator it = m_pluginDirectories.begin(); it != end; ++it) {
88         String pattern = *it + "\\*";
89 
90         hFind = FindFirstFileW(pattern.charactersWithNullTermination(), &findFileData);
91 
92         if (hFind == INVALID_HANDLE_VALUE)
93             continue;
94 
95         do {
96             if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
97                 continue;
98 
99             String filename = String(findFileData.cFileName, wcslen(findFileData.cFileName));
100             if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) &&
101                 (!equalIgnoringCase(filename, "Plugin.dll") || !it->endsWith("Shockwave 10", false)))
102                 continue;
103 
104             String fullPath = *it + "\\" + filename;
105             if (!uniqueFilenames.add(fullPath).second)
106                 continue;
107 
108             paths.add(fullPath);
109 
110             if (equalIgnoringCase(filename, "npdsplay.dll"))
111                 oldWMPPluginPath = fullPath;
112             else if (equalIgnoringCase(filename, "np-mswmp.dll"))
113                 newWMPPluginPath = fullPath;
114 
115         } while (FindNextFileW(hFind, &findFileData) != 0);
116 
117         FindClose(hFind);
118     }
119 
120     addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
121     addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);
122 
123     // If both the old and new WMP plugin are present in the plugins set,
124     // we remove the old one so we don't end up choosing the old one.
125     if (!oldWMPPluginPath.isEmpty() && !newWMPPluginPath.isEmpty())
126         paths.remove(oldWMPPluginPath);
127 }
128 
parseVersionString(const String & versionString)129 static inline Vector<int> parseVersionString(const String& versionString)
130 {
131     Vector<int> version;
132 
133     unsigned startPos = 0;
134     unsigned endPos;
135 
136     while (startPos < versionString.length()) {
137         for (endPos = startPos; endPos < versionString.length(); ++endPos)
138             if (versionString[endPos] == '.' || versionString[endPos] == '_')
139                 break;
140 
141         int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
142         version.append(versionComponent);
143 
144         startPos = endPos + 1;
145     }
146 
147     return version;
148 }
149 
150 // This returns whether versionA is higher than versionB
compareVersions(const Vector<int> & versionA,const Vector<int> & versionB)151 static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
152 {
153     for (unsigned i = 0; i < versionA.size(); i++) {
154         if (i >= versionB.size())
155             return true;
156 
157         if (versionA[i] > versionB[i])
158             return true;
159         else if (versionA[i] < versionB[i])
160             return false;
161     }
162 
163     // If we come here, the versions are either the same or versionB has an extra component, just return false
164     return false;
165 }
166 
addMozillaPluginDirectories(Vector<String> & directories)167 static inline void addMozillaPluginDirectories(Vector<String>& directories)
168 {
169     // Enumerate all Mozilla plugin directories in the registry
170     HKEY key;
171     LONG result;
172 
173     result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Mozilla"), 0, KEY_READ, &key);
174     if (result == ERROR_SUCCESS) {
175         WCHAR name[128];
176         FILETIME lastModified;
177 
178         // Enumerate subkeys
179         for (int i = 0;; i++) {
180             DWORD nameLen = sizeof(name) / sizeof(WCHAR);
181             result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
182 
183             if (result != ERROR_SUCCESS)
184                 break;
185 
186             String extensionsPath = String(name, nameLen) + "\\Extensions";
187             HKEY extensionsKey;
188 
189             // Try opening the key
190             result = RegOpenKeyEx(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
191 
192             if (result == ERROR_SUCCESS) {
193                 // Now get the plugins directory
194                 WCHAR pluginsDirectoryStr[_MAX_PATH];
195                 DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
196                 DWORD type;
197 
198                 result = RegQueryValueEx(extensionsKey, TEXT("Plugins"), 0, &type, (LPBYTE)&pluginsDirectoryStr, &pluginsDirectorySize);
199 
200                 if (result == ERROR_SUCCESS && type == REG_SZ)
201                     directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));
202 
203                 RegCloseKey(extensionsKey);
204             }
205         }
206 
207         RegCloseKey(key);
208     }
209 }
210 
addWindowsMediaPlayerPluginDirectory(Vector<String> & directories)211 static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
212 {
213     // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
214     WCHAR pluginDirectoryStr[_MAX_PATH + 1];
215     DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(TEXT("%SYSTEMDRIVE%\\PFiles\\Plugins"), pluginDirectoryStr, _countof(pluginDirectoryStr));
216 
217     if (pluginDirectorySize > 0 && pluginDirectorySize <= _countof(pluginDirectoryStr))
218         directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
219 
220     DWORD type;
221     WCHAR installationDirectoryStr[_MAX_PATH];
222     DWORD installationDirectorySize = sizeof(installationDirectoryStr);
223 
224     HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\MediaPlayer"), TEXT("Installation Directory"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
225 
226     if (result == ERROR_SUCCESS && type == REG_SZ)
227         directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
228 }
229 
addQuickTimePluginDirectory(Vector<String> & directories)230 static inline void addQuickTimePluginDirectory(Vector<String>& directories)
231 {
232     DWORD type;
233     WCHAR installationDirectoryStr[_MAX_PATH];
234     DWORD installationDirectorySize = sizeof(installationDirectoryStr);
235 
236     HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Apple Computer, Inc.\\QuickTime"), TEXT("InstallDir"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
237 
238     if (result == ERROR_SUCCESS && type == REG_SZ) {
239         String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
240         directories.append(pluginDir);
241     }
242 }
243 
addAdobeAcrobatPluginDirectory(Vector<String> & directories)244 static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
245 {
246     HKEY key;
247     HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Adobe\\Acrobat Reader"), 0, KEY_READ, &key);
248     if (result != ERROR_SUCCESS)
249         return;
250 
251     WCHAR name[128];
252     FILETIME lastModified;
253 
254     Vector<int> latestAcrobatVersion;
255     String latestAcrobatVersionString;
256 
257     // Enumerate subkeys
258     for (int i = 0;; i++) {
259         DWORD nameLen = sizeof(name) / sizeof(WCHAR);
260         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
261 
262         if (result != ERROR_SUCCESS)
263             break;
264 
265         Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
266         if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
267             latestAcrobatVersion = acrobatVersion;
268             latestAcrobatVersionString = String(name, nameLen);
269         }
270     }
271 
272     if (!latestAcrobatVersionString.isNull()) {
273         DWORD type;
274         WCHAR acrobatInstallPathStr[_MAX_PATH];
275         DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
276 
277         String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
278         result = SHGetValue(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, (LPBYTE)acrobatInstallPathStr, &acrobatInstallPathSize);
279 
280         if (result == ERROR_SUCCESS) {
281             String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
282             directories.append(acrobatPluginDirectory);
283         }
284     }
285 
286     RegCloseKey(key);
287 }
288 
safariPluginsDirectory()289 static inline String safariPluginsDirectory()
290 {
291     WCHAR moduleFileNameStr[_MAX_PATH];
292     static String pluginsDirectory;
293     static bool cachedPluginDirectory = false;
294 
295     if (!cachedPluginDirectory) {
296         cachedPluginDirectory = true;
297 
298         int moduleFileNameLen = GetModuleFileName(0, moduleFileNameStr, _MAX_PATH);
299 
300         if (!moduleFileNameLen || moduleFileNameLen == _MAX_PATH)
301             goto exit;
302 
303         if (!PathRemoveFileSpec(moduleFileNameStr))
304             goto exit;
305 
306         pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
307     }
308 exit:
309     return pluginsDirectory;
310 }
311 
addMacromediaPluginDirectories(Vector<String> & directories)312 static inline void addMacromediaPluginDirectories(Vector<String>& directories)
313 {
314     WCHAR systemDirectoryStr[MAX_PATH];
315 
316     if (GetSystemDirectory(systemDirectoryStr, _countof(systemDirectoryStr)) == 0)
317         return;
318 
319     WCHAR macromediaDirectoryStr[MAX_PATH];
320 
321     PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Flash"));
322     directories.append(macromediaDirectoryStr);
323 
324     PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Shockwave 10"));
325     directories.append(macromediaDirectoryStr);
326 }
327 
defaultPluginDirectories()328 Vector<String> PluginDatabase::defaultPluginDirectories()
329 {
330     Vector<String> directories;
331     String ourDirectory = safariPluginsDirectory();
332 
333     if (!ourDirectory.isNull())
334         directories.append(ourDirectory);
335     addQuickTimePluginDirectory(directories);
336     addAdobeAcrobatPluginDirectory(directories);
337     addMozillaPluginDirectories(directories);
338     addWindowsMediaPlayerPluginDirectory(directories);
339     addMacromediaPluginDirectories(directories);
340 
341     return directories;
342 }
343 
isPreferredPluginDirectory(const String & directory)344 bool PluginDatabase::isPreferredPluginDirectory(const String& directory)
345 {
346     String ourDirectory = safariPluginsDirectory();
347 
348     if (!ourDirectory.isNull() && !directory.isNull())
349         return ourDirectory == directory;
350 
351     return false;
352 }
353 
354 }
355