13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file.
4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/enumerate_modules_model_win.h"
6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <Tlhelp32.h>
8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <wintrust.h>
9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/command_line.h"
11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/environment.h"
12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/file_path.h"
13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/file_version_info_win.h"
14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/metrics/histogram.h"
15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/string_number_conversions.h"
16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/string_util.h"
17201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/time.h"
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/utf_string_conversions.h"
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/values.h"
20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/version.h"
21201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/win/registry.h"
223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/scoped_handle.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/sha2.h"
24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/net/service_providers_win.h"
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/chrome_constants.h"
26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/chrome_switches.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "grit/generated_resources.h"
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// The period of time (in milliseconds) to wait until checking to see if any
32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// incompatible modules exist.
33513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic const int kModuleCheckDelayMs = 60 * 1000;
34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// The path to the Shell Extension key in the Windows registry.
36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstatic const wchar_t kRegPath[] =
37201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Short-hand for things on the blacklist you should simply get rid of.
40201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstatic const ModuleEnumerator::RecommendedAction kUninstallLink =
41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    static_cast<ModuleEnumerator::RecommendedAction>(
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ModuleEnumerator::UNINSTALL | ModuleEnumerator::SEE_LINK);
43201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Short-hand for things on the blacklist we are investigating and have info.
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const ModuleEnumerator::RecommendedAction kInvestigatingLink =
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    static_cast<ModuleEnumerator::RecommendedAction>(
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ModuleEnumerator::INVESTIGATING | ModuleEnumerator::SEE_LINK);
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
49201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// A sort method that sorts by bad modules first, then by full name (including
50201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// path).
51513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic bool ModuleSort(const ModuleEnumerator::Module& a,
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                       const ModuleEnumerator::Module& b) {
53201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (a.status != b.status)
54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return a.status > b.status;
55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (a.location == b.location)
57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return a.name < b.name;
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return a.location < b.location;
60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace {
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Used to protect the LoadedModuleVector which is accessed
65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// from both the UI thread and the FILE thread.
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbase::Lock* lock = NULL;
67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// A struct to help de-duping modules before adding them to the enumerated
69201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// modules vector.
70201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstruct FindModule {
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch public:
72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  explicit FindModule(const ModuleEnumerator::Module& x)
73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    : module(x) {}
74201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool operator()(const ModuleEnumerator::Module& module_in) const {
75201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return (module.location == module_in.location) &&
76201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           (module.name == module_in.name);
77201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
78201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const ModuleEnumerator::Module& module;
80201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch};
81201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Returns the long path name given a short path name. A short path name is a
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// path that follows the 8.3 convention and has ~x in it. If the path is already
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// a long path name, the function returns the current path without modification.
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ConvertToLongPath(const string16& short_path, string16* long_path) {
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  wchar_t long_path_buf[MAX_PATH];
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DWORD return_value = GetLongPathName(short_path.c_str(), long_path_buf,
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       MAX_PATH);
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (return_value != 0 && return_value < MAX_PATH) {
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *long_path = long_path_buf;
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}  // namespace
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// The browser process module blacklist. This lists modules that are known
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// to cause compatibility issues within the browser process. When adding to this
101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// list, make sure that all paths are lower-case, in long pathname form, end
102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// with a slash and use environments variables (or just look at one of the
103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// comments below and keep it consistent with that). When adding an entry with
104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// an environment variable not currently used in the list below, make sure to
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// update the list in PreparePathMappings. Filename, Description/Signer, and
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Location must be entered as hashes (see GenerateHash). Filename is mandatory.
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Entries without any Description, Signer info, or Location will never be
108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// marked as confirmed bad (only as suspicious).
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst ModuleEnumerator::BlacklistEntry ModuleEnumerator::kModuleBlacklist[] = {
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // NOTE: Please keep this list sorted by dll name, then location.
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Version 3.2.1.6 seems to be implicated in most cases (and 3.2.2.2 in some).
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // There is a more recent version available for download.
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // accelerator.dll, "%programfiles%\\speedbit video accelerator\\".
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "7ba9402f", "c9132d48", "", "", "", kInvestigatingLink },
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // apiqq0.dll, "%temp%\\".
118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "26134911", "59145acf", "", "", "", kUninstallLink },
119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // arking0.dll, "%systemroot%\\system32\\".
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "f5d8f549", "23d01d5b", "", "", "", kUninstallLink },
122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // arking1.dll, "%systemroot%\\system32\\".
124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "c60ca062", "23d01d5b", "", "", "", kUninstallLink },
125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Said to belong to Killer NIC from BigFoot Networks (not verified). Versions
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 6.0.0.7 and 6.0.0.10 implicated.
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // bfllr.dll, "%systemroot%\\system32\\".
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "6bb57633", "23d01d5b", "", "", "", kInvestigatingLink },
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // clickpotatolitesahook.dll, "". Different version each report.
132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "0396e037.dll", "", "", "", "", kUninstallLink },
133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // cvasds0.dll, "%temp%\\".
135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "5ce0037c", "59145acf", "", "", "", kUninstallLink },
136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // cwalsp.dll, "%systemroot%\\system32\\".
138201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "e579a039", "23d01d5b", "", "", "", kUninstallLink },
139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
140201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // dsoqq0.dll, "%temp%\\".
141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "1c4df325", "59145acf", "", "", "", kUninstallLink },
142201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This looks like a malware edition of a Brazilian Bank plugin, sometimes
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // referred to as Malware.Banc.A.
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // gbieh.dll, "%programfiles%\\gbplugin\\".
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "4cb4f2e3", "88e4a3b1", "", "", "", kUninstallLink },
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
148201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // hblitesahook.dll. Each report has different version number in location.
149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "5d10b363", "", "", "", "", kUninstallLink },
150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // icf.dll, "%systemroot%\\system32\\".
152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "303825ed", "23d01d5b", "", "", "", INVESTIGATING },
153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // idmmbc.dll (IDM), "%systemroot%\\system32\\". See: http://crbug.com/26892/.
155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "b8dce5c3", "23d01d5b", "", "", "6.03",
156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      static_cast<RecommendedAction>(UPDATE | DISABLE) },
157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // imon.dll (NOD32), "%systemroot%\\system32\\". See: http://crbug.com/21715.
159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "8f42f22e", "23d01d5b", "", "", "4.0",
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      static_cast<RecommendedAction>(UPDATE | DISABLE) },
161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // is3lsp.dll, "%commonprogramfiles%\\is3\\anti-spyware\\".
1633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  { "7ffbdce9", "bc5673f2", "", "", "",
1643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      static_cast<RecommendedAction>(UPDATE | DISABLE | SEE_LINK) },
165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // jsi.dll, "%programfiles%\\profilecraze\\".
167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "f9555eea", "e3548061", "", "", "", kUninstallLink },
168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // kernel.dll, "%programfiles%\\contentwatch\\internet protection\\modules\\".
170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "ead2768e", "4e61ce60", "", "", "", INVESTIGATING },
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // mgking0.dll, "%systemroot%\\system32\\".
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "d0893e38", "23d01d5b", "", "", "", kUninstallLink },
174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // mgking0.dll, "%temp%\\".
176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "d0893e38", "59145acf", "", "", "", kUninstallLink },
177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // mgking1.dll, "%systemroot%\\system32\\".
179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "3e837222", "23d01d5b", "", "", "", kUninstallLink },
180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // mgking1.dll, "%temp%\\".
182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "3e837222", "59145acf", "", "", "", kUninstallLink },
183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
184201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // mstcipha.ime, "%systemroot%\\system32\\".
185201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "5523579e", "23d01d5b", "", "", "", INVESTIGATING },
186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // mwtsp.dll, "%systemroot%\\system32\\".
188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "9830bff6", "23d01d5b", "", "", "", kUninstallLink },
189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // nodqq0.dll, "%temp%\\".
191201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "b86ce04d", "59145acf", "", "", "", kUninstallLink },
192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // nProtect GameGuard Anti-cheat system. Every report has a different
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // location, since it is installed into and run from a game folder. Various
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // versions implicated.
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // npggnt.des, no fixed location.
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "f2c8790d", "", "", "", "", kInvestigatingLink },
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
199201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // nvlsp.dll,
200201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // "%programfiles%\\nvidia corporation\\networkaccessmanager\\bin32\\".
201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "37f907e2", "3ad0ff23", "", "", "", INVESTIGATING },
202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // post0.dll, "%systemroot%\\system32\\".
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "7405c0c8", "23d01d5b", "", "", "", kUninstallLink },
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // radhslib.dll (Naomi web filter), "%programfiles%\\rnamfler\\".
207201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // See http://crbug.com/12517.
208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "7edcd250", "0733dc3e", "", "", "", INVESTIGATING },
209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // rlls.dll, "%programfiles%\\relevantknowledge\\".
211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "a1ed94a7", "ea9d6b36", "", "", "", kUninstallLink },
212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
213201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // rooksdol.dll, "%programfiles%\\trusteer\\rapport\\bin\\".
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "802aefef", "06120e13", "", "", "3.5.1008.40", INVESTIGATING },
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // sdata.dll, "%programdata%\\srtserv\\".
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "1936d5cc", "223c44be", "", "", "", kUninstallLink },
218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // searchtree.dll,
220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // "%programfiles%\\contentwatch\\internet protection\\modules\\".
221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "f6915a31", "4e61ce60", "", "", "", INVESTIGATING },
222513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
223201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // sgprxy.dll, "%commonprogramfiles%\\is3\\anti-spyware\\".
224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "005965ea", "bc5673f2", "", "", "", INVESTIGATING },
225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // swi_filter_0001.dll (Sophos Web Intelligence),
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // "%programfiles%\\sophos\\sophos anti-virus\\web intelligence\\".
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // A small random sample all showed version 1.0.5.0.
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "61112d7b", "25fb120f", "", "", "", kInvestigatingLink },
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // twking0.dll, "%systemroot%\\system32\\".
232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "0355549b", "23d01d5b", "", "", "", kUninstallLink },
233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // twking1.dll, "%systemroot%\\system32\\".
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "02e44508", "23d01d5b", "", "", "", kUninstallLink },
236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // vksaver.dll, "%systemroot%\\system32\\".
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "c4a784d5", "23d01d5b", "", "", "", kUninstallLink },
239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // vlsp.dll (Venturi Firewall?), "%systemroot%\\system32\\".
241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "2e4eb93d", "23d01d5b", "", "", "", INVESTIGATING },
242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // vmn3_1dn.dll, "%appdata%\\roaming\\vmndtxtb\\".
244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "bba2037d", "9ab68585", "", "", "", kUninstallLink },
245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // webanalyzer.dll,
247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // "%programfiles%\\contentwatch\\internet protection\\modules\\".
248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "c70b697d", "4e61ce60", "", "", "", INVESTIGATING },
249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // wowst0.dll, "%systemroot%\\system32\\".
251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "38ad9963", "23d01d5b", "", "", "", kUninstallLink },
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // wxbase28u_vc_cw.dll, "%systemroot%\\system32\\".
254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "e967210d", "23d01d5b", "", "", "", kUninstallLink },
255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Generates an 8 digit hash from the input given.
258513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic void GenerateHash(const std::string& input, std::string* output) {
259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (input.empty()) {
260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    *output = "";
261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
264513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  uint8 hash[4];
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::SHA256HashString(input, hash, sizeof(hash));
266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash)));
267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// -----------------------------------------------------------------------------
270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
271513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
272513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ModuleEnumerator::NormalizeModule(Module* module) {
273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  string16 path = module->location;
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!ConvertToLongPath(path, &module->location))
275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->location = path;
276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  module->location = l10n_util::ToLower(module->location);
278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
279513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Location contains the filename, so the last slash is where the path
280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // ends.
281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  size_t last_slash = module->location.find_last_of(L"\\");
282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (last_slash != string16::npos) {
283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->name = module->location.substr(last_slash + 1);
284513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->location = module->location.substr(0, last_slash + 1);
285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->name = module->location;
287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->location.clear();
288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Some version strings have things like (win7_rtm.090713-1255) appended
291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // to them. Remove that.
292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  size_t first_space = module->version.find_first_of(L" ");
293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (first_space != string16::npos)
294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->version = module->version.substr(0, first_space);
295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  module->normalized = true;
297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
300513209b27ff55e2841eac0e4120199c23acce758Ben MurdochModuleEnumerator::ModuleStatus ModuleEnumerator::Match(
301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const ModuleEnumerator::Module& module,
302513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const ModuleEnumerator::BlacklistEntry& blacklisted) {
303513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // All modules must be normalized before matching against blacklist.
304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(module.normalized);
305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Filename is mandatory and version should not contain spaces.
306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(strlen(blacklisted.filename) > 0);
307513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(!strstr(blacklisted.version_from, " "));
308513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(!strstr(blacklisted.version_to, " "));
309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
310513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string filename_hash, location_hash;
311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GenerateHash(WideToUTF8(module.name), &filename_hash);
312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GenerateHash(WideToUTF8(module.location), &location_hash);
313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
314513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Filenames are mandatory. Location is mandatory if given.
315513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (filename_hash == blacklisted.filename &&
316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          (std::string(blacklisted.location).empty() ||
317513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          location_hash == blacklisted.location)) {
318513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // We have a name match against the blacklist (and possibly location match
319513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // also), so check version.
320513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_ptr<Version> module_version(
32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        Version::GetVersionFromString(UTF16ToASCII(module.version)));
322513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_ptr<Version> version_min(
323513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        Version::GetVersionFromString(blacklisted.version_from));
324513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_ptr<Version> version_max(
325513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        Version::GetVersionFromString(blacklisted.version_to));
326513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    bool version_ok = !version_min.get() && !version_max.get();
327513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!version_ok) {
328513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      bool too_low = version_min.get() &&
329513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          (!module_version.get() ||
330513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          module_version->CompareTo(*version_min.get()) < 0);
331513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      bool too_high = version_max.get() &&
332513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          (!module_version.get() ||
333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          module_version->CompareTo(*version_max.get()) >= 0);
334513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      version_ok = !too_low && !too_high;
335513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
336513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
337513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (version_ok) {
338513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // At this point, the names match and there is no version specified
339513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // or the versions also match.
340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
341513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      std::string desc_or_signer(blacklisted.desc_or_signer);
342513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      std::string signer_hash, description_hash;
343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      GenerateHash(WideToUTF8(module.digital_signer), &signer_hash);
344513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      GenerateHash(WideToUTF8(module.description), &description_hash);
345513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      // If signatures match (or both are empty), then we have a winner.
3473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (signer_hash == desc_or_signer)
348513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        return CONFIRMED_BAD;
349513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      // If descriptions match (or both are empty) and the locations match, then
3513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      // we also have a confirmed match.
3523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (description_hash == desc_or_signer &&
353513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          !location_hash.empty() && location_hash == blacklisted.location) {
354513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        return CONFIRMED_BAD;
355513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      }
356513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
357513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // We are not sure, but it is likely bad.
358513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return SUSPECTED_BAD;
359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
360513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
361513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
362513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return NOT_MATCHED;
363513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
364513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
365513209b27ff55e2841eac0e4120199c23acce758Ben MurdochModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer)
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : enumerated_modules_(NULL),
36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      observer_(observer),
3683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      limited_mode_(false),
369201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      callback_thread_id_(BrowserThread::ID_COUNT) {
370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
372513209b27ff55e2841eac0e4120199c23acce758Ben MurdochModuleEnumerator::~ModuleEnumerator() {
373513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid ModuleEnumerator::ScanNow(ModulesVector* list, bool limited_mode) {
376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  enumerated_modules_ = list;
3773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
3783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  limited_mode_ = limited_mode;
3793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
3803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!limited_mode_) {
3813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_));
3823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
3833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    BrowserThread::PostTask(
3843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        BrowserThread::FILE, FROM_HERE,
3853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            NewRunnableMethod(this, &ModuleEnumerator::ScanImpl));
3863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  } else {
3873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    // Run it synchronously.
3883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    ScanImpl();
3893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
390513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
391513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
3923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid ModuleEnumerator::ScanImpl() {
393201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  base::TimeTicks start_time = base::TimeTicks::Now();
394201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
395513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  enumerated_modules_->clear();
396513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
397513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Make sure the path mapping vector is setup so we can collapse paths.
398513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PreparePathMappings();
399513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
400201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Enumerating loaded modules must happen first since the other types of
401201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // modules check for duplication against the loaded modules.
4023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::TimeTicks checkpoint = base::TimeTicks::Now();
403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EnumerateLoadedModules();
4043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::TimeTicks checkpoint2 = base::TimeTicks::Now();
4053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateLoadedModules",
4063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      checkpoint2 - checkpoint);
407201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
4083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  checkpoint = checkpoint2;
409201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EnumerateShellExtensions();
4103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  checkpoint2 = base::TimeTicks::Now();
4113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateShellExtensions",
4123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      checkpoint2 - checkpoint);
413201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
4143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  checkpoint = checkpoint2;
415201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EnumerateWinsockModules();
4163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  checkpoint2 = base::TimeTicks::Now();
4173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules",
4183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      checkpoint2 - checkpoint);
419201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
420201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MatchAgainstBlacklist();
421201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
422201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::sort(enumerated_modules_->begin(),
423201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch            enumerated_modules_->end(), ModuleSort);
424201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
4253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!limited_mode_) {
4263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    // Send a reply back on the UI thread.
4273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    BrowserThread::PostTask(
4283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        callback_thread_id_, FROM_HERE,
4293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        NewRunnableMethod(this, &ModuleEnumerator::ReportBack));
4303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  } else {
4313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    // We are on the main thread already.
4323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    ReportBack();
4333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
4353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  UMA_HISTOGRAM_TIMES("Conflicts.EnumerationTotalTime",
4363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      base::TimeTicks::Now() - start_time);
437201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
438201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
439201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ModuleEnumerator::EnumerateLoadedModules() {
440513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Get all modules in the current process.
4413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::win::ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
4423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                               ::GetCurrentProcessId()));
443513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!snap.Get())
444513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
445513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
446513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Walk the module list.
447513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  MODULEENTRY32 module = { sizeof(module) };
448513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!::Module32First(snap.Get(), &module))
449513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
450513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
451513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  do {
452513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // It would be weird to present chrome.exe as a loaded module.
453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (_wcsicmp(chrome::kBrowserProcessExecutableName, module.szModule) == 0)
454513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      continue;
455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
456513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    Module entry;
457513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.type = LOADED_MODULE;
458513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.location = module.szExePath;
459201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    PopulateModuleInformation(&entry);
460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
461513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    NormalizeModule(&entry);
462513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CollapsePath(&entry);
463513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    enumerated_modules_->push_back(entry);
464513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } while (::Module32Next(snap.Get(), &module));
465201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
466201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ModuleEnumerator::EnumerateShellExtensions() {
468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadShellExtensions(HKEY_LOCAL_MACHINE);
469201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadShellExtensions(HKEY_CURRENT_USER);
470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ModuleEnumerator::ReadShellExtensions(HKEY parent) {
473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  base::win::RegistryValueIterator registration(parent, kRegPath);
474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  while (registration.Valid()) {
475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    std::wstring key(std::wstring(L"CLSID\\") + registration.Name() +
476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        L"\\InProcServer32");
477201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    base::win::RegKey clsid;
47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ) != ERROR_SUCCESS) {
479201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ++registration;
480201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      continue;
481201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
482201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    string16 dll;
48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (clsid.ReadValue(L"", &dll) != ERROR_SUCCESS) {
484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ++registration;
485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      continue;
486201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
487201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    clsid.Close();
488201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
489201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    Module entry;
490201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    entry.type = SHELL_EXTENSION;
491201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    entry.location = dll;
492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    PopulateModuleInformation(&entry);
493201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
494201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    NormalizeModule(&entry);
495201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CollapsePath(&entry);
496201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    AddToListWithoutDuplicating(entry);
497201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
498201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    ++registration;
499201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
500201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
501513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
502201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ModuleEnumerator::EnumerateWinsockModules() {
503513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Add to this list the Winsock LSP DLLs.
504513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  WinsockLayeredServiceProviderList layered_providers;
505513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GetWinsockLayeredServiceProviders(&layered_providers);
506513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (size_t i = 0; i < layered_providers.size(); ++i) {
507513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    Module entry;
508513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.type = WINSOCK_MODULE_REGISTRATION;
509513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.status = NOT_MATCHED;
510513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.normalized = false;
511513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.location = layered_providers[i].path;
512513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.description = layered_providers[i].name;
513513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.recommended_action = NONE;
514201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    entry.duplicate_count = 0;
515513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
516513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    wchar_t expanded[MAX_PATH];
517513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DWORD size = ExpandEnvironmentStrings(
518513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        entry.location.c_str(), expanded, MAX_PATH);
519513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (size != 0 && size <= MAX_PATH) {
520513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      entry.digital_signer =
521513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          GetSubjectNameFromDigitalSignature(FilePath(expanded));
522513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
523513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    entry.version = base::IntToString16(layered_providers[i].version);
524513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
525513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Paths have already been collapsed.
526513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    NormalizeModule(&entry);
527201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    AddToListWithoutDuplicating(entry);
528513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
529201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
530513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
531201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ModuleEnumerator::PopulateModuleInformation(Module* module) {
532201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  module->status = NOT_MATCHED;
533201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  module->duplicate_count = 0;
534201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  module->normalized = false;
535201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  module->digital_signer =
536201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      GetSubjectNameFromDigitalSignature(FilePath(module->location));
537201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  module->recommended_action = NONE;
538201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<FileVersionInfo> version_info(
539201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      FileVersionInfo::CreateFileVersionInfo(FilePath(module->location)));
540201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (version_info.get()) {
541201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    FileVersionInfoWin* version_info_win =
542201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        static_cast<FileVersionInfoWin*>(version_info.get());
543201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
544201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info();
545201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (fixed_file_info) {
546201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      module->description = version_info_win->file_description();
547201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      module->version = version_info_win->file_version();
548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      module->product_name = version_info_win->product_name();
549201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
550201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
552513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ModuleEnumerator::AddToListWithoutDuplicating(const Module& module) {
554201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(module.normalized);
555201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // These are registered modules, not loaded modules so the same module
556201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // can be registered multiple times, often dozens of times. There is no need
557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // to list each registration, so we just increment the count for each module
558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // that is counted multiple times.
559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ModulesVector::iterator iter;
560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  iter = std::find_if(enumerated_modules_->begin(),
561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      enumerated_modules_->end(),
562201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      FindModule(module));
563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (iter != enumerated_modules_->end()) {
564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    iter->duplicate_count++;
565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    iter->type = static_cast<ModuleType>(iter->type | module.type);
566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else {
567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    enumerated_modules_->push_back(module);
568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
569513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
570513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
571513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ModuleEnumerator::PreparePathMappings() {
572513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  path_mapping_.clear();
573513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
574513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<base::Environment> environment(base::Environment::Create());
575513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::vector<string16> env_vars;
576513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  env_vars.push_back(L"LOCALAPPDATA");
577513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  env_vars.push_back(L"ProgramFiles");
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  env_vars.push_back(L"ProgramData");
579513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  env_vars.push_back(L"USERPROFILE");
580513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  env_vars.push_back(L"SystemRoot");
581513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  env_vars.push_back(L"TEMP");
582201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  env_vars.push_back(L"TMP");
583201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  env_vars.push_back(L"CommonProgramFiles");
584513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (std::vector<string16>::const_iterator variable = env_vars.begin();
585513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       variable != env_vars.end(); ++variable) {
586513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    std::string path;
587513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (environment->GetVar(WideToASCII(*variable).c_str(), &path)) {
588513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      path_mapping_.push_back(
589513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          std::make_pair(l10n_util::ToLower(UTF8ToWide(path)) + L"\\",
590513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                         L"%" + l10n_util::ToLower(*variable) + L"%"));
591513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
592513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
593513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
594513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
595513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ModuleEnumerator::CollapsePath(Module* entry) {
596513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Take the path and see if we can use any of the substitution values
597513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // from the vector constructed above to replace c:\windows with, for
598201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // example, %systemroot%. The most collapsed path (the one with the
599201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // minimum length) wins.
600201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t min_length = MAXINT;
601201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  string16 location = entry->location;
602513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (PathMapping::const_iterator mapping = path_mapping_.begin();
603513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       mapping != path_mapping_.end(); ++mapping) {
604513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    string16 prefix = mapping->first;
605201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (StartsWith(location, prefix, false)) {
606201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      string16 new_location = mapping->second +
607201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              location.substr(prefix.length() - 1);
608201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      size_t length = new_location.length() - mapping->second.length();
609201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      if (length < min_length) {
610201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        entry->location = new_location;
611201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        min_length = length;
612201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      }
613513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
614513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
615513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
616513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
617513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ModuleEnumerator::MatchAgainstBlacklist() {
618513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (size_t m = 0; m < enumerated_modules_->size(); ++m) {
619513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Match this module against the blacklist.
620513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    Module* module = &(*enumerated_modules_)[m];
621513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module->status = GOOD;  // We change this below potentially.
622513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    for (size_t i = 0; i < arraysize(kModuleBlacklist); ++i) {
623513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      #if !defined(NDEBUG)
624513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        // This saves time when constructing the blacklist.
625513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        std::string hashes(kModuleBlacklist[i].filename);
626513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        std::string hash1, hash2, hash3;
627513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        GenerateHash(kModuleBlacklist[i].filename, &hash1);
628513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        hashes += " - " + hash1;
629513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        GenerateHash(kModuleBlacklist[i].location, &hash2);
630513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        hashes += " - " + hash2;
631513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        GenerateHash(kModuleBlacklist[i].desc_or_signer, &hash3);
632513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        hashes += " - " + hash3;
633513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      #endif
634513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
635513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ModuleStatus status = Match(*module, kModuleBlacklist[i]);
636513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (status != NOT_MATCHED) {
637513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        // We have a match against the blacklist. Mark it as such.
638513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        module->status = status;
639513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        module->recommended_action = kModuleBlacklist[i].help_tip;
640513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        break;
641513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      }
642513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
643201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
644201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Modules loaded from these locations are frequently malicious
645201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // and notorious for changing frequently so they are not good candidates
646201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // for blacklisting individually. Mark them as suspicious if we haven't
647201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // classified them as bad yet.
648201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (module->status == NOT_MATCHED || module->status == GOOD) {
649201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      if (StartsWith(module->location, L"%temp%", false) ||
650201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          StartsWith(module->location, L"%tmp%", false)) {
651201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        module->status = SUSPECTED_BAD;
652201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      }
653201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
654513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
655513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
656513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
657513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ModuleEnumerator::ReportBack() {
6583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!limited_mode_)
6593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_));
660513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  observer_->DoneScanning();
661513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
662513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
663513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstring16 ModuleEnumerator::GetSubjectNameFromDigitalSignature(
664513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const FilePath& filename) {
665513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  HCERTSTORE store = NULL;
666513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  HCRYPTMSG message = NULL;
667513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
668513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Find the crypto message for this filename.
669513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool result = !!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
670513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   filename.value().c_str(),
671513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
672513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   CERT_QUERY_FORMAT_FLAG_BINARY,
673513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   0,
674513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   NULL,
675513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   NULL,
676513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   NULL,
677513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   &store,
678513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   &message,
679513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   NULL);
680513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!result)
681513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return string16();
682513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
683513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Determine the size of the signer info data.
684513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DWORD signer_info_size = 0;
685513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  result = !!CryptMsgGetParam(message,
686513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              CMSG_SIGNER_INFO_PARAM,
687513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              0,
688513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              NULL,
689513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              &signer_info_size);
690513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!result)
691513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return string16();
692513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
693513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Allocate enough space to hold the signer info.
694513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_array<BYTE> signer_info_buffer(new BYTE[signer_info_size]);
695513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  CMSG_SIGNER_INFO* signer_info =
696513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get());
697513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
698513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Obtain the signer info.
699513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  result = !!CryptMsgGetParam(message,
700513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              CMSG_SIGNER_INFO_PARAM,
701513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              0,
702513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              signer_info,
703513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              &signer_info_size);
704513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!result)
705513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return string16();
706513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
707513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Search for the signer certificate.
708513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  CERT_INFO CertInfo = {0};
709513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PCCERT_CONTEXT cert_context = NULL;
710513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  CertInfo.Issuer = signer_info->Issuer;
711513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  CertInfo.SerialNumber = signer_info->SerialNumber;
712513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
713513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  cert_context = CertFindCertificateInStore(
714513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      store,
715513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
716513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      0,
717513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      CERT_FIND_SUBJECT_CERT,
718513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      &CertInfo,
719513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      NULL);
720513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!cert_context)
721513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return string16();
722513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
723513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Determine the size of the Subject name.
724513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DWORD subject_name_size = 0;
725513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!(subject_name_size = CertGetNameString(cert_context,
726513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                              CERT_NAME_SIMPLE_DISPLAY_TYPE,
727513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                              0,
728513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                              NULL,
729513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                              NULL,
730513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                              0))) {
731513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return string16();
732513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
733513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
734513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  string16 subject_name;
735513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  subject_name.resize(subject_name_size);
736513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
737513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Get subject name.
738513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!(CertGetNameString(cert_context,
739513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          CERT_NAME_SIMPLE_DISPLAY_TYPE,
740513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          0,
741513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          NULL,
742513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          const_cast<LPWSTR>(subject_name.c_str()),
743513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          subject_name_size))) {
744513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return string16();
745513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
746513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
747513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return subject_name;
748513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
749513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
750513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch//  ----------------------------------------------------------------------------
751513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
75221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// static
75321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenEnumerateModulesModel* EnumerateModulesModel::GetInstance() {
75421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return Singleton<EnumerateModulesModel>::get();
75521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
75621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool EnumerateModulesModel::ShouldShowConflictWarning() const {
758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the user has acknowledged the conflict notification, then we don't need
759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // to show it again (because the scanning only happens once per the lifetime
760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // of the process). If we were to run the scanning more than once, then we'd
761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // need to clear the flag somewhere when we are ready to show it again.
762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (conflict_notification_acknowledged_)
763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return confirmed_bad_modules_detected_ > 0;
766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid EnumerateModulesModel::AcknowledgeConflictNotification() {
769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!conflict_notification_acknowledged_) {
770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    conflict_notification_acknowledged_ = true;
771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NotificationService::current()->Notify(
772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NotificationType::MODULE_INCOMPATIBILITY_BADGE_CHANGE,
773ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        Source<EnumerateModulesModel>(this),
774ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NotificationService::NoDetails());
775ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
777ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
778513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid EnumerateModulesModel::ScanNow() {
779513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (scanning_)
780513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;  // A scan is already in progress.
781513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
782513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  lock->Acquire();  // Balanced in DoneScanning();
783513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
784513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scanning_ = true;
785513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
786513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Instruct the ModuleEnumerator class to load this on the File thread.
787513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // ScanNow does not block.
788513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!module_enumerator_)
789513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module_enumerator_ = new ModuleEnumerator(this);
7903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  module_enumerator_->ScanNow(&enumerated_modules_, limited_mode_);
791513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
792513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
793ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenListValue* EnumerateModulesModel::GetModuleList() const {
794513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (scanning_)
795513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return NULL;
796513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
797513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  lock->Acquire();
798513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
799513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (enumerated_modules_.empty()) {
800513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    lock->Release();
801513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return NULL;
802513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
803513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
804513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ListValue* list = new ListValue();
805513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
806513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (ModuleEnumerator::ModulesVector::const_iterator module =
807513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch           enumerated_modules_.begin();
808513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       module != enumerated_modules_.end(); ++module) {
809513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DictionaryValue* data = new DictionaryValue();
810513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetInteger("type", module->type);
811201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    string16 type_string;
812201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if ((module->type & ModuleEnumerator::LOADED_MODULE) == 0) {
813201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // Module is not loaded, denote type of module.
814201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      if (module->type & ModuleEnumerator::SHELL_EXTENSION)
815201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        type_string = ASCIIToWide("Shell Extension");
816201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      if (module->type & ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) {
817201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        if (!type_string.empty())
818201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          type_string += ASCIIToWide(", ");
819201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        type_string += ASCIIToWide("Winsock");
820201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      }
821201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // Must be one of the above type.
822201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      DCHECK(!type_string.empty());
8233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (!limited_mode_) {
8243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        type_string += ASCIIToWide(" -- ");
8253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        type_string += l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_LOADED_YET);
8263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      }
827201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
828201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    data->SetString("type_description", type_string);
829513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetInteger("status", module->status);
830513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetString("location", module->location);
831513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetString("name", module->name);
832513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetString("product_name", module->product_name);
833513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetString("description", module->description);
834201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    data->SetString("version", module->version);
835513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    data->SetString("digital_signer", module->digital_signer);
836513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
8373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    if (!limited_mode_) {
8383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      // Figure out the possible resolution help string.
8393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      string16 actions;
8403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      string16 separator = ASCIIToWide(" ") + l10n_util::GetStringUTF16(
8413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPERATOR) +
8423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          ASCIIToWide(" ");
843513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
8443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (module->recommended_action & ModuleEnumerator::NONE) {
8453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        actions = l10n_util::GetStringUTF16(
8463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            IDS_CONFLICTS_CHECK_INVESTIGATING);
8473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      }
8483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (module->recommended_action & ModuleEnumerator::UNINSTALL) {
8493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        if (!actions.empty())
8503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          actions += separator;
8513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        actions = l10n_util::GetStringUTF16(
8523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UNINSTALL);
8533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      }
8543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (module->recommended_action & ModuleEnumerator::UPDATE) {
8553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        if (!actions.empty())
8563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          actions += separator;
8573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        actions += l10n_util::GetStringUTF16(
8583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UPDATE);
8593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      }
8603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (module->recommended_action & ModuleEnumerator::DISABLE) {
8613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        if (!actions.empty())
8623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          actions += separator;
8633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        actions += l10n_util::GetStringUTF16(
8643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_DISABLE);
8653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      }
8663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      string16 possible_resolution = actions.empty() ? ASCIIToWide("") :
8673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_POSSIBLE_ACTIONS) +
8683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          ASCIIToWide(" ") +
8693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen          actions;
8703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      data->SetString("possibleResolution", possible_resolution);
8713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      data->SetString("help_url",
8723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      ConstructHelpCenterUrl(*module).spec().c_str());
873513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
874513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
875513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    list->Append(data);
876513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
877513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
878513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  lock->Release();
879513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return list;
880513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
881513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
882513209b27ff55e2841eac0e4120199c23acce758Ben MurdochEnumerateModulesModel::EnumerateModulesModel()
883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : limited_mode_(false),
884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      scanning_(false),
885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      conflict_notification_acknowledged_(false),
8864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      confirmed_bad_modules_detected_(0),
8874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      suspected_bad_modules_detected_(0) {
888513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
889513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (cmd_line.HasSwitch(switches::kConflictingModulesCheck)) {
890513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    check_modules_timer_.Start(
8914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs),
8924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        this, &EnumerateModulesModel::ScanNow);
893513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
894513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  lock = new base::Lock();
896513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
897513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
898513209b27ff55e2841eac0e4120199c23acce758Ben MurdochEnumerateModulesModel::~EnumerateModulesModel() {
899513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  delete lock;
900513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
901513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
902513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid EnumerateModulesModel::DoneScanning() {
903513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  confirmed_bad_modules_detected_ = 0;
904513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  suspected_bad_modules_detected_ = 0;
905513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (ModuleEnumerator::ModulesVector::const_iterator module =
906513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    enumerated_modules_.begin();
907513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    module != enumerated_modules_.end(); ++module) {
908513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (module->status == ModuleEnumerator::CONFIRMED_BAD)
909513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        ++confirmed_bad_modules_detected_;
910513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (module->status == ModuleEnumerator::SUSPECTED_BAD)
911513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        ++suspected_bad_modules_detected_;
912513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
913513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
914513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scanning_ = false;
915513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  lock->Release();
916513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
9173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  UMA_HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules",
9183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                           suspected_bad_modules_detected_);
9193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  UMA_HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules",
9203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                           confirmed_bad_modules_detected_);
9213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
9223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Notifications are not available in limited mode.
9233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (limited_mode_)
9243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return;
925201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
926513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NotificationService::current()->Notify(
927513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      NotificationType::MODULE_LIST_ENUMERATED,
928513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      Source<EnumerateModulesModel>(this),
929513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      NotificationService::NoDetails());
930513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
9313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Command line flag must be enabled for the notification to get sent out.
9323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Otherwise we'd get the badge (while the feature is disabled) when we
9333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // navigate to about:conflicts and find confirmed matches.
9343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
9353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!cmd_line.HasSwitch(switches::kConflictingModulesCheck))
9363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return;
9373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NotificationService::current()->Notify(
939ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::MODULE_INCOMPATIBILITY_BADGE_CHANGE,
940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      Source<EnumerateModulesModel>(this),
941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::NoDetails());
942513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
943513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
944513209b27ff55e2841eac0e4120199c23acce758Ben MurdochGURL EnumerateModulesModel::ConstructHelpCenterUrl(
945ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ModuleEnumerator::Module& module) const {
946513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!(module.recommended_action & ModuleEnumerator::SEE_LINK))
947513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return GURL();
948513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
949513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Construct the needed hashes.
950513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string filename, location, description, signer;
951513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GenerateHash(WideToUTF8(module.name), &filename);
952513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GenerateHash(WideToUTF8(module.location), &location);
953513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GenerateHash(WideToUTF8(module.description), &description);
954513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GenerateHash(WideToUTF8(module.digital_signer), &signer);
955513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
9563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  string16 url = l10n_util::GetStringFUTF16(IDS_HELP_CENTER_VIEW_CONFLICTS,
9573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      ASCIIToUTF16(filename), ASCIIToUTF16(location),
9583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      ASCIIToUTF16(description), ASCIIToUTF16(signer));
9593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return GURL(UTF16ToUTF8(url));
960513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
961