15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/enumerate_modules_model_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Tlhelp32.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wintrust.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_version_info_win.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/version.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/win/windows_version.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/service_providers_win.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "crypto/sha2.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The period of time (in milliseconds) to wait until checking to see if any
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// incompatible modules exist.
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const int kModuleCheckDelayMs = 45 * 1000;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The path to the Shell Extension key in the Windows registry.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const wchar_t kRegPath[] =
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Short-hand for things on the blacklist you should simply get rid of.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ModuleEnumerator::RecommendedAction kUninstallLink =
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<ModuleEnumerator::RecommendedAction>(
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ModuleEnumerator::UNINSTALL | ModuleEnumerator::SEE_LINK);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Short-hand for things on the blacklist we are investigating and have info.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ModuleEnumerator::RecommendedAction kInvestigatingLink =
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<ModuleEnumerator::RecommendedAction>(
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ModuleEnumerator::INVESTIGATING | ModuleEnumerator::SEE_LINK);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A sort method that sorts by bad modules first, then by full name (including
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// path).
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool ModuleSort(const ModuleEnumerator::Module& a,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const ModuleEnumerator::Module& b) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (a.status != b.status)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a.status > b.status;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (a.location == b.location)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a.name < b.name;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return a.location < b.location;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to protect the LoadedModuleVector which is accessed
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from both the UI thread and the FILE thread.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Lock* lock = NULL;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A struct to help de-duping modules before adding them to the enumerated
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modules vector.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FindModule {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit FindModule(const ModuleEnumerator::Module& x)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : module(x) {}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const ModuleEnumerator::Module& module_in) const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (module.location == module_in.location) &&
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (module.name == module_in.name);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ModuleEnumerator::Module& module;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the long path name given a short path name. A short path name is a
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// path that follows the 8.3 convention and has ~x in it. If the path is already
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a long path name, the function returns the current path without modification.
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ConvertToLongPath(const base::string16& short_path,
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       base::string16* long_path) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t long_path_buf[MAX_PATH];
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD return_value = GetLongPathName(short_path.c_str(), long_path_buf,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       MAX_PATH);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (return_value != 0 && return_value < MAX_PATH) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *long_path = long_path_buf;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The browser process module blacklist. This lists modules that are known
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to cause compatibility issues within the browser process. When adding to this
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list, make sure that all paths are lower-case, in long pathname form, end
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with a slash and use environments variables (or just look at one of the
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// comments below and keep it consistent with that). When adding an entry with
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an environment variable not currently used in the list below, make sure to
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// update the list in PreparePathMappings. Filename, Description/Signer, and
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Location must be entered as hashes (see GenerateHash). Filename is mandatory.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Entries without any Description, Signer info, or Location will never be
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// marked as confirmed bad (only as suspicious).
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ModuleEnumerator::BlacklistEntry ModuleEnumerator::kModuleBlacklist[] = {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Please keep this list sorted by dll name, then location.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Version 3.2.1.6 seems to be implicated in most cases (and 3.2.2.2 in some).
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is a more recent version available for download.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // accelerator.dll, "%programfiles%\\speedbit video accelerator\\".
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "7ba9402f", "c9132d48", "", "", "", ALL, kInvestigatingLink },
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // apiqq0.dll, "%temp%\\".
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "26134911", "59145acf", "", "", "", ALL, kUninstallLink },
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // arking0.dll, "%systemroot%\\system32\\".
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "f5d8f549", "23d01d5b", "", "", "", ALL, kUninstallLink },
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // arking1.dll, "%systemroot%\\system32\\".
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "c60ca062", "23d01d5b", "", "", "", ALL, kUninstallLink },
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // aswjsflt.dll, "%ProgramFiles%\\avast software\\avast\\", "AVAST Software".
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // NOTE: The digital signature of the DLL is double null terminated.
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // when blocked from running.
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "2ea5422a", "6b3a1b00", "a7db0e0c", "", "8.0", XP,
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // aswjsflt.dll, "%ProgramFiles%\\alwil software\\avast5\\", "AVAST Software".
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // NOTE: The digital signature of the DLL is double null terminated.
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // when blocked from running.
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "2ea5422a", "d8686924", "a7db0e0c", "", "8.0", XP,
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Said to belong to Killer NIC from BigFoot Networks (not verified). Versions
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 6.0.0.7 and 6.0.0.10 implicated.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bfllr.dll, "%systemroot%\\system32\\".
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "6bb57633", "23d01d5b", "", "", "", ALL, kInvestigatingLink },
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clickpotatolitesahook.dll, "". Different version each report.
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "0396e037.dll", "", "", "", "", ALL, kUninstallLink },
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cvasds0.dll, "%temp%\\".
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "5ce0037c", "59145acf", "", "", "", ALL, kUninstallLink },
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cwalsp.dll, "%systemroot%\\system32\\".
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "e579a039", "23d01d5b", "", "", "", ALL, kUninstallLink },
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // datamngr.dll (1), "%programfiles%\\searchqu toolbar\\datamngr\\".
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "7add320b", "470a3da3", "", "", "", ALL, kUninstallLink },
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // datamngr.dll (2), "%programfiles%\\windows searchqu toolbar\\".
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "7add320b", "7a3c8be3", "", "", "", ALL, kUninstallLink },
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dsoqq0.dll, "%temp%\\".
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "1c4df325", "59145acf", "", "", "", ALL, kUninstallLink },
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // flt.dll, "%programfiles%\\tueagles\\".
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "6d01f4a1", "7935e9c2", "", "", "", ALL, kUninstallLink },
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This looks like a malware edition of a Brazilian Bank plugin, sometimes
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // referred to as Malware.Banc.A.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // gbieh.dll, "%programfiles%\\gbplugin\\".
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "4cb4f2e3", "88e4a3b1", "", "", "", ALL, kUninstallLink },
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hblitesahook.dll. Each report has different version number in location.
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "5d10b363", "", "", "", "", ALL, kUninstallLink },
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icf.dll, "%systemroot%\\system32\\".
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "303825ed", "23d01d5b", "", "", "", ALL, INVESTIGATING },
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // idmmbc.dll (IDM), "%systemroot%\\system32\\". See: http://crbug.com/26892/.
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "b8dce5c3", "23d01d5b", "", "", "6.03", ALL,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<RecommendedAction>(UPDATE | DISABLE) },
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // imon.dll (NOD32), "%systemroot%\\system32\\". See: http://crbug.com/21715.
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "8f42f22e", "23d01d5b", "", "", "4.0", ALL,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<RecommendedAction>(UPDATE | DISABLE) },
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is3lsp.dll, "%commonprogramfiles%\\is3\\anti-spyware\\".
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "7ffbdce9", "bc5673f2", "", "", "", ALL,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<RecommendedAction>(UPDATE | DISABLE | SEE_LINK) },
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // jsi.dll, "%programfiles%\\profilecraze\\".
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "f9555eea", "e3548061", "", "", "", ALL, kUninstallLink },
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kernel.dll, "%programfiles%\\contentwatch\\internet protection\\modules\\".
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "ead2768e", "4e61ce60", "", "", "", ALL, INVESTIGATING },
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mgking0.dll, "%systemroot%\\system32\\".
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "d0893e38", "23d01d5b", "", "", "", ALL, kUninstallLink },
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mgking0.dll, "%temp%\\".
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "d0893e38", "59145acf", "", "", "", ALL, kUninstallLink },
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mgking1.dll, "%systemroot%\\system32\\".
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "3e837222", "23d01d5b", "", "", "", ALL, kUninstallLink },
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mgking1.dll, "%temp%\\".
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "3e837222", "59145acf", "", "", "", ALL, kUninstallLink },
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mstcipha.ime, "%systemroot%\\system32\\".
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "5523579e", "23d01d5b", "", "", "", ALL, INVESTIGATING },
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mwtsp.dll, "%systemroot%\\system32\\".
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "9830bff6", "23d01d5b", "", "", "", ALL, kUninstallLink },
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nodqq0.dll, "%temp%\\".
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "b86ce04d", "59145acf", "", "", "", ALL, kUninstallLink },
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nProtect GameGuard Anti-cheat system. Every report has a different
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // location, since it is installed into and run from a game folder. Various
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // versions implicated.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // npggnt.des, no fixed location.
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "f2c8790d", "", "", "", "", ALL, kInvestigatingLink },
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nvlsp.dll,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "%programfiles%\\nvidia corporation\\networkaccessmanager\\bin32\\".
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "37f907e2", "3ad0ff23", "", "", "", ALL, INVESTIGATING },
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // post0.dll, "%systemroot%\\system32\\".
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "7405c0c8", "23d01d5b", "", "", "", ALL, kUninstallLink },
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // questbrwsearch.dll, "%programfiles%\\questbrwsearch\\".
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "0953ed09", "f0d5eeda", "", "", "", ALL, kUninstallLink },
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // questscan.dll, "%programfiles%\\questscan\\".
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "f4f3391e", "119d20f7", "", "", "", ALL, kUninstallLink },
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // radhslib.dll (Naomi web filter), "%programfiles%\\rnamfler\\".
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://crbug.com/12517.
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "7edcd250", "0733dc3e", "", "", "", ALL, INVESTIGATING },
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rlls.dll, "%programfiles%\\relevantknowledge\\".
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "a1ed94a7", "ea9d6b36", "", "", "", ALL, kUninstallLink },
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rooksdol.dll, "%programfiles%\\trusteer\\rapport\\bin\\".
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "802aefef", "06120e13", "", "", "3.5.1008.40", ALL, UPDATE },
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scanquery.dll, "%programfiles%\\scanquery\\".
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "0b52d2ae", "a4cc88b1", "", "", "", ALL, kUninstallLink },
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sdata.dll, "%programdata%\\srtserv\\".
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "1936d5cc", "223c44be", "", "", "", ALL, kUninstallLink },
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // searchtree.dll,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "%programfiles%\\contentwatch\\internet protection\\modules\\".
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "f6915a31", "4e61ce60", "", "", "", ALL, INVESTIGATING },
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sgprxy.dll, "%commonprogramfiles%\\is3\\anti-spyware\\".
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "005965ea", "bc5673f2", "", "", "", ALL, INVESTIGATING },
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // snxhk.dll, "%ProgramFiles%\\avast software\\avast\\", "AVAST Software".
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // NOTE: The digital signature of the DLL is double null terminated.
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // when blocked from running.
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "46c16aa8", "6b3a1b00", "a7db0e0c", "", "8.0", XP,
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // snxhk.dll, "%ProgramFiles%\\alwil software\\avast5\\", "AVAST Software".
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // NOTE: The digital signature of the DLL is double null terminated.
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // when blocked from running.
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "46c16aa8", "d8686924", "a7db0e0c", "", "8.0", XP,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // sprotector.dll, "". Different location each report.
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "24555d74", "", "", "", "", ALL, kUninstallLink },
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // swi_filter_0001.dll (Sophos Web Intelligence),
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "%programfiles%\\sophos\\sophos anti-virus\\web intelligence\\".
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A small random sample all showed version 1.0.5.0.
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "61112d7b", "25fb120f", "", "", "", ALL, kInvestigatingLink },
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // twking0.dll, "%systemroot%\\system32\\".
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "0355549b", "23d01d5b", "", "", "", ALL, kUninstallLink },
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // twking1.dll, "%systemroot%\\system32\\".
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "02e44508", "23d01d5b", "", "", "", ALL, kUninstallLink },
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // vksaver.dll, "%systemroot%\\system32\\".
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "c4a784d5", "23d01d5b", "", "", "", ALL, kUninstallLink },
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // vlsp.dll (Venturi Firewall?), "%systemroot%\\system32\\".
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "2e4eb93d", "23d01d5b", "", "", "", ALL, INVESTIGATING },
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // vmn3_1dn.dll, "%appdata%\\roaming\\vmndtxtb\\".
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "bba2037d", "9ab68585", "", "", "", ALL, kUninstallLink },
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // webanalyzer.dll,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "%programfiles%\\contentwatch\\internet protection\\modules\\".
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "c70b697d", "4e61ce60", "", "", "", ALL, INVESTIGATING },
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wowst0.dll, "%systemroot%\\system32\\".
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "38ad9963", "23d01d5b", "", "", "", ALL, kUninstallLink },
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wxbase28u_vc_cw.dll, "%systemroot%\\system32\\".
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  { "e967210d", "23d01d5b", "", "", "", ALL, kUninstallLink },
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generates an 8 digit hash from the input given.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void GenerateHash(const std::string& input, std::string* output) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (input.empty()) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *output = "";
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 hash[4];
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::SHA256HashString(input, hash, sizeof(hash));
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  *output = base::StringToLowerASCII(base::HexEncode(hash, sizeof(hash)));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::NormalizeModule(Module* module) {
329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 path = module->location;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ConvertToLongPath(path, &module->location))
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->location = path;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->location = base::i18n::ToLower(module->location);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Location contains the filename, so the last slash is where the path
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ends.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t last_slash = module->location.find_last_of(L"\\");
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (last_slash != base::string16::npos) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->name = module->location.substr(last_slash + 1);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->location = module->location.substr(0, last_slash + 1);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->name = module->location;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->location.clear();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some version strings have things like (win7_rtm.090713-1255) appended
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to them. Remove that.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t first_space = module->version.find_first_of(L" ");
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (first_space != base::string16::npos)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->version = module->version.substr(0, first_space);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->normalized = true;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModuleEnumerator::ModuleStatus ModuleEnumerator::Match(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModuleEnumerator::Module& module,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModuleEnumerator::BlacklistEntry& blacklisted) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All modules must be normalized before matching against blacklist.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(module.normalized);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Filename is mandatory and version should not contain spaces.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(strlen(blacklisted.filename) > 0);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!strstr(blacklisted.version_from, " "));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!strstr(blacklisted.version_to, " "));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::win::Version version = base::win::GetVersion();
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch (version) {
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)     case base::win::VERSION_XP:
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!(blacklisted.os & XP)) return NOT_MATCHED;
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    default:
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename_hash, location_hash;
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateHash(base::WideToUTF8(module.name), &filename_hash);
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateHash(base::WideToUTF8(module.location), &location_hash);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Filenames are mandatory. Location is mandatory if given.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filename_hash == blacklisted.filename &&
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (std::string(blacklisted.location).empty() ||
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          location_hash == blacklisted.location)) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have a name match against the blacklist (and possibly location match
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // also), so check version.
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Version module_version(base::UTF16ToASCII(module.version));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Version version_min(blacklisted.version_from);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Version version_max(blacklisted.version_to);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool version_ok = !version_min.IsValid() && !version_max.IsValid();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!version_ok) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool too_low = version_min.IsValid() &&
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (!module_version.IsValid() ||
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          module_version.CompareTo(version_min) < 0);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool too_high = version_max.IsValid() &&
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (!module_version.IsValid() ||
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          module_version.CompareTo(version_max) >= 0);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version_ok = !too_low && !too_high;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (version_ok) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // At this point, the names match and there is no version specified
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // or the versions also match.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string desc_or_signer(blacklisted.desc_or_signer);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string signer_hash, description_hash;
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GenerateHash(base::WideToUTF8(module.digital_signer), &signer_hash);
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GenerateHash(base::WideToUTF8(module.description), &description_hash);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If signatures match (or both are empty), then we have a winner.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (signer_hash == desc_or_signer)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return CONFIRMED_BAD;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If descriptions match (or both are empty) and the locations match, then
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // we also have a confirmed match.
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (description_hash == desc_or_signer &&
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          !location_hash.empty() && location_hash == blacklisted.location)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return CONFIRMED_BAD;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We are not sure, but it is likely bad.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SUSPECTED_BAD;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NOT_MATCHED;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : enumerated_modules_(NULL),
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(observer),
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      limited_mode_(false),
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_thread_id_(BrowserThread::ID_COUNT) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModuleEnumerator::~ModuleEnumerator() {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::ScanNow(ModulesVector* list, bool limited_mode) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enumerated_modules_ = list;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  limited_mode_ = limited_mode;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!limited_mode_) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_));
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::Bind(&ModuleEnumerator::ScanImpl, this));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Run it synchronously.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScanImpl();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::ScanImpl() {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks start_time = base::TimeTicks::Now();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enumerated_modules_->clear();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the path mapping vector is setup so we can collapse paths.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PreparePathMappings();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enumerating loaded modules must happen first since the other types of
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modules check for duplication against the loaded modules.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks checkpoint = base::TimeTicks::Now();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumerateLoadedModules();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks checkpoint2 = base::TimeTicks::Now();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateLoadedModules",
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      checkpoint2 - checkpoint);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checkpoint = checkpoint2;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumerateShellExtensions();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checkpoint2 = base::TimeTicks::Now();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateShellExtensions",
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      checkpoint2 - checkpoint);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checkpoint = checkpoint2;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumerateWinsockModules();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checkpoint2 = base::TimeTicks::Now();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules",
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      checkpoint2 - checkpoint);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MatchAgainstBlacklist();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(enumerated_modules_->begin(),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            enumerated_modules_->end(), ModuleSort);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!limited_mode_) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send a reply back on the UI thread.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(callback_thread_id_, FROM_HERE,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::Bind(&ModuleEnumerator::ReportBack, this));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are on the main thread already.
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportBack();
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("Conflicts.EnumerationTotalTime",
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::TimeTicks::Now() - start_time);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::EnumerateLoadedModules() {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get all modules in the current process.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ::GetCurrentProcessId()));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!snap.Get())
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Walk the module list.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MODULEENTRY32 module = { sizeof(module) };
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::Module32First(snap.Get(), &module))
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It would be weird to present chrome.exe as a loaded module.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (_wcsicmp(chrome::kBrowserProcessExecutableName, module.szModule) == 0)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Module entry;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.type = LOADED_MODULE;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.location = module.szExePath;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PopulateModuleInformation(&entry);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NormalizeModule(&entry);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CollapsePath(&entry);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enumerated_modules_->push_back(entry);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (::Module32Next(snap.Get(), &module));
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::EnumerateShellExtensions() {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadShellExtensions(HKEY_LOCAL_MACHINE);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadShellExtensions(HKEY_CURRENT_USER);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::ReadShellExtensions(HKEY parent) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegistryValueIterator registration(parent, kRegPath);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (registration.Valid()) {
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring key(std::wstring(L"CLSID\\") + registration.Name() +
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        L"\\InProcServer32");
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::RegKey clsid;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ) != ERROR_SUCCESS) {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++registration;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 dll;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (clsid.ReadValue(L"", &dll) != ERROR_SUCCESS) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++registration;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clsid.Close();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Module entry;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.type = SHELL_EXTENSION;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.location = dll;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PopulateModuleInformation(&entry);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NormalizeModule(&entry);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CollapsePath(&entry);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToListWithoutDuplicating(entry);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++registration;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::EnumerateWinsockModules() {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add to this list the Winsock LSP DLLs.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WinsockLayeredServiceProviderList layered_providers;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetWinsockLayeredServiceProviders(&layered_providers);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < layered_providers.size(); ++i) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Module entry;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.type = WINSOCK_MODULE_REGISTRATION;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.status = NOT_MATCHED;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.normalized = false;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.location = layered_providers[i].path;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.description = layered_providers[i].name;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.recommended_action = NONE;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.duplicate_count = 0;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t expanded[MAX_PATH];
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD size = ExpandEnvironmentStrings(
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry.location.c_str(), expanded, MAX_PATH);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size != 0 && size <= MAX_PATH) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry.digital_signer =
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetSubjectNameFromDigitalSignature(base::FilePath(expanded));
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.version = base::IntToString16(layered_providers[i].version);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Paths have already been collapsed.
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NormalizeModule(&entry);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToListWithoutDuplicating(entry);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::PopulateModuleInformation(Module* module) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->status = NOT_MATCHED;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->duplicate_count = 0;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->normalized = false;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->digital_signer =
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetSubjectNameFromDigitalSignature(base::FilePath(module->location));
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module->recommended_action = NONE;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FileVersionInfo> version_info(
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileVersionInfo::CreateFileVersionInfo(base::FilePath(module->location)));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version_info.get()) {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileVersionInfoWin* version_info_win =
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<FileVersionInfoWin*>(version_info.get());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info();
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fixed_file_info) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module->description = version_info_win->file_description();
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module->version = version_info_win->file_version();
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module->product_name = version_info_win->product_name();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::AddToListWithoutDuplicating(const Module& module) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(module.normalized);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These are registered modules, not loaded modules so the same module
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can be registered multiple times, often dozens of times. There is no need
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to list each registration, so we just increment the count for each module
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that is counted multiple times.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModulesVector::iterator iter;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter = std::find_if(enumerated_modules_->begin(),
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      enumerated_modules_->end(),
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      FindModule(module));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter != enumerated_modules_->end()) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter->duplicate_count++;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter->type = static_cast<ModuleType>(iter->type | module.type);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enumerated_modules_->push_back(module);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::PreparePathMappings() {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path_mapping_.clear();
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> environment(base::Environment::Create());
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<base::string16> env_vars;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"LOCALAPPDATA");
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"ProgramFiles");
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"ProgramData");
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"USERPROFILE");
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"SystemRoot");
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"TEMP");
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"TMP");
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env_vars.push_back(L"CommonProgramFiles");
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::vector<base::string16>::const_iterator variable = env_vars.begin();
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       variable != env_vars.end(); ++variable) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string path;
645a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (environment->GetVar(base::UTF16ToASCII(*variable).c_str(), &path)) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path_mapping_.push_back(
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          std::make_pair(base::i18n::ToLower(base::UTF8ToUTF16(path)) + L"\\",
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         L"%" + base::i18n::ToLower(*variable) + L"%"));
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::CollapsePath(Module* entry) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take the path and see if we can use any of the substitution values
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the vector constructed above to replace c:\windows with, for
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // example, %systemroot%. The most collapsed path (the one with the
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // minimum length) wins.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t min_length = MAXINT;
659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 location = entry->location;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PathMapping::const_iterator mapping = path_mapping_.begin();
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       mapping != path_mapping_.end(); ++mapping) {
662a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 prefix = mapping->first;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (StartsWith(location, prefix, false)) {
664a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 new_location = mapping->second +
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              location.substr(prefix.length() - 1);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t length = new_location.length() - mapping->second.length();
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (length < min_length) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry->location = new_location;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        min_length = length;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::MatchAgainstBlacklist() {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t m = 0; m < enumerated_modules_->size(); ++m) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Match this module against the blacklist.
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Module* module = &(*enumerated_modules_)[m];
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module->status = GOOD;  // We change this below potentially.
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < arraysize(kModuleBlacklist); ++i) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      #if !defined(NDEBUG)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This saves time when constructing the blacklist.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string hashes(kModuleBlacklist[i].filename);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string hash1, hash2, hash3;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GenerateHash(kModuleBlacklist[i].filename, &hash1);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hashes += " - " + hash1;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GenerateHash(kModuleBlacklist[i].location, &hash2);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hashes += " - " + hash2;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GenerateHash(kModuleBlacklist[i].desc_or_signer, &hash3);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hashes += " - " + hash3;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      #endif
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ModuleStatus status = Match(*module, kModuleBlacklist[i]);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (status != NOT_MATCHED) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We have a match against the blacklist. Mark it as such.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        module->status = status;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        module->recommended_action = kModuleBlacklist[i].help_tip;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Modules loaded from these locations are frequently malicious
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and notorious for changing frequently so they are not good candidates
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for blacklisting individually. Mark them as suspicious if we haven't
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // classified them as bad yet.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (module->status == NOT_MATCHED || module->status == GOOD) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (StartsWith(module->location, L"%temp%", false) ||
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          StartsWith(module->location, L"%tmp%", false)) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        module->status = SUSPECTED_BAD;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ModuleEnumerator::ReportBack() {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!limited_mode_)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->DoneScanning();
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 ModuleEnumerator::GetSubjectNameFromDigitalSignature(
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& filename) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HCERTSTORE store = NULL;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HCRYPTMSG message = NULL;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the crypto message for this filename.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = !!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   filename.value().c_str(),
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   CERT_QUERY_FORMAT_FLAG_BINARY,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   0,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   NULL,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   NULL,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   NULL,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &store,
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &message,
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   NULL);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result)
739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the size of the signer info data.
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD signer_info_size = 0;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = !!CryptMsgGetParam(message,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CMSG_SIGNER_INFO_PARAM,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0,
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              NULL,
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &signer_info_size);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result)
749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate enough space to hold the signer info.
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<BYTE[]> signer_info_buffer(new BYTE[signer_info_size]);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CMSG_SIGNER_INFO* signer_info =
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get());
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the signer info.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = !!CryptMsgGetParam(message,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CMSG_SIGNER_INFO_PARAM,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              signer_info,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &signer_info_size);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result)
763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search for the signer certificate.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_INFO CertInfo = {0};
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PCCERT_CONTEXT cert_context = NULL;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertInfo.Issuer = signer_info->Issuer;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertInfo.SerialNumber = signer_info->SerialNumber;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_context = CertFindCertificateInStore(
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      store,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_FIND_SUBJECT_CERT,
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CertInfo,
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cert_context)
779a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the size of the Subject name.
782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DWORD subject_name_size = CertGetNameString(
783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      cert_context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!subject_name_size)
785a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
787a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 subject_name;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subject_name.resize(subject_name_size);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get subject name.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(CertGetNameString(cert_context,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          CERT_NAME_SIMPLE_DISPLAY_TYPE,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          0,
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NULL,
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const_cast<LPWSTR>(subject_name.c_str()),
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          subject_name_size))) {
797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return subject_name;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  ----------------------------------------------------------------------------
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumerateModulesModel* EnumerateModulesModel::GetInstance() {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<EnumerateModulesModel>::get();
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EnumerateModulesModel::ShouldShowConflictWarning() const {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the user has acknowledged the conflict notification, then we don't need
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to show it again (because the scanning only happens once per the lifetime
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the process). If we were to run the scanning more than once, then we'd
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to clear the flag somewhere when we are ready to show it again.
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (conflict_notification_acknowledged_)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return confirmed_bad_modules_detected_ > 0;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumerateModulesModel::AcknowledgeConflictNotification() {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!conflict_notification_acknowledged_) {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    conflict_notification_acknowledged_ = true;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<EnumerateModulesModel>(this),
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NotificationService::NoDetails());
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumerateModulesModel::ScanNow() {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scanning_)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // A scan is already in progress.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock->Acquire();  // Balanced in DoneScanning();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scanning_ = true;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Instruct the ModuleEnumerator class to load this on the File thread.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ScanNow does not block.
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!module_enumerator_)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module_enumerator_ = new ModuleEnumerator(this);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module_enumerator_->ScanNow(&enumerated_modules_, limited_mode_);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* EnumerateModulesModel::GetModuleList() const {
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scanning_)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock->Acquire();
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enumerated_modules_.empty()) {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock->Release();
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* list = new base::ListValue();
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ModuleEnumerator::ModulesVector::const_iterator module =
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           enumerated_modules_.begin();
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       module != enumerated_modules_.end(); ++module) {
8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* data = new base::DictionaryValue();
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetInteger("type", module->type);
864a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 type_string;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((module->type & ModuleEnumerator::LOADED_MODULE) == 0) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Module is not loaded, denote type of module.
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (module->type & ModuleEnumerator::SHELL_EXTENSION)
8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        type_string = base::ASCIIToWide("Shell Extension");
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (module->type & ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!type_string.empty())
8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          type_string += base::ASCIIToWide(", ");
8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        type_string += base::ASCIIToWide("Winsock");
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Must be one of the above type.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!type_string.empty());
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!limited_mode_) {
8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        type_string += base::ASCIIToWide(" -- ");
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        type_string += l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_LOADED_YET);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("type_description", type_string);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetInteger("status", module->status);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("location", module->location);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("name", module->name);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("product_name", module->product_name);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("description", module->description);
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("version", module->version);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetString("digital_signer", module->digital_signer);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!limited_mode_) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Figure out the possible resolution help string.
892a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 actions;
8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::string16 separator = base::ASCIIToWide(" ") +
8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          l10n_util::GetStringUTF16(
8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPARATOR) +
8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::ASCIIToWide(" ");
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (module->recommended_action & ModuleEnumerator::NONE) {
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        actions = l10n_util::GetStringUTF16(
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IDS_CONFLICTS_CHECK_INVESTIGATING);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (module->recommended_action & ModuleEnumerator::UNINSTALL) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!actions.empty())
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          actions += separator;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        actions = l10n_util::GetStringUTF16(
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UNINSTALL);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (module->recommended_action & ModuleEnumerator::UPDATE) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!actions.empty())
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          actions += separator;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        actions += l10n_util::GetStringUTF16(
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UPDATE);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (module->recommended_action & ModuleEnumerator::DISABLE) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!actions.empty())
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          actions += separator;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        actions += l10n_util::GetStringUTF16(
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_DISABLE);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::string16 possible_resolution =
9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          actions.empty() ? base::ASCIIToWide("")
9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          : l10n_util::GetStringUTF16(
9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                IDS_CONFLICTS_CHECK_POSSIBLE_ACTIONS) +
9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::ASCIIToWide(" ") +
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          actions;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data->SetString("possibleResolution", possible_resolution);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data->SetString("help_url",
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ConstructHelpCenterUrl(*module).spec().c_str());
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list->Append(data);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock->Release();
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return list;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)GURL EnumerateModulesModel::GetFirstNotableConflict() {
939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  lock->Acquire();
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GURL url;
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (enumerated_modules_.empty()) {
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    lock->Release();
944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return GURL();
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (ModuleEnumerator::ModulesVector::const_iterator module =
948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           enumerated_modules_.begin();
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       module != enumerated_modules_.end(); ++module) {
950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!(module->recommended_action & ModuleEnumerator::NOTIFY_USER))
951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    url = ConstructHelpCenterUrl(*module);
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(url.is_valid());
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    break;
956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  lock->Release();
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return url;
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumerateModulesModel::EnumerateModulesModel()
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : limited_mode_(false),
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scanning_(false),
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      conflict_notification_acknowledged_(false),
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      confirmed_bad_modules_detected_(0),
968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      suspected_bad_modules_detected_(0),
969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      modules_to_notify_about_(0) {
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock = new base::Lock();
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumerateModulesModel::~EnumerateModulesModel() {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete lock;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
977868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void EnumerateModulesModel::MaybePostScanningTask() {
978868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static bool done = false;
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!done) {
980868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    done = true;
981868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
982868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
983cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (base::win::GetVersion() == base::win::VERSION_XP) {
984868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      check_modules_timer_.Start(FROM_HERE,
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs),
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          this, &EnumerateModulesModel::ScanNow);
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
989868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumerateModulesModel::DoneScanning() {
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  confirmed_bad_modules_detected_ = 0;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suspected_bad_modules_detected_ = 0;
994868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  modules_to_notify_about_ = 0;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ModuleEnumerator::ModulesVector::const_iterator module =
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       enumerated_modules_.begin();
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       module != enumerated_modules_.end(); ++module) {
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (module->status == ModuleEnumerator::CONFIRMED_BAD) {
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ++confirmed_bad_modules_detected_;
1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (module->recommended_action & ModuleEnumerator::NOTIFY_USER)
1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ++modules_to_notify_about_;
1002868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (module->status == ModuleEnumerator::SUSPECTED_BAD) {
1003868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ++suspected_bad_modules_detected_;
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (module->recommended_action & ModuleEnumerator::NOTIFY_USER)
1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ++modules_to_notify_about_;
1006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scanning_ = false;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock->Release();
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules",
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           suspected_bad_modules_detected_);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules",
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           confirmed_bad_modules_detected_);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifications are not available in limited mode.
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (limited_mode_)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_MODULE_LIST_ENUMERATED,
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<EnumerateModulesModel>(this),
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::NoDetails());
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL EnumerateModulesModel::ConstructHelpCenterUrl(
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModuleEnumerator::Module& module) const {
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!(module.recommended_action & ModuleEnumerator::SEE_LINK) &&
1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !(module.recommended_action & ModuleEnumerator::NOTIFY_USER))
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GURL();
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the needed hashes.
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename, location, description, signer;
10355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateHash(base::WideToUTF8(module.name), &filename);
10365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateHash(base::WideToUTF8(module.location), &location);
10375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateHash(base::WideToUTF8(module.description), &description);
10385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateHash(base::WideToUTF8(module.digital_signer), &signer);
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1040a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 url =
1041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      l10n_util::GetStringFUTF16(IDS_HELP_CENTER_VIEW_CONFLICTS,
10425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::ASCIIToUTF16(filename), base::ASCIIToUTF16(location),
10435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::ASCIIToUTF16(description), base::ASCIIToUTF16(signer));
10445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GURL(base::UTF16ToUTF8(url));
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1046