| Index: chrome_frame/test/chrome_frame_ui_test_utils.cc
|
| diff --git a/chrome_frame/test/chrome_frame_ui_test_utils.cc b/chrome_frame/test/chrome_frame_ui_test_utils.cc
|
| deleted file mode 100644
|
| index cfd2b557a7604ae006bf9a5b5dd2f009331a7fe4..0000000000000000000000000000000000000000
|
| --- a/chrome_frame/test/chrome_frame_ui_test_utils.cc
|
| +++ /dev/null
|
| @@ -1,748 +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/chrome_frame_ui_test_utils.h"
|
| -
|
| -#include <windows.h>
|
| -
|
| -#include <sstream>
|
| -#include <stack>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/path_service.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "base/win/scoped_bstr.h"
|
| -#include "chrome/common/chrome_paths.h"
|
| -#include "chrome_frame/test/win_event_receiver.h"
|
| -#include "chrome_frame/utils.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "third_party/iaccessible2/ia2_api_all.h"
|
| -#include "ui/gfx/point.h"
|
| -#include "ui/gfx/rect.h"
|
| -
|
| -namespace chrome_frame_test {
|
| -
|
| -// Timeout for waiting on Chrome to create the accessibility tree for the DOM.
|
| -const int kChromeDOMAccessibilityTreeTimeoutMs = 10 * 1000;
|
| -
|
| -// Timeout for waiting on a menu to popup.
|
| -const int kMenuPopupTimeoutMs = 10 * 1000;
|
| -
|
| -// AccObject methods
|
| -AccObject::AccObject(IAccessible* accessible, int child_id)
|
| - : accessible_(accessible), child_id_(child_id) {
|
| - DCHECK(accessible);
|
| - if (child_id != CHILDID_SELF) {
|
| - base::win::ScopedComPtr<IDispatch> dispatch;
|
| - // This class does not support referring to a full MSAA object using the
|
| - // parent object and the child id.
|
| - HRESULT result = accessible_->get_accChild(child_id_, dispatch.Receive());
|
| - if (result != S_FALSE && result != E_NOINTERFACE) {
|
| - LOG(ERROR) << "AccObject created which refers to full MSAA object using "
|
| - "parent object and child id. This should NOT be done.";
|
| - }
|
| - DCHECK(result == S_FALSE || result == E_NOINTERFACE);
|
| - }
|
| -}
|
| -
|
| -// static
|
| -AccObject* AccObject::CreateFromWindow(HWND hwnd) {
|
| - base::win::ScopedComPtr<IAccessible> accessible;
|
| - ::AccessibleObjectFromWindow(hwnd, OBJID_CLIENT,
|
| - IID_IAccessible, reinterpret_cast<void**>(accessible.Receive()));
|
| - if (accessible)
|
| - return new AccObject(accessible);
|
| - return NULL;
|
| -}
|
| -
|
| -// static
|
| -AccObject* AccObject::CreateFromEvent(HWND hwnd, LONG object_id,
|
| - LONG child_id) {
|
| - base::win::ScopedComPtr<IAccessible> accessible;
|
| - base::win::ScopedVariant acc_child_id;
|
| - ::AccessibleObjectFromEvent(hwnd, object_id, child_id, accessible.Receive(),
|
| - acc_child_id.Receive());
|
| - if (accessible && acc_child_id.type() == VT_I4)
|
| - return new AccObject(accessible, V_I4(&acc_child_id));
|
| - return NULL;
|
| -}
|
| -
|
| -// static
|
| -AccObject* AccObject::CreateFromDispatch(IDispatch* dispatch) {
|
| - if (dispatch) {
|
| - base::win::ScopedComPtr<IAccessible> accessible;
|
| - accessible.QueryFrom(dispatch);
|
| - if (accessible)
|
| - return new AccObject(accessible);
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -// static
|
| -AccObject* AccObject::CreateFromPoint(int x, int y) {
|
| - base::win::ScopedComPtr<IAccessible> accessible;
|
| - base::win::ScopedVariant child_id;
|
| - POINT point = {x, y};
|
| - ::AccessibleObjectFromPoint(point, accessible.Receive(), child_id.Receive());
|
| - if (accessible && child_id.type() == VT_I4)
|
| - return new AccObject(accessible, V_I4(&child_id));
|
| - return NULL;
|
| -}
|
| -
|
| -bool AccObject::DoDefaultAction() {
|
| - // Prevent clients from using this method to try to select menu items, which
|
| - // does not work with a locked desktop.
|
| - std::wstring class_name;
|
| - if (GetWindowClassName(&class_name)) {
|
| - DCHECK(class_name != L"#32768") << "Do not use DoDefaultAction with menus";
|
| - }
|
| -
|
| - HRESULT result = accessible_->accDoDefaultAction(child_id_);
|
| - EXPECT_HRESULT_SUCCEEDED(result)
|
| - << "Could not do default action for AccObject: " << GetDescription();
|
| - return SUCCEEDED(result);
|
| -}
|
| -
|
| -bool AccObject::LeftClick() {
|
| - return PostMouseClickAtCenter(WM_LBUTTONDOWN, WM_LBUTTONUP);
|
| -}
|
| -
|
| -bool AccObject::RightClick() {
|
| - return PostMouseClickAtCenter(WM_RBUTTONDOWN, WM_RBUTTONUP);
|
| -}
|
| -
|
| -bool AccObject::Focus() {
|
| - EXPECT_HRESULT_SUCCEEDED(
|
| - accessible_->accSelect(SELFLAG_TAKEFOCUS, child_id_));
|
| -
|
| - // Double check that the object actually received focus. In some cases
|
| - // the parent object must have the focus first.
|
| - bool did_focus = false;
|
| - base::win::ScopedVariant focused;
|
| - if (SUCCEEDED(accessible_->get_accFocus(focused.Receive()))) {
|
| - if (focused.type() != VT_EMPTY)
|
| - did_focus = true;
|
| - }
|
| - EXPECT_TRUE(did_focus) << "Could not focus AccObject: " << GetDescription();
|
| - return did_focus;
|
| -}
|
| -
|
| -bool AccObject::Select() {
|
| - // SELFLAG_TAKESELECTION needs to be combined with the focus in order to
|
| - // take effect.
|
| - int selection_flag = SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION;
|
| - EXPECT_HRESULT_SUCCEEDED(accessible_->accSelect(selection_flag, child_id_));
|
| -
|
| - // Double check that the object actually received selection.
|
| - bool did_select = false;
|
| - base::win::ScopedVariant selected;
|
| - if (SUCCEEDED(accessible_->get_accSelection(selected.Receive()))) {
|
| - if (selected.type() != VT_EMPTY)
|
| - did_select = true;
|
| - }
|
| - EXPECT_TRUE(did_select) << "Could not select AccObject: " << GetDescription();
|
| - return did_select;
|
| -}
|
| -
|
| -bool AccObject::SetValue(const std::wstring& value) {
|
| - base::win::ScopedBstr value_bstr(value.c_str());
|
| - EXPECT_HRESULT_SUCCEEDED(accessible_->put_accValue(child_id_, value_bstr));
|
| -
|
| - // Double check that the object's value has actually changed. Some objects'
|
| - // values can not be changed.
|
| - bool did_set_value = false;
|
| - std::wstring actual_value = L"-";
|
| - if (GetValue(&actual_value) && value == actual_value) {
|
| - did_set_value = true;
|
| - }
|
| - EXPECT_TRUE(did_set_value) << "Could not set value for AccObject: "
|
| - << GetDescription();
|
| - return did_set_value;
|
| -}
|
| -
|
| -bool AccObject::GetName(std::wstring* name) {
|
| - DCHECK(name);
|
| - base::win::ScopedBstr name_bstr;
|
| - HRESULT result = accessible_->get_accName(child_id_, name_bstr.Receive());
|
| - if (SUCCEEDED(result))
|
| - name->assign(name_bstr, name_bstr.Length());
|
| - return SUCCEEDED(result);
|
| -}
|
| -
|
| -bool AccObject::GetRoleText(std::wstring* role_text) {
|
| - DCHECK(role_text);
|
| - base::win::ScopedVariant role_variant;
|
| - if (SUCCEEDED(accessible_->get_accRole(child_id_, role_variant.Receive()))) {
|
| - if (role_variant.type() == VT_I4) {
|
| - wchar_t role_text_array[50];
|
| - UINT characters = ::GetRoleText(V_I4(&role_variant), role_text_array,
|
| - arraysize(role_text_array));
|
| - if (characters) {
|
| - *role_text = role_text_array;
|
| - return true;
|
| - } else {
|
| - LOG(ERROR) << "GetRoleText failed for role: " << V_I4(&role_variant);
|
| - }
|
| - } else if (role_variant.type() == VT_BSTR) {
|
| - *role_text = V_BSTR(&role_variant);
|
| - return true;
|
| - } else {
|
| - LOG(ERROR) << "Role was unexpected variant type: "
|
| - << role_variant.type();
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool AccObject::GetValue(std::wstring* value) {
|
| - DCHECK(value);
|
| - base::win::ScopedBstr value_bstr;
|
| - HRESULT result = accessible_->get_accValue(child_id_, value_bstr.Receive());
|
| - if (SUCCEEDED(result))
|
| - value->assign(value_bstr, value_bstr.Length());
|
| - return SUCCEEDED(result);
|
| -}
|
| -
|
| -bool AccObject::GetState(int* state) {
|
| - DCHECK(state);
|
| - base::win::ScopedVariant state_variant;
|
| - if (SUCCEEDED(accessible_->get_accState(child_id_,
|
| - state_variant.Receive()))) {
|
| - if (state_variant.type() == VT_I4) {
|
| - *state = V_I4(&state_variant);
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool AccObject::GetLocation(gfx::Rect* location) {
|
| - DCHECK(location);
|
| - long left, top, width, height; // NOLINT
|
| - HRESULT result = accessible_->accLocation(&left, &top, &width, &height,
|
| - child_id_);
|
| - if (SUCCEEDED(result))
|
| - *location = gfx::Rect(left, top, width, height);
|
| - return SUCCEEDED(result);
|
| -}
|
| -
|
| -bool AccObject::GetLocationInClient(gfx::Rect* client_location) {
|
| - DCHECK(client_location);
|
| - gfx::Rect location;
|
| - if (!GetLocation(&location))
|
| - return false;
|
| - HWND container_window = NULL;
|
| - if (!GetWindow(&container_window))
|
| - return false;
|
| - POINT offset = {0, 0};
|
| - if (!::ScreenToClient(container_window, &offset)) {
|
| - LOG(ERROR) << "Could not convert from screen to client coordinates for "
|
| - "window containing accessibility object: "
|
| - << GetDescription();
|
| - return false;
|
| - }
|
| - location.Offset(offset.x, offset.y);
|
| - *client_location = location;
|
| - return true;
|
| -}
|
| -
|
| -AccObject* AccObject::GetParent() {
|
| - if (IsSimpleElement())
|
| - return new AccObject(accessible_);
|
| - base::win::ScopedComPtr<IDispatch> dispatch;
|
| - if (FAILED(accessible_->get_accParent(dispatch.Receive())))
|
| - return NULL;
|
| - return AccObject::CreateFromDispatch(dispatch.get());
|
| -}
|
| -
|
| -bool AccObject::GetChildren(RefCountedAccObjectVector* client_objects) {
|
| - DCHECK(client_objects);
|
| - int child_count;
|
| - if (!GetChildCount(&child_count)) {
|
| - LOG(ERROR) << "Failed to get child count of AccObject";
|
| - return false;
|
| - }
|
| - if (child_count == 0)
|
| - return true;
|
| -
|
| - RefCountedAccObjectVector objects;
|
| - // Find children using |AccessibleChildren|.
|
| - scoped_ptr<VARIANT[]> children(new VARIANT[child_count]);
|
| - long found_child_count; // NOLINT
|
| - if (FAILED(AccessibleChildren(accessible_, 0L, child_count,
|
| - children.get(),
|
| - &found_child_count))) {
|
| - LOG(ERROR) << "Failed to get children of accessible object";
|
| - return false;
|
| - }
|
| - if (found_child_count > 0) {
|
| - for (int i = 0; i < found_child_count; i++) {
|
| - scoped_refptr<AccObject> obj = CreateFromVariant(this, children[i]);
|
| - if (obj)
|
| - objects.push_back(obj);
|
| - ::VariantClear(&children[i]);
|
| - }
|
| - }
|
| -
|
| - // In some cases, there are more children which can be found only by using
|
| - // the deprecated |accNavigate| method. Many of the menus, such as
|
| - // 'Favorites', cannot be found in IE6 using |AccessibileChildren|. Here we
|
| - // attempt a best effort at finding some remaining children.
|
| - int remaining_child_count = child_count - found_child_count;
|
| - scoped_refptr<AccObject> child_object;
|
| - if (remaining_child_count > 0) {
|
| - GetFromNavigation(NAVDIR_FIRSTCHILD, &child_object);
|
| - }
|
| - while (remaining_child_count > 0 && child_object) {
|
| - // Add to the children list if this child was not found earlier.
|
| - bool already_found = false;
|
| - for (size_t i = 0; i < objects.size(); ++i) {
|
| - if (child_object->Equals(objects[i])) {
|
| - already_found = true;
|
| - break;
|
| - }
|
| - }
|
| - if (!already_found) {
|
| - objects.push_back(child_object);
|
| - remaining_child_count--;
|
| - }
|
| - scoped_refptr<AccObject> next_child_object;
|
| - child_object->GetFromNavigation(NAVDIR_NEXT, &next_child_object);
|
| - child_object = next_child_object;
|
| - }
|
| -
|
| - client_objects->insert(client_objects->end(), objects.begin(), objects.end());
|
| - return true;
|
| -}
|
| -
|
| -bool AccObject::GetChildCount(int* child_count) {
|
| - DCHECK(child_count);
|
| - *child_count = 0;
|
| - if (!IsSimpleElement()) {
|
| - long long_child_count; // NOLINT
|
| - if (FAILED(accessible_->get_accChildCount(&long_child_count)))
|
| - return false;
|
| - *child_count = static_cast<int>(long_child_count);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool AccObject::GetFromNavigation(long navigation_type,
|
| - scoped_refptr<AccObject>* object) {
|
| - DCHECK(object);
|
| - bool is_child_navigation = navigation_type == NAVDIR_FIRSTCHILD ||
|
| - navigation_type == NAVDIR_LASTCHILD;
|
| - DCHECK(!is_child_navigation || !IsSimpleElement());
|
| - base::win::ScopedVariant object_variant;
|
| - HRESULT result = accessible_->accNavigate(navigation_type,
|
| - child_id_,
|
| - object_variant.Receive());
|
| - if (FAILED(result)) {
|
| - LOG(WARNING) << "Navigation from accessibility object failed";
|
| - return false;
|
| - }
|
| - if (result == S_FALSE || object_variant.type() == VT_EMPTY) {
|
| - // This indicates that there was no accessibility object found by the
|
| - // navigation.
|
| - return true;
|
| - }
|
| - AccObject* navigated_to_object;
|
| - if (!is_child_navigation && !IsSimpleElement()) {
|
| - scoped_refptr<AccObject> parent = GetParent();
|
| - if (!parent.get()) {
|
| - LOG(WARNING) << "Could not get parent for accessibiliy navigation";
|
| - return false;
|
| - }
|
| - navigated_to_object = CreateFromVariant(parent, object_variant);
|
| - } else {
|
| - navigated_to_object = CreateFromVariant(this, object_variant);
|
| - }
|
| - if (!navigated_to_object)
|
| - return false;
|
| - *object = navigated_to_object;
|
| - return true;
|
| -}
|
| -
|
| -bool AccObject::GetWindow(HWND* window) {
|
| - DCHECK(window);
|
| - return SUCCEEDED(::WindowFromAccessibleObject(accessible_, window)) && window;
|
| -}
|
| -
|
| -bool AccObject::GetWindowClassName(std::wstring* class_name) {
|
| - DCHECK(class_name);
|
| - HWND container_window = NULL;
|
| - if (GetWindow(&container_window)) {
|
| - wchar_t class_arr[MAX_PATH];
|
| - if (::GetClassName(container_window, class_arr, arraysize(class_arr))) {
|
| - *class_name = class_arr;
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool AccObject::GetSelectionRange(int* start_offset, int* end_offset) {
|
| - DCHECK(start_offset);
|
| - DCHECK(end_offset);
|
| - base::win::ScopedComPtr<IAccessibleText> accessible_text;
|
| - HRESULT hr = DoQueryService(IID_IAccessibleText,
|
| - accessible_,
|
| - accessible_text.Receive());
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Could not get IAccessibleText interface. Error: " << hr
|
| - << "\nIs IAccessible2Proxy.dll registered?";
|
| - return false;
|
| - }
|
| -
|
| - LONG selection_count = 0;
|
| - accessible_text->get_nSelections(&selection_count);
|
| - LONG start = 0, end = 0;
|
| - if (selection_count > 0) {
|
| - if (FAILED(accessible_text->get_selection(0, &start, &end))) {
|
| - LOG(WARNING) << "Could not get first selection";
|
| - return false;
|
| - }
|
| - }
|
| - *start_offset = start;
|
| - *end_offset = end;
|
| - return true;
|
| -}
|
| -
|
| -bool AccObject::GetSelectedText(std::wstring* text) {
|
| - DCHECK(text);
|
| - int start = 0, end = 0;
|
| - if (!GetSelectionRange(&start, &end))
|
| - return false;
|
| - base::win::ScopedComPtr<IAccessibleText> accessible_text;
|
| - HRESULT hr = DoQueryService(IID_IAccessibleText,
|
| - accessible_,
|
| - accessible_text.Receive());
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Could not get IAccessibleText interface. Error: " << hr
|
| - << "\nIs IAccessible2Proxy.dll registered?";
|
| - return false;
|
| - }
|
| - base::win::ScopedBstr text_bstr;
|
| - if (FAILED(accessible_text->get_text(start, end, text_bstr.Receive()))) {
|
| - LOG(WARNING) << "Could not get text from selection range";
|
| - return false;
|
| - }
|
| - text->assign(text_bstr, text_bstr.Length());
|
| - return true;
|
| -}
|
| -
|
| -bool AccObject::IsSimpleElement() {
|
| - return V_I4(&child_id_) != CHILDID_SELF;
|
| -}
|
| -
|
| -bool AccObject::Equals(AccObject* other) {
|
| - if (other) {
|
| - DCHECK(child_id_.type() == VT_I4 && other->child_id_.type() == VT_I4);
|
| - return accessible_.get() == other->accessible_.get() &&
|
| - V_I4(&child_id_) == V_I4(&other->child_id_);
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -std::wstring AccObject::GetDescription() {
|
| - std::wstring name = L"-", role_text = L"-", value = L"-";
|
| - if (GetName(&name))
|
| - name = L"'" + name + L"'";
|
| - if (GetRoleText(&role_text))
|
| - role_text = L"'" + role_text + L"'";
|
| - if (GetValue(&value))
|
| - value = L"'" + value + L"'";
|
| - int state = 0;
|
| - GetState(&state);
|
| - return base::StringPrintf(L"[%ls, %ls, %ls, 0x%x]", name.c_str(),
|
| - role_text.c_str(), value.c_str(), state);
|
| -}
|
| -
|
| -std::wstring AccObject::GetTree() {
|
| - std::wostringstream string_stream;
|
| - string_stream << L"Accessibility object tree:" << std::endl;
|
| - string_stream << L"[name, role_text, value, state]" << std::endl;
|
| -
|
| - std::stack<std::pair<scoped_refptr<AccObject>, int> > pairs;
|
| - pairs.push(std::make_pair(this, 0));
|
| - while (!pairs.empty()) {
|
| - scoped_refptr<AccObject> object = pairs.top().first;
|
| - int depth = pairs.top().second;
|
| - pairs.pop();
|
| -
|
| - for (int i = 0; i < depth; ++i)
|
| - string_stream << L" ";
|
| - string_stream << object->GetDescription() << std::endl;
|
| -
|
| - RefCountedAccObjectVector children;
|
| - if (object->GetChildren(&children)) {
|
| - for (int i = static_cast<int>(children.size()) - 1; i >= 0; --i)
|
| - pairs.push(std::make_pair(children[i], depth + 1));
|
| - }
|
| - }
|
| - return string_stream.str();
|
| -}
|
| -
|
| -// static
|
| -AccObject* AccObject::CreateFromVariant(AccObject* object,
|
| - const VARIANT& variant) {
|
| - IAccessible* accessible = object->accessible_;
|
| - if (V_VT(&variant) == VT_I4) {
|
| - // According to MSDN, a server is allowed to return a full Accessibility
|
| - // object using the parent object and the child id. If get_accChild is
|
| - // called with the id, the server must return the actual IAccessible
|
| - // interface. Do that here to get an actual IAccessible interface if
|
| - // possible, since this class operates under the assumption that if the
|
| - // child id is not CHILDID_SELF, the object is a simple element. See the
|
| - // DCHECK in the constructor.
|
| - base::win::ScopedComPtr<IDispatch> dispatch;
|
| - HRESULT result = accessible->get_accChild(variant,
|
| - dispatch.Receive());
|
| - if (result == S_FALSE || result == E_NOINTERFACE) {
|
| - // The object in question really is a simple element.
|
| - return new AccObject(accessible, V_I4(&variant));
|
| - } else if (SUCCEEDED(result)) {
|
| - // The object in question was actually a full object.
|
| - return CreateFromDispatch(dispatch.get());
|
| - }
|
| - VLOG(1) << "Failed to determine if child id refers to a full "
|
| - << "object. Error: " << result << std::endl
|
| - << "Parent object: " << base::WideToUTF8(object->GetDescription())
|
| - << std::endl << "Child ID: " << V_I4(&variant);
|
| - return NULL;
|
| - } else if (V_VT(&variant) == VT_DISPATCH) {
|
| - return CreateFromDispatch(V_DISPATCH(&variant));
|
| - }
|
| - LOG(WARNING) << "Unrecognizable child type";
|
| - return NULL;
|
| -}
|
| -
|
| -bool AccObject::PostMouseClickAtCenter(int button_down, int button_up) {
|
| - std::wstring class_name;
|
| - if (!GetWindowClassName(&class_name)) {
|
| - LOG(ERROR) << "Could not get class name of window for accessibility "
|
| - << "object: " << GetDescription();
|
| - return false;
|
| - }
|
| - gfx::Rect location;
|
| - if (class_name == L"#32768") {
|
| - // For some reason, it seems that menus expect screen coordinates.
|
| - if (!GetLocation(&location))
|
| - return false;
|
| - } else {
|
| - if (!GetLocationInClient(&location))
|
| - return false;
|
| - }
|
| -
|
| - gfx::Point center = location.CenterPoint();
|
| - return PostMouseButtonMessages(button_down, button_up,
|
| - center.x(), center.y());
|
| -}
|
| -
|
| -bool AccObject::PostMouseButtonMessages(
|
| - int button_down, int button_up, int x, int y) {
|
| - HWND container_window;
|
| - if (!GetWindow(&container_window))
|
| - return false;
|
| -
|
| - LPARAM coordinates = MAKELPARAM(x, y);
|
| - ::PostMessage(container_window, button_down, 0, coordinates);
|
| - ::PostMessage(container_window, button_up, 0, coordinates);
|
| - return true;
|
| -}
|
| -
|
| -// AccObjectMatcher methods
|
| -AccObjectMatcher::AccObjectMatcher(const std::wstring& name,
|
| - const std::wstring& role_text,
|
| - const std::wstring& value)
|
| - : name_(name), role_text_(role_text), value_(value) {
|
| -}
|
| -
|
| -bool AccObjectMatcher::FindHelper(AccObject* object,
|
| - scoped_refptr<AccObject>* match) const {
|
| - if (DoesMatch(object)) {
|
| - *match = object;
|
| - } else {
|
| - // Try to match the children of |object|.
|
| - AccObject::RefCountedAccObjectVector children;
|
| - if (!object->GetChildren(&children)) {
|
| - LOG(ERROR) << "Could not get children of AccObject";
|
| - return false;
|
| - }
|
| - for (size_t i = 0; i < children.size(); ++i) {
|
| - if (!FindHelper(children[i], match)) {
|
| - return false;
|
| - }
|
| - if (*match)
|
| - break;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool AccObjectMatcher::Find(AccObject* object,
|
| - scoped_refptr<AccObject>* match) const {
|
| - DCHECK(object);
|
| - DCHECK(match);
|
| - *match = NULL;
|
| - return FindHelper(object, match);
|
| -}
|
| -
|
| -bool AccObjectMatcher::FindInWindow(HWND hwnd,
|
| - scoped_refptr<AccObject>* match) const {
|
| - scoped_refptr<AccObject> object(AccObject::CreateFromWindow(hwnd));
|
| - if (!object) {
|
| - VLOG(1) << "Failed to get accessible object from window";
|
| - return false;
|
| - }
|
| - return Find(object.get(), match);
|
| -}
|
| -
|
| -bool AccObjectMatcher::DoesMatch(AccObject* object) const {
|
| - DCHECK(object);
|
| - bool does_match = true;
|
| - std::wstring name, role_text, value;
|
| - if (name_.length()) {
|
| - object->GetName(&name);
|
| - does_match = MatchPattern(StringToUpperASCII(name),
|
| - StringToUpperASCII(name_));
|
| - }
|
| - if (does_match && role_text_.length()) {
|
| - object->GetRoleText(&role_text);
|
| - does_match = MatchPattern(role_text, role_text_);
|
| - }
|
| - if (does_match && value_.length()) {
|
| - object->GetValue(&value);
|
| - does_match = MatchPattern(value, value_);
|
| - }
|
| - return does_match;
|
| -}
|
| -
|
| -std::wstring AccObjectMatcher::GetDescription() const {
|
| - std::wostringstream ss;
|
| - ss << L"[";
|
| - if (name_.length())
|
| - ss << L"Name: '" << name_ << L"', ";
|
| - if (role_text_.length())
|
| - ss << L"Role: '" << role_text_ << L"', ";
|
| - if (value_.length())
|
| - ss << L"Value: '" << value_ << L"'";
|
| - ss << L"]";
|
| - return ss.str();
|
| -}
|
| -
|
| -// AccEventObserver methods
|
| -AccEventObserver::AccEventObserver()
|
| - : event_handler_(new EventHandler(this)),
|
| - is_watching_(false) {
|
| - event_receiver_.SetListenerForEvents(this, EVENT_SYSTEM_MENUPOPUPSTART,
|
| - EVENT_OBJECT_VALUECHANGE);
|
| -}
|
| -
|
| -AccEventObserver::~AccEventObserver() {
|
| - event_handler_->observer_ = NULL;
|
| -}
|
| -
|
| -void AccEventObserver::WatchForOneValueChange(const AccObjectMatcher& matcher) {
|
| - is_watching_ = true;
|
| - watching_for_matcher_ = matcher;
|
| -}
|
| -
|
| -void AccEventObserver::OnEventReceived(DWORD event,
|
| - HWND hwnd,
|
| - LONG object_id,
|
| - LONG child_id) {
|
| - // Process events in a separate task to stop reentrancy problems.
|
| - DCHECK(base::MessageLoop::current());
|
| - base::MessageLoop::current()->PostTask(
|
| - FROM_HERE, base::Bind(&EventHandler::Handle, event_handler_.get(), event,
|
| - hwnd, object_id, child_id));
|
| -}
|
| -
|
| -// AccEventObserver::EventHandler methods
|
| -AccEventObserver::EventHandler::EventHandler(AccEventObserver* observer)
|
| - : observer_(observer) {
|
| -}
|
| -
|
| -void AccEventObserver::EventHandler::Handle(DWORD event,
|
| - HWND hwnd,
|
| - LONG object_id,
|
| - LONG child_id) {
|
| - if (!observer_)
|
| - return;
|
| -
|
| - switch (event) {
|
| - case EVENT_SYSTEM_MENUPOPUPSTART:
|
| - observer_->OnMenuPopup(hwnd);
|
| - break;
|
| - case IA2_EVENT_DOCUMENT_LOAD_COMPLETE:
|
| - observer_->OnAccDocLoad(hwnd);
|
| - break;
|
| - case IA2_EVENT_TEXT_CARET_MOVED: {
|
| - scoped_refptr<AccObject> object(
|
| - AccObject::CreateFromEvent(hwnd, object_id, child_id));
|
| - if (object)
|
| - observer_->OnTextCaretMoved(hwnd, object.get());
|
| - break;
|
| - }
|
| - case EVENT_OBJECT_VALUECHANGE:
|
| - if (observer_->is_watching_) {
|
| - scoped_refptr<AccObject> object(
|
| - AccObject::CreateFromEvent(hwnd, object_id, child_id));
|
| - if (object) {
|
| - if (observer_->watching_for_matcher_.DoesMatch(object.get())) {
|
| - // Stop watching before calling OnAccValueChange in case the
|
| - // client invokes our watch method during the call.
|
| - observer_->is_watching_ = false;
|
| - std::wstring new_value;
|
| - if (object->GetValue(&new_value)) {
|
| - observer_->OnAccValueChange(hwnd, object.get(), new_value);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| -}
|
| -
|
| -// Other methods
|
| -bool FindAccObjectInWindow(HWND hwnd, const AccObjectMatcher& matcher,
|
| - scoped_refptr<AccObject>* object) {
|
| - DCHECK(object);
|
| - EXPECT_TRUE(matcher.FindInWindow(hwnd, object));
|
| - EXPECT_TRUE(*object) << "Element not found for matcher: "
|
| - << matcher.GetDescription();
|
| - if (!*object)
|
| - DumpAccessibilityTreeForWindow(hwnd);
|
| - return *object;
|
| -}
|
| -
|
| -void DumpAccessibilityTreeForWindow(HWND hwnd) {
|
| - scoped_refptr<AccObject> object(AccObject::CreateFromWindow(hwnd));
|
| - if (object)
|
| - std::wcout << object->GetTree();
|
| - else
|
| - std::cout << "Could not get IAccessible for window" << std::endl;
|
| -}
|
| -
|
| -bool IsDesktopUnlocked() {
|
| - HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
|
| - if (desk)
|
| - ::CloseDesktop(desk);
|
| - return desk;
|
| -}
|
| -
|
| -base::FilePath GetIAccessible2ProxyStubPath() {
|
| - base::FilePath path;
|
| - PathService::Get(chrome::DIR_APP, &path);
|
| - return path.AppendASCII("IAccessible2Proxy.dll");
|
| -}
|
| -
|
| -} // namespace chrome_frame_test
|
|
|