diff options
Diffstat (limited to 'chrome/test/accessibility/accessibility_util.cc')
-rw-r--r-- | chrome/test/accessibility/accessibility_util.cc | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/chrome/test/accessibility/accessibility_util.cc b/chrome/test/accessibility/accessibility_util.cc new file mode 100644 index 0000000..0861cc2 --- /dev/null +++ b/chrome/test/accessibility/accessibility_util.cc @@ -0,0 +1,553 @@ +// Copyright (c) 2006-2008 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/test/accessibility/accessibility_util.h" + +#include "app/l10n_util.h" +#include "base/win_util.h" +#include "chrome/browser/view_ids.h" +#include "chrome/test/accessibility/constants.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" + +VARIANT id_self = {VT_I4, CHILDID_SELF}; + +// TODO(beng): clean this up +static const wchar_t* kBrowserWindowKey = L"__BROWSER_WINDOW__"; + +static BOOL CALLBACK WindowEnumProc(HWND hwnd, LPARAM data) { + std::wstring class_name = win_util::GetClassName(hwnd); + if (class_name == CHROME_HWND_VIEW_CONTAINER) { + HANDLE window_interface = GetProp(hwnd, kBrowserWindowKey); + if (window_interface) { + HWND* out = reinterpret_cast<HWND*>(data); + *out = hwnd; + return FALSE; + } + } + return TRUE; +} + +HWND GetChromeBrowserWnd(IAccessible** acc_obj) { + HWND hwnd = NULL; + + EnumWindows(WindowEnumProc, reinterpret_cast<LPARAM>(&hwnd)); + + if (!hwnd) { + CHK_RELEASE(*acc_obj); + return NULL; + } + + // Get accessibility object for Chrome, only if requested (not NULL). + if (!acc_obj) + return hwnd; + + *acc_obj = NULL; + + // Get accessibility object for Chrome Main Window. If failed to get it, + // return only window handle. + IAccessible* root_acc_obj = NULL; + HRESULT hr = S_OK; + hr = AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(&root_acc_obj)); + if ((S_OK != hr) || !root_acc_obj) + return hwnd; + + const std::wstring product_name = l10n_util::GetString(IDS_PRODUCT_NAME); + BSTR name; + + // Confirm if it is Chrome Main Window using its accessibility object's + // Name and Role property. If it's not the desired object, return only + // window handle. + hr = root_acc_obj->get_accName(id_self, &name); + if ((S_OK != hr) || (!name) || + (0 != _wcsicmp(name, product_name.c_str())) ) { + CHK_RELEASE(root_acc_obj); + return hwnd; + } + if (ROLE_SYSTEM_WINDOW != GetRole(root_acc_obj)) { + CHK_RELEASE(root_acc_obj); + return hwnd; + } + + // Get accessibility child objects for Chrome Main Window. If failed, return + // only window handle. + INT64 child_cnt = GetChildCount(root_acc_obj); + VARIANT* children = reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), + sizeof(VARIANT))); + + if (!children) { + CHK_RELEASE(root_acc_obj); + return hwnd; + } + + hr = GetChildrenArray(root_acc_obj, children); + if (S_OK != hr) { + CHK_RELEASE(root_acc_obj); + free(children); + return hwnd; + } + + // Fetch desired child (Chrome App Window) of Chrome Main Window. + IAccessible* app_acc_obj = NULL; + GetChildAccObject(root_acc_obj, children[CHROME_APP_ACC_INDEX], &app_acc_obj); + if (!app_acc_obj) { + CHK_RELEASE(app_acc_obj); + free(children); + return hwnd; + } + + // Confirm if it is Chrome App Window by using it's accessibility object's + // Name and Role property. If it's not the desired object, return only + // window handle. + hr = app_acc_obj->get_accName(id_self, &name); + if ((S_OK != hr) || (!name) || + (0 != _wcsicmp(name, product_name.c_str())) ) { + CHK_RELEASE(app_acc_obj); + CHK_RELEASE(root_acc_obj); + free(children); + return hwnd; + } + if (ROLE_SYSTEM_APPLICATION != GetRole(app_acc_obj)) { + CHK_RELEASE(app_acc_obj); + CHK_RELEASE(root_acc_obj); + free(children); + return hwnd; + } + + // Get accessibility object for Chrome Client. If failed, return only + // window handle. + hr = GetChildrenArray(app_acc_obj, children); + if (S_OK != hr) { + CHK_RELEASE(app_acc_obj); + CHK_RELEASE(root_acc_obj); + free(children); + return hwnd; + } + + // Chrome Window has only one child which is Chrome Client. + GetChildAccObject(app_acc_obj, children[CHROME_CLIENT_ACC_INDEX], acc_obj); + + // Done using [children] array. + free(children); + + // Confirm if it is Chrome client using it's accessibility object's Name + // and Role property. If it's not the desired object, return only window + // handle. + hr = (*acc_obj)->get_accName(id_self, &name); + if ((S_OK != hr) || (!name) || + (0 != _wcsicmp(name, product_name.c_str())) ) { + CHK_RELEASE(*acc_obj); + } + if (ROLE_SYSTEM_CLIENT != GetRole(*acc_obj)) + CHK_RELEASE(*acc_obj); + + CHK_RELEASE(app_acc_obj); + CHK_RELEASE(root_acc_obj); + return hwnd; +} + +HRESULT GetChildAccessible(std::wstring parent_name, unsigned int child_index, + IAccessible** acc_obj) { + // Validate input and initialize. + if (!acc_obj) + return E_INVALIDARG; + + *acc_obj = NULL; + + // Get accessibility object and window handle for Chrome parent. + IAccessible* parent = NULL; + if (0 == parent_name.compare(BROWSER_STR)) + GetChromeBrowserWnd(&parent); + if (0 == parent_name.compare(BROWSER_VIEW_STR)) + GetBrowserViewAccessible(&parent); + if (0 == parent_name.compare(TOOLBAR_STR)) + GetToolbarAccessible(&parent); + if (0 == parent_name.compare(TABSTRIP_STR)) + GetTabStripAccessible(&parent); + + if (!parent) + return E_FAIL; + + bool get_iaccessible = false; + + // Validate child index. + INT64 child_cnt = GetChildCount(parent); + if (child_index >= child_cnt) + get_iaccessible = true; + + HRESULT hr = S_OK; + + if (get_iaccessible) { + // Child retrieved by child index, potentially further down the hierarchy. + VARIANT child_var; + child_var.vt = VT_I4; + child_var.lVal = child_index; + hr = GetChildAccObject(parent, child_var, acc_obj); + } else { + // Get array of child items of parent object. + VARIANT* children = reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), + sizeof(VARIANT))); + if (children) { + hr = GetChildrenArray(parent, children); + if (S_OK == hr) { + // Fetch child IAccessible. + if (acc_obj) + hr = GetChildAccObject(parent, children[child_index], acc_obj); + } + free(children); + } + } + + CHK_RELEASE(parent); + return hr; +} + +HRESULT GetTabStripAccessible(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_VIEW_STR, TABSTRIP_ACC_INDEX, acc_obj); +} + +HRESULT GetBrowserViewAccessible(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_STR, BROWSER_VIEW_ACC_INDEX, acc_obj); +} + +HRESULT GetToolbarAccessible(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_VIEW_STR, VIEW_ID_TOOLBAR, acc_obj); +} + +HRESULT GetBrowserMinimizeButton(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_STR, CHROME_MIN_ACC_INDEX, acc_obj); +} + +HRESULT GetBrowserMaximizeButton(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_STR, CHROME_MAX_ACC_INDEX, acc_obj); +} + +HRESULT GetBrowserRestoreButton(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_STR, CHROME_RESTORE_ACC_INDEX, acc_obj); +} + +HRESULT GetBrowserCloseButton(IAccessible** acc_obj) { + return GetChildAccessible(BROWSER_STR, CHROME_CLOSE_ACC_INDEX, acc_obj); +} + +HRESULT GetBackButton(IAccessible** acc_obj) { + return GetChildAccessible(TOOLBAR_STR, VIEW_ID_BACK_BUTTON, acc_obj); +} + +HRESULT GetForwardButton(IAccessible** acc_obj) { + return GetChildAccessible(TOOLBAR_STR, VIEW_ID_FORWARD_BUTTON, acc_obj); +} + +HRESULT GetStarButton(IAccessible** acc_obj) { + return GetChildAccessible(TOOLBAR_STR, VIEW_ID_STAR_BUTTON, acc_obj); +} + +HRESULT GetGoButton(IAccessible** acc_obj) { + return GetChildAccessible(TOOLBAR_STR, VIEW_ID_GO_BUTTON, acc_obj); +} + +HRESULT GetPageMenuButton(IAccessible** acc_obj) { + return GetChildAccessible(TOOLBAR_STR, VIEW_ID_PAGE_MENU, acc_obj); +} + +HRESULT GetAppMenuButton(IAccessible** acc_obj) { + return GetChildAccessible(TOOLBAR_STR, VIEW_ID_APP_MENU, acc_obj); +} + +HWND GetAddressBarWnd(IAccessible** acc_obj) { + // Initialize, if requested. + if (acc_obj) + *acc_obj = NULL; + + HWND hwnd = NULL; + HWND hwnd_addr_bar = NULL; + + // Get window handle for Chrome Browser. + hwnd = GetChromeBrowserWnd(NULL); + if (NULL != hwnd) { + // Get AddressBar/OmniBox (edit box) window handle. + hwnd_addr_bar = FindWindowEx(hwnd, 0, CHROME_AUTOCOMPLETE_EDIT, NULL); + + // Get accessibility object for address bar, if requested. + if (acc_obj && hwnd_addr_bar) { + AccessibleObjectFromWindow(hwnd_addr_bar, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(acc_obj)); + } + } + + return hwnd_addr_bar; +} + +HWND GetFindTextWnd(IAccessible** acc_obj) { + // Initialize, if requested. + if (acc_obj) + *acc_obj = NULL; + + HWND hwnd = NULL; + HWND hwnd_find = NULL; + + // Get window handle for Chrome Browser. + hwnd = GetChromeBrowserWnd(NULL); + if (NULL != hwnd) { + // Get handle of a window, which is contains edit box for Find string. + hwnd_find = FindWindowEx(hwnd, 0, CHROME_HWND_VIEW_CONTAINER, NULL); + + // Get accessibility object, if requested. + if (acc_obj && hwnd_find) { + AccessibleObjectFromWindow(hwnd_find, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(acc_obj)); + } + } + + return hwnd_find; +} + +HWND GetAuthWnd(IAccessible** acc_obj) { + // Initialize, if requested. + if (acc_obj) + *acc_obj = NULL; + + HWND hwnd = NULL; + HWND hwnd_tab = NULL; + HWND hwnd_auth = NULL; + + // Get window handle for Chrome Browser. + hwnd = GetChromeBrowserWnd(NULL); + if (hwnd) { + // Get window handle for tab. + hwnd_tab = FindWindowEx(hwnd, 0, CHROME_TAB_CONTENTS, NULL); + if (!hwnd_tab) + return hwnd_auth; + + // Get handle for Authentication window. + hwnd_auth = FindWindowEx(hwnd_tab, 0, CHROME_HWND_VIEW_CONTAINER, + AUTH_TITLE); + + // Get accessibility object, if requested. + if (acc_obj && hwnd_auth) { + AccessibleObjectFromWindow(hwnd_auth, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(acc_obj)); + } + } + + return hwnd_auth; +} + +HRESULT GetChildAccObject(IAccessible* acc_obj, VARIANT child, + IAccessible** child_acc_obj) { + // Validate input. + if (!acc_obj || !child_acc_obj) + return E_INVALIDARG; + + HRESULT hr = S_OK; + IDispatch* disp = NULL; + + // Check the child type and fetch object accordingly. + if (child.vt == VT_DISPATCH) { + child.pdispVal-> + QueryInterface(IID_IAccessible, + reinterpret_cast<void**>(child_acc_obj)); + } else if (child.vt == VT_I4) { + hr = acc_obj->get_accChild(child, &disp); + if ((hr == S_OK) && disp) { + disp->QueryInterface(IID_IAccessible, + reinterpret_cast<void**>(child_acc_obj)); + CHK_RELEASE(disp); + } + } + + return hr; +} + +HRESULT GetParentAccObject(IAccessible* acc_obj, IAccessible** parent_acc_obj) { + // Validate input. + if (!acc_obj || !parent_acc_obj) + return E_INVALIDARG; + + HRESULT hr = S_OK; + IDispatch* disp = NULL; + + // Fetch parent object. + hr = acc_obj->get_accParent(&disp); + if ((hr == S_OK) && disp) { + disp->QueryInterface(IID_IAccessible, + reinterpret_cast<void**>(parent_acc_obj)); + CHK_RELEASE(disp); + } + + return hr; +} + +INT64 GetChildCount(IAccessible* acc_obj) { + HRESULT hr = S_OK; + LONG child_cnt = 0; + + // Validate input. Object can have 0 children, so return -1 on invalid input. + if (!acc_obj) + return -1; + + // Get child count. + acc_obj->get_accChildCount(&child_cnt); + return child_cnt; +} + +HRESULT GetChildrenArray(IAccessible* acc_obj, VARIANT* children) { + HRESULT hr = S_OK; + INT64 child_start = 0; + LONG child_obtained = 0; + INT64 child_cnt = GetChildCount(acc_obj); + + // Validate input. + if (!acc_obj || !children) + return E_INVALIDARG; + + // Validate every item and initialize it. + int i = 0; + for (; (i < child_cnt) && (children + i); i++) { + VariantInit(children + i); + } + + // If all items in array are not initialized, return error. + if (i != child_cnt) + return E_FAIL; + + // Get IDs of child items. + AccessibleChildren(acc_obj, LONG(child_start), LONG(child_cnt), children, + &child_obtained); + return hr; +} + +HRESULT ActivateWnd(IAccessible* acc_obj, HWND hwnd) { + HRESULT hr = S_OK; + + // Select and focus the object, if accessibility object is specified. + if (acc_obj) + hr = acc_obj->accSelect(SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION, id_self); + + // Send message to window, if window handle is specified. + if (hwnd) + SetActiveWindow(hwnd); + + return hr; +} + +BSTR GetTabName(INT64 tab_index) { + HRESULT hr = S_OK; + BSTR name; + + // Validate tab index specified. + if (tab_index < 1) + return NULL; + + // Get accessibility object for Tabstrip. + IAccessible* tab_strip_acc_obj = NULL; + GetTabStripAccessible(&tab_strip_acc_obj); + + // Get Tab from Tabstrip and return it's Name. + if (tab_strip_acc_obj) { + INT64 child_cnt = GetChildCount(tab_strip_acc_obj); + VARIANT* children = reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), + sizeof(VARIANT))); + if (children) { + // Get tab object. tab_index = index in child array, because first child + // in tabstrip is '+' button. + hr = GetChildrenArray(tab_strip_acc_obj, children); + if (S_OK == hr) { + IAccessible* temp_acc_obj = NULL; + hr = GetChildAccObject(tab_strip_acc_obj, children[tab_index], + &temp_acc_obj); + if ((S_OK == hr) && (children[tab_index].vt == VT_DISPATCH) && + (temp_acc_obj)) { + hr = temp_acc_obj->get_accName(id_self, &name); + } else if (children[tab_index].vt == VT_I4) { + hr = tab_strip_acc_obj->get_accName(children[1], &name); + } + CHK_RELEASE(temp_acc_obj); + CHK_RELEASE(tab_strip_acc_obj); + return name; + } + } + CHK_RELEASE(tab_strip_acc_obj); + } + + return NULL; +} + +INT64 GetTabCnt() { + // Get accessibility object for Tabstrip. + IAccessible* tab_strip_acc_obj = NULL; + GetTabStripAccessible(&tab_strip_acc_obj); + + // If Tabstrip is invalid, return -1 to indicate error. + if (!tab_strip_acc_obj) + return -1; + + // Get child count. + INT64 child_cnt = 0; + child_cnt = GetChildCount(tab_strip_acc_obj); + CHK_RELEASE(tab_strip_acc_obj); + + // Don't count 1st child as it is '+' button. + return (child_cnt - 1); +} + +std::wstring GetName(IAccessible* acc_obj, VARIANT child) { + HRESULT hr = S_OK; + + // Validate input. + if (!acc_obj) + return std::wstring(); + + // Get Name. + BSTR name; + hr = acc_obj->get_accName(child, &name); + if (S_OK != hr) + return std::wstring(); + + return std::wstring(name); +} + +LONG GetRole(IAccessible* acc_obj, VARIANT child) { + HRESULT hr = S_OK; + LPTSTR role_str = NULL; + + // Validate input. + if (!acc_obj) + return -1; + + // Get Role. + VARIANT role; + VariantInit(&role); + hr = acc_obj->get_accRole(child, &role); + if (S_OK != hr || VT_I4 != role.vt) { + VariantClear(&role); + return -1; + } + + // Return the role value + return role.lVal; +} + +LONG GetState(IAccessible* acc_obj, VARIANT child) { + HRESULT hr = S_OK; + LPTSTR state_str = NULL; + std::wstring complete_state; + + // Validate input. + if (!acc_obj) + return -1; + + // Get State. + VARIANT state; + VariantInit(&state); + hr = acc_obj->get_accState(child, &state); + if (S_OK != hr || VT_I4 != state.vt) { + VariantClear(&state); + return -1; + } + + VariantClear(&state); + return state.lVal; +} |