OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <oleacc.h> |
| 6 |
| 7 #include "chrome_frame/test/net/dialog_watchdog.h" |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/scoped_comptr_win.h" |
| 11 #include "base/string_util.h" |
| 12 |
| 13 #include "chrome_frame/test/chrome_frame_test_utils.h" |
| 14 #include "chrome_frame/function_stub.h" |
| 15 |
| 16 namespace { |
| 17 // Uses the IAccessible interface for the window to set the focus. |
| 18 // This can be useful when you don't have control over the thread that |
| 19 // owns the window. |
| 20 // NOTE: this depends on oleacc.lib which the net tests already depend on |
| 21 // but other unit tests don't depend on oleacc so we can't just add the method |
| 22 // directly into chrome_frame_test_utils.cc (without adding a |
| 23 // #pragma comment(lib, "oleacc.lib")). |
| 24 bool SetFocusToAccessibleWindow(HWND hwnd) { |
| 25 bool ret = false; |
| 26 ScopedComPtr<IAccessible> acc; |
| 27 AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, |
| 28 reinterpret_cast<void**>(acc.Receive())); |
| 29 if (acc) { |
| 30 VARIANT self = { VT_I4 }; |
| 31 self.lVal = CHILDID_SELF; |
| 32 ret = SUCCEEDED(acc->accSelect(SELFLAG_TAKEFOCUS, self)); |
| 33 } |
| 34 return ret; |
| 35 } |
| 36 |
| 37 } // namespace |
| 38 |
| 39 SupplyProxyCredentials::SupplyProxyCredentials(const char* username, |
| 40 const char* password) |
| 41 : username_(username), password_(password) { |
| 42 } |
| 43 |
| 44 bool SupplyProxyCredentials::OnDialogDetected(HWND hwnd, |
| 45 const std::string& caption) { |
| 46 // IE's dialog caption (en-US). |
| 47 if (caption.compare("Windows Security") != 0) |
| 48 return false; |
| 49 |
| 50 DialogProps props = {0}; |
| 51 ::EnumChildWindows(hwnd, EnumChildren, reinterpret_cast<LPARAM>(&props)); |
| 52 DCHECK(::IsWindow(props.username_)); |
| 53 DCHECK(::IsWindow(props.password_)); |
| 54 |
| 55 // We can't use SetWindowText to set the username/password, so simulate |
| 56 // keyboard input instead. |
| 57 chrome_frame_test::ForceSetForegroundWindow(hwnd); |
| 58 CHECK(SetFocusToAccessibleWindow(props.username_)); |
| 59 chrome_frame_test::SendString(username_.c_str()); |
| 60 Sleep(100); |
| 61 |
| 62 chrome_frame_test::SendVirtualKey(VK_TAB); |
| 63 Sleep(100); |
| 64 chrome_frame_test::SendString(password_.c_str()); |
| 65 |
| 66 Sleep(100); |
| 67 chrome_frame_test::SendVirtualKey(VK_RETURN); |
| 68 |
| 69 return true; |
| 70 } |
| 71 |
| 72 // static |
| 73 BOOL SupplyProxyCredentials::EnumChildren(HWND hwnd, LPARAM param) { |
| 74 if (!::IsWindowVisible(hwnd)) |
| 75 return TRUE; // Ignore but continue to enumerate. |
| 76 |
| 77 DialogProps* props = reinterpret_cast<DialogProps*>(param); |
| 78 |
| 79 char class_name[MAX_PATH] = {0}; |
| 80 ::GetClassNameA(hwnd, class_name, arraysize(class_name)); |
| 81 if (lstrcmpiA(class_name, "Edit") == 0) { |
| 82 if (props->username_ == NULL || props->username_ == hwnd) { |
| 83 props->username_ = hwnd; |
| 84 } else if (props->password_ == NULL) { |
| 85 props->password_ = hwnd; |
| 86 } |
| 87 } else { |
| 88 EnumChildWindows(hwnd, EnumChildren, param); |
| 89 } |
| 90 |
| 91 return TRUE; |
| 92 } |
| 93 |
| 94 DialogWatchdog::DialogWatchdog() : hook_(NULL), hook_stub_(NULL) { |
| 95 Initialize(); |
| 96 } |
| 97 |
| 98 DialogWatchdog::~DialogWatchdog() { |
| 99 Uninitialize(); |
| 100 } |
| 101 |
| 102 bool DialogWatchdog::Initialize() { |
| 103 DCHECK(hook_ == NULL); |
| 104 DCHECK(hook_stub_ == NULL); |
| 105 hook_stub_ = FunctionStub::Create(reinterpret_cast<uintptr_t>(this), |
| 106 WinEventHook); |
| 107 hook_ = SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW, NULL, |
| 108 reinterpret_cast<WINEVENTPROC>(hook_stub_->code()), 0, |
| 109 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); |
| 110 |
| 111 return hook_ != NULL; |
| 112 } |
| 113 |
| 114 void DialogWatchdog::Uninitialize() { |
| 115 if (hook_) { |
| 116 ::UnhookWinEvent(hook_); |
| 117 hook_ = NULL; |
| 118 FunctionStub::Destroy(hook_stub_); |
| 119 hook_stub_ = NULL; |
| 120 } |
| 121 } |
| 122 |
| 123 // static |
| 124 void DialogWatchdog::WinEventHook(DialogWatchdog* me, HWINEVENTHOOK hook, |
| 125 DWORD event, HWND hwnd, LONG object_id, |
| 126 LONG child_id, DWORD event_thread_id, |
| 127 DWORD event_time) { |
| 128 // Check for a dialog class ("#32770") and notify observers if we find one. |
| 129 char class_name[MAX_PATH] = {0}; |
| 130 ::GetClassNameA(hwnd, class_name, arraysize(class_name)); |
| 131 if (lstrcmpA(class_name, "#32770") == 0) { |
| 132 int len = ::GetWindowTextLength(hwnd); |
| 133 std::string text; |
| 134 ::GetWindowTextA(hwnd, WriteInto(&text, len + 1), len + 1); |
| 135 me->OnDialogFound(hwnd, text); |
| 136 } |
| 137 } |
| 138 |
| 139 void DialogWatchdog::OnDialogFound(HWND hwnd, const std::string& caption) { |
| 140 std::vector<DialogWatchdogObserver*>::iterator it = observers_.begin(); |
| 141 while (it != observers_.end()) { |
| 142 if ((*it)->OnDialogDetected(hwnd, caption)) |
| 143 break; |
| 144 it++; |
| 145 } |
| 146 } |
OLD | NEW |