• 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  * Copyright (C) 2008-2009 Torch Mobile, Inc.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "config.h"
29 #include "PluginDatabase.h"
30 
31 #include "Frame.h"
32 #include "KURL.h"
33 #include "PluginPackage.h"
34 #include <windows.h>
35 #include <shlwapi.h>
36 
37 #if OS(WINCE)
38 // WINCE doesn't support Registry Key Access Rights. The parameter should always be 0
39 #ifndef KEY_ENUMERATE_SUB_KEYS
40 #define KEY_ENUMERATE_SUB_KEYS 0
41 #endif
42 
SHGetValue(HKEY hkey,LPCWSTR pszSubKey,LPCWSTR pszValue,LPDWORD pdwType,LPVOID pvData,LPDWORD pcbData)43 DWORD SHGetValue(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue, LPDWORD pdwType, LPVOID pvData, LPDWORD pcbData)
44 {
45     HKEY key;
46     if (RegOpenKeyEx(hkey, pszSubKey, 0, 0, &key) == ERROR_SUCCESS) {
47         DWORD result = RegQueryValueEx(key, pszValue, 0, pdwType, (LPBYTE)pvData, pcbData);
48         RegCloseKey(key);
49         return result;
50     }
51     return ERROR_INVALID_NAME;
52 }
53 
PathRemoveFileSpec(LPWSTR moduleFileNameStr)54 BOOL PathRemoveFileSpec(LPWSTR moduleFileNameStr)
55 {
56     if (!*moduleFileNameStr)
57         return FALSE;
58 
59     LPWSTR lastPos = 0;
60     LPWSTR curPos = moduleFileNameStr;
61     do {
62         if (*curPos == L'/' || *curPos == L'\\')
63             lastPos = curPos;
64     } while (*++curPos);
65 
66     if (lastPos == curPos - 1)
67         return FALSE;
68 
69     if (lastPos)
70         *lastPos = 0;
71     else {
72         moduleFileNameStr[0] = L'\\';
73         moduleFileNameStr[1] = 0;
74     }
75 
76     return TRUE;
77 }
78 #endif
79 
80 namespace WebCore {
81 
addPluginPathsFromRegistry(HKEY rootKey,HashSet<String> & paths)82 static inline void addPluginPathsFromRegistry(HKEY rootKey, HashSet<String>& paths)
83 {
84     HKEY key;
85     HRESULT result = RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key);
86 
87     if (result != ERROR_SUCCESS)
88         return;
89 
90     wchar_t name[128];
91     FILETIME lastModified;
92 
93     // Enumerate subkeys
94     for (int i = 0;; i++) {
95         DWORD nameLen = WTF_ARRAY_LENGTH(name);
96         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
97 
98         if (result != ERROR_SUCCESS)
99             break;
100 
101         WCHAR pathStr[_MAX_PATH];
102         DWORD pathStrSize = sizeof(pathStr);
103         DWORD type;
104 
105         result = SHGetValue(key, name, TEXT("Path"), &type, (LPBYTE)pathStr, &pathStrSize);
106         if (result != ERROR_SUCCESS || type != REG_SZ)
107             continue;
108 
109         paths.add(String(pathStr, pathStrSize / sizeof(WCHAR) - 1));
110     }
111 
112     RegCloseKey(key);
113 }
114 
getPluginPathsInDirectories(HashSet<String> & paths) const115 void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const
116 {
117     // FIXME: This should be a case insensitive set.
118     HashSet<String> uniqueFilenames;
119 
120     HANDLE hFind = INVALID_HANDLE_VALUE;
121     WIN32_FIND_DATAW findFileData;
122 
123     String oldWMPPluginPath;
124     String newWMPPluginPath;
125 
126     Vector<String>::const_iterator end = m_pluginDirectories.end();
127     for (Vector<String>::const_iterator it = m_pluginDirectories.begin(); it != end; ++it) {
128         String pattern = *it + "\\*";
129 
130         hFind = FindFirstFileW(pattern.charactersWithNullTermination(), &findFileData);
131 
132         if (hFind == INVALID_HANDLE_VALUE)
133             continue;
134 
135         do {
136             if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
137                 continue;
138 
139             String filename = String(findFileData.cFileName, wcslen(findFileData.cFileName));
140             if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) &&
141                 (!equalIgnoringCase(filename, "Plugin.dll") || !it->endsWith("Shockwave 10", false)))
142                 continue;
143 
144             String fullPath = *it + "\\" + filename;
145             if (!uniqueFilenames.add(fullPath).second)
146                 continue;
147 
148             paths.add(fullPath);
149 
150             if (equalIgnoringCase(filename, "npdsplay.dll"))
151                 oldWMPPluginPath = fullPath;
152             else if (equalIgnoringCase(filename, "np-mswmp.dll"))
153                 newWMPPluginPath = fullPath;
154 
155         } while (FindNextFileW(hFind, &findFileData) != 0);
156 
157         FindClose(hFind);
158     }
159 
160     addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
161     addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);
162 
163     // If both the old and new WMP plugin are present in the plugins set,
164     // we remove the old one so we don't end up choosing the old one.
165     if (!oldWMPPluginPath.isEmpty() && !newWMPPluginPath.isEmpty())
166         paths.remove(oldWMPPluginPath);
167 }
168 
parseVersionString(const String & versionString)169 static inline Vector<int> parseVersionString(const String& versionString)
170 {
171     Vector<int> version;
172 
173     unsigned startPos = 0;
174     unsigned endPos;
175 
176     while (startPos < versionString.length()) {
177         for (endPos = startPos; endPos < versionString.length(); ++endPos)
178             if (versionString[endPos] == '.' || versionString[endPos] == '_')
179                 break;
180 
181         int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
182         version.append(versionComponent);
183 
184         startPos = endPos + 1;
185     }
186 
187     return version;
188 }
189 
190 // This returns whether versionA is higher than versionB
compareVersions(const Vector<int> & versionA,const Vector<int> & versionB)191 static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
192 {
193     for (unsigned i = 0; i < versionA.size(); i++) {
194         if (i >= versionB.size())
195             return true;
196 
197         if (versionA[i] > versionB[i])
198             return true;
199         else if (versionA[i] < versionB[i])
200             return false;
201     }
202 
203     // If we come here, the versions are either the same or versionB has an extra component, just return false
204     return false;
205 }
206 
addMozillaPluginDirectories(Vector<String> & directories)207 static inline void addMozillaPluginDirectories(Vector<String>& directories)
208 {
209     // Enumerate all Mozilla plugin directories in the registry
210     HKEY key;
211     LONG result;
212 
213     result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Mozilla"), 0, KEY_READ, &key);
214     if (result == ERROR_SUCCESS) {
215         WCHAR name[128];
216         FILETIME lastModified;
217 
218         // Enumerate subkeys
219         for (int i = 0;; i++) {
220             DWORD nameLen = sizeof(name) / sizeof(WCHAR);
221             result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
222 
223             if (result != ERROR_SUCCESS)
224                 break;
225 
226             String extensionsPath = String(name, nameLen) + "\\Extensions";
227             HKEY extensionsKey;
228 
229             // Try opening the key
230             result = RegOpenKeyEx(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
231 
232             if (result == ERROR_SUCCESS) {
233                 // Now get the plugins directory
234                 WCHAR pluginsDirectoryStr[_MAX_PATH];
235                 DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
236                 DWORD type;
237 
238                 result = RegQueryValueEx(extensionsKey, TEXT("Plugins"), 0, &type, (LPBYTE)&pluginsDirectoryStr, &pluginsDirectorySize);
239 
240                 if (result == ERROR_SUCCESS && type == REG_SZ)
241                     directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));
242 
243                 RegCloseKey(extensionsKey);
244             }
245         }
246 
247         RegCloseKey(key);
248     }
249 }
250 
addWindowsMediaPlayerPluginDirectory(Vector<String> & directories)251 static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
252 {
253 #if !OS(WINCE)
254     // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
255     WCHAR pluginDirectoryStr[_MAX_PATH + 1];
256     DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(TEXT("%SYSTEMDRIVE%\\PFiles\\Plugins"), pluginDirectoryStr, WTF_ARRAY_LENGTH(pluginDirectoryStr));
257 
258     if (pluginDirectorySize > 0 && pluginDirectorySize <= WTF_ARRAY_LENGTH(pluginDirectoryStr))
259         directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
260 #endif
261 
262     DWORD type;
263     WCHAR installationDirectoryStr[_MAX_PATH];
264     DWORD installationDirectorySize = sizeof(installationDirectoryStr);
265 
266     HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\MediaPlayer"), TEXT("Installation Directory"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
267 
268     if (result == ERROR_SUCCESS && type == REG_SZ)
269         directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
270 }
271 
addQuickTimePluginDirectory(Vector<String> & directories)272 static inline void addQuickTimePluginDirectory(Vector<String>& directories)
273 {
274     DWORD type;
275     WCHAR installationDirectoryStr[_MAX_PATH];
276     DWORD installationDirectorySize = sizeof(installationDirectoryStr);
277 
278     HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Apple Computer, Inc.\\QuickTime"), TEXT("InstallDir"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
279 
280     if (result == ERROR_SUCCESS && type == REG_SZ) {
281         String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
282         directories.append(pluginDir);
283     }
284 }
285 
addAdobeAcrobatPluginDirectory(Vector<String> & directories)286 static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
287 {
288     HKEY key;
289     HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Adobe\\Acrobat Reader"), 0, KEY_READ, &key);
290     if (result != ERROR_SUCCESS)
291         return;
292 
293     WCHAR name[128];
294     FILETIME lastModified;
295 
296     Vector<int> latestAcrobatVersion;
297     String latestAcrobatVersionString;
298 
299     // Enumerate subkeys
300     for (int i = 0;; i++) {
301         DWORD nameLen = sizeof(name) / sizeof(WCHAR);
302         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
303 
304         if (result != ERROR_SUCCESS)
305             break;
306 
307         Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
308         if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
309             latestAcrobatVersion = acrobatVersion;
310             latestAcrobatVersionString = String(name, nameLen);
311         }
312     }
313 
314     if (!latestAcrobatVersionString.isNull()) {
315         DWORD type;
316         WCHAR acrobatInstallPathStr[_MAX_PATH];
317         DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
318 
319         String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
320         result = SHGetValue(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, (LPBYTE)acrobatInstallPathStr, &acrobatInstallPathSize);
321 
322         if (result == ERROR_SUCCESS) {
323             String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
324             directories.append(acrobatPluginDirectory);
325         }
326     }
327 
328     RegCloseKey(key);
329 }
330 
addJavaPluginDirectory(Vector<String> & directories)331 static inline void addJavaPluginDirectory(Vector<String>& directories)
332 {
333     HKEY key;
334     HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\JavaSoft\\Java Plug-in"), 0, KEY_READ, &key);
335     if (result != ERROR_SUCCESS)
336         return;
337 
338     WCHAR name[128];
339     FILETIME lastModified;
340 
341     Vector<int> latestJavaVersion;
342     String latestJavaVersionString;
343 
344     // Enumerate subkeys
345     for (int i = 0;; i++) {
346         DWORD nameLen = sizeof(name) / sizeof(WCHAR);
347         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
348 
349         if (result != ERROR_SUCCESS)
350             break;
351 
352         Vector<int> javaVersion = parseVersionString(String(name, nameLen));
353         if (compareVersions(javaVersion, latestJavaVersion)) {
354             latestJavaVersion = javaVersion;
355             latestJavaVersionString = String(name, nameLen);
356         }
357     }
358 
359     if (!latestJavaVersionString.isEmpty()) {
360         DWORD type;
361         WCHAR javaInstallPathStr[_MAX_PATH];
362         DWORD javaInstallPathSize = sizeof(javaInstallPathStr);
363         DWORD useNewPluginValue;
364         DWORD useNewPluginSize;
365 
366         String javaPluginKeyPath = "Software\\JavaSoft\\Java Plug-in\\" + latestJavaVersionString;
367         result = SHGetValue(HKEY_LOCAL_MACHINE, javaPluginKeyPath.charactersWithNullTermination(), TEXT("UseNewJavaPlugin"), &type, (LPVOID)&useNewPluginValue, &useNewPluginSize);
368 
369         if (result == ERROR_SUCCESS && useNewPluginValue == 1) {
370             result = SHGetValue(HKEY_LOCAL_MACHINE, javaPluginKeyPath.charactersWithNullTermination(), TEXT("JavaHome"), &type, (LPBYTE)javaInstallPathStr, &javaInstallPathSize);
371             if (result == ERROR_SUCCESS) {
372                 String javaPluginDirectory = String(javaInstallPathStr, javaInstallPathSize / sizeof(WCHAR) - 1) + "\\bin\\new_plugin";
373                 directories.append(javaPluginDirectory);
374             }
375         }
376     }
377 
378     RegCloseKey(key);
379 }
380 
safariPluginsDirectory()381 static inline String safariPluginsDirectory()
382 {
383     WCHAR moduleFileNameStr[_MAX_PATH];
384     static String pluginsDirectory;
385     static bool cachedPluginDirectory = false;
386 
387     if (!cachedPluginDirectory) {
388         cachedPluginDirectory = true;
389 
390         int moduleFileNameLen = GetModuleFileName(0, moduleFileNameStr, _MAX_PATH);
391 
392         if (!moduleFileNameLen || moduleFileNameLen == _MAX_PATH)
393             goto exit;
394 
395         if (!PathRemoveFileSpec(moduleFileNameStr))
396             goto exit;
397 
398         pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
399     }
400 exit:
401     return pluginsDirectory;
402 }
403 
addMacromediaPluginDirectories(Vector<String> & directories)404 static inline void addMacromediaPluginDirectories(Vector<String>& directories)
405 {
406 #if !OS(WINCE)
407     WCHAR systemDirectoryStr[MAX_PATH];
408 
409     if (!GetSystemDirectory(systemDirectoryStr, WTF_ARRAY_LENGTH(systemDirectoryStr)))
410         return;
411 
412     WCHAR macromediaDirectoryStr[MAX_PATH];
413 
414     PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Flash"));
415     directories.append(macromediaDirectoryStr);
416 
417     PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Shockwave 10"));
418     directories.append(macromediaDirectoryStr);
419 #endif
420 }
421 
defaultPluginDirectories()422 Vector<String> PluginDatabase::defaultPluginDirectories()
423 {
424     Vector<String> directories;
425     String ourDirectory = safariPluginsDirectory();
426 
427     if (!ourDirectory.isNull())
428         directories.append(ourDirectory);
429     addQuickTimePluginDirectory(directories);
430     addAdobeAcrobatPluginDirectory(directories);
431     addMozillaPluginDirectories(directories);
432     addWindowsMediaPlayerPluginDirectory(directories);
433     addMacromediaPluginDirectories(directories);
434 #if PLATFORM(QT)
435     addJavaPluginDirectory(directories);
436 #endif
437 
438     return directories;
439 }
440 
isPreferredPluginDirectory(const String & directory)441 bool PluginDatabase::isPreferredPluginDirectory(const String& directory)
442 {
443     String ourDirectory = safariPluginsDirectory();
444 
445     if (!ourDirectory.isNull() && !directory.isNull())
446         return ourDirectory == directory;
447 
448     return false;
449 }
450 
451 }
452