Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Side by Side Diff: webkit/glue/plugins/plugin_list_win.cc

Issue 6012002: Move the NPAPI files from webkit/glue/plugins to webkit/plugins/npapi and put... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/plugin_list_posix.cc ('k') | webkit/glue/plugins/plugin_stream.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/glue/plugins/plugin_list.h"
6
7 #include <tchar.h>
8
9 #include <set>
10
11 #include "base/basictypes.h"
12 #include "base/command_line.h"
13 #include "base/file_util.h"
14 #include "base/path_service.h"
15 #include "base/scoped_ptr.h"
16 #include "base/string_number_conversions.h"
17 #include "base/string_split.h"
18 #include "base/string_util.h"
19 #include "base/win/registry.h"
20 #include "webkit/glue/plugins/plugin_constants_win.h"
21 #include "webkit/glue/plugins/plugin_lib.h"
22 #include "webkit/glue/webkit_glue.h"
23
24 namespace {
25
26 const TCHAR kRegistryApps[] =
27 _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths");
28 const TCHAR kRegistryFirefox[] = _T("firefox.exe");
29 const TCHAR kRegistryAcrobat[] = _T("Acrobat.exe");
30 const TCHAR kRegistryAcrobatReader[] = _T("AcroRd32.exe");
31 const TCHAR kRegistryWindowsMedia[] = _T("wmplayer.exe");
32 const TCHAR kRegistryQuickTime[] = _T("QuickTimePlayer.exe");
33 const TCHAR kRegistryPath[] = _T("Path");
34 const TCHAR kRegistryFirefoxInstalled[] =
35 _T("SOFTWARE\\Mozilla\\Mozilla Firefox");
36 const TCHAR kRegistryJava[] =
37 _T("Software\\JavaSoft\\Java Runtime Environment");
38 const TCHAR kRegistryBrowserJavaVersion[] = _T("BrowserJavaVersion");
39 const TCHAR kRegistryCurrentJavaVersion[] = _T("CurrentVersion");
40 const TCHAR kRegistryJavaHome[] = _T("JavaHome");
41 const TCHAR kJavaDeploy1[] = _T("npdeploytk.dll");
42 const TCHAR kJavaDeploy2[] = _T("npdeployjava1.dll");
43
44 // The application path where we expect to find plugins.
45 void GetAppDirectory(std::set<FilePath>* plugin_dirs) {
46 FilePath app_path;
47 if (!webkit_glue::GetApplicationDirectory(&app_path))
48 return;
49
50 app_path = app_path.AppendASCII("plugins");
51 plugin_dirs->insert(app_path);
52 }
53
54 // The executable path where we expect to find plugins.
55 void GetExeDirectory(std::set<FilePath>* plugin_dirs) {
56 FilePath exe_path;
57 if (!webkit_glue::GetExeDirectory(&exe_path))
58 return;
59
60 exe_path = exe_path.AppendASCII("plugins");
61 plugin_dirs->insert(exe_path);
62 }
63
64 // Gets the installed path for a registered app.
65 bool GetInstalledPath(const TCHAR* app, FilePath* out) {
66 std::wstring reg_path(kRegistryApps);
67 reg_path.append(L"\\");
68 reg_path.append(app);
69
70 base::win::RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ);
71 std::wstring path;
72 if (key.ReadValue(kRegistryPath, &path)) {
73 *out = FilePath(path);
74 return true;
75 }
76
77 return false;
78 }
79
80 // Search the registry at the given path and detect plugin directories.
81 void GetPluginsInRegistryDirectory(
82 HKEY root_key,
83 const std::wstring& registry_folder,
84 std::set<FilePath>* plugin_dirs) {
85 for (base::win::RegistryKeyIterator iter(root_key, registry_folder.c_str());
86 iter.Valid(); ++iter) {
87 // Use the registry to gather plugin across the file system.
88 std::wstring reg_path = registry_folder;
89 reg_path.append(L"\\");
90 reg_path.append(iter.Name());
91 base::win::RegKey key(root_key, reg_path.c_str(), KEY_READ);
92
93 std::wstring path;
94 if (key.ReadValue(kRegistryPath, &path))
95 plugin_dirs->insert(FilePath(path));
96 }
97 }
98
99 // Enumerate through the registry key to find all installed FireFox paths.
100 // FireFox 3 beta and version 2 can coexist. See bug: 1025003
101 void GetFirefoxInstalledPaths(std::vector<FilePath>* out) {
102 base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE,
103 kRegistryFirefoxInstalled);
104 for (; it.Valid(); ++it) {
105 std::wstring full_path = std::wstring(kRegistryFirefoxInstalled) + L"\\" +
106 it.Name() + L"\\Main";
107 base::win::RegKey key(HKEY_LOCAL_MACHINE, full_path.c_str(), KEY_READ);
108 std::wstring install_dir;
109 if (!key.ReadValue(L"Install Directory", &install_dir))
110 continue;
111 out->push_back(FilePath(install_dir));
112 }
113 }
114
115 // Get plugin directory locations from the Firefox install path. This is kind
116 // of a kludge, but it helps us locate the flash player for users that
117 // already have it for firefox. Not having to download yet-another-plugin
118 // is a good thing.
119 void GetFirefoxDirectory(std::set<FilePath>* plugin_dirs) {
120 std::vector<FilePath> paths;
121 GetFirefoxInstalledPaths(&paths);
122 for (unsigned int i = 0; i < paths.size(); ++i) {
123 plugin_dirs->insert(paths[i].Append(L"plugins"));
124 }
125
126 FilePath firefox_app_data_plugin_path;
127 if (PathService::Get(base::DIR_APP_DATA, &firefox_app_data_plugin_path)) {
128 firefox_app_data_plugin_path =
129 firefox_app_data_plugin_path.AppendASCII("Mozilla")
130 .AppendASCII("plugins");
131 plugin_dirs->insert(firefox_app_data_plugin_path);
132 }
133 }
134
135 // Hardcoded logic to detect Acrobat plugins locations.
136 void GetAcrobatDirectory(std::set<FilePath>* plugin_dirs) {
137 FilePath path;
138 if (!GetInstalledPath(kRegistryAcrobatReader, &path) &&
139 !GetInstalledPath(kRegistryAcrobat, &path)) {
140 return;
141 }
142
143 plugin_dirs->insert(path.Append(L"Browser"));
144 }
145
146 // Hardcoded logic to detect QuickTime plugin location.
147 void GetQuicktimeDirectory(std::set<FilePath>* plugin_dirs) {
148 FilePath path;
149 if (GetInstalledPath(kRegistryQuickTime, &path))
150 plugin_dirs->insert(path.Append(L"plugins"));
151 }
152
153 // Hardcoded logic to detect Windows Media Player plugin location.
154 void GetWindowsMediaDirectory(std::set<FilePath>* plugin_dirs) {
155 FilePath path;
156 if (GetInstalledPath(kRegistryWindowsMedia, &path))
157 plugin_dirs->insert(path);
158
159 // If the Windows Media Player Firefox plugin is installed before Firefox,
160 // the plugin will get written under PFiles\Plugins on one the drives
161 // (usually, but not always, the last letter).
162 int size = GetLogicalDriveStrings(0, NULL);
163 if (size) {
164 scoped_array<wchar_t> strings(new wchar_t[size]);
165 if (GetLogicalDriveStrings(size, strings.get())) {
166 wchar_t* next_drive = strings.get();
167 while (*next_drive) {
168 if (GetDriveType(next_drive) == DRIVE_FIXED) {
169 FilePath pfiles(next_drive);
170 pfiles = pfiles.Append(L"PFiles\\Plugins");
171 if (file_util::PathExists(pfiles))
172 plugin_dirs->insert(pfiles);
173 }
174 next_drive = &next_drive[wcslen(next_drive) + 1];
175 }
176 }
177 }
178 }
179
180 // Hardcoded logic to detect Java plugin location.
181 void GetJavaDirectory(std::set<FilePath>* plugin_dirs) {
182 // Load the new NPAPI Java plugin
183 // 1. Open the main JRE key under HKLM
184 base::win::RegKey java_key(HKEY_LOCAL_MACHINE, kRegistryJava,
185 KEY_QUERY_VALUE);
186
187 // 2. Read the current Java version
188 std::wstring java_version;
189 if (!java_key.ReadValue(kRegistryBrowserJavaVersion, &java_version))
190 java_key.ReadValue(kRegistryCurrentJavaVersion, &java_version);
191
192 if (!java_version.empty()) {
193 java_key.OpenKey(java_version.c_str(), KEY_QUERY_VALUE);
194
195 // 3. Install path of the JRE binaries is specified in "JavaHome"
196 // value under the Java version key.
197 std::wstring java_plugin_directory;
198 if (java_key.ReadValue(kRegistryJavaHome, &java_plugin_directory)) {
199 // 4. The new plugin resides under the 'bin/new_plugin'
200 // subdirectory.
201 DCHECK(!java_plugin_directory.empty());
202 java_plugin_directory.append(L"\\bin\\new_plugin");
203
204 // 5. We don't know the exact name of the DLL but it's in the form
205 // NP*.dll so just invoke LoadPlugins on this path.
206 plugin_dirs->insert(FilePath(java_plugin_directory));
207 }
208 }
209 }
210
211 } // anonymous namespace
212
213 namespace NPAPI {
214
215 void PluginList::PlatformInit() {
216 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
217 dont_load_new_wmp_ = command_line.HasSwitch(kUseOldWMPPluginSwitch);
218 }
219
220 void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) {
221 // We use a set for uniqueness, which we require, over order, which we do not.
222 std::set<FilePath> dirs;
223
224 // Load from the application-specific area
225 GetAppDirectory(&dirs);
226
227 // Load from the executable area
228 GetExeDirectory(&dirs);
229
230 // Load Java
231 GetJavaDirectory(&dirs);
232
233 // Load firefox plugins too. This is mainly to try to locate
234 // a pre-installed Flash player.
235 GetFirefoxDirectory(&dirs);
236
237 // Firefox hard-codes the paths of some popular plugins to ensure that
238 // the plugins are found. We are going to copy this as well.
239 GetAcrobatDirectory(&dirs);
240 GetQuicktimeDirectory(&dirs);
241 GetWindowsMediaDirectory(&dirs);
242
243 for (std::set<FilePath>::iterator i = dirs.begin(); i != dirs.end(); ++i)
244 plugin_dirs->push_back(*i);
245 }
246
247 void PluginList::LoadPluginsFromDir(const FilePath &path,
248 std::vector<WebPluginInfo>* plugins,
249 std::set<FilePath>* visited_plugins) {
250 WIN32_FIND_DATA find_file_data;
251 HANDLE find_handle;
252
253 std::wstring dir = path.value();
254 // FindFirstFile requires that you specify a wildcard for directories.
255 dir.append(L"\\NP*.DLL");
256
257 find_handle = FindFirstFile(dir.c_str(), &find_file_data);
258 if (find_handle == INVALID_HANDLE_VALUE)
259 return;
260
261 do {
262 if (!(find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
263 FilePath filename = path.Append(find_file_data.cFileName);
264 LoadPlugin(filename, plugins);
265 visited_plugins->insert(filename);
266 }
267 } while (FindNextFile(find_handle, &find_file_data) != 0);
268
269 DCHECK(GetLastError() == ERROR_NO_MORE_FILES);
270 FindClose(find_handle);
271 }
272
273 void PluginList::LoadPluginsFromRegistry(
274 std::vector<WebPluginInfo>* plugins,
275 std::set<FilePath>* visited_plugins) {
276 std::set<FilePath> plugin_dirs;
277
278 GetPluginsInRegistryDirectory(
279 HKEY_CURRENT_USER, kRegistryMozillaPlugins, &plugin_dirs);
280 GetPluginsInRegistryDirectory(
281 HKEY_LOCAL_MACHINE, kRegistryMozillaPlugins, &plugin_dirs);
282
283 for (std::set<FilePath>::iterator i = plugin_dirs.begin();
284 i != plugin_dirs.end(); ++i) {
285 LoadPlugin(*i, plugins);
286 visited_plugins->insert(*i);
287 }
288 }
289
290 // Returns true if the given plugins share at least one mime type. This is used
291 // to differentiate newer versions of a plugin vs two plugins which happen to
292 // have the same filename.
293 bool HaveSharedMimeType(const WebPluginInfo& plugin1,
294 const WebPluginInfo& plugin2) {
295 for (size_t i = 0; i < plugin1.mime_types.size(); ++i) {
296 for (size_t j = 0; j < plugin2.mime_types.size(); ++j) {
297 if (plugin1.mime_types[i].mime_type == plugin2.mime_types[j].mime_type)
298 return true;
299 }
300 }
301
302 return false;
303 }
304
305 // Compares Windows style version strings (i.e. 1,2,3,4). Returns true if b's
306 // version is newer than a's, or false if it's equal or older.
307 bool IsNewerVersion(const std::wstring& a, const std::wstring& b) {
308 std::vector<std::wstring> a_ver, b_ver;
309 base::SplitString(a, ',', &a_ver);
310 base::SplitString(b, ',', &b_ver);
311 if (a_ver.size() == 1 && b_ver.size() == 1) {
312 a_ver.clear();
313 b_ver.clear();
314 base::SplitString(a, '.', &a_ver);
315 base::SplitString(b, '.', &b_ver);
316 }
317 if (a_ver.size() != b_ver.size())
318 return false;
319 for (size_t i = 0; i < a_ver.size(); i++) {
320 int cur_a, cur_b;
321 base::StringToInt(a_ver[i], &cur_a);
322 base::StringToInt(b_ver[i], &cur_b);
323
324 if (cur_a > cur_b)
325 return false;
326 if (cur_a < cur_b)
327 return true;
328 }
329 return false;
330 }
331
332 bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
333 std::vector<WebPluginInfo>* plugins) {
334 // Version check
335
336 for (size_t i = 0; i < plugins->size(); ++i) {
337 std::wstring plugin1 =
338 StringToLowerASCII((*plugins)[i].path.BaseName().ToWStringHack());
339 std::wstring plugin2 =
340 StringToLowerASCII(info.path.BaseName().ToWStringHack());
341 if ((plugin1 == plugin2 && HaveSharedMimeType((*plugins)[i], info)) ||
342 (plugin1 == kJavaDeploy1 && plugin2 == kJavaDeploy2) ||
343 (plugin1 == kJavaDeploy2 && plugin2 == kJavaDeploy1)) {
344 if (!IsNewerVersion((*plugins)[i].version, info.version))
345 return false; // We have loaded a plugin whose version is newer.
346
347 plugins->erase(plugins->begin() + i);
348 break;
349 }
350 }
351
352 // Troublemakers
353
354 std::wstring filename = StringToLowerASCII(info.path.BaseName().value());
355 // Depends on XPCOM.
356 if (filename == kMozillaActiveXPlugin)
357 return false;
358
359 // Disable the Yahoo Application State plugin as it crashes the plugin
360 // process on return from NPObjectStub::OnInvoke. Please refer to
361 // http://b/issue?id=1372124 for more information.
362 if (filename == kYahooApplicationStatePlugin)
363 return false;
364
365 // Disable the WangWang protocol handler plugin (npww.dll) as it crashes
366 // chrome during shutdown. Firefox also disables this plugin.
367 // Please refer to http://code.google.com/p/chromium/issues/detail?id=3953
368 // for more information.
369 if (filename == kWanWangProtocolHandlerPlugin)
370 return false;
371
372 // We only work with newer versions of the Java plugin which use NPAPI only
373 // and don't depend on XPCOM.
374 if (filename == kJavaPlugin1 || filename == kJavaPlugin2) {
375 std::vector<std::wstring> ver;
376 base::SplitString(info.version, '.', &ver);
377 int major, minor, update;
378 if (ver.size() == 4 &&
379 base::StringToInt(ver[0], &major) &&
380 base::StringToInt(ver[1], &minor) &&
381 base::StringToInt(ver[2], &update)) {
382 if (major == 6 && minor == 0 && update < 120)
383 return false; // Java SE6 Update 11 or older.
384 }
385 }
386
387 // Special WMP handling
388
389 // If both the new and old WMP plugins exist, only load the new one.
390 if (filename == kNewWMPPlugin) {
391 if (dont_load_new_wmp_)
392 return false;
393
394 for (size_t i = 0; i < plugins->size(); ++i) {
395 if ((*plugins)[i].path.BaseName().value() == kOldWMPPlugin) {
396 plugins->erase(plugins->begin() + i);
397 break;
398 }
399 }
400 } else if (filename == kOldWMPPlugin) {
401 for (size_t i = 0; i < plugins->size(); ++i) {
402 if ((*plugins)[i].path.BaseName().value() == kNewWMPPlugin)
403 return false;
404 }
405 }
406
407 return true;
408 }
409
410 } // namespace NPAPI
OLDNEW
« no previous file with comments | « webkit/glue/plugins/plugin_list_posix.cc ('k') | webkit/glue/plugins/plugin_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698