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); |
-} |