PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp

https://bitbucket.org/zenoalbisser/webkit
C++ | 408 lines | 290 code | 71 blank | 47 comment | 70 complexity | 22538bede50dcb39c06c0eaa67a0de37 MD5 | raw file
  1. /*
  2. * Copyright (C) 2010 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  14. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  17. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  23. * THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "PluginInfoStore.h"
  27. #include "NetscapePluginModule.h"
  28. #include <WebCore/FileSystem.h>
  29. #include <WebCore/PathWalker.h>
  30. #include <shlwapi.h>
  31. using namespace WebCore;
  32. namespace WebKit {
  33. static inline Vector<int> parseVersionString(const String& versionString)
  34. {
  35. Vector<int> version;
  36. unsigned startPos = 0;
  37. unsigned endPos;
  38. while (startPos < versionString.length()) {
  39. for (endPos = startPos; endPos < versionString.length(); ++endPos)
  40. if (versionString[endPos] == '.' || versionString[endPos] == '_')
  41. break;
  42. int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
  43. version.append(versionComponent);
  44. startPos = endPos + 1;
  45. }
  46. return version;
  47. }
  48. // This returns whether versionA is higher than versionB
  49. static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
  50. {
  51. for (unsigned i = 0; i < versionA.size(); i++) {
  52. if (i >= versionB.size())
  53. return true;
  54. if (versionA[i] > versionB[i])
  55. return true;
  56. else if (versionA[i] < versionB[i])
  57. return false;
  58. }
  59. // If we come here, the versions are either the same or versionB has an extra component, just return false
  60. return false;
  61. }
  62. static inline String safariPluginsDirectory()
  63. {
  64. static String pluginsDirectory;
  65. static bool cachedPluginDirectory = false;
  66. if (!cachedPluginDirectory) {
  67. cachedPluginDirectory = true;
  68. WCHAR moduleFileNameStr[MAX_PATH];
  69. int moduleFileNameLen = ::GetModuleFileNameW(0, moduleFileNameStr, WTF_ARRAY_LENGTH(moduleFileNameStr));
  70. if (!moduleFileNameLen || moduleFileNameLen == WTF_ARRAY_LENGTH(moduleFileNameStr))
  71. return pluginsDirectory;
  72. if (!::PathRemoveFileSpecW(moduleFileNameStr))
  73. return pluginsDirectory;
  74. pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
  75. }
  76. return pluginsDirectory;
  77. }
  78. static inline void addMozillaPluginDirectories(Vector<String>& directories)
  79. {
  80. // Enumerate all Mozilla plugin directories in the registry
  81. HKEY key;
  82. LONG result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Mozilla", 0, KEY_READ, &key);
  83. if (result != ERROR_SUCCESS)
  84. return;
  85. WCHAR name[128];
  86. FILETIME lastModified;
  87. // Enumerate subkeys
  88. for (int i = 0;; i++) {
  89. DWORD nameLen = WTF_ARRAY_LENGTH(name);
  90. result = ::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
  91. if (result != ERROR_SUCCESS)
  92. break;
  93. String extensionsPath = String(name, nameLen) + "\\Extensions";
  94. HKEY extensionsKey;
  95. // Try opening the key
  96. result = ::RegOpenKeyExW(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
  97. if (result == ERROR_SUCCESS) {
  98. // Now get the plugins directory
  99. WCHAR pluginsDirectoryStr[MAX_PATH];
  100. DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
  101. DWORD type;
  102. result = ::RegQueryValueExW(extensionsKey, L"Plugins", 0, &type, reinterpret_cast<LPBYTE>(&pluginsDirectoryStr), &pluginsDirectorySize);
  103. if (result == ERROR_SUCCESS && type == REG_SZ)
  104. directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));
  105. ::RegCloseKey(extensionsKey);
  106. }
  107. }
  108. ::RegCloseKey(key);
  109. }
  110. static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
  111. {
  112. // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
  113. WCHAR pluginDirectoryStr[MAX_PATH + 1];
  114. DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(L"%SYSTEMDRIVE%\\PFiles\\Plugins", pluginDirectoryStr, WTF_ARRAY_LENGTH(pluginDirectoryStr));
  115. if (pluginDirectorySize > 0 && pluginDirectorySize <= WTF_ARRAY_LENGTH(pluginDirectoryStr))
  116. directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
  117. DWORD type;
  118. WCHAR installationDirectoryStr[MAX_PATH];
  119. DWORD installationDirectorySize = sizeof(installationDirectoryStr);
  120. HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\MediaPlayer", L"Installation Directory", &type, reinterpret_cast<LPBYTE>(&installationDirectoryStr), &installationDirectorySize);
  121. if (result == ERROR_SUCCESS && type == REG_SZ)
  122. directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
  123. }
  124. static inline void addQuickTimePluginDirectory(Vector<String>& directories)
  125. {
  126. DWORD type;
  127. WCHAR installationDirectoryStr[MAX_PATH];
  128. DWORD installationDirectorySize = sizeof(installationDirectoryStr);
  129. HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Apple Computer, Inc.\\QuickTime", L"InstallDir", &type, reinterpret_cast<LPBYTE>(&installationDirectoryStr), &installationDirectorySize);
  130. if (result == ERROR_SUCCESS && type == REG_SZ) {
  131. String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
  132. directories.append(pluginDir);
  133. }
  134. }
  135. static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
  136. {
  137. HKEY key;
  138. HRESULT result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Adobe\\Acrobat Reader", 0, KEY_READ, &key);
  139. if (result != ERROR_SUCCESS)
  140. return;
  141. WCHAR name[128];
  142. FILETIME lastModified;
  143. Vector<int> latestAcrobatVersion;
  144. String latestAcrobatVersionString;
  145. // Enumerate subkeys
  146. for (int i = 0;; i++) {
  147. DWORD nameLen = WTF_ARRAY_LENGTH(name);
  148. result = ::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
  149. if (result != ERROR_SUCCESS)
  150. break;
  151. Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
  152. if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
  153. latestAcrobatVersion = acrobatVersion;
  154. latestAcrobatVersionString = String(name, nameLen);
  155. }
  156. }
  157. if (!latestAcrobatVersionString.isNull()) {
  158. DWORD type;
  159. WCHAR acrobatInstallPathStr[MAX_PATH];
  160. DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
  161. String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
  162. result = ::SHGetValueW(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, reinterpret_cast<LPBYTE>(acrobatInstallPathStr), &acrobatInstallPathSize);
  163. if (result == ERROR_SUCCESS) {
  164. String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
  165. directories.append(acrobatPluginDirectory);
  166. }
  167. }
  168. ::RegCloseKey(key);
  169. }
  170. static inline void addMacromediaPluginDirectories(Vector<String>& directories)
  171. {
  172. #if !OS(WINCE)
  173. WCHAR systemDirectoryStr[MAX_PATH];
  174. if (!::GetSystemDirectoryW(systemDirectoryStr, WTF_ARRAY_LENGTH(systemDirectoryStr)))
  175. return;
  176. WCHAR macromediaDirectoryStr[MAX_PATH];
  177. if (!::PathCombineW(macromediaDirectoryStr, systemDirectoryStr, L"macromed\\Flash"))
  178. return;
  179. directories.append(macromediaDirectoryStr);
  180. if (!::PathCombineW(macromediaDirectoryStr, systemDirectoryStr, L"macromed\\Shockwave 10"))
  181. return;
  182. directories.append(macromediaDirectoryStr);
  183. #endif
  184. }
  185. Vector<String> PluginInfoStore::pluginsDirectories()
  186. {
  187. Vector<String> directories;
  188. String ourDirectory = safariPluginsDirectory();
  189. if (!ourDirectory.isNull())
  190. directories.append(ourDirectory);
  191. addQuickTimePluginDirectory(directories);
  192. addAdobeAcrobatPluginDirectory(directories);
  193. addMozillaPluginDirectories(directories);
  194. addWindowsMediaPlayerPluginDirectory(directories);
  195. addMacromediaPluginDirectories(directories);
  196. return directories;
  197. }
  198. Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory)
  199. {
  200. Vector<String> paths;
  201. PathWalker walker(directory, "*");
  202. if (!walker.isValid())
  203. return paths;
  204. do {
  205. if (walker.data().dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  206. continue;
  207. String filename = walker.data().cFileName;
  208. if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) && (!equalIgnoringCase(filename, "Plugin.dll") || !directory.endsWith("Shockwave 10", false)))
  209. continue;
  210. paths.append(directory + "\\" + filename);
  211. } while (walker.step());
  212. return paths;
  213. }
  214. static void addPluginPathsFromRegistry(HKEY rootKey, Vector<String>& paths)
  215. {
  216. HKEY key;
  217. if (::RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key) != ERROR_SUCCESS)
  218. return;
  219. for (size_t i = 0; ; ++i) {
  220. // MSDN says that key names have a maximum length of 255 characters.
  221. wchar_t name[256];
  222. DWORD nameLen = WTF_ARRAY_LENGTH(name);
  223. if (::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, 0) != ERROR_SUCCESS)
  224. break;
  225. wchar_t path[MAX_PATH];
  226. DWORD pathSizeInBytes = sizeof(path);
  227. DWORD type;
  228. if (::SHGetValueW(key, name, L"Path", &type, path, &pathSizeInBytes) != ERROR_SUCCESS)
  229. continue;
  230. if (type != REG_SZ)
  231. continue;
  232. paths.append(path);
  233. }
  234. ::RegCloseKey(key);
  235. }
  236. Vector<String> PluginInfoStore::individualPluginPaths()
  237. {
  238. Vector<String> paths;
  239. addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
  240. addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);
  241. return paths;
  242. }
  243. static uint64_t fileVersion(DWORD leastSignificant, DWORD mostSignificant)
  244. {
  245. ULARGE_INTEGER version;
  246. version.LowPart = leastSignificant;
  247. version.HighPart = mostSignificant;
  248. return version.QuadPart;
  249. }
  250. bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
  251. {
  252. return NetscapePluginModule::getPluginInfo(pluginPath, plugin);
  253. }
  254. static bool isOldWindowsMediaPlayerPlugin(const PluginModuleInfo& plugin)
  255. {
  256. return equalIgnoringCase(plugin.info.file, "npdsplay.dll");
  257. }
  258. static bool isNewWindowsMediaPlayerPlugin(const PluginModuleInfo& plugin)
  259. {
  260. return equalIgnoringCase(plugin.info.file, "np-mswmp.dll");
  261. }
  262. bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin)
  263. {
  264. if (plugin.info.name == "Citrix ICA Client") {
  265. // The Citrix ICA Client plug-in requires a Mozilla-based browser; see <rdar://6418681>.
  266. return false;
  267. }
  268. if (plugin.info.name == "Silverlight Plug-In") {
  269. // workaround for <rdar://5557379> Crash in Silverlight when opening microsoft.com.
  270. // the latest 1.0 version of Silverlight does not reproduce this crash, so allow it
  271. // and any newer versions
  272. static const uint64_t minimumRequiredVersion = fileVersion(0x51BE0000, 0x00010000);
  273. return plugin.fileVersion >= minimumRequiredVersion;
  274. }
  275. if (equalIgnoringCase(plugin.info.file, "npmozax.dll")) {
  276. // Bug 15217: Mozilla ActiveX control complains about missing xpcom_core.dll
  277. return false;
  278. }
  279. if (equalIgnoringCase(plugin.info.file, "npwpf.dll")) {
  280. // Bug 57119: Microsoft Windows Presentation Foundation (WPF) plug-in complains about missing xpcom.dll
  281. return false;
  282. }
  283. if (plugin.info.name == "Yahoo Application State Plugin") {
  284. // https://bugs.webkit.org/show_bug.cgi?id=26860
  285. // Bug in Yahoo Application State plug-in earlier than 1.0.0.6 leads to heap corruption.
  286. static const uint64_t minimumRequiredVersion = fileVersion(0x00000006, 0x00010000);
  287. return plugin.fileVersion >= minimumRequiredVersion;
  288. }
  289. if (isOldWindowsMediaPlayerPlugin(plugin)) {
  290. // Don't load the old Windows Media Player plugin if we've already loaded the new Windows
  291. // Media Player plugin.
  292. for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
  293. if (!isNewWindowsMediaPlayerPlugin(alreadyLoadedPlugins[i]))
  294. continue;
  295. return false;
  296. }
  297. return true;
  298. }
  299. if (isNewWindowsMediaPlayerPlugin(plugin)) {
  300. // Remove the old Windows Media Player plugin if we've already added it.
  301. for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
  302. if (!isOldWindowsMediaPlayerPlugin(alreadyLoadedPlugins[i]))
  303. continue;
  304. alreadyLoadedPlugins.remove(i);
  305. }
  306. return true;
  307. }
  308. // FIXME: We should prefer a newer version of a plugin to an older version, rather than loading
  309. // only the first. <http://webkit.org/b/58469>
  310. String pluginFileName = pathGetFileName(plugin.path);
  311. for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
  312. const PluginModuleInfo& loadedPlugin = alreadyLoadedPlugins[i];
  313. // If a plug-in with the same filename already exists, we don't want to load it.
  314. if (equalIgnoringCase(pluginFileName, pathGetFileName(loadedPlugin.path)))
  315. return false;
  316. }
  317. return true;
  318. }
  319. } // namespace WebKit