| Index: chrome_frame/test/win_event_receiver.cc
|
| diff --git a/chrome_frame/test/win_event_receiver.cc b/chrome_frame/test/win_event_receiver.cc
|
| deleted file mode 100644
|
| index b8188056ef8b3d63f98ab138754979bacb4ecaad..0000000000000000000000000000000000000000
|
| --- a/chrome_frame/test/win_event_receiver.cc
|
| +++ /dev/null
|
| @@ -1,275 +0,0 @@
|
| -// Copyright (c) 2012 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.
|
| -
|
| -#include "chrome_frame/test/win_event_receiver.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/weak_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/win/object_watcher.h"
|
| -#include "chrome_frame/function_stub.h"
|
| -
|
| -// WinEventReceiver methods
|
| -WinEventReceiver::WinEventReceiver()
|
| - : listener_(NULL),
|
| - hook_(NULL),
|
| - hook_stub_(NULL) {
|
| -}
|
| -
|
| -WinEventReceiver::~WinEventReceiver() {
|
| - StopReceivingEvents();
|
| -}
|
| -
|
| -void WinEventReceiver::SetListenerForEvent(WinEventListener* listener,
|
| - DWORD event) {
|
| - SetListenerForEvents(listener, event, event);
|
| -}
|
| -
|
| -void WinEventReceiver::SetListenerForEvents(WinEventListener* listener,
|
| - DWORD event_min, DWORD event_max) {
|
| - DCHECK(listener != NULL);
|
| - StopReceivingEvents();
|
| -
|
| - listener_ = listener;
|
| -
|
| - InitializeHook(event_min, event_max);
|
| -}
|
| -
|
| -void WinEventReceiver::StopReceivingEvents() {
|
| - if (hook_) {
|
| - ::UnhookWinEvent(hook_);
|
| - hook_ = NULL;
|
| - FunctionStub::Destroy(hook_stub_);
|
| - hook_stub_ = NULL;
|
| - }
|
| -}
|
| -
|
| -bool WinEventReceiver::InitializeHook(DWORD event_min, DWORD event_max) {
|
| - DCHECK(hook_ == NULL);
|
| - DCHECK(hook_stub_ == NULL);
|
| - hook_stub_ = FunctionStub::Create(reinterpret_cast<uintptr_t>(this),
|
| - WinEventHook);
|
| - // Don't use WINEVENT_SKIPOWNPROCESS here because we fake generate an event
|
| - // in the mock IE event sink (IA2_EVENT_DOCUMENT_LOAD_COMPLETE) that we want
|
| - // to catch.
|
| - hook_ = SetWinEventHook(event_min, event_max, NULL,
|
| - reinterpret_cast<WINEVENTPROC>(hook_stub_->code()), 0,
|
| - 0, WINEVENT_OUTOFCONTEXT);
|
| - LOG_IF(ERROR, hook_ == NULL) << "Unable to SetWinEvent hook";
|
| - return hook_ != NULL;
|
| -}
|
| -
|
| -// static
|
| -void WinEventReceiver::WinEventHook(WinEventReceiver* me, HWINEVENTHOOK hook,
|
| - DWORD event, HWND hwnd, LONG object_id,
|
| - LONG child_id, DWORD event_thread_id,
|
| - DWORD event_time) {
|
| - DCHECK(me->listener_ != NULL);
|
| - me->listener_->OnEventReceived(event, hwnd, object_id, child_id);
|
| -}
|
| -
|
| -// Notifies WindowWatchdog when the process owning a given window exits.
|
| -//
|
| -// If the process terminates before its handle may be obtained, this class will
|
| -// still properly notifyy the WindowWatchdog.
|
| -//
|
| -// Notification is always delivered via a message loop task in the message loop
|
| -// that is active when the instance is constructed.
|
| -class WindowWatchdog::ProcessExitObserver
|
| - : public base::win::ObjectWatcher::Delegate {
|
| - public:
|
| - // Initiates the process watch. Will always return without notifying the
|
| - // watchdog.
|
| - ProcessExitObserver(WindowWatchdog* window_watchdog, HWND hwnd);
|
| - virtual ~ProcessExitObserver();
|
| -
|
| - // base::ObjectWatcher::Delegate implementation
|
| - virtual void OnObjectSignaled(HANDLE process_handle);
|
| -
|
| - private:
|
| - WindowWatchdog* window_watchdog_;
|
| - HANDLE process_handle_;
|
| - HWND hwnd_;
|
| -
|
| - base::WeakPtrFactory<ProcessExitObserver> weak_factory_;
|
| - base::win::ObjectWatcher object_watcher_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ProcessExitObserver);
|
| -};
|
| -
|
| -WindowWatchdog::ProcessExitObserver::ProcessExitObserver(
|
| - WindowWatchdog* window_watchdog, HWND hwnd)
|
| - : window_watchdog_(window_watchdog),
|
| - process_handle_(NULL),
|
| - hwnd_(hwnd),
|
| - weak_factory_(this) {
|
| - DWORD pid = 0;
|
| - ::GetWindowThreadProcessId(hwnd, &pid);
|
| - if (pid != 0) {
|
| - process_handle_ = ::OpenProcess(SYNCHRONIZE, FALSE, pid);
|
| - }
|
| -
|
| - if (process_handle_ != NULL) {
|
| - object_watcher_.StartWatching(process_handle_, this);
|
| - } else {
|
| - // Process is gone, so the window must be gone too. Notify our observer!
|
| - base::MessageLoop::current()->PostTask(
|
| - FROM_HERE, base::Bind(&ProcessExitObserver::OnObjectSignaled,
|
| - weak_factory_.GetWeakPtr(), HANDLE(NULL)));
|
| - }
|
| -}
|
| -
|
| -WindowWatchdog::ProcessExitObserver::~ProcessExitObserver() {
|
| - if (process_handle_ != NULL) {
|
| - ::CloseHandle(process_handle_);
|
| - }
|
| -}
|
| -
|
| -void WindowWatchdog::ProcessExitObserver::OnObjectSignaled(
|
| - HANDLE process_handle) {
|
| - window_watchdog_->OnHwndProcessExited(hwnd_);
|
| -}
|
| -
|
| -WindowWatchdog::WindowWatchdog() {}
|
| -
|
| -void WindowWatchdog::AddObserver(WindowObserver* observer,
|
| - const std::string& caption_pattern,
|
| - const std::string& class_name_pattern) {
|
| - if (observers_.empty()) {
|
| - // SetListenerForEvents takes an event_min and event_max.
|
| - // EVENT_OBJECT_DESTROY, EVENT_OBJECT_SHOW, and EVENT_OBJECT_HIDE are
|
| - // consecutive, in that order; hence we supply only DESTROY and HIDE to
|
| - // denote exactly the required set.
|
| - win_event_receiver_.SetListenerForEvents(
|
| - this, EVENT_OBJECT_DESTROY, EVENT_OBJECT_HIDE);
|
| - }
|
| -
|
| - ObserverEntry new_entry = {
|
| - observer,
|
| - caption_pattern,
|
| - class_name_pattern,
|
| - OpenWindowList() };
|
| -
|
| - observers_.push_back(new_entry);
|
| -}
|
| -
|
| -void WindowWatchdog::RemoveObserver(WindowObserver* observer) {
|
| - for (ObserverEntryList::iterator i = observers_.begin();
|
| - i != observers_.end(); ) {
|
| - i = (observer == i->observer) ? observers_.erase(i) : ++i;
|
| - }
|
| -
|
| - if (observers_.empty())
|
| - win_event_receiver_.StopReceivingEvents();
|
| -}
|
| -
|
| -std::string WindowWatchdog::GetWindowCaption(HWND hwnd) {
|
| - std::string caption;
|
| - int len = ::GetWindowTextLength(hwnd) + 1;
|
| - if (len > 1)
|
| - ::GetWindowTextA(hwnd, WriteInto(&caption, len), len);
|
| - return caption;
|
| -}
|
| -
|
| -bool WindowWatchdog::MatchingWindow(const ObserverEntry& entry,
|
| - const std::string& caption,
|
| - const std::string& class_name) {
|
| - bool should_match_caption = !entry.caption_pattern.empty();
|
| - bool should_match_class = !entry.class_name_pattern.empty();
|
| -
|
| - if (should_match_caption &&
|
| - MatchPattern(caption, entry.caption_pattern) &&
|
| - !should_match_class) {
|
| - return true;
|
| - }
|
| - if (should_match_class &&
|
| - MatchPattern(class_name, entry.class_name_pattern)) {
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void WindowWatchdog::HandleOnOpen(HWND hwnd) {
|
| - std::string caption = GetWindowCaption(hwnd);
|
| - char class_name[MAX_PATH] = {0};
|
| - GetClassNameA(hwnd, class_name, arraysize(class_name));
|
| -
|
| - // Instantiated only if there is at least one interested observer. Each
|
| - // interested observer will maintain a reference to this object, such that it
|
| - // is deleted when the last observer disappears.
|
| - linked_ptr<ProcessExitObserver> process_exit_observer;
|
| -
|
| - // Identify the interested observers and mark them as watching this HWND for
|
| - // close.
|
| - ObserverEntryList interested_observers;
|
| - for (ObserverEntryList::iterator entry_iter = observers_.begin();
|
| - entry_iter != observers_.end(); ++entry_iter) {
|
| - if (MatchingWindow(*entry_iter, caption, class_name)) {
|
| - if (process_exit_observer == NULL) {
|
| - process_exit_observer.reset(new ProcessExitObserver(this, hwnd));
|
| - }
|
| -
|
| - entry_iter->open_windows.push_back(
|
| - OpenWindowEntry(hwnd, process_exit_observer));
|
| -
|
| - interested_observers.push_back(*entry_iter);
|
| - }
|
| - }
|
| -
|
| - // Notify the interested observers in a separate pass in case AddObserver or
|
| - // RemoveObserver is called as a side-effect of the notification.
|
| - for (ObserverEntryList::iterator entry_iter = interested_observers.begin();
|
| - entry_iter != interested_observers.end(); ++entry_iter) {
|
| - entry_iter->observer->OnWindowOpen(hwnd);
|
| - }
|
| -}
|
| -
|
| -void WindowWatchdog::HandleOnClose(HWND hwnd) {
|
| - // Identify the interested observers, reaping OpenWindow entries as
|
| - // appropriate
|
| - ObserverEntryList interested_observers;
|
| - for (ObserverEntryList::iterator entry_iter = observers_.begin();
|
| - entry_iter != observers_.end(); ++entry_iter) {
|
| - size_t num_open_windows = entry_iter->open_windows.size();
|
| -
|
| - OpenWindowList::iterator window_iter = entry_iter->open_windows.begin();
|
| - while (window_iter != entry_iter->open_windows.end()) {
|
| - if (hwnd == window_iter->first) {
|
| - window_iter = entry_iter->open_windows.erase(window_iter);
|
| - } else {
|
| - ++window_iter;
|
| - }
|
| - }
|
| -
|
| - if (num_open_windows != entry_iter->open_windows.size()) {
|
| - interested_observers.push_back(*entry_iter);
|
| - }
|
| - }
|
| -
|
| - // Notify the interested observers in a separate pass in case AddObserver or
|
| - // RemoveObserver is called as a side-effect of the notification.
|
| - for (ObserverEntryList::iterator entry_iter = interested_observers.begin();
|
| - entry_iter != interested_observers.end(); ++entry_iter) {
|
| - entry_iter->observer->OnWindowClose(hwnd);
|
| - }
|
| -}
|
| -
|
| -void WindowWatchdog::OnEventReceived(
|
| - DWORD event, HWND hwnd, LONG object_id, LONG child_id) {
|
| - // We need to look for top level windows and a natural check is for
|
| - // WS_CHILD. Instead, checking for WS_CAPTION allows us to filter
|
| - // out other stray popups
|
| - if (event == EVENT_OBJECT_SHOW) {
|
| - HandleOnOpen(hwnd);
|
| - } else {
|
| - DCHECK(event == EVENT_OBJECT_DESTROY || event == EVENT_OBJECT_HIDE);
|
| - HandleOnClose(hwnd);
|
| - }
|
| -}
|
| -
|
| -void WindowWatchdog::OnHwndProcessExited(HWND hwnd) {
|
| - HandleOnClose(hwnd);
|
| -}
|
|
|