Index: chrome_frame/test/net/dialog_watchdog.cc |
=================================================================== |
--- chrome_frame/test/net/dialog_watchdog.cc (revision 0) |
+++ chrome_frame/test/net/dialog_watchdog.cc (revision 0) |
@@ -0,0 +1,146 @@ |
+// Copyright (c) 2009 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 <oleacc.h> |
+ |
+#include "chrome_frame/test/net/dialog_watchdog.h" |
+ |
+#include "base/logging.h" |
+#include "base/scoped_comptr_win.h" |
+#include "base/string_util.h" |
+ |
+#include "chrome_frame/test/chrome_frame_test_utils.h" |
+#include "chrome_frame/function_stub.h" |
+ |
+namespace { |
+// Uses the IAccessible interface for the window to set the focus. |
+// This can be useful when you don't have control over the thread that |
+// owns the window. |
+// NOTE: this depends on oleacc.lib which the net tests already depend on |
+// but other unit tests don't depend on oleacc so we can't just add the method |
+// directly into chrome_frame_test_utils.cc (without adding a |
+// #pragma comment(lib, "oleacc.lib")). |
+bool SetFocusToAccessibleWindow(HWND hwnd) { |
+ bool ret = false; |
+ ScopedComPtr<IAccessible> acc; |
+ AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, |
+ reinterpret_cast<void**>(acc.Receive())); |
+ if (acc) { |
+ VARIANT self = { VT_I4 }; |
+ self.lVal = CHILDID_SELF; |
+ ret = SUCCEEDED(acc->accSelect(SELFLAG_TAKEFOCUS, self)); |
+ } |
+ return ret; |
+} |
+ |
+} // namespace |
+ |
+SupplyProxyCredentials::SupplyProxyCredentials(const char* username, |
+ const char* password) |
+ : username_(username), password_(password) { |
+} |
+ |
+bool SupplyProxyCredentials::OnDialogDetected(HWND hwnd, |
+ const std::string& caption) { |
+ // IE's dialog caption (en-US). |
+ if (caption.compare("Windows Security") != 0) |
+ return false; |
+ |
+ DialogProps props = {0}; |
+ ::EnumChildWindows(hwnd, EnumChildren, reinterpret_cast<LPARAM>(&props)); |
+ DCHECK(::IsWindow(props.username_)); |
+ DCHECK(::IsWindow(props.password_)); |
+ |
+ // We can't use SetWindowText to set the username/password, so simulate |
+ // keyboard input instead. |
+ chrome_frame_test::ForceSetForegroundWindow(hwnd); |
+ CHECK(SetFocusToAccessibleWindow(props.username_)); |
+ chrome_frame_test::SendString(username_.c_str()); |
+ Sleep(100); |
+ |
+ chrome_frame_test::SendVirtualKey(VK_TAB); |
+ Sleep(100); |
+ chrome_frame_test::SendString(password_.c_str()); |
+ |
+ Sleep(100); |
+ chrome_frame_test::SendVirtualKey(VK_RETURN); |
+ |
+ return true; |
+} |
+ |
+// static |
+BOOL SupplyProxyCredentials::EnumChildren(HWND hwnd, LPARAM param) { |
+ if (!::IsWindowVisible(hwnd)) |
+ return TRUE; // Ignore but continue to enumerate. |
+ |
+ DialogProps* props = reinterpret_cast<DialogProps*>(param); |
+ |
+ char class_name[MAX_PATH] = {0}; |
+ ::GetClassNameA(hwnd, class_name, arraysize(class_name)); |
+ if (lstrcmpiA(class_name, "Edit") == 0) { |
+ if (props->username_ == NULL || props->username_ == hwnd) { |
+ props->username_ = hwnd; |
+ } else if (props->password_ == NULL) { |
+ props->password_ = hwnd; |
+ } |
+ } else { |
+ EnumChildWindows(hwnd, EnumChildren, param); |
+ } |
+ |
+ return TRUE; |
+} |
+ |
+DialogWatchdog::DialogWatchdog() : hook_(NULL), hook_stub_(NULL) { |
+ Initialize(); |
+} |
+ |
+DialogWatchdog::~DialogWatchdog() { |
+ Uninitialize(); |
+} |
+ |
+bool DialogWatchdog::Initialize() { |
+ DCHECK(hook_ == NULL); |
+ DCHECK(hook_stub_ == NULL); |
+ hook_stub_ = FunctionStub::Create(reinterpret_cast<uintptr_t>(this), |
+ WinEventHook); |
+ hook_ = SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW, NULL, |
+ reinterpret_cast<WINEVENTPROC>(hook_stub_->code()), 0, |
+ 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); |
+ |
+ return hook_ != NULL; |
+} |
+ |
+void DialogWatchdog::Uninitialize() { |
+ if (hook_) { |
+ ::UnhookWinEvent(hook_); |
+ hook_ = NULL; |
+ FunctionStub::Destroy(hook_stub_); |
+ hook_stub_ = NULL; |
+ } |
+} |
+ |
+// static |
+void DialogWatchdog::WinEventHook(DialogWatchdog* me, HWINEVENTHOOK hook, |
+ DWORD event, HWND hwnd, LONG object_id, |
+ LONG child_id, DWORD event_thread_id, |
+ DWORD event_time) { |
+ // Check for a dialog class ("#32770") and notify observers if we find one. |
+ char class_name[MAX_PATH] = {0}; |
+ ::GetClassNameA(hwnd, class_name, arraysize(class_name)); |
+ if (lstrcmpA(class_name, "#32770") == 0) { |
+ int len = ::GetWindowTextLength(hwnd); |
+ std::string text; |
+ ::GetWindowTextA(hwnd, WriteInto(&text, len + 1), len + 1); |
+ me->OnDialogFound(hwnd, text); |
+ } |
+} |
+ |
+void DialogWatchdog::OnDialogFound(HWND hwnd, const std::string& caption) { |
+ std::vector<DialogWatchdogObserver*>::iterator it = observers_.begin(); |
+ while (it != observers_.end()) { |
+ if ((*it)->OnDialogDetected(hwnd, caption)) |
+ break; |
+ it++; |
+ } |
+} |