| /* |
| * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
| * Copyright (C) 2008 Collabora, Ltd. All rights reserved. |
| * Copyright (C) 2008-2009 Torch Mobile, Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "PluginDatabase.h" |
| |
| #include "PluginPackage.h" |
| #include <WebCore/Frame.h> |
| #include <wtf/URL.h> |
| #include <wtf/WindowsExtras.h> |
| |
| namespace WebCore { |
| |
| static inline void addPluginPathsFromRegistry(HKEY rootKey, HashSet<String>& paths) |
| { |
| HKEY key; |
| HRESULT result = RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key); |
| |
| if (result != ERROR_SUCCESS) |
| return; |
| |
| wchar_t name[128]; |
| FILETIME lastModified; |
| |
| // Enumerate subkeys |
| for (int i = 0;; i++) { |
| DWORD nameLen = WTF_ARRAY_LENGTH(name); |
| result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified); |
| |
| if (result != ERROR_SUCCESS) |
| break; |
| |
| WCHAR pathStr[_MAX_PATH]; |
| DWORD pathStrSize = sizeof(pathStr); |
| DWORD type; |
| |
| result = getRegistryValue(key, name, L"Path", &type, pathStr, &pathStrSize); |
| if (result != ERROR_SUCCESS || type != REG_SZ) |
| continue; |
| |
| paths.add(String(pathStr, pathStrSize / sizeof(WCHAR) - 1)); |
| } |
| |
| RegCloseKey(key); |
| } |
| |
| #if ENABLE(NETSCAPE_PLUGIN_API) |
| void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const |
| { |
| // FIXME: This should be a case insensitive set. |
| HashSet<String> uniqueFilenames; |
| |
| HANDLE hFind = INVALID_HANDLE_VALUE; |
| WIN32_FIND_DATAW findFileData; |
| |
| String oldWMPPluginPath; |
| String newWMPPluginPath; |
| |
| for (auto& directory : m_pluginDirectories) { |
| String pattern = directory + "\\*"; |
| |
| hFind = FindFirstFileW(pattern.wideCharacters().data(), &findFileData); |
| |
| if (hFind == INVALID_HANDLE_VALUE) |
| continue; |
| |
| do { |
| if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
| continue; |
| |
| String filename(findFileData.cFileName, wcslen(findFileData.cFileName)); |
| if (!(startsWithLettersIgnoringASCIICase(filename, "np") && filename.endsWithIgnoringASCIICase("dll")) |
| && !(equalLettersIgnoringASCIICase(filename, "plugin.dll") && directory.endsWithIgnoringASCIICase("shockwave 10"))) |
| continue; |
| |
| String fullPath = directory + "\\" + filename; |
| if (!uniqueFilenames.add(fullPath).isNewEntry) |
| continue; |
| |
| paths.add(fullPath); |
| |
| if (equalLettersIgnoringASCIICase(filename, "npdsplay.dll")) |
| oldWMPPluginPath = fullPath; |
| else if (equalLettersIgnoringASCIICase(filename, "np-mswmp.dll")) |
| newWMPPluginPath = fullPath; |
| |
| } while (FindNextFileW(hFind, &findFileData) != 0); |
| |
| FindClose(hFind); |
| } |
| |
| addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths); |
| addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths); |
| |
| // If both the old and new WMP plugin are present in the plugins set, |
| // we remove the old one so we don't end up choosing the old one. |
| if (!oldWMPPluginPath.isEmpty() && !newWMPPluginPath.isEmpty()) |
| paths.remove(oldWMPPluginPath); |
| } |
| #endif |
| |
| static inline Vector<int> parseVersionString(const String& versionString) |
| { |
| Vector<int> version; |
| |
| unsigned startPos = 0; |
| unsigned endPos; |
| |
| while (startPos < versionString.length()) { |
| for (endPos = startPos; endPos < versionString.length(); ++endPos) |
| if (versionString[endPos] == '.' || versionString[endPos] == '_') |
| break; |
| |
| int versionComponent = versionString.substring(startPos, endPos - startPos).toInt(); |
| version.append(versionComponent); |
| |
| startPos = endPos + 1; |
| } |
| |
| return version; |
| } |
| |
| // This returns whether versionA is higher than versionB |
| static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB) |
| { |
| for (unsigned i = 0; i < versionA.size(); i++) { |
| if (i >= versionB.size()) |
| return true; |
| |
| if (versionA[i] > versionB[i]) |
| return true; |
| else if (versionA[i] < versionB[i]) |
| return false; |
| } |
| |
| // If we come here, the versions are either the same or versionB has an extra component, just return false |
| return false; |
| } |
| |
| static inline void addMozillaPluginDirectories(Vector<String>& directories) |
| { |
| // Enumerate all Mozilla plugin directories in the registry |
| HKEY key; |
| LONG result; |
| |
| result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Mozilla"), 0, KEY_READ, &key); |
| if (result == ERROR_SUCCESS) { |
| WCHAR name[128]; |
| FILETIME lastModified; |
| |
| // Enumerate subkeys |
| for (int i = 0;; i++) { |
| DWORD nameLen = sizeof(name) / sizeof(WCHAR); |
| result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified); |
| |
| if (result != ERROR_SUCCESS) |
| break; |
| |
| String extensionsPath = String(name, nameLen) + "\\Extensions"; |
| HKEY extensionsKey; |
| |
| // Try opening the key |
| result = RegOpenKeyEx(key, extensionsPath.wideCharacters().data(), 0, KEY_READ, &extensionsKey); |
| |
| if (result == ERROR_SUCCESS) { |
| // Now get the plugins directory |
| WCHAR pluginsDirectoryStr[_MAX_PATH]; |
| DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr); |
| DWORD type; |
| |
| result = RegQueryValueEx(extensionsKey, TEXT("Plugins"), 0, &type, (LPBYTE)&pluginsDirectoryStr, &pluginsDirectorySize); |
| |
| if (result == ERROR_SUCCESS && type == REG_SZ) |
| directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1)); |
| |
| RegCloseKey(extensionsKey); |
| } |
| } |
| |
| RegCloseKey(key); |
| } |
| } |
| |
| static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories) |
| { |
| // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs |
| WCHAR pluginDirectoryStr[_MAX_PATH + 1]; |
| DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(TEXT("%SYSTEMDRIVE%\\PFiles\\Plugins"), pluginDirectoryStr, WTF_ARRAY_LENGTH(pluginDirectoryStr)); |
| |
| if (pluginDirectorySize > 0 && pluginDirectorySize <= WTF_ARRAY_LENGTH(pluginDirectoryStr)) |
| directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1)); |
| |
| DWORD type; |
| WCHAR installationDirectoryStr[_MAX_PATH]; |
| DWORD installationDirectorySize = sizeof(installationDirectoryStr); |
| |
| HRESULT result = getRegistryValue(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\MediaPlayer", L"Installation Directory", &type, &installationDirectoryStr, &installationDirectorySize); |
| |
| if (result == ERROR_SUCCESS && type == REG_SZ) |
| directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1)); |
| } |
| |
| static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories) |
| { |
| HKEY key; |
| HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Adobe\\Acrobat Reader"), 0, KEY_READ, &key); |
| if (result != ERROR_SUCCESS) |
| return; |
| |
| WCHAR name[128]; |
| FILETIME lastModified; |
| |
| Vector<int> latestAcrobatVersion; |
| String latestAcrobatVersionString; |
| |
| // Enumerate subkeys |
| for (int i = 0;; i++) { |
| DWORD nameLen = sizeof(name) / sizeof(WCHAR); |
| result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified); |
| |
| if (result != ERROR_SUCCESS) |
| break; |
| |
| Vector<int> acrobatVersion = parseVersionString(String(name, nameLen)); |
| if (compareVersions(acrobatVersion, latestAcrobatVersion)) { |
| latestAcrobatVersion = acrobatVersion; |
| latestAcrobatVersionString = String(name, nameLen); |
| } |
| } |
| |
| if (!latestAcrobatVersionString.isNull()) { |
| DWORD type; |
| WCHAR acrobatInstallPathStr[_MAX_PATH]; |
| DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr); |
| |
| String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath"; |
| result = getRegistryValue(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.wideCharacters().data(), 0, &type, acrobatInstallPathStr, &acrobatInstallPathSize); |
| |
| if (result == ERROR_SUCCESS) { |
| String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser"; |
| directories.append(acrobatPluginDirectory); |
| } |
| } |
| |
| RegCloseKey(key); |
| } |
| |
| static inline String safariPluginsDirectory() |
| { |
| WCHAR moduleFileNameStr[_MAX_PATH]; |
| static String pluginsDirectory; |
| static bool cachedPluginDirectory = false; |
| |
| if (!cachedPluginDirectory) { |
| cachedPluginDirectory = true; |
| |
| int moduleFileNameLen = GetModuleFileName(0, moduleFileNameStr, _MAX_PATH); |
| |
| if (!moduleFileNameLen || moduleFileNameLen == _MAX_PATH) |
| goto exit; |
| |
| if (!PathRemoveFileSpec(moduleFileNameStr)) |
| goto exit; |
| |
| pluginsDirectory = String(moduleFileNameStr) + "\\Plugins"; |
| } |
| exit: |
| return pluginsDirectory; |
| } |
| |
| static inline void addMacromediaPluginDirectories(Vector<String>& directories) |
| { |
| WCHAR systemDirectoryStr[MAX_PATH]; |
| |
| if (!GetSystemDirectory(systemDirectoryStr, WTF_ARRAY_LENGTH(systemDirectoryStr))) |
| return; |
| |
| WCHAR macromediaDirectoryStr[MAX_PATH]; |
| |
| PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Flash")); |
| directories.append(macromediaDirectoryStr); |
| |
| PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Shockwave 10")); |
| directories.append(macromediaDirectoryStr); |
| } |
| |
| #if ENABLE(NETSCAPE_PLUGIN_API) |
| Vector<String> PluginDatabase::defaultPluginDirectories() |
| { |
| Vector<String> directories; |
| String ourDirectory = safariPluginsDirectory(); |
| |
| if (!ourDirectory.isNull()) |
| directories.append(ourDirectory); |
| addAdobeAcrobatPluginDirectory(directories); |
| addMozillaPluginDirectories(directories); |
| addWindowsMediaPlayerPluginDirectory(directories); |
| addMacromediaPluginDirectories(directories); |
| |
| return directories; |
| } |
| |
| bool PluginDatabase::isPreferredPluginDirectory(const String& directory) |
| { |
| String ourDirectory = safariPluginsDirectory(); |
| |
| if (!ourDirectory.isNull() && !directory.isNull()) |
| return ourDirectory == directory; |
| |
| return false; |
| } |
| #endif |
| |
| } |