2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "PluginDatabase.h"
32 #include "PluginPackage.h"
38 static inline void addPluginsFromRegistry(HKEY rootKey, PluginSet& plugins)
41 HRESULT result = RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key);
43 if (result != ERROR_SUCCESS)
47 FILETIME lastModified;
50 for (int i = 0;; i++) {
51 DWORD nameLen = _countof(name);
52 result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
54 if (result != ERROR_SUCCESS)
57 WCHAR pathStr[_MAX_PATH];
58 DWORD pathStrSize = sizeof(pathStr);
61 result = SHGetValue(key, name, TEXT("Path"), &type, (LPBYTE)pathStr, &pathStrSize);
62 if (result != ERROR_SUCCESS || type != REG_SZ)
65 String path(pathStr, pathStrSize / sizeof(WCHAR) - 1);
68 if (!getFileModificationTime(path, modifiedTime))
71 RefPtr<PluginPackage> package = PluginPackage::createPackage(path, modifiedTime);
80 PluginSet PluginDatabase::getPluginsInPaths() const
82 // FIXME: This should be a case insensitive set.
83 HashSet<String> uniqueFilenames;
86 HANDLE hFind = INVALID_HANDLE_VALUE;
87 WIN32_FIND_DATAW findFileData;
89 RefPtr<PluginPackage> oldWMPPlugin;
90 RefPtr<PluginPackage> newWMPPlugin;
92 Vector<String>::const_iterator end = m_pluginPaths.end();
93 for (Vector<String>::const_iterator it = m_pluginPaths.begin(); it != end; ++it) {
94 String pattern = *it + "\\*";
96 hFind = FindFirstFileW(pattern.charactersWithNullTermination(), &findFileData);
98 if (hFind == INVALID_HANDLE_VALUE)
102 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
105 String filename = String(findFileData.cFileName, wcslen(findFileData.cFileName));
106 if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) &&
107 (!equalIgnoringCase(filename, "Plugin.dll") || !it->endsWith("Shockwave 10", false)))
110 String fullPath = *it + "\\" + filename;
111 if (!uniqueFilenames.add(fullPath).second)
115 if (!getFileModificationTime(fullPath, modifiedTime))
118 RefPtr<PluginPackage> pluginPackage = PluginPackage::createPackage(fullPath, modifiedTime);
121 plugins.add(pluginPackage);
123 if (equalIgnoringCase(filename, "npdsplay.dll"))
124 oldWMPPlugin = pluginPackage;
125 else if (equalIgnoringCase(filename, "np-mswmp.dll"))
126 newWMPPlugin = pluginPackage;
129 } while (FindNextFileW(hFind, &findFileData) != 0);
134 addPluginsFromRegistry(HKEY_LOCAL_MACHINE, plugins);
135 addPluginsFromRegistry(HKEY_CURRENT_USER, plugins);
137 // If both the old and new WMP plugin are present in the plugins set,
138 // we remove the old one so we don't end up choosing the old one.
139 if (oldWMPPlugin && newWMPPlugin)
140 plugins.remove(oldWMPPlugin);
145 static inline Vector<int> parseVersionString(const String& versionString)
149 unsigned startPos = 0;
152 while (startPos < versionString.length()) {
153 for (endPos = startPos; endPos < versionString.length(); ++endPos)
154 if (versionString[endPos] == '.' || versionString[endPos] == '_')
157 int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
158 version.append(versionComponent);
160 startPos = endPos + 1;
166 // This returns whether versionA is higher than versionB
167 static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
169 for (unsigned i = 0; i < versionA.size(); i++) {
170 if (i >= versionB.size())
173 if (versionA[i] > versionB[i])
175 else if (versionA[i] < versionB[i])
179 // If we come here, the versions are either the same or versionB has an extra component, just return false
183 static inline void addMozillaPluginPaths(Vector<String>& paths)
185 // Enumerate all Mozilla plugin directories in the registry
189 result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Mozilla"), 0, KEY_READ, &key);
190 if (result == ERROR_SUCCESS) {
192 FILETIME lastModified;
195 for (int i = 0;; i++) {
196 DWORD nameLen = sizeof(name) / sizeof(WCHAR);
197 result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
199 if (result != ERROR_SUCCESS)
202 String extensionsPath = String(name, nameLen) + "\\Extensions";
205 // Try opening the key
206 result = RegOpenKeyEx(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
208 if (result == ERROR_SUCCESS) {
209 // Now get the plugins path
210 WCHAR pluginsPathStr[_MAX_PATH];
211 DWORD pluginsPathSize = sizeof(pluginsPathStr);
214 result = RegQueryValueEx(extensionsKey, TEXT("Plugins"), 0, &type, (LPBYTE)&pluginsPathStr, &pluginsPathSize);
216 if (result == ERROR_SUCCESS && type == REG_SZ)
217 paths.append(String(pluginsPathStr, pluginsPathSize / sizeof(WCHAR) - 1));
219 RegCloseKey(extensionsKey);
227 static inline void addWindowsMediaPlayerPluginPath(Vector<String>& paths)
229 // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
230 WCHAR pluginDirectoryStr[_MAX_PATH + 1];
231 DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(TEXT("%SYSTEMDRIVE%\\PFiles\\Plugins"), pluginDirectoryStr, _countof(pluginDirectoryStr));
233 if (pluginDirectorySize > 0 && pluginDirectorySize <= _countof(pluginDirectoryStr))
234 paths.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
237 WCHAR installationDirectoryStr[_MAX_PATH];
238 DWORD installationDirectorySize = sizeof(installationDirectoryStr);
240 HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\MediaPlayer"), TEXT("Installation Directory"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
242 if (result == ERROR_SUCCESS && type == REG_SZ)
243 paths.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
246 static inline void addQuickTimePluginPath(Vector<String>& paths)
249 WCHAR installationDirectoryStr[_MAX_PATH];
250 DWORD installationDirectorySize = sizeof(installationDirectoryStr);
252 HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Apple Computer, Inc.\\QuickTime"), TEXT("InstallDir"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
254 if (result == ERROR_SUCCESS && type == REG_SZ) {
255 String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
256 paths.append(pluginDir);
260 static inline void addAdobeAcrobatPluginPath(Vector<String>& paths)
263 HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Adobe\\Acrobat Reader"), 0, KEY_READ, &key);
264 if (result != ERROR_SUCCESS)
268 FILETIME lastModified;
270 Vector<int> latestAcrobatVersion;
271 String latestAcrobatVersionString;
274 for (int i = 0;; i++) {
275 DWORD nameLen = sizeof(name) / sizeof(WCHAR);
276 result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
278 if (result != ERROR_SUCCESS)
281 Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
282 if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
283 latestAcrobatVersion = acrobatVersion;
284 latestAcrobatVersionString = String(name, nameLen);
288 if (!latestAcrobatVersionString.isNull()) {
290 WCHAR acrobatInstallPathStr[_MAX_PATH];
291 DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
293 String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
294 result = SHGetValue(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, (LPBYTE)acrobatInstallPathStr, &acrobatInstallPathSize);
296 if (result == ERROR_SUCCESS) {
297 String acrobatPluginPath = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
298 paths.append(acrobatPluginPath);
305 static inline String safariPluginsPath()
307 WCHAR moduleFileNameStr[_MAX_PATH];
308 static String pluginsPath;
309 static bool cachedPluginPath = false;
311 if (!cachedPluginPath) {
312 cachedPluginPath = true;
314 int moduleFileNameLen = GetModuleFileName(0, moduleFileNameStr, _MAX_PATH);
316 if (!moduleFileNameLen || moduleFileNameLen == _MAX_PATH)
319 if (!PathRemoveFileSpec(moduleFileNameStr))
322 pluginsPath = String(moduleFileNameStr) + "\\Plugins";
328 static inline void addMacromediaPluginPaths(Vector<String>& paths)
330 WCHAR systemDirectoryStr[MAX_PATH];
332 if (GetSystemDirectory(systemDirectoryStr, _countof(systemDirectoryStr)) == 0)
335 WCHAR macromediaDirectoryStr[MAX_PATH];
337 PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Flash"));
338 paths.append(macromediaDirectoryStr);
340 PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Shockwave 10"));
341 paths.append(macromediaDirectoryStr);
344 Vector<String> PluginDatabase::defaultPluginPaths()
346 Vector<String> paths;
347 String ourPath = safariPluginsPath();
349 if (!ourPath.isNull())
350 paths.append(ourPath);
351 addQuickTimePluginPath(paths);
352 addAdobeAcrobatPluginPath(paths);
353 addMozillaPluginPaths(paths);
354 addWindowsMediaPlayerPluginPath(paths);
355 addMacromediaPluginPaths(paths);
360 bool PluginDatabase::isPreferredPluginPath(const String& path)
362 String ourPath = safariPluginsPath();
364 if (!ourPath.isNull() && !path.isNull())
365 return ourPath == path;