Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef CHROME_COMMON_CONFLICTS_MODULE_WATCHER_WIN_H_ | |
| 6 #define CHROME_COMMON_CONFLICTS_MODULE_WATCHER_WIN_H_ | |
| 7 | |
| 8 #include "base/callback.h" | |
| 9 #include "base/files/file_path.h" | |
| 10 #include "base/memory/ref_counted.h" | |
| 11 #include "base/synchronization/lock.h" | |
| 12 | |
| 13 namespace base { | |
| 14 template <class ObserverType> | |
| 15 class ObserverListThreadSafe; | |
| 16 } // namespace base | |
| 17 | |
| 18 namespace conflicts { | |
| 19 | |
| 20 class ModuleWatcherTest; | |
| 21 | |
| 22 // This class observes modules as they are loaded and unloaded into a process' | |
| 23 // address space. It works by installing a DllNotification callback, and | |
| 24 // also enumerating all currently loaded modules at the time of its creation. | |
| 25 // It doesn't really make sense to create more than one of these in a process, | |
| 26 // although it's entirely possible. | |
| 27 class ModuleWatcher { | |
| 28 public: | |
| 29 // The types of events that are observed by the watcher. | |
| 30 enum EventType { | |
|
sky
2016/11/04 16:27:24
Generally favor enum class for new code.
chrisha
2016/11/04 19:15:49
Good point. I'll actually be moving this in a Mojo
| |
| 31 // The module was already loaded at the time of creation of the | |
| 32 // ModuleWatcher. | |
| 33 MODULE_ALREADY_LOADED, | |
| 34 // The module was not loaded at the time of creation of the ModuleWatcher | |
| 35 // and is being loaded. | |
| 36 MODULE_LOADED, | |
| 37 // The module is being unloaded. | |
| 38 MODULE_UNLOADED, | |
| 39 }; | |
| 40 | |
| 41 // A notification about a module being loaded or unloaded. | |
| 42 struct ModuleEvent { | |
| 43 // The type of event. | |
| 44 EventType event_type; | |
| 45 // The full path to the module being loaded or unloaded. | |
| 46 base::FilePath module_path; | |
| 47 // The load address of the module. | |
| 48 void* load_address; | |
| 49 // The size of the module in memory, in bytes. | |
| 50 size_t size; | |
| 51 }; | |
| 52 | |
| 53 // Clients may register callbacks with the following type in order to receive | |
| 54 // notifications. | |
| 55 using OnModuleEventCallback = base::Callback<void(const ModuleEvent& event)>; | |
| 56 class Observer; | |
| 57 | |
| 58 ModuleWatcher(); | |
| 59 ~ModuleWatcher(); | |
| 60 | |
| 61 // Registers a callback with this ModuleWatcher. The thread on which the | |
|
sky
2016/11/04 16:27:24
Can you motivate why you need the threading comple
chrisha
2016/11/04 19:15:49
The problem is with the LdrDllNotification callbac
| |
| 62 // callback is registered is the thread on which the callback will be invoked. | |
| 63 // To unregister the callback simply delete the resulting Observer object. | |
| 64 // Note that the observer must be destroyed on the same thread on which it | |
| 65 // was created. (See ObserverListThreadSafe::RemoveObserver for details.) | |
| 66 // NOTE: This is a wrapper around ObserverListThreadSafe that effectively | |
| 67 // creates a CallbackListThreadSafe. If anybody goes looking for such a thing | |
| 68 // and stumbles upon this code, contact chrisha@ about generalizing it. | |
| 69 std::unique_ptr<Observer> RegisterCallback( | |
|
sky
2016/11/04 16:27:24
Generally in chrome code and Observer is an interf
chrisha
2016/11/04 19:15:49
Yeah, or "Subscription" if I want to follow the Ca
| |
| 70 const OnModuleEventCallback& callback); | |
| 71 | |
| 72 // Starts the watcher. This enumerates all loaded modules and registers a | |
| 73 // DllNotification callback for continued notifications. This is threadsafe. | |
| 74 // Note that it is possible to receive duplicate notifications for some | |
| 75 // modules as the initial loaded module enumerations is racy with the | |
| 76 // installation of the callback. In this case you will receive both a | |
| 77 // MODULE_LOADED and a MODULE_ALREADY_LOADED event for the same module. Since | |
| 78 // the callback is installed first no modules will be missed. | |
| 79 void Start(); | |
| 80 | |
| 81 // Stops the watcher. The watcher may subsequently be restarted. Doesn't | |
| 82 // need to be called explicitly as ~ModuleWatcher will do so as well. This | |
| 83 // is thread-safe. | |
| 84 void Stop(); | |
| 85 | |
| 86 // Returns true if the watcher is currently running, false otherwise. | |
| 87 bool IsRunning(); | |
| 88 | |
| 89 protected: | |
| 90 // Used as a bridge between the operating system notifications and this class. | |
| 91 class Bridge; | |
| 92 | |
| 93 // The Bridge requires access to Notify. | |
| 94 friend class Bridge; | |
| 95 // For unittesting. | |
| 96 friend class ModuleWatcherTest; | |
| 97 // Observers require access to |observer_list_|. | |
| 98 friend class Observer; | |
| 99 | |
| 100 // Registers a Dll Notification callback with the OS. Returns true on success, | |
| 101 // false otherwise. Modifies |dll_notification_cookie_|. Requires |lock_| to | |
| 102 // already be acquired. | |
| 103 bool RegisterDllNotificationCallback(); | |
| 104 | |
| 105 // Removes the installed Dll Notification callback. This should only | |
| 106 // be called if InstallDllNotificationCallback returned true. Returns true on | |
| 107 // success, false otherwise. Requires |lock_| to already be acquired. | |
| 108 bool UnregisterDllNotificationCallback(); | |
| 109 | |
| 110 // Enumerates all currently loaded modules, firing off callbacks. Returns | |
| 111 // true on success, false otherwise. | |
| 112 bool EnumerateAlreadyLoadedModules(); | |
| 113 | |
| 114 // Invoked by ModuleWatcherHelper. Dispatches the provided ModuleEvent to all | |
| 115 // registered observers. | |
| 116 void Notify(const ModuleEvent& event); | |
| 117 | |
| 118 // The list of registered observers. This is directly modified by | |
| 119 // ModuleWatcher::Observer. | |
| 120 scoped_refptr<base::ObserverListThreadSafe<Observer>> observer_list_; | |
| 121 | |
| 122 private: | |
| 123 base::Lock lock_; | |
| 124 // Indicates whether or not the ModuleWatcher is currently started. Under | |
| 125 // lock_. | |
| 126 bool started_; | |
| 127 // Used by the DllNotification mechanism. Under lock_. | |
| 128 void* dll_notification_cookie_; | |
| 129 | |
| 130 DISALLOW_COPY_AND_ASSIGN(ModuleWatcher); | |
| 131 }; | |
| 132 | |
| 133 // Observer class. This is all implementation detail, plumbing callbacks to | |
| 134 // an ObserverListThreadSafe and handling automatic unregistration. Nothing to | |
| 135 // see here. | |
| 136 class ModuleWatcher::Observer { | |
| 137 public: | |
| 138 ~Observer(); | |
| 139 | |
| 140 protected: | |
| 141 friend ModuleWatcher; | |
| 142 | |
| 143 // Constructor. To actually create one of these use | |
| 144 // ModuleWatcher::RegisterCallback | |
| 145 Observer(const OnModuleEventCallback& callback, | |
| 146 ModuleWatcher* module_watcher); | |
| 147 | |
| 148 // Used by ModuleWatcher to dispatch events to this observer. | |
| 149 void Notify(const ModuleEvent& event); | |
| 150 | |
| 151 // The bound callback. | |
| 152 OnModuleEventCallback callback_; | |
|
sky
2016/11/04 16:27:24
Style guide says no protected members.
| |
| 153 // The parent ModuleWatcher to which this observer belongs. | |
| 154 ModuleWatcher* module_watcher_; | |
| 155 | |
| 156 private: | |
| 157 DISALLOW_COPY_AND_ASSIGN(Observer); | |
| 158 }; | |
| 159 | |
| 160 } // namespace conflicts | |
| 161 | |
| 162 #endif // CHROME_COMMON_CONFLICTS_MODULE_WATCHER_WIN_H_ | |
| OLD | NEW |