Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / enumerate_modules_model_win.h
bloba0a6b27f48ca4dcfc92e8388855bd4fa834d954a
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_ENUMERATE_MODULES_MODEL_WIN_H_
6 #define CHROME_BROWSER_ENUMERATE_MODULES_MODEL_WIN_H_
8 #include <utility>
9 #include <vector>
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/singleton.h"
14 #include "base/strings/string16.h"
15 #include "base/timer/timer.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "url/gurl.h"
19 class EnumerateModulesModel;
21 namespace base {
22 class FilePath;
23 class ListValue;
26 // A helper class that implements the enumerate module functionality on the File
27 // thread.
28 class ModuleEnumerator : public base::RefCountedThreadSafe<ModuleEnumerator> {
29 public:
30 // What type of module we are dealing with. Loaded modules are modules we
31 // detect as loaded in the process at the time of scanning. The others are
32 // modules of interest and may or may not be loaded in the process at the
33 // time of scan.
34 enum ModuleType {
35 LOADED_MODULE = 1 << 0,
36 SHELL_EXTENSION = 1 << 1,
37 WINSOCK_MODULE_REGISTRATION = 1 << 2,
40 // The blacklist status of the module. Suspected Bad modules have been
41 // partially matched (ie. name matches and location, but not description)
42 // whereas Confirmed Bad modules have been identified further (ie.
43 // AuthentiCode signer matches).
44 enum ModuleStatus {
45 // This is returned by the matching function when comparing against the
46 // blacklist and the module does not match the current entry in the
47 // blacklist.
48 NOT_MATCHED,
49 // The module is not on the blacklist. Assume it is good.
50 GOOD,
51 // Module is a suspected bad module.
52 SUSPECTED_BAD,
53 // Module is a bad bad dog.
54 CONFIRMED_BAD,
57 // A bitmask with the possible resolutions for bad modules.
58 enum RecommendedAction {
59 NONE = 0,
60 INVESTIGATING = 1 << 0,
61 UNINSTALL = 1 << 1,
62 DISABLE = 1 << 2,
63 UPDATE = 1 << 3,
64 SEE_LINK = 1 << 4,
65 NOTIFY_USER = 1 << 5,
68 // Which Windows OS is affected.
69 enum OperatingSystem {
70 ALL = -1,
71 XP = 1 << 0,
74 // The structure we populate when enumerating modules.
75 struct Module {
76 // The type of module found
77 ModuleType type;
78 // The module status (benign/bad/etc).
79 ModuleStatus status;
80 // The module path, not including filename.
81 base::string16 location;
82 // The name of the module (filename).
83 base::string16 name;
84 // The name of the product the module belongs to.
85 base::string16 product_name;
86 // The module file description.
87 base::string16 description;
88 // The module version.
89 base::string16 version;
90 // The signer of the digital certificate for the module.
91 base::string16 digital_signer;
92 // The help tips bitmask.
93 RecommendedAction recommended_action;
94 // The duplicate count within each category of modules.
95 int duplicate_count;
96 // Whether this module has been normalized (necessary before checking it
97 // against blacklist).
98 bool normalized;
101 // A vector typedef of all modules enumerated.
102 typedef std::vector<Module> ModulesVector;
104 // A structure we populate with the blacklist entries.
105 struct BlacklistEntry {
106 const char* filename;
107 const char* location;
108 const char* desc_or_signer;
109 const char* version_from; // Version where conflict started.
110 const char* version_to; // First version that works.
111 OperatingSystem os; // Bitmask, representing what OS this entry applies to.
112 RecommendedAction help_tip;
115 // A static function that normalizes the module information in the |module|
116 // struct. Module information needs to be normalized before comparing against
117 // the blacklist. This is because the same module can be described in many
118 // different ways, ie. file paths can be presented in long/short name form,
119 // and are not case sensitive on Windows. Also, the version string returned
120 // can include appended text, which we don't want to use during comparison
121 // against the blacklist.
122 static void NormalizeModule(Module* module);
124 // A static function that checks whether |module| has been |blacklisted|.
125 static ModuleStatus Match(const Module& module,
126 const BlacklistEntry& blacklisted);
128 explicit ModuleEnumerator(EnumerateModulesModel* observer);
129 ~ModuleEnumerator();
131 // Start scanning the loaded module list (if a scan is not already in
132 // progress). This function does not block while reading the module list
133 // (unless we are in limited_mode, see below), and will notify when done
134 // through the MODULE_LIST_ENUMERATED notification.
135 // The process will also send MODULE_INCOMPATIBILITY_BADGE_CHANGE to let
136 // observers know when it is time to update the wrench menu badge.
137 // When in |limited_mode|, this function will not leverage the File thread
138 // to run asynchronously and will therefore block until scanning is done
139 // (and will also not send out any notifications).
140 void ScanNow(ModulesVector* list, bool limited_mode);
142 private:
143 FRIEND_TEST_ALL_PREFIXES(EnumerateModulesTest, CollapsePath);
145 // The (currently) hard coded blacklist of known bad modules.
146 static const BlacklistEntry kModuleBlacklist[];
148 // This function does the actual file scanning work on the FILE thread (or
149 // block the main thread when in limited_mode). It enumerates all loaded
150 // modules in the process and other modules of interest, such as the
151 // registered Winsock LSP modules and stores them in |enumerated_modules_|.
152 // It then normalizes the module info and matches them against a blacklist
153 // of known bad modules. Finally, it calls ReportBack to let the observer
154 // know we are done.
155 void ScanImpl();
157 // Enumerate all modules loaded into the Chrome process.
158 void EnumerateLoadedModules();
160 // Enumerate all registered Windows shell extensions.
161 void EnumerateShellExtensions();
163 // Enumerate all registered Winsock LSP modules.
164 void EnumerateWinsockModules();
166 // Reads the registered shell extensions found under |parent| key in the
167 // registry.
168 void ReadShellExtensions(HKEY parent);
170 // Given a |module|, initializes the structure and loads additional
171 // information using the location field of the module.
172 void PopulateModuleInformation(Module* module);
174 // Checks the module list to see if a |module| of the same type, location
175 // and name has been added before and if so, increments its duplication
176 // counter. If it doesn't appear in the list, it is added.
177 void AddToListWithoutDuplicating(const Module&);
179 // Builds up a vector of path values mapping to environment variable,
180 // with pairs like [c:\windows\, %systemroot%]. This is later used to
181 // collapse paths like c:\windows\system32 into %systemroot%\system32, which
182 // we can use for comparison against our blacklist (which uses only env vars).
183 // NOTE: The vector will not contain an exhaustive list of environment
184 // variables, only the ones currently found on the blacklist or ones that are
185 // likely to appear there.
186 void PreparePathMappings();
188 // For a given |module|, collapse the path from c:\windows to %systemroot%,
189 // based on the |path_mapping_| vector.
190 void CollapsePath(Module* module);
192 // Takes each module in the |enumerated_modules_| vector and matches it
193 // against a fixed blacklist of bad and suspected bad modules.
194 void MatchAgainstBlacklist();
196 // This function executes on the UI thread when the scanning and matching
197 // process is done. It notifies the observer.
198 void ReportBack();
200 // Given a filename, returns the Subject (who signed it) retrieved from
201 // the digital signature (Authenticode).
202 base::string16 GetSubjectNameFromDigitalSignature(
203 const base::FilePath& filename);
205 // The typedef for the vector that maps a regular file path to %env_var%.
206 typedef std::vector< std::pair<base::string16, base::string16> > PathMapping;
208 // The vector of paths to %env_var%, used to account for differences in
209 // where people keep there files, c:\windows vs. d:\windows, etc.
210 PathMapping path_mapping_;
212 // The vector containing all the enumerated modules (loaded and modules of
213 // interest).
214 ModulesVector* enumerated_modules_;
216 // The observer, who needs to be notified when we are done.
217 EnumerateModulesModel* observer_;
219 // See limited_mode below.
220 bool limited_mode_;
222 // The thread that we need to call back on to report that we are done.
223 content::BrowserThread::ID callback_thread_id_;
225 DISALLOW_COPY_AND_ASSIGN(ModuleEnumerator);
228 // This is a singleton class that enumerates all modules loaded into Chrome,
229 // both currently loaded modules (called DLLs on Windows) and modules 'of
230 // interest', such as WinSock LSP modules. This class also marks each module
231 // as benign or suspected bad or outright bad, using a supplied blacklist that
232 // is currently hard-coded.
234 // To use this class, grab the singleton pointer and call ScanNow().
235 // Then wait to get notified through MODULE_LIST_ENUMERATED when the list is
236 // ready.
238 // This class can be used on the UI thread as it asynchronously offloads the
239 // file work over to the FILE thread and reports back to the caller with a
240 // notification.
241 class EnumerateModulesModel {
242 public:
243 // UMA histogram constants.
244 enum UmaModuleConflictHistogramOptions {
245 ACTION_BUBBLE_SHOWN = 0,
246 ACTION_BUBBLE_LEARN_MORE,
247 ACTION_MENU_LEARN_MORE,
248 ACTION_BOUNDARY, // Must be the last value.
251 static EnumerateModulesModel* GetInstance();
253 // Record via UMA what the user selected.
254 static void RecordLearnMoreStat(bool from_menu);
256 // Returns true if we should show the conflict notification. The conflict
257 // notification is only shown once during the lifetime of the process.
258 bool ShouldShowConflictWarning() const;
260 // Called when the user has acknowledged the conflict notification.
261 void AcknowledgeConflictNotification();
263 // Returns the number of suspected bad modules found in the last scan.
264 // Returns 0 if no scan has taken place yet.
265 int suspected_bad_modules_detected() const {
266 return suspected_bad_modules_detected_;
269 // Returns the number of confirmed bad modules found in the last scan.
270 // Returns 0 if no scan has taken place yet.
271 int confirmed_bad_modules_detected() const {
272 return confirmed_bad_modules_detected_;
275 // Returns how many modules to notify the user about.
276 int modules_to_notify_about() const {
277 return modules_to_notify_about_;
280 // Set to true when we the scanning process can not rely on certain Chrome
281 // services to exists.
282 void set_limited_mode(bool limited_mode) {
283 limited_mode_ = limited_mode;
286 // Checks to see if a scanning task should be started and sets one off, if so.
287 void MaybePostScanningTask();
289 // Asynchronously start the scan for the loaded module list, except when in
290 // limited_mode (in which case it blocks).
291 void ScanNow();
293 // Gets the whole module list as a ListValue.
294 base::ListValue* GetModuleList() const;
296 // Gets the Help Center URL for the first *notable* conflict module that we've
297 // elected to notify the user about.
298 GURL GetFirstNotableConflict();
300 private:
301 friend struct DefaultSingletonTraits<EnumerateModulesModel>;
302 friend class ModuleEnumerator;
304 EnumerateModulesModel();
305 virtual ~EnumerateModulesModel();
307 // Called on the UI thread when the helper class is done scanning.
308 void DoneScanning();
310 // Constructs a Help Center article URL for help with a particular module.
311 // The module must have the SEE_LINK attribute for |recommended_action| set,
312 // otherwise this returns a blank string.
313 GURL ConstructHelpCenterUrl(const ModuleEnumerator::Module& module) const;
315 // The vector containing all the modules enumerated. Will be normalized and
316 // any bad modules will be marked.
317 ModuleEnumerator::ModulesVector enumerated_modules_;
319 // The object responsible for enumerating the modules on the File thread.
320 scoped_refptr<ModuleEnumerator> module_enumerator_;
322 // When this singleton object is constructed we go and fire off this timer to
323 // start scanning for modules after a certain amount of time has passed.
324 base::OneShotTimer<EnumerateModulesModel> check_modules_timer_;
326 // While normally |false|, this mode can be set to indicate that the scanning
327 // process should not rely on certain services normally available to Chrome,
328 // such as the resource bundle and the notification system, not to mention
329 // having multiple threads. This mode is useful during diagnostics, which
330 // runs without firing up all necessary Chrome services first.
331 bool limited_mode_;
333 // True if we are currently scanning for modules.
334 bool scanning_;
336 // Whether the conflict notification has been acknowledged by the user.
337 bool conflict_notification_acknowledged_;
339 // The number of confirmed bad modules (not including suspected bad ones)
340 // found during last scan.
341 int confirmed_bad_modules_detected_;
343 // The number of bad modules the user needs to be aggressively notified about.
344 int modules_to_notify_about_;
346 // The number of suspected bad modules (not including confirmed bad ones)
347 // found during last scan.
348 int suspected_bad_modules_detected_;
350 DISALLOW_COPY_AND_ASSIGN(EnumerateModulesModel);
353 #endif // CHROME_BROWSER_ENUMERATE_MODULES_MODEL_WIN_H_