| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome_frame/test/chrome_frame_ui_test_utils.h" | 5 #include "chrome_frame/test/chrome_frame_ui_test_utils.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 #include <stack> | 10 #include <stack> |
| 11 | 11 |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/scoped_bstr_win.h" | 13 #include "base/scoped_bstr_win.h" |
| 14 #include "base/scoped_ptr.h" | 14 #include "base/scoped_ptr.h" |
| 15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "gfx/point.h" |
| 17 #include "gfx/rect.h" | 18 #include "gfx/rect.h" |
| 18 #include "chrome_frame/test/win_event_receiver.h" | 19 #include "chrome_frame/test/win_event_receiver.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 21 |
| 21 namespace chrome_frame_test { | 22 namespace chrome_frame_test { |
| 22 | 23 |
| 23 // Timeout for waiting on Chrome to create the accessibility tree for the DOM. | 24 // Timeout for waiting on Chrome to create the accessibility tree for the DOM. |
| 24 const int kChromeDOMAccessibilityTreeTimeoutMs = 10 * 1000; | 25 const int kChromeDOMAccessibilityTreeTimeoutMs = 10 * 1000; |
| 25 | 26 |
| 26 // Timeout for waiting on a menu to popup. | 27 // Timeout for waiting on a menu to popup. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 39 LOG(ERROR) << "AccObject created which refers to full MSAA object using " | 40 LOG(ERROR) << "AccObject created which refers to full MSAA object using " |
| 40 "parent object and child id. This should NOT be done."; | 41 "parent object and child id. This should NOT be done."; |
| 41 } | 42 } |
| 42 DCHECK(result == S_FALSE || result == E_NOINTERFACE); | 43 DCHECK(result == S_FALSE || result == E_NOINTERFACE); |
| 43 } | 44 } |
| 44 } | 45 } |
| 45 | 46 |
| 46 // static | 47 // static |
| 47 AccObject* AccObject::CreateFromWindow(HWND hwnd) { | 48 AccObject* AccObject::CreateFromWindow(HWND hwnd) { |
| 48 ScopedComPtr<IAccessible> accessible; | 49 ScopedComPtr<IAccessible> accessible; |
| 49 AccessibleObjectFromWindow(hwnd, OBJID_CLIENT, | 50 ::AccessibleObjectFromWindow(hwnd, OBJID_CLIENT, |
| 50 IID_IAccessible, reinterpret_cast<void**>(accessible.Receive())); | 51 IID_IAccessible, reinterpret_cast<void**>(accessible.Receive())); |
| 51 if (accessible) | 52 if (accessible) |
| 52 return new AccObject(accessible); | 53 return new AccObject(accessible); |
| 53 return NULL; | 54 return NULL; |
| 54 } | 55 } |
| 55 | 56 |
| 56 // static | 57 // static |
| 57 AccObject* AccObject::CreateFromEvent(HWND hwnd, LONG object_id, | 58 AccObject* AccObject::CreateFromEvent(HWND hwnd, LONG object_id, |
| 58 LONG child_id) { | 59 LONG child_id) { |
| 59 ScopedComPtr<IAccessible> accessible; | 60 ScopedComPtr<IAccessible> accessible; |
| 60 ScopedVariant acc_child_id; | 61 ScopedVariant acc_child_id; |
| 61 AccessibleObjectFromEvent(hwnd, object_id, child_id, accessible.Receive(), | 62 ::AccessibleObjectFromEvent(hwnd, object_id, child_id, accessible.Receive(), |
| 62 acc_child_id.Receive()); | 63 acc_child_id.Receive()); |
| 63 if (accessible && acc_child_id.type() == VT_I4) | 64 if (accessible && acc_child_id.type() == VT_I4) |
| 64 return new AccObject(accessible, V_I4(&acc_child_id)); | 65 return new AccObject(accessible, V_I4(&acc_child_id)); |
| 65 return NULL; | 66 return NULL; |
| 66 } | 67 } |
| 67 | 68 |
| 68 // static | 69 // static |
| 69 AccObject* AccObject::CreateFromDispatch(IDispatch* dispatch) { | 70 AccObject* AccObject::CreateFromDispatch(IDispatch* dispatch) { |
| 70 if (dispatch) { | 71 if (dispatch) { |
| 71 ScopedComPtr<IAccessible> accessible; | 72 ScopedComPtr<IAccessible> accessible; |
| 72 accessible.QueryFrom(dispatch); | 73 accessible.QueryFrom(dispatch); |
| 73 if (accessible) | 74 if (accessible) |
| 74 return new AccObject(accessible); | 75 return new AccObject(accessible); |
| 75 } | 76 } |
| 76 return NULL; | 77 return NULL; |
| 77 } | 78 } |
| 78 | 79 |
| 79 // static | 80 // static |
| 80 AccObject* AccObject::CreateFromPoint(int x, int y) { | 81 AccObject* AccObject::CreateFromPoint(int x, int y) { |
| 81 ScopedComPtr<IAccessible> accessible; | 82 ScopedComPtr<IAccessible> accessible; |
| 82 ScopedVariant child_id; | 83 ScopedVariant child_id; |
| 83 POINT point = {x, y}; | 84 POINT point = {x, y}; |
| 84 AccessibleObjectFromPoint(point, accessible.Receive(), child_id.Receive()); | 85 ::AccessibleObjectFromPoint(point, accessible.Receive(), child_id.Receive()); |
| 85 if (accessible && child_id.type() == VT_I4) | 86 if (accessible && child_id.type() == VT_I4) |
| 86 return new AccObject(accessible, V_I4(&child_id)); | 87 return new AccObject(accessible, V_I4(&child_id)); |
| 87 return NULL; | 88 return NULL; |
| 88 } | 89 } |
| 89 | 90 |
| 90 bool AccObject::DoDefaultAction() { | 91 bool AccObject::DoDefaultAction() { |
| 92 HWND parent_window = NULL; |
| 93 ::WindowFromAccessibleObject(accessible_, &parent_window); |
| 94 if (!parent_window) { |
| 95 DLOG(ERROR) << "Could not get the window containing the given " |
| 96 << "accessibility object: " << GetDescription(); |
| 97 return false; |
| 98 } |
| 99 wchar_t class_name[MAX_PATH]; |
| 100 if (!::GetClassName(parent_window, class_name, arraysize(class_name))) { |
| 101 DLOG(ERROR) << "Could not get class name from accessibily object's window"; |
| 102 return false; |
| 103 } |
| 104 if (std::wstring(class_name) == L"#32768") { |
| 105 // Hack: if the desktop is locked, menu items cannot be selected using |
| 106 // accDoDefaultAction for some unknown reason. Get around this by |
| 107 // sending mouse button messages at the menu item location. Do this |
| 108 // even if the desktop is unlocked for consistency. We do not do this |
| 109 // for all objects because DoDefaultAction is not always equivalent to |
| 110 // a mouse click. |
| 111 gfx::Rect menu_item_rect; |
| 112 if (GetLocation(&menu_item_rect)) { |
| 113 DLOG(WARNING) << "Attempting to click menu item via mouse messages. " |
| 114 << "May not work for all menus"; |
| 115 // WM_LBUTTON* messages supposedly expect relative coordinates to the |
| 116 // client area, which for popup menus seems to be the entire desktop. |
| 117 gfx::Point center = menu_item_rect.CenterPoint(); |
| 118 LPARAM coordinates = (center.y() << 16) | center.x(); |
| 119 ::PostMessage(parent_window, WM_LBUTTONDOWN, (WPARAM)0, coordinates); |
| 120 ::PostMessage(parent_window, WM_LBUTTONUP, (WPARAM)0, coordinates); |
| 121 return true; |
| 122 } |
| 123 // TODO(kkania): Try sending the access key for the menu item to the |
| 124 // menu if the mouse button messages are found to be insufficient |
| 125 // at times. |
| 126 DLOG(ERROR) << "Could not get location of menu item via MSAA. " |
| 127 << "Accessibility object: " << WideToUTF8(this->GetDescription()) |
| 128 << std::endl << "This is necessary to select a menu item since the " |
| 129 << "desktop is locked."; |
| 130 return false; |
| 131 } |
| 132 |
| 91 HRESULT result = accessible_->accDoDefaultAction(child_id_); | 133 HRESULT result = accessible_->accDoDefaultAction(child_id_); |
| 92 EXPECT_HRESULT_SUCCEEDED(result) | 134 EXPECT_HRESULT_SUCCEEDED(result) |
| 93 << "Could not do default action for AccObject: " << GetDescription(); | 135 << "Could not do default action for AccObject: " << GetDescription(); |
| 94 return SUCCEEDED(result); | 136 return SUCCEEDED(result); |
| 95 } | 137 } |
| 96 | 138 |
| 97 bool AccObject::Focus() { | 139 bool AccObject::Focus() { |
| 98 EXPECT_HRESULT_SUCCEEDED( | 140 EXPECT_HRESULT_SUCCEEDED( |
| 99 accessible_->accSelect(SELFLAG_TAKEFOCUS, child_id_)); | 141 accessible_->accSelect(SELFLAG_TAKEFOCUS, child_id_)); |
| 100 | 142 |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 const std::wstring& role_text, | 402 const std::wstring& role_text, |
| 361 const std::wstring& value) | 403 const std::wstring& value) |
| 362 : name_(name), role_text_(role_text), value_(value) { | 404 : name_(name), role_text_(role_text), value_(value) { |
| 363 } | 405 } |
| 364 | 406 |
| 365 bool AccObjectMatcher::FindHelper(AccObject* object, | 407 bool AccObjectMatcher::FindHelper(AccObject* object, |
| 366 scoped_refptr<AccObject>* match) const { | 408 scoped_refptr<AccObject>* match) const { |
| 367 // Determine if |object| is a match. | 409 // Determine if |object| is a match. |
| 368 bool does_match = true; | 410 bool does_match = true; |
| 369 std::wstring name, role_text, value; | 411 std::wstring name, role_text, value; |
| 370 if (name_.length()) | 412 if (name_.length()) { |
| 371 does_match = object->GetName(&name) && MatchPatternWide(name, name_); | 413 object->GetName(&name); |
| 414 does_match = MatchPatternWide(name, name_); |
| 415 } |
| 372 if (does_match && role_text_.length()) { | 416 if (does_match && role_text_.length()) { |
| 373 does_match = object->GetRoleText(&role_text) && | 417 object->GetRoleText(&role_text); |
| 374 MatchPatternWide(role_text, role_text_); | 418 does_match = MatchPatternWide(role_text, role_text_); |
| 375 } | 419 } |
| 376 if (does_match && value_.length()) | 420 if (does_match && value_.length()) { |
| 377 does_match = object->GetValue(&value) && MatchPatternWide(value, value_); | 421 object->GetValue(&value); |
| 378 | 422 does_match = MatchPatternWide(value, value_); |
| 423 } |
| 379 if (does_match) { | 424 if (does_match) { |
| 380 *match = object; | 425 *match = object; |
| 381 } else { | 426 } else { |
| 382 // Try to match the children of |object|. | 427 // Try to match the children of |object|. |
| 383 AccObject::RefCountedAccObjectVector children; | 428 AccObject::RefCountedAccObjectVector children; |
| 384 if (!object->GetChildren(&children)) { | 429 if (!object->GetChildren(&children)) { |
| 385 LOG(ERROR) << "Could not get children of AccObject"; | 430 LOG(ERROR) << "Could not get children of AccObject"; |
| 386 return false; | 431 return false; |
| 387 } | 432 } |
| 388 for (size_t i = 0; i < children.size(); ++i) { | 433 for (size_t i = 0; i < children.size(); ++i) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 } | 493 } |
| 449 | 494 |
| 450 bool IsDesktopUnlocked() { | 495 bool IsDesktopUnlocked() { |
| 451 HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); | 496 HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); |
| 452 if (desk) | 497 if (desk) |
| 453 ::CloseDesktop(desk); | 498 ::CloseDesktop(desk); |
| 454 return desk; | 499 return desk; |
| 455 } | 500 } |
| 456 | 501 |
| 457 } // namespace chrome_frame_test | 502 } // namespace chrome_frame_test |
| OLD | NEW |