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