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

Side by Side Diff: chrome/browser/win/enumerate_modules_model.h

Issue 2037883004: [Win] Add reporting of total number of modules loaded in browser process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/webui/conflicts_ui.cc ('k') | chrome/browser/win/enumerate_modules_model.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_WIN_ENUMERATE_MODULES_MODEL_H_ 5 #ifndef CHROME_BROWSER_WIN_ENUMERATE_MODULES_MODEL_H_
6 #define CHROME_BROWSER_WIN_ENUMERATE_MODULES_MODEL_H_ 6 #define CHROME_BROWSER_WIN_ENUMERATE_MODULES_MODEL_H_
7 7
8 #include <memory>
8 #include <utility> 9 #include <utility>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/gtest_prod_util.h" 12 #include "base/gtest_prod_util.h"
12 #include "base/macros.h" 13 #include "base/macros.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/observer_list.h"
14 #include "base/memory/singleton.h"
15 #include "base/strings/string16.h" 15 #include "base/strings/string16.h"
16 #include "base/timer/timer.h" 16 #include "base/timer/timer.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "url/gurl.h" 18 #include "url/gurl.h"
19 19
20 class EnumerateModulesModel; 20 class EnumerateModulesModel;
21 21
22 namespace base { 22 namespace base {
23 class FilePath; 23 class FilePath;
24 class ListValue; 24 class ListValue;
25 } 25 }
26 26
27 // A helper class that implements the enumerate module functionality on the File 27 // A helper class that implements the enumerate module functionality on the FILE
28 // thread. 28 // thread. Not to be used directly.
29 class ModuleEnumerator : public base::RefCountedThreadSafe<ModuleEnumerator> { 29 // TODO(chrisha): Move this to a separate .h and .cc.
30 class ModuleEnumerator {
30 public: 31 public:
31 // What type of module we are dealing with. Loaded modules are modules we 32 // What type of module we are dealing with. Loaded modules are modules we
32 // detect as loaded in the process at the time of scanning. The others are 33 // detect as loaded in the process at the time of scanning. The others are
33 // modules of interest and may or may not be loaded in the process at the 34 // modules of interest and may or may not be loaded in the process at the
34 // time of scan. 35 // time of scan.
35 enum ModuleType { 36 enum ModuleType {
36 LOADED_MODULE = 1 << 0, 37 LOADED_MODULE = 1 << 0,
37 SHELL_EXTENSION = 1 << 1, 38 SHELL_EXTENSION = 1 << 1,
38 WINSOCK_MODULE_REGISTRATION = 1 << 2, 39 WINSOCK_MODULE_REGISTRATION = 1 << 2,
39 }; 40 };
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 // The duplicate count within each category of modules. 109 // The duplicate count within each category of modules.
109 int duplicate_count; 110 int duplicate_count;
110 // Whether this module has been normalized (necessary before checking it 111 // Whether this module has been normalized (necessary before checking it
111 // against blacklist). 112 // against blacklist).
112 bool normalized; 113 bool normalized;
113 }; 114 };
114 115
115 // A vector typedef of all modules enumerated. 116 // A vector typedef of all modules enumerated.
116 typedef std::vector<Module> ModulesVector; 117 typedef std::vector<Module> ModulesVector;
117 118
118 // A structure we populate with the blacklist entries.
119 struct BlacklistEntry {
120 const char* filename;
121 const char* location;
122 const char* desc_or_signer;
123 const char* version_from; // Version where conflict started.
124 const char* version_to; // First version that works.
125 OperatingSystem os; // Bitmask, representing what OS this entry applies to.
126 RecommendedAction help_tip;
127 };
128
129 // A static function that normalizes the module information in the |module| 119 // A static function that normalizes the module information in the |module|
130 // struct. Module information needs to be normalized before comparing against 120 // struct. Module information needs to be normalized before comparing against
131 // the blacklist. This is because the same module can be described in many 121 // the blacklist. This is because the same module can be described in many
132 // different ways, ie. file paths can be presented in long/short name form, 122 // different ways, ie. file paths can be presented in long/short name form,
133 // and are not case sensitive on Windows. Also, the version string returned 123 // and are not case sensitive on Windows. Also, the version string returned
134 // can include appended text, which we don't want to use during comparison 124 // can include appended text, which we don't want to use during comparison
135 // against the blacklist. 125 // against the blacklist.
136 static void NormalizeModule(Module* module); 126 static void NormalizeModule(Module* module);
137 127
138 // A static function that checks whether |module| has been |blacklisted|. 128 // Constructs a ModuleEnumerator that will notify the provided |observer| once
139 static ModuleStatus Match(const Module& module, 129 // enumeration is complete. |observer| must outlive the ModuleEnumerator.
140 const BlacklistEntry& blacklisted);
141
142 explicit ModuleEnumerator(EnumerateModulesModel* observer); 130 explicit ModuleEnumerator(EnumerateModulesModel* observer);
143 131
132 ~ModuleEnumerator();
133
144 // Start scanning the loaded module list (if a scan is not already in 134 // Start scanning the loaded module list (if a scan is not already in
145 // progress). This function does not block while reading the module list 135 // progress). This function does not block while reading the module list and
146 // (unless we are in limited_mode, see below), and will notify when done 136 // will notify when done by calling the DoneScanning method of |observer_|.
147 // through the MODULE_LIST_ENUMERATED notification. 137 void ScanNow(ModulesVector* list);
148 // The process will also send MODULE_INCOMPATIBILITY_BADGE_CHANGE to let
149 // observers know when it is time to update the wrench menu badge.
150 // When in |limited_mode|, this function will not leverage the File thread
151 // to run asynchronously and will therefore block until scanning is done
152 // (and will also not send out any notifications).
153 void ScanNow(ModulesVector* list, bool limited_mode);
154 138
155 private: 139 private:
156 FRIEND_TEST_ALL_PREFIXES(EnumerateModulesTest, CollapsePath); 140 FRIEND_TEST_ALL_PREFIXES(EnumerateModulesTest, CollapsePath);
157 141
158 friend class base::RefCountedThreadSafe<ModuleEnumerator>; 142 // This function does the actual file scanning work on the FILE thread. It
159 ~ModuleEnumerator(); 143 // enumerates all loaded modules in the process and other modules of interest,
160 144 // such as the registered Winsock LSP modules and stores them in
161 // The (currently) hard coded blacklist of known bad modules. 145 // |enumerated_modules_|. It then normalizes the module info and matches them
162 static const BlacklistEntry kModuleBlacklist[]; 146 // against a blacklist of known bad modules. Finally, notifies the observer
163 147 // that the enumeration is complete by invoking DoneScanning.
164 // This function does the actual file scanning work on the FILE thread (or
165 // block the main thread when in limited_mode). It enumerates all loaded
166 // modules in the process and other modules of interest, such as the
167 // registered Winsock LSP modules and stores them in |enumerated_modules_|.
168 // It then normalizes the module info and matches them against a blacklist
169 // of known bad modules. Finally, it calls ReportBack to let the observer
170 // know we are done.
171 void ScanImpl(); 148 void ScanImpl();
172 149
173 // Enumerate all modules loaded into the Chrome process. 150 // Enumerate all modules loaded into the Chrome process.
174 void EnumerateLoadedModules(); 151 void EnumerateLoadedModules();
175 152
176 // Enumerate all registered Windows shell extensions. 153 // Enumerate all registered Windows shell extensions.
177 void EnumerateShellExtensions(); 154 void EnumerateShellExtensions();
178 155
179 // Enumerate all registered Winsock LSP modules. 156 // Enumerate all registered Winsock LSP modules.
180 void EnumerateWinsockModules(); 157 void EnumerateWinsockModules();
(...skipping 17 matching lines...) Expand all
198 // we can use for comparison against our blacklist (which uses only env vars). 175 // we can use for comparison against our blacklist (which uses only env vars).
199 // NOTE: The vector will not contain an exhaustive list of environment 176 // NOTE: The vector will not contain an exhaustive list of environment
200 // variables, only the ones currently found on the blacklist or ones that are 177 // variables, only the ones currently found on the blacklist or ones that are
201 // likely to appear there. 178 // likely to appear there.
202 void PreparePathMappings(); 179 void PreparePathMappings();
203 180
204 // For a given |module|, collapse the path from c:\windows to %systemroot%, 181 // For a given |module|, collapse the path from c:\windows to %systemroot%,
205 // based on the |path_mapping_| vector. 182 // based on the |path_mapping_| vector.
206 void CollapsePath(Module* module); 183 void CollapsePath(Module* module);
207 184
208 // Takes each module in the |enumerated_modules_| vector and matches it
209 // against a fixed blacklist of bad and suspected bad modules.
210 void MatchAgainstBlacklist();
211
212 // This function executes on the UI thread when the scanning and matching
213 // process is done. It notifies the observer.
214 void ReportBack();
215
216 // Given a filename, returns the Subject (who signed it) retrieved from 185 // Given a filename, returns the Subject (who signed it) retrieved from
217 // the digital signature (Authenticode). 186 // the digital signature (Authenticode).
218 base::string16 GetSubjectNameFromDigitalSignature( 187 base::string16 GetSubjectNameFromDigitalSignature(
219 const base::FilePath& filename); 188 const base::FilePath& filename);
220 189
190 // Reports (via UMA) a handful of high-level metrics regarding third party
191 // modules in this process. Called by ScanImpl after modules have been
192 // enumerated and processed.
193 void ReportThirdPartyMetrics();
194
221 // The typedef for the vector that maps a regular file path to %env_var%. 195 // The typedef for the vector that maps a regular file path to %env_var%.
222 typedef std::vector< std::pair<base::string16, base::string16> > PathMapping; 196 typedef std::vector<std::pair<base::string16, base::string16>> PathMapping;
223 197
224 // The vector of paths to %env_var%, used to account for differences in 198 // The vector of paths to %env_var%, used to account for differences in
225 // where people keep there files, c:\windows vs. d:\windows, etc. 199 // where people keep there files, c:\windows vs. d:\windows, etc.
226 PathMapping path_mapping_; 200 PathMapping path_mapping_;
227 201
228 // The vector containing all the enumerated modules (loaded and modules of 202 // The vector containing all the enumerated modules (loaded and modules of
229 // interest). 203 // interest).
230 ModulesVector* enumerated_modules_; 204 ModulesVector* enumerated_modules_;
231 205
232 // The observer, who needs to be notified when we are done. 206 // The observer, which needs to be notified when the scan is complete.
233 EnumerateModulesModel* observer_; 207 EnumerateModulesModel* observer_;
234 208
235 // See limited_mode below.
236 bool limited_mode_;
237
238 // The thread that we need to call back on to report that we are done.
239 content::BrowserThread::ID callback_thread_id_;
240
241 DISALLOW_COPY_AND_ASSIGN(ModuleEnumerator); 209 DISALLOW_COPY_AND_ASSIGN(ModuleEnumerator);
242 }; 210 };
243 211
244 // This is a singleton class that enumerates all modules loaded into Chrome, 212 // This is a singleton class that enumerates all modules loaded into Chrome,
245 // both currently loaded modules (called DLLs on Windows) and modules 'of 213 // both currently loaded modules (called DLLs on Windows) and modules 'of
246 // interest', such as WinSock LSP modules. This class also marks each module 214 // interest', such as WinSock LSP modules. This class also marks each module
247 // as benign or suspected bad or outright bad, using a supplied blacklist that 215 // as benign or suspected bad or outright bad, using a supplied blacklist that
248 // is currently hard-coded. 216 // is currently hard-coded.
249 // 217 //
250 // To use this class, grab the singleton pointer and call ScanNow(). 218 // To use this class, grab the singleton pointer and call ScanNow().
251 // Then wait to get notified through MODULE_LIST_ENUMERATED when the list is 219 // Then wait to get notified through MODULE_LIST_ENUMERATED when the list is
252 // ready. 220 // ready.
253 // 221 //
254 // This class can be used on the UI thread as it asynchronously offloads the 222 // The member functions of this class may only be used from the UI thread. The
255 // file work over to the FILE thread and reports back to the caller with a 223 // bulk of the work is actually performed on the FILE thread.
256 // notification. 224 //
225 // TODO(chrisha): If this logic is ever extended to other platforms, then make
226 // this file generic for all platforms, and remove the precompiler logic in
227 // app_menu_icon_controller.*.
257 class EnumerateModulesModel { 228 class EnumerateModulesModel {
258 public: 229 public:
259 // UMA histogram constants. 230 // UMA histogram constants.
260 enum UmaModuleConflictHistogramOptions { 231 enum UmaModuleConflictHistogramOptions {
261 ACTION_BUBBLE_SHOWN = 0, 232 ACTION_BUBBLE_SHOWN = 0,
262 ACTION_BUBBLE_LEARN_MORE, 233 ACTION_BUBBLE_LEARN_MORE,
263 ACTION_MENU_LEARN_MORE, 234 ACTION_MENU_LEARN_MORE,
264 ACTION_BOUNDARY, // Must be the last value. 235 ACTION_BOUNDARY, // Must be the last value.
265 }; 236 };
266 237
238 // Observer class used to determine when a scan has completed and when any
239 // associated UI elements have been dismissed.
240 class Observer {
241 public:
242 // Invoked when EnumerateModulesModel has completed a scan of modules.
243 virtual void OnScanCompleted() {}
244
245 // Invoked when a user has acknowledged incompatible modules found in a
246 // module scan.
247 virtual void OnConflictsAcknowledged() {}
248
249 protected:
250 virtual ~Observer() = default;
251 };
252
253 // Returns the singleton instance of this class.
267 static EnumerateModulesModel* GetInstance(); 254 static EnumerateModulesModel* GetInstance();
268 255
256 // Adds an |observer| to the enumerator. Callbacks will occur on the UI
257 // thread.
258 void AddObserver(Observer* observer);
259
260 // Removes an |observer| from the enumerator.
261 void RemoveObserver(Observer* observer);
262
269 // Returns true if we should show the conflict notification. The conflict 263 // Returns true if we should show the conflict notification. The conflict
270 // notification is only shown once during the lifetime of the process. 264 // notification is only shown once during the lifetime of the process.
271 bool ShouldShowConflictWarning() const; 265 bool ShouldShowConflictWarning() const;
272 266
273 // Called when the user has acknowledged the conflict notification. 267 // Called when the user has acknowledged the conflict notification.
274 void AcknowledgeConflictNotification(); 268 void AcknowledgeConflictNotification();
275 269
276 // Returns the number of suspected bad modules found in the last scan. 270 // Returns the number of suspected bad modules found in the last scan.
277 // Returns 0 if no scan has taken place yet. 271 // Returns 0 if no scan has taken place yet.
278 int suspected_bad_modules_detected() const { 272 int suspected_bad_modules_detected() const;
279 return suspected_bad_modules_detected_;
280 }
281 273
282 // Returns the number of confirmed bad modules found in the last scan. 274 // Returns the number of confirmed bad modules found in the last scan.
283 // Returns 0 if no scan has taken place yet. 275 // Returns 0 if no scan has taken place yet.
284 int confirmed_bad_modules_detected() const { 276 int confirmed_bad_modules_detected() const;
285 return confirmed_bad_modules_detected_;
286 }
287 277
288 // Returns how many modules to notify the user about. 278 // Returns how many modules to notify the user about.
289 int modules_to_notify_about() const { 279 int modules_to_notify_about() const;
290 return modules_to_notify_about_;
291 }
292
293 // Set to true when we the scanning process can not rely on certain Chrome
294 // services to exists.
295 void set_limited_mode(bool limited_mode) {
296 limited_mode_ = limited_mode;
297 }
298 280
299 // Checks to see if a scanning task should be started and sets one off, if so. 281 // Checks to see if a scanning task should be started and sets one off, if so.
300 void MaybePostScanningTask(); 282 void MaybePostScanningTask();
301 283
302 // Asynchronously start the scan for the loaded module list, except when in 284 // Asynchronously start the scan for the loaded module list.
303 // limited_mode (in which case it blocks).
304 void ScanNow(); 285 void ScanNow();
305 286
306 // Gets the whole module list as a ListValue. 287 // Gets the whole module list as a ListValue.
307 base::ListValue* GetModuleList() const; 288 base::ListValue* GetModuleList();
308 289
309 // Gets the Help Center URL for the first *notable* conflict module that we've 290 // Returns the site to which the user should be taken when the conflict bubble
310 // elected to notify the user about. 291 // or app menu item is clicked. For now this is simply chrome://conflicts,
311 GURL GetFirstNotableConflict(); 292 // which contains detailed information about conflicts. Returns an empty URL
293 // if there are no conficts. May only be called on UI thread.
294 GURL GetConflictUrl();
312 295
313 private: 296 private:
314 friend struct base::DefaultSingletonTraits<EnumerateModulesModel>;
315 friend class ModuleEnumerator; 297 friend class ModuleEnumerator;
316 298
299 // Private to enforce singleton nature of this class.
317 EnumerateModulesModel(); 300 EnumerateModulesModel();
318 virtual ~EnumerateModulesModel(); 301 ~EnumerateModulesModel();
319 302
320 // Called on the UI thread when the helper class is done scanning. 303 // Called on the UI thread when the helper class is done scanning. The
304 // ModuleEnumerator that calls this must not do any work after causing this
305 // function to be called, as the EnumerateModulesModel may delete the
306 // ModuleEnumerator.
321 void DoneScanning(); 307 void DoneScanning();
322 308
323 // Constructs a Help Center article URL for help with a particular module.
324 // The module must have the SEE_LINK attribute for |recommended_action| set,
325 // otherwise this returns a blank string.
326 GURL ConstructHelpCenterUrl(const ModuleEnumerator::Module& module) const;
327
328 // The vector containing all the modules enumerated. Will be normalized and 309 // The vector containing all the modules enumerated. Will be normalized and
329 // any bad modules will be marked. 310 // any bad modules will be marked. Written to on the FILE thread by the
311 // |module_enumerator_|, read from on the UI thread by this class.
330 ModuleEnumerator::ModulesVector enumerated_modules_; 312 ModuleEnumerator::ModulesVector enumerated_modules_;
331 313
332 // The object responsible for enumerating the modules on the File thread. 314 // The object responsible for enumerating the modules on the FILE thread.
333 scoped_refptr<ModuleEnumerator> module_enumerator_; 315 // Only used from the UI thread. This ends up internally doing its work on the
316 // FILE thread.
317 std::unique_ptr<ModuleEnumerator> module_enumerator_;
334 318
335 // When this singleton object is constructed we go and fire off this timer to 319 // Whether the conflict notification has been acknowledged by the user. Only
336 // start scanning for modules after a certain amount of time has passed. 320 // modified on the UI thread.
337 base::OneShotTimer check_modules_timer_;
338
339 // While normally |false|, this mode can be set to indicate that the scanning
340 // process should not rely on certain services normally available to Chrome,
341 // such as the resource bundle and the notification system, not to mention
342 // having multiple threads. This mode is useful during diagnostics, which
343 // runs without firing up all necessary Chrome services first.
344 bool limited_mode_;
345
346 // True if we are currently scanning for modules.
347 bool scanning_;
348
349 // Whether the conflict notification has been acknowledged by the user.
350 bool conflict_notification_acknowledged_; 321 bool conflict_notification_acknowledged_;
351 322
352 // The number of confirmed bad modules (not including suspected bad ones) 323 // The number of confirmed bad modules (not including suspected bad ones)
353 // found during last scan. 324 // found during last scan. Only modified on the UI thread.
354 int confirmed_bad_modules_detected_; 325 int confirmed_bad_modules_detected_;
355 326
356 // The number of bad modules the user needs to be aggressively notified about. 327 // The number of bad modules the user needs to be aggressively notified about.
328 // Only modified on the UI thread.
357 int modules_to_notify_about_; 329 int modules_to_notify_about_;
358 330
359 // The number of suspected bad modules (not including confirmed bad ones) 331 // The number of suspected bad modules (not including confirmed bad ones)
360 // found during last scan. 332 // found during last scan. Only modified on the UI thread.
361 int suspected_bad_modules_detected_; 333 int suspected_bad_modules_detected_;
362 334
335 base::ObserverList<Observer> observers_;
336
363 DISALLOW_COPY_AND_ASSIGN(EnumerateModulesModel); 337 DISALLOW_COPY_AND_ASSIGN(EnumerateModulesModel);
364 }; 338 };
365 339
366 #endif // CHROME_BROWSER_WIN_ENUMERATE_MODULES_MODEL_H_ 340 #endif // CHROME_BROWSER_WIN_ENUMERATE_MODULES_MODEL_H_
OLDNEW
« no previous file with comments | « chrome/browser/ui/webui/conflicts_ui.cc ('k') | chrome/browser/win/enumerate_modules_model.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698