// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_FRAME_TEST_WIN_EVENT_RECEIVER_H_ #define CHROME_FRAME_TEST_WIN_EVENT_RECEIVER_H_ #include <windows.h> #include <string> #include <vector> #include <utility> #include "base/memory/linked_ptr.h" #include "base/win/object_watcher.h" struct FunctionStub; // Listens to WinEvents from the WinEventReceiver. class WinEventListener { public: virtual ~WinEventListener() {} // Called when an event has been received. |hwnd| is the window that generated // the event, or null if no window is associated with the event. virtual void OnEventReceived(DWORD event, HWND hwnd, LONG object_id, LONG child_id) = 0; }; // Receives WinEvents and forwards them to its listener. The event types the // listener wants to receive can be specified. class WinEventReceiver { public: WinEventReceiver(); ~WinEventReceiver(); // Sets the sole listener of this receiver. The listener will receive all // WinEvents of the given event type. Any previous listener will be // replaced. |listener| should not be NULL. void SetListenerForEvent(WinEventListener* listener, DWORD event); // Same as above, but sets a range of events to listen for. void SetListenerForEvents(WinEventListener* listener, DWORD event_min, DWORD event_max); // Stops receiving events and forwarding them to the listener. It is // permitted to call this even if the receiver has already been stopped. void StopReceivingEvents(); private: bool InitializeHook(DWORD event_min, DWORD event_max); static void CALLBACK WinEventHook(WinEventReceiver* me, HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG object_id, LONG child_id, DWORD event_thread_id, DWORD event_time); WinEventListener* listener_; HWINEVENTHOOK hook_; FunctionStub* hook_stub_; }; // Receives notifications when a window is opened or closed. class WindowObserver { public: virtual ~WindowObserver() {} virtual void OnWindowOpen(HWND hwnd) = 0; virtual void OnWindowClose(HWND hwnd) = 0; }; // Notifies observers when windows whose captions match specified patterns // open or close. When a window opens, its caption is compared to the patterns // associated with each observer. Observers registered with matching patterns // are notified of the window's opening and will be notified when the same // window is closed (including if the owning process terminates without closing // the window). // // Changes to a window's caption while it is open do not affect the set of // observers to be notified when it closes. // // Observers are not notified of the closing of windows that were already open // when they were registered. // // Observers may call AddObserver and/or RemoveObserver during notifications. // // Each instance of this class must only be accessed from a single thread, and // that thread must be running a message loop. class WindowWatchdog : public WinEventListener { public: WindowWatchdog(); // Register |observer| to be notified when windows matching |caption_pattern| // and/or |class_name_pattern| are opened or closed. A single observer may be // registered multiple times. // If a single window caption and/or class name matches multiple // registrations of a single observer, the observer will be notified once per // matching registration. void AddObserver(WindowObserver* observer, const std::string& caption_pattern, const std::string& class_name_pattern); // Remove all registrations of |observer|. The |observer| will not be notified // during or after this call. void RemoveObserver(WindowObserver* observer); private: class ProcessExitObserver; // The Delegate object is actually a ProcessExitObserver, but declaring // it as such would require fully declaring the ProcessExitObserver class // here in order for linked_ptr to access its destructor. typedef std::pair<HWND, linked_ptr<base::win::ObjectWatcher::Delegate> > OpenWindowEntry; typedef std::vector<OpenWindowEntry> OpenWindowList; struct ObserverEntry { WindowObserver* observer; std::string caption_pattern; std::string class_name_pattern; OpenWindowList open_windows; }; typedef std::vector<ObserverEntry> ObserverEntryList; // WinEventListener implementation. virtual void OnEventReceived( DWORD event, HWND hwnd, LONG object_id, LONG child_id); static std::string GetWindowCaption(HWND hwnd); void HandleOnOpen(HWND hwnd); void HandleOnClose(HWND hwnd); void OnHwndProcessExited(HWND hwnd); // Returns true if the caption pattern and/or the class name pattern in the // observer entry structure matches the caption and/or class name passed in. bool MatchingWindow(const ObserverEntry& entry, const std::string& caption, const std::string& class_name); ObserverEntryList observers_; WinEventReceiver win_event_receiver_; DISALLOW_COPY_AND_ASSIGN(WindowWatchdog); }; #endif // CHROME_FRAME_TEST_WIN_EVENT_RECEIVER_H_