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