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.
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
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.
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.
29
#include "PluginDatabase.h"
33
#include "PluginPackage.h"
34
#include "WindowsExtras.h"
37
// WINCE doesn't support Registry Key Access Rights. The parameter should always be 0
38
#ifndef KEY_ENUMERATE_SUB_KEYS
39
#define KEY_ENUMERATE_SUB_KEYS 0
42
BOOL PathRemoveFileSpec(LPWSTR moduleFileNameStr)
44
if (!*moduleFileNameStr)
48
LPWSTR curPos = moduleFileNameStr;
50
if (*curPos == L'/' || *curPos == L'\\')
54
if (lastPos == curPos - 1)
60
moduleFileNameStr[0] = L'\\';
61
moduleFileNameStr[1] = 0;
70
static inline void addPluginPathsFromRegistry(HKEY rootKey, HashSet<String>& paths)
73
HRESULT result = RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key);
75
if (result != ERROR_SUCCESS)
79
FILETIME lastModified;
82
for (int i = 0;; i++) {
83
DWORD nameLen = WTF_ARRAY_LENGTH(name);
84
result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
86
if (result != ERROR_SUCCESS)
89
WCHAR pathStr[_MAX_PATH];
90
DWORD pathStrSize = sizeof(pathStr);
93
result = getRegistryValue(key, name, L"Path", &type, pathStr, &pathStrSize);
94
if (result != ERROR_SUCCESS || type != REG_SZ)
97
paths.add(String(pathStr, pathStrSize / sizeof(WCHAR) - 1));
103
void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const
105
// FIXME: This should be a case insensitive set.
106
HashSet<String> uniqueFilenames;
108
HANDLE hFind = INVALID_HANDLE_VALUE;
109
WIN32_FIND_DATAW findFileData;
111
String oldWMPPluginPath;
112
String newWMPPluginPath;
114
Vector<String>::const_iterator end = m_pluginDirectories.end();
115
for (Vector<String>::const_iterator it = m_pluginDirectories.begin(); it != end; ++it) {
116
String pattern = *it + "\\*";
118
hFind = FindFirstFileW(pattern.charactersWithNullTermination(), &findFileData);
120
if (hFind == INVALID_HANDLE_VALUE)
124
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
127
String filename = String(findFileData.cFileName, wcslen(findFileData.cFileName));
128
if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) &&
129
(!equalIgnoringCase(filename, "Plugin.dll") || !it->endsWith("Shockwave 10", false)))
132
String fullPath = *it + "\\" + filename;
133
if (!uniqueFilenames.add(fullPath).isNewEntry)
138
if (equalIgnoringCase(filename, "npdsplay.dll"))
139
oldWMPPluginPath = fullPath;
140
else if (equalIgnoringCase(filename, "np-mswmp.dll"))
141
newWMPPluginPath = fullPath;
143
} while (FindNextFileW(hFind, &findFileData) != 0);
148
addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
149
addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);
151
// If both the old and new WMP plugin are present in the plugins set,
152
// we remove the old one so we don't end up choosing the old one.
153
if (!oldWMPPluginPath.isEmpty() && !newWMPPluginPath.isEmpty())
154
paths.remove(oldWMPPluginPath);
157
static inline Vector<int> parseVersionString(const String& versionString)
161
unsigned startPos = 0;
164
while (startPos < versionString.length()) {
165
for (endPos = startPos; endPos < versionString.length(); ++endPos)
166
if (versionString[endPos] == '.' || versionString[endPos] == '_')
169
int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
170
version.append(versionComponent);
172
startPos = endPos + 1;
178
// This returns whether versionA is higher than versionB
179
static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
181
for (unsigned i = 0; i < versionA.size(); i++) {
182
if (i >= versionB.size())
185
if (versionA[i] > versionB[i])
187
else if (versionA[i] < versionB[i])
191
// If we come here, the versions are either the same or versionB has an extra component, just return false
195
static inline void addMozillaPluginDirectories(Vector<String>& directories)
197
// Enumerate all Mozilla plugin directories in the registry
201
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Mozilla"), 0, KEY_READ, &key);
202
if (result == ERROR_SUCCESS) {
204
FILETIME lastModified;
207
for (int i = 0;; i++) {
208
DWORD nameLen = sizeof(name) / sizeof(WCHAR);
209
result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
211
if (result != ERROR_SUCCESS)
214
String extensionsPath = String(name, nameLen) + "\\Extensions";
217
// Try opening the key
218
result = RegOpenKeyEx(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
220
if (result == ERROR_SUCCESS) {
221
// Now get the plugins directory
222
WCHAR pluginsDirectoryStr[_MAX_PATH];
223
DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
226
result = RegQueryValueEx(extensionsKey, TEXT("Plugins"), 0, &type, (LPBYTE)&pluginsDirectoryStr, &pluginsDirectorySize);
228
if (result == ERROR_SUCCESS && type == REG_SZ)
229
directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));
231
RegCloseKey(extensionsKey);
239
static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
242
// The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
243
WCHAR pluginDirectoryStr[_MAX_PATH + 1];
244
DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(TEXT("%SYSTEMDRIVE%\\PFiles\\Plugins"), pluginDirectoryStr, WTF_ARRAY_LENGTH(pluginDirectoryStr));
246
if (pluginDirectorySize > 0 && pluginDirectorySize <= WTF_ARRAY_LENGTH(pluginDirectoryStr))
247
directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
251
WCHAR installationDirectoryStr[_MAX_PATH];
252
DWORD installationDirectorySize = sizeof(installationDirectoryStr);
254
HRESULT result = getRegistryValue(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\MediaPlayer", L"Installation Directory", &type, &installationDirectoryStr, &installationDirectorySize);
256
if (result == ERROR_SUCCESS && type == REG_SZ)
257
directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
260
static inline void addQuickTimePluginDirectory(Vector<String>& directories)
263
WCHAR installationDirectoryStr[_MAX_PATH];
264
DWORD installationDirectorySize = sizeof(installationDirectoryStr);
266
HRESULT result = getRegistryValue(HKEY_LOCAL_MACHINE, L"Software\\Apple Computer, Inc.\\QuickTime", L"InstallDir", &type, &installationDirectoryStr, &installationDirectorySize);
268
if (result == ERROR_SUCCESS && type == REG_SZ) {
269
String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
270
directories.append(pluginDir);
274
static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
277
HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Adobe\\Acrobat Reader"), 0, KEY_READ, &key);
278
if (result != ERROR_SUCCESS)
282
FILETIME lastModified;
284
Vector<int> latestAcrobatVersion;
285
String latestAcrobatVersionString;
288
for (int i = 0;; i++) {
289
DWORD nameLen = sizeof(name) / sizeof(WCHAR);
290
result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
292
if (result != ERROR_SUCCESS)
295
Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
296
if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
297
latestAcrobatVersion = acrobatVersion;
298
latestAcrobatVersionString = String(name, nameLen);
302
if (!latestAcrobatVersionString.isNull()) {
304
WCHAR acrobatInstallPathStr[_MAX_PATH];
305
DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
307
String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
308
result = getRegistryValue(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, acrobatInstallPathStr, &acrobatInstallPathSize);
310
if (result == ERROR_SUCCESS) {
311
String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
312
directories.append(acrobatPluginDirectory);
319
static inline void addJavaPluginDirectory(Vector<String>& directories)
322
HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\JavaSoft\\Java Plug-in"), 0, KEY_READ, &key);
323
if (result != ERROR_SUCCESS)
327
FILETIME lastModified;
329
Vector<int> latestJavaVersion;
330
String latestJavaVersionString;
333
for (int i = 0;; i++) {
334
DWORD nameLen = sizeof(name) / sizeof(WCHAR);
335
result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
337
if (result != ERROR_SUCCESS)
340
Vector<int> javaVersion = parseVersionString(String(name, nameLen));
341
if (compareVersions(javaVersion, latestJavaVersion)) {
342
latestJavaVersion = javaVersion;
343
latestJavaVersionString = String(name, nameLen);
347
if (!latestJavaVersionString.isEmpty()) {
349
WCHAR javaInstallPathStr[_MAX_PATH];
350
DWORD javaInstallPathSize = sizeof(javaInstallPathStr);
351
DWORD useNewPluginValue;
352
DWORD useNewPluginSize;
354
String javaPluginKeyPath = "Software\\JavaSoft\\Java Plug-in\\" + latestJavaVersionString;
355
result = getRegistryValue(HKEY_LOCAL_MACHINE, javaPluginKeyPath.charactersWithNullTermination(), L"UseNewJavaPlugin", &type, &useNewPluginValue, &useNewPluginSize);
357
if (result == ERROR_SUCCESS && useNewPluginValue == 1) {
358
result = getRegistryValue(HKEY_LOCAL_MACHINE, javaPluginKeyPath.charactersWithNullTermination(), L"JavaHome", &type, javaInstallPathStr, &javaInstallPathSize);
359
if (result == ERROR_SUCCESS) {
360
String javaPluginDirectory = String(javaInstallPathStr, javaInstallPathSize / sizeof(WCHAR) - 1) + "\\bin\\new_plugin";
361
directories.append(javaPluginDirectory);
369
static inline String safariPluginsDirectory()
371
WCHAR moduleFileNameStr[_MAX_PATH];
372
static String pluginsDirectory;
373
static bool cachedPluginDirectory = false;
375
if (!cachedPluginDirectory) {
376
cachedPluginDirectory = true;
378
int moduleFileNameLen = GetModuleFileName(0, moduleFileNameStr, _MAX_PATH);
380
if (!moduleFileNameLen || moduleFileNameLen == _MAX_PATH)
383
if (!PathRemoveFileSpec(moduleFileNameStr))
386
pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
389
return pluginsDirectory;
392
static inline void addMacromediaPluginDirectories(Vector<String>& directories)
395
WCHAR systemDirectoryStr[MAX_PATH];
397
if (!GetSystemDirectory(systemDirectoryStr, WTF_ARRAY_LENGTH(systemDirectoryStr)))
400
WCHAR macromediaDirectoryStr[MAX_PATH];
402
PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Flash"));
403
directories.append(macromediaDirectoryStr);
405
PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Shockwave 10"));
406
directories.append(macromediaDirectoryStr);
411
static inline void addQtWebKitPluginPath(Vector<String>& directories)
413
Vector<String> qtPaths;
414
String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").constData());
415
qtPath.split(UChar(';'), false, qtPaths);
416
directories.append(qtPaths);
420
Vector<String> PluginDatabase::defaultPluginDirectories()
422
Vector<String> directories;
423
String ourDirectory = safariPluginsDirectory();
425
if (!ourDirectory.isNull())
426
directories.append(ourDirectory);
427
addQuickTimePluginDirectory(directories);
428
addAdobeAcrobatPluginDirectory(directories);
429
addMozillaPluginDirectories(directories);
430
addWindowsMediaPlayerPluginDirectory(directories);
431
addMacromediaPluginDirectories(directories);
433
addJavaPluginDirectory(directories);
434
addQtWebKitPluginPath(directories);
440
bool PluginDatabase::isPreferredPluginDirectory(const String& directory)
442
String ourDirectory = safariPluginsDirectory();
444
if (!ourDirectory.isNull() && !directory.isNull())
445
return ourDirectory == directory;