text: // 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_
  