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. 4 5 #ifndef CHROME_FRAME_TEST_WIN_EVENT_RECEIVER_H_ 6 #define CHROME_FRAME_TEST_WIN_EVENT_RECEIVER_H_ 7 8 #include <windows.h> 9 10 #include <string> 11 #include <vector> 12 #include <utility> 13 14 #include "base/memory/linked_ptr.h" 15 #include "base/win/object_watcher.h" 16 17 struct FunctionStub; 18 19 // Listens to WinEvents from the WinEventReceiver. 20 class WinEventListener { 21 public: 22 virtual ~WinEventListener() {} 23 // Called when an event has been received. |hwnd| is the window that generated 24 // the event, or null if no window is associated with the event. 25 virtual void OnEventReceived(DWORD event, HWND hwnd, LONG object_id, 26 LONG child_id) = 0; 27 }; 28 29 // Receives WinEvents and forwards them to its listener. The event types the 30 // listener wants to receive can be specified. 31 class WinEventReceiver { 32 public: 33 WinEventReceiver(); 34 ~WinEventReceiver(); 35 36 // Sets the sole listener of this receiver. The listener will receive all 37 // WinEvents of the given event type. Any previous listener will be 38 // replaced. |listener| should not be NULL. 39 void SetListenerForEvent(WinEventListener* listener, DWORD event); 40 41 // Same as above, but sets a range of events to listen for. 42 void SetListenerForEvents(WinEventListener* listener, DWORD event_min, 43 DWORD event_max); 44 45 // Stops receiving events and forwarding them to the listener. It is 46 // permitted to call this even if the receiver has already been stopped. 47 void StopReceivingEvents(); 48 49 private: 50 bool InitializeHook(DWORD event_min, DWORD event_max); 51 52 static void CALLBACK WinEventHook(WinEventReceiver* me, HWINEVENTHOOK hook, 53 DWORD event, HWND hwnd, LONG object_id, LONG child_id, 54 DWORD event_thread_id, DWORD event_time); 55 56 WinEventListener* listener_; 57 HWINEVENTHOOK hook_; 58 FunctionStub* hook_stub_; 59 }; 60 61 // Receives notifications when a window is opened or closed. 62 class WindowObserver { 63 public: 64 virtual ~WindowObserver() {} 65 virtual void OnWindowOpen(HWND hwnd) = 0; 66 virtual void OnWindowClose(HWND hwnd) = 0; 67 }; 68 69 // Notifies observers when windows whose captions match specified patterns 70 // open or close. When a window opens, its caption is compared to the patterns 71 // associated with each observer. Observers registered with matching patterns 72 // are notified of the window's opening and will be notified when the same 73 // window is closed (including if the owning process terminates without closing 74 // the window). 75 // 76 // Changes to a window's caption while it is open do not affect the set of 77 // observers to be notified when it closes. 78 // 79 // Observers are not notified of the closing of windows that were already open 80 // when they were registered. 81 // 82 // Observers may call AddObserver and/or RemoveObserver during notifications. 83 // 84 // Each instance of this class must only be accessed from a single thread, and 85 // that thread must be running a message loop. 86 class WindowWatchdog : public WinEventListener { 87 public: 88 WindowWatchdog(); 89 // Register |observer| to be notified when windows matching |caption_pattern| 90 // and/or |class_name_pattern| are opened or closed. A single observer may be 91 // registered multiple times. 92 // If a single window caption and/or class name matches multiple 93 // registrations of a single observer, the observer will be notified once per 94 // matching registration. 95 void AddObserver(WindowObserver* observer, 96 const std::string& caption_pattern, 97 const std::string& class_name_pattern); 98 99 // Remove all registrations of |observer|. The |observer| will not be notified 100 // during or after this call. 101 void RemoveObserver(WindowObserver* observer); 102 103 private: 104 class ProcessExitObserver; 105 106 // The Delegate object is actually a ProcessExitObserver, but declaring 107 // it as such would require fully declaring the ProcessExitObserver class 108 // here in order for linked_ptr to access its destructor. 109 typedef std::pair<HWND, linked_ptr<base::win::ObjectWatcher::Delegate> > 110 OpenWindowEntry; 111 typedef std::vector<OpenWindowEntry> OpenWindowList; 112 113 struct ObserverEntry { 114 WindowObserver* observer; 115 std::string caption_pattern; 116 std::string class_name_pattern; 117 OpenWindowList open_windows; 118 }; 119 120 typedef std::vector<ObserverEntry> ObserverEntryList; 121 122 // WinEventListener implementation. 123 virtual void OnEventReceived( 124 DWORD event, HWND hwnd, LONG object_id, LONG child_id); 125 126 static std::string GetWindowCaption(HWND hwnd); 127 128 void HandleOnOpen(HWND hwnd); 129 void HandleOnClose(HWND hwnd); 130 void OnHwndProcessExited(HWND hwnd); 131 132 // Returns true if the caption pattern and/or the class name pattern in the 133 // observer entry structure matches the caption and/or class name passed in. 134 bool MatchingWindow(const ObserverEntry& entry, 135 const std::string& caption, 136 const std::string& class_name); 137 138 ObserverEntryList observers_; 139 WinEventReceiver win_event_receiver_; 140 141 DISALLOW_COPY_AND_ASSIGN(WindowWatchdog); 142 }; 143 144 145 146 #endif // CHROME_FRAME_TEST_WIN_EVENT_RECEIVER_H_ 147