| Index: content/browser/accessibility/accessibility_win_browsertest.cc
|
| diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
|
| index 4c0359ba243e1f930e8c041866d25b9b4a924330..b3f553d024ecdab4c173e27ca5e7c1b065bfc58b 100644
|
| --- a/content/browser/accessibility/accessibility_win_browsertest.cc
|
| +++ b/content/browser/accessibility/accessibility_win_browsertest.cc
|
| @@ -5,11 +5,13 @@
|
| #include <vector>
|
|
|
| #include "base/memory/scoped_ptr.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| #include "base/win/scoped_bstr.h"
|
| #include "base/win/scoped_comptr.h"
|
| #include "base/win/scoped_variant.h"
|
| #include "content/browser/accessibility/accessibility_mode_helper.h"
|
| +#include "content/browser/accessibility/accessibility_tree_formatter.h"
|
| #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
|
| #include "content/browser/renderer_host/render_view_host_impl.h"
|
| #include "content/public/browser/notification_service.h"
|
| @@ -22,6 +24,7 @@
|
| #include "content/public/test/content_browser_test_utils.h"
|
| #include "content/shell/browser/shell.h"
|
| #include "content/test/accessibility_browser_test_utils.h"
|
| +#include "net/base/escape.h"
|
| #include "third_party/iaccessible2/ia2_api_all.h"
|
| #include "third_party/isimpledom/ISimpleDOMNode.h"
|
| #include "ui/aura/window.h"
|
| @@ -31,9 +34,195 @@ namespace content {
|
|
|
| namespace {
|
|
|
| -// Helpers --------------------------------------------------------------------
|
|
|
| -base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant(
|
| +const char INPUT_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33) "
|
| + "WebKit \"KHTML, like\".";
|
| +const char TEXTAREA_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33)\n"
|
| + "WebKit \n\"KHTML, like\".";
|
| +const LONG CONTENTS_LENGTH = static_cast<LONG>(
|
| + (sizeof(INPUT_CONTENTS) - 1) / sizeof(char));
|
| +
|
| +
|
| +// AccessibilityWinBrowserTest ------------------------------------------------
|
| +
|
| +class AccessibilityWinBrowserTest : public ContentBrowserTest {
|
| + public:
|
| + AccessibilityWinBrowserTest();
|
| + virtual ~AccessibilityWinBrowserTest();
|
| +
|
| + protected:
|
| + class AccessibleChecker;
|
| + void LoadInitialAccessibilityTreeFromHtml(const std::string& html);
|
| + IAccessible* GetRendererAccessible();
|
| + void ExecuteScript(const std::wstring& script);
|
| + void SetUpInputField(
|
| + base::win::ScopedComPtr<IAccessibleText>* input_text);
|
| + void SetUpTextareaField(
|
| + base::win::ScopedComPtr<IAccessibleText>* textarea_text);
|
| +
|
| +
|
| + static base::win::ScopedComPtr<IAccessible>
|
| + AccessibilityWinBrowserTest::GetAccessibleFromVariant(
|
| + IAccessible* parent,
|
| + VARIANT* var);
|
| + static HRESULT QueryIAccessible2(IAccessible* accessible,
|
| + IAccessible2** accessible2);
|
| + static void FindNodeInAccessibilityTree(IAccessible* node,
|
| + int32 expected_role,
|
| + const std::wstring& expected_name,
|
| + int32 depth,
|
| + bool* found);
|
| + static void CheckTextAtOffset(
|
| + base::win::ScopedComPtr<IAccessibleText>& element,
|
| + LONG offset,
|
| + IA2TextBoundaryType boundary_type,
|
| + LONG expected_start_offset,
|
| + LONG expected_end_offset,
|
| + const std::wstring& expected_text);
|
| + static std::vector<base::win::ScopedVariant> GetAllAccessibleChildren(
|
| + IAccessible* element);
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest);
|
| +};
|
| +
|
| +AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() {
|
| +}
|
| +
|
| +AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
|
| +}
|
| +
|
| +void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
|
| + const std::string& html) {
|
| + AccessibilityNotificationWaiter waiter(
|
| + shell(), AccessibilityModeComplete,
|
| + ui::AX_EVENT_LOAD_COMPLETE);
|
| + GURL html_data_url("data:text/html," + html);
|
| + NavigateToURL(shell(), html_data_url);
|
| + waiter.WaitForNotification();
|
| +}
|
| +
|
| +// Retrieve the MSAA client accessibility object for the Render Widget Host View
|
| +// of the selected tab.
|
| +IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() {
|
| + content::WebContents* web_contents = shell()->web_contents();
|
| + return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible();
|
| +}
|
| +
|
| +void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) {
|
| + shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script);
|
| +}
|
| +
|
| +// Loads a page with an input text field and places sample text in it. Also,
|
| +// places the caret on the last character.
|
| +void AccessibilityWinBrowserTest::SetUpInputField(
|
| + base::win::ScopedComPtr<IAccessibleText>* input_text) {
|
| + ASSERT_NE(nullptr, input_text);
|
| + LoadInitialAccessibilityTreeFromHtml(std::string("<!DOCTYPE html><html><body>"
|
| + "<form><label for='textField'>Browser name:</label>"
|
| + "<input type='text' id='textField' name='name' value='") +
|
| + net::EscapeQueryParamValue(INPUT_CONTENTS, false) + std::string(
|
| + "'></form></body></html>"));
|
| +
|
| + // Retrieve the IAccessible interface for the web page.
|
| + base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible());
|
| + std::vector<base::win::ScopedVariant> document_children =
|
| + GetAllAccessibleChildren(document.get());
|
| + ASSERT_EQ(1, document_children.size());
|
| +
|
| + base::win::ScopedComPtr<IAccessible2> form;
|
| + HRESULT hr = QueryIAccessible2(GetAccessibleFromVariant(
|
| + document.get(), document_children[0].AsInput()).get(), form.Receive());
|
| + ASSERT_EQ(S_OK, hr);
|
| + std::vector<base::win::ScopedVariant> form_children =
|
| + GetAllAccessibleChildren(form.get());
|
| + ASSERT_EQ(2, form_children.size());
|
| +
|
| + // Find the input text field.
|
| + base::win::ScopedComPtr<IAccessible2> input;
|
| + hr = QueryIAccessible2(GetAccessibleFromVariant(
|
| + form.get(), form_children[1].AsInput()).get(), input.Receive());
|
| + ASSERT_EQ(S_OK, hr);
|
| + LONG input_role = 0;
|
| + hr = input->role(&input_role);
|
| + ASSERT_EQ(S_OK, hr);
|
| + ASSERT_EQ(ROLE_SYSTEM_TEXT, input_role);
|
| +
|
| + // Retrieve the IAccessibleText interface for the field.
|
| + hr = input.QueryInterface(input_text->Receive());
|
| + ASSERT_EQ(S_OK, hr);
|
| +
|
| + // Set the caret on the last character.
|
| + AccessibilityNotificationWaiter waiter(
|
| + shell(), AccessibilityModeComplete,
|
| + ui::AX_EVENT_TEXT_SELECTION_CHANGED);
|
| + std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
|
| + static_cast<int>(CONTENTS_LENGTH - 1)));
|
| + ExecuteScript(std::wstring(
|
| + L"var textField = document.getElementById('textField');"
|
| + L"textField.focus();"
|
| + L"textField.setSelectionRange(") +
|
| + caret_offset + L"," + caret_offset + L");");
|
| + waiter.WaitForNotification();
|
| +}
|
| +
|
| +// Loads a page with a textarea text field and places sample text in it. Also,
|
| +// places the caret on the last character.
|
| +void AccessibilityWinBrowserTest::SetUpTextareaField(
|
| + base::win::ScopedComPtr<IAccessibleText>* textarea_text) {
|
| + ASSERT_NE(nullptr, textarea_text);
|
| + LoadInitialAccessibilityTreeFromHtml(std::string("<!DOCTYPE html><html><body>"
|
| + "<textarea id='textField' rows='3' cols='60'>") +
|
| + net::EscapeQueryParamValue(TEXTAREA_CONTENTS, false) + std::string(
|
| + "</textarea></body></html>"));
|
| +
|
| + // Retrieve the IAccessible interface for the web page.
|
| + base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible());
|
| + std::vector<base::win::ScopedVariant> document_children =
|
| + GetAllAccessibleChildren(document.get());
|
| + ASSERT_EQ(1, document_children.size());
|
| +
|
| + base::win::ScopedComPtr<IAccessible2> section;
|
| + HRESULT hr = QueryIAccessible2(GetAccessibleFromVariant(
|
| + document.get(), document_children[0].AsInput()).get(), section.Receive());
|
| + ASSERT_EQ(S_OK, hr);
|
| + std::vector<base::win::ScopedVariant> section_children =
|
| + GetAllAccessibleChildren(section.get());
|
| + ASSERT_EQ(1, section_children.size());
|
| +
|
| + // Find the textarea text field.
|
| + base::win::ScopedComPtr<IAccessible2> textarea;
|
| + hr = QueryIAccessible2(GetAccessibleFromVariant(
|
| + section.get(), section_children[0].AsInput()).get(), textarea.Receive());
|
| + ASSERT_EQ(S_OK, hr);
|
| + LONG textarea_role = 0;
|
| + hr = textarea->role(&textarea_role);
|
| + ASSERT_EQ(S_OK, hr);
|
| + ASSERT_EQ(ROLE_SYSTEM_TEXT, textarea_role);
|
| +
|
| + // Retrieve the IAccessibleText interface for the field.
|
| + hr = textarea.QueryInterface(textarea_text->Receive());
|
| + ASSERT_EQ(S_OK, hr);
|
| +
|
| + // Set the caret on the last character.
|
| + AccessibilityNotificationWaiter waiter(
|
| + shell(), AccessibilityModeComplete,
|
| + ui::AX_EVENT_TEXT_SELECTION_CHANGED);
|
| + std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
|
| + static_cast<int>(CONTENTS_LENGTH - 1)));
|
| + ExecuteScript(std::wstring(
|
| + L"var textField = document.getElementById('textField');"
|
| + L"textField.focus();"
|
| + L"textField.setSelectionRange(") +
|
| + caret_offset + L"," + caret_offset + L");");
|
| + waiter.WaitForNotification();
|
| +}
|
| +
|
| +
|
| +// Static helpers ------------------------------------------------
|
| +
|
| +base::win::ScopedComPtr<IAccessible>
|
| +AccessibilityWinBrowserTest::GetAccessibleFromVariant(
|
| IAccessible* parent,
|
| VARIANT* var) {
|
| base::win::ScopedComPtr<IAccessible> ptr;
|
| @@ -41,7 +230,7 @@ base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant(
|
| case VT_DISPATCH: {
|
| IDispatch* dispatch = V_DISPATCH(var);
|
| if (dispatch)
|
| - ptr.QueryFrom(dispatch);
|
| + dispatch->QueryInterface(ptr.Receive());
|
| break;
|
| }
|
|
|
| @@ -57,9 +246,11 @@ base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant(
|
| return ptr;
|
| }
|
|
|
| -HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) {
|
| - // TODO(ctguil): For some reason querying the IAccessible2 interface from
|
| - // IAccessible fails.
|
| +HRESULT AccessibilityWinBrowserTest::QueryIAccessible2(
|
| + IAccessible* accessible,
|
| + IAccessible2** accessible2) {
|
| + // IA2 Spec dictates that IServiceProvider should be used instead of
|
| + // QueryInterface when retrieving IAccessible2.
|
| base::win::ScopedComPtr<IServiceProvider> service_provider;
|
| HRESULT hr = accessible->QueryInterface(service_provider.Receive());
|
| return SUCCEEDED(hr) ?
|
| @@ -69,11 +260,12 @@ HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) {
|
| // Recursively search through all of the descendants reachable from an
|
| // IAccessible node and return true if we find one with the given role
|
| // and name.
|
| -void RecursiveFindNodeInAccessibilityTree(IAccessible* node,
|
| - int32 expected_role,
|
| - const std::wstring& expected_name,
|
| - int32 depth,
|
| - bool* found) {
|
| +void AccessibilityWinBrowserTest::FindNodeInAccessibilityTree(
|
| + IAccessible* node,
|
| + int32 expected_role,
|
| + const std::wstring& expected_name,
|
| + int32 depth,
|
| + bool* found) {
|
| base::win::ScopedBstr name_bstr;
|
| base::win::ScopedVariant childid_self(CHILDID_SELF);
|
| node->get_accName(childid_self, name_bstr.Receive());
|
| @@ -95,22 +287,13 @@ void RecursiveFindNodeInAccessibilityTree(IAccessible* node,
|
| return;
|
| }
|
|
|
| - LONG child_count = 0;
|
| - HRESULT hr = node->get_accChildCount(&child_count);
|
| - ASSERT_EQ(S_OK, hr);
|
| -
|
| - scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]);
|
| - LONG obtained_count = 0;
|
| - hr = AccessibleChildren(
|
| - node, 0, child_count, child_array.get(), &obtained_count);
|
| - ASSERT_EQ(S_OK, hr);
|
| - ASSERT_EQ(child_count, obtained_count);
|
| -
|
| - for (int index = 0; index < obtained_count; index++) {
|
| + std::vector<base::win::ScopedVariant> children = GetAllAccessibleChildren(
|
| + node);
|
| + for (size_t i = 0; i < children.size(); ++i) {
|
| base::win::ScopedComPtr<IAccessible> child_accessible(
|
| - GetAccessibleFromResultVariant(node, &child_array.get()[index]));
|
| - if (child_accessible.get()) {
|
| - RecursiveFindNodeInAccessibilityTree(
|
| + GetAccessibleFromVariant(node, children[i].AsInput()));
|
| + if (child_accessible) {
|
| + FindNodeInAccessibilityTree(
|
| child_accessible.get(), expected_role, expected_name, depth + 1,
|
| found);
|
| if (*found)
|
| @@ -119,54 +302,60 @@ void RecursiveFindNodeInAccessibilityTree(IAccessible* node,
|
| }
|
| }
|
|
|
| -
|
| -// AccessibilityWinBrowserTest ------------------------------------------------
|
| -
|
| -class AccessibilityWinBrowserTest : public ContentBrowserTest {
|
| - public:
|
| - AccessibilityWinBrowserTest();
|
| - virtual ~AccessibilityWinBrowserTest();
|
| -
|
| - protected:
|
| - void LoadInitialAccessibilityTreeFromHtml(const std::string& html);
|
| - IAccessible* GetRendererAccessible();
|
| - void ExecuteScript(const std::wstring& script);
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest);
|
| -};
|
| -
|
| -AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() {
|
| -}
|
| -
|
| -AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
|
| +// Ensures that the text and the start and end offsets retrieved using
|
| +// get_textAtOffset match the expected values.
|
| +void AccessibilityWinBrowserTest::CheckTextAtOffset(
|
| + base::win::ScopedComPtr<IAccessibleText>& element,
|
| + LONG offset,
|
| + IA2TextBoundaryType boundary_type,
|
| + LONG expected_start_offset,
|
| + LONG expected_end_offset,
|
| + const std::wstring& expected_text) {
|
| + testing::Message message;
|
| + message << "While checking for \'" << expected_text << "\' at " <<
|
| + expected_start_offset << '-' << expected_end_offset << '.';
|
| + SCOPED_TRACE(message);
|
| +
|
| + LONG start_offset = 0;
|
| + LONG end_offset = 0;
|
| + base::win::ScopedBstr text;
|
| + HRESULT hr = element->get_textAtOffset(
|
| + offset, boundary_type,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_OK, hr);
|
| + EXPECT_EQ(expected_start_offset, start_offset);
|
| + EXPECT_EQ(expected_end_offset, end_offset);
|
| + EXPECT_EQ(expected_text, std::wstring(text, text.Length()));
|
| }
|
|
|
| -void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
|
| - const std::string& html) {
|
| - AccessibilityNotificationWaiter waiter(
|
| - shell(), AccessibilityModeComplete,
|
| - ui::AX_EVENT_LOAD_COMPLETE);
|
| - GURL html_data_url("data:text/html," + html);
|
| - NavigateToURL(shell(), html_data_url);
|
| - waiter.WaitForNotification();
|
| -}
|
| +std::vector<base::win::ScopedVariant>
|
| +AccessibilityWinBrowserTest::GetAllAccessibleChildren(
|
| + IAccessible* element) {
|
| + LONG child_count = 0;
|
| + HRESULT hr = element->get_accChildCount(&child_count);
|
| + EXPECT_EQ(S_OK, hr);
|
| + if (child_count <= 0)
|
| + return std::vector<base::win::ScopedVariant>();
|
|
|
| -// Retrieve the MSAA client accessibility object for the Render Widget Host View
|
| -// of the selected tab.
|
| -IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() {
|
| - content::WebContents* web_contents = shell()->web_contents();
|
| - return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible();
|
| -}
|
| + scoped_ptr<VARIANT[]> children_array(new VARIANT[child_count]);
|
| + LONG obtained_count = 0;
|
| + hr = AccessibleChildren(
|
| + element, 0, child_count, children_array.get(), &obtained_count);
|
| + EXPECT_EQ(S_OK, hr);
|
| + EXPECT_EQ(child_count, obtained_count);
|
|
|
| -void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) {
|
| - shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script);
|
| + std::vector<base::win::ScopedVariant> children(
|
| + static_cast<size_t>(child_count));
|
| + for (size_t i = 0; i < children.size(); i++) {
|
| + children[i].Reset(children_array[i]);
|
| + }
|
| + return children;
|
| }
|
|
|
|
|
| // AccessibleChecker ----------------------------------------------------------
|
|
|
| -class AccessibleChecker {
|
| +class AccessibilityWinBrowserTest::AccessibleChecker {
|
| public:
|
| // This constructor can be used if the IA2 role will be the same as the MSAA
|
| // role.
|
| @@ -228,9 +417,10 @@ class AccessibleChecker {
|
| AccessibleCheckerVector children_;
|
| };
|
|
|
| -AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
|
| - int32 expected_role,
|
| - const std::wstring& expected_value)
|
| +AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker(
|
| + const std::wstring& expected_name,
|
| + int32 expected_role,
|
| + const std::wstring& expected_value)
|
| : name_(expected_name),
|
| role_(expected_role),
|
| ia2_role_(expected_role),
|
| @@ -238,10 +428,11 @@ AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
|
| state_(-1) {
|
| }
|
|
|
| -AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
|
| - int32 expected_role,
|
| - int32 expected_ia2_role,
|
| - const std::wstring& expected_value)
|
| +AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker(
|
| + const std::wstring& expected_name,
|
| + int32 expected_role,
|
| + int32 expected_ia2_role,
|
| + const std::wstring& expected_value)
|
| : name_(expected_name),
|
| role_(expected_role),
|
| ia2_role_(expected_ia2_role),
|
| @@ -249,10 +440,11 @@ AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
|
| state_(-1) {
|
| }
|
|
|
| -AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
|
| - const std::wstring& expected_role,
|
| - int32 expected_ia2_role,
|
| - const std::wstring& expected_value)
|
| +AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker(
|
| + const std::wstring& expected_name,
|
| + const std::wstring& expected_role,
|
| + int32 expected_ia2_role,
|
| + const std::wstring& expected_value)
|
| : name_(expected_name),
|
| role_(expected_role.c_str()),
|
| ia2_role_(expected_ia2_role),
|
| @@ -260,14 +452,15 @@ AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
|
| state_(-1) {
|
| }
|
|
|
| -void AccessibleChecker::AppendExpectedChild(
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::AppendExpectedChild(
|
| AccessibleChecker* expected_child) {
|
| children_.push_back(expected_child);
|
| }
|
|
|
| -void AccessibleChecker::CheckAccessible(IAccessible* accessible) {
|
| - SCOPED_TRACE("while checking " +
|
| - base::UTF16ToUTF8(RoleVariantToString(role_)));
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessible(
|
| + IAccessible* accessible) {
|
| + SCOPED_TRACE("While checking "
|
| + + base::UTF16ToUTF8(RoleVariantToString(role_)));
|
| CheckAccessibleName(accessible);
|
| CheckAccessibleRole(accessible);
|
| CheckIA2Role(accessible);
|
| @@ -276,15 +469,18 @@ void AccessibleChecker::CheckAccessible(IAccessible* accessible) {
|
| CheckAccessibleChildren(accessible);
|
| }
|
|
|
| -void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedValue(
|
| + const std::wstring& expected_value) {
|
| value_ = expected_value;
|
| }
|
|
|
| -void AccessibleChecker::SetExpectedState(LONG expected_state) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedState(
|
| + LONG expected_state) {
|
| state_ = expected_state;
|
| }
|
|
|
| -void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleName(
|
| + IAccessible* accessible) {
|
| base::win::ScopedBstr name;
|
| base::win::ScopedVariant childid_self(CHILDID_SELF);
|
| HRESULT hr = accessible->get_accName(childid_self, name.Receive());
|
| @@ -299,7 +495,8 @@ void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) {
|
| }
|
| }
|
|
|
| -void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleRole(
|
| + IAccessible* accessible) {
|
| base::win::ScopedVariant role;
|
| base::win::ScopedVariant childid_self(CHILDID_SELF);
|
| HRESULT hr = accessible->get_accRole(childid_self, role.Receive());
|
| @@ -309,7 +506,8 @@ void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) {
|
| << "\nGot role: " << RoleVariantToString(role);
|
| }
|
|
|
| -void AccessibleChecker::CheckIA2Role(IAccessible* accessible) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckIA2Role(
|
| + IAccessible* accessible) {
|
| base::win::ScopedComPtr<IAccessible2> accessible2;
|
| HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive());
|
| ASSERT_EQ(S_OK, hr);
|
| @@ -321,7 +519,8 @@ void AccessibleChecker::CheckIA2Role(IAccessible* accessible) {
|
| << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role);
|
| }
|
|
|
| -void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleValue(
|
| + IAccessible* accessible) {
|
| // Don't check the value if if's a DOCUMENT role, because the value
|
| // is supposed to be the url (and we don't keep track of that in the
|
| // test expectations).
|
| @@ -341,7 +540,8 @@ void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) {
|
| EXPECT_EQ(value_, std::wstring(value, value.Length()));
|
| }
|
|
|
| -void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) {
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleState(
|
| + IAccessible* accessible) {
|
| if (state_ < 0)
|
| return;
|
|
|
| @@ -360,31 +560,29 @@ void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) {
|
| << "\nGot state: " << IAccessibleStateToString(obj_state);
|
| }
|
|
|
| -void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) {
|
| - LONG child_count = 0;
|
| - HRESULT hr = parent->get_accChildCount(&child_count);
|
| - EXPECT_EQ(S_OK, hr);
|
| +void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleChildren(
|
| + IAccessible* parent) {
|
| + std::vector<base::win::ScopedVariant> obtained_children =
|
| + GetAllAccessibleChildren(parent);
|
| + size_t child_count = obtained_children.size();
|
| ASSERT_EQ(child_count, children_.size());
|
|
|
| - scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]);
|
| - LONG obtained_count = 0;
|
| - hr = AccessibleChildren(parent, 0, child_count,
|
| - child_array.get(), &obtained_count);
|
| - ASSERT_EQ(S_OK, hr);
|
| - ASSERT_EQ(child_count, obtained_count);
|
| -
|
| - VARIANT* child = child_array.get();
|
| - for (AccessibleCheckerVector::iterator child_checker = children_.begin();
|
| - child_checker != children_.end();
|
| + AccessibleCheckerVector::iterator child_checker;
|
| + std::vector<base::win::ScopedVariant>::iterator child;
|
| + for (child_checker = children_.begin(),
|
| + child = obtained_children.begin();
|
| + child_checker != children_.end()
|
| + && child != obtained_children.end();
|
| ++child_checker, ++child) {
|
| base::win::ScopedComPtr<IAccessible> child_accessible(
|
| - GetAccessibleFromResultVariant(parent, child));
|
| + GetAccessibleFromVariant(parent, child->AsInput()));
|
| ASSERT_TRUE(child_accessible.get());
|
| (*child_checker)->CheckAccessible(child_accessible.get());
|
| }
|
| }
|
|
|
| -base::string16 AccessibleChecker::RoleVariantToString(
|
| +base::string16
|
| +AccessibilityWinBrowserTest::AccessibleChecker::RoleVariantToString(
|
| const base::win::ScopedVariant& role) {
|
| if (role.type() == VT_I4)
|
| return IAccessibleRoleToString(V_I4(&role));
|
| @@ -667,7 +865,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| ASSERT_EQ(S_OK, hr);
|
|
|
| bool found = false;
|
| - RecursiveFindNodeInAccessibilityTree(
|
| + FindNodeInAccessibilityTree(
|
| browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found);
|
| ASSERT_EQ(found, true);
|
| }
|
| @@ -754,4 +952,519 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestRoleGroup) {
|
| document_checker.CheckAccessible(GetRendererAccessible());
|
| }
|
|
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestSetCaretOffset) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| +
|
| + LONG caret_offset = 0;
|
| + HRESULT hr = input_text->get_caretOffset(&caret_offset);
|
| + EXPECT_EQ(S_OK, hr);
|
| + EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
|
| +
|
| + AccessibilityNotificationWaiter waiter(
|
| + shell(), AccessibilityModeComplete,
|
| + ui::AX_EVENT_TEXT_SELECTION_CHANGED);
|
| + caret_offset = 0;
|
| + hr = input_text->setCaretOffset(caret_offset);
|
| + EXPECT_EQ(S_OK, hr);
|
| + waiter.WaitForNotification();
|
| +
|
| + hr = input_text->get_caretOffset(&caret_offset);
|
| + EXPECT_EQ(S_OK, hr);
|
| + EXPECT_EQ(0, caret_offset);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestMultiLineSetCaretOffset) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| +
|
| + LONG caret_offset = 0;
|
| + HRESULT hr = textarea_text->get_caretOffset(&caret_offset);
|
| + EXPECT_EQ(S_OK, hr);
|
| + EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
|
| +
|
| + AccessibilityNotificationWaiter waiter(
|
| + shell(), AccessibilityModeComplete,
|
| + ui::AX_EVENT_TEXT_SELECTION_CHANGED);
|
| + caret_offset = 0;
|
| + hr = textarea_text->setCaretOffset(caret_offset);
|
| + EXPECT_EQ(S_OK, hr);
|
| + waiter.WaitForNotification();
|
| +
|
| + hr = textarea_text->get_caretOffset(&caret_offset);
|
| + EXPECT_EQ(S_OK, hr);
|
| + EXPECT_EQ(0, caret_offset);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestTextAtOffsetWithInvalidArgs) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| + HRESULT hr = input_text->get_textAtOffset(
|
| + 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL);
|
| + EXPECT_EQ(E_INVALIDARG, hr);
|
| +
|
| + // Test invalid offset.
|
| + LONG start_offset = 0;
|
| + LONG end_offset = 0;
|
| + base::win::ScopedBstr text;
|
| + LONG invalid_offset = -5;
|
| + hr = input_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(E_INVALIDARG, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + invalid_offset = CONTENTS_LENGTH + 1;
|
| + hr = input_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_WORD,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(E_INVALIDARG, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| +
|
| + // According to the IA2 Spec, only line boundaries should succeed when
|
| + // the offset is one past the end of the text.
|
| + invalid_offset = CONTENTS_LENGTH;
|
| + hr = input_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = input_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_WORD,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = input_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = input_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_ALL,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| +
|
| + // The same behavior should be observed when the special offset
|
| + // IA2_TEXT_OFFSET_LENGTH is used.
|
| + hr = input_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_CHAR,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = input_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_WORD,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = input_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_SENTENCE,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = input_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_ALL,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestMultiLineTextAtOffsetWithInvalidArgs) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| + HRESULT hr = textarea_text->get_textAtOffset(
|
| + 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL);
|
| + EXPECT_EQ(E_INVALIDARG, hr);
|
| +
|
| + // Test invalid offset.
|
| + LONG start_offset = 0;
|
| + LONG end_offset = 0;
|
| + base::win::ScopedBstr text;
|
| + LONG invalid_offset = -5;
|
| + hr = textarea_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(E_INVALIDARG, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + invalid_offset = CONTENTS_LENGTH + 1;
|
| + hr = textarea_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_WORD,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(E_INVALIDARG, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| +
|
| + // According to the IA2 Spec, only line boundaries should succeed when
|
| + // the offset is one past the end of the text.
|
| + invalid_offset = CONTENTS_LENGTH;
|
| + hr = textarea_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = textarea_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_WORD,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = textarea_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = textarea_text->get_textAtOffset(
|
| + invalid_offset, IA2_TEXT_BOUNDARY_ALL,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| +
|
| + // The same behavior should be observed when the special offset
|
| + // IA2_TEXT_OFFSET_LENGTH is used.
|
| + hr = textarea_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_CHAR,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = textarea_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_WORD,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = textarea_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_SENTENCE,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| + hr = textarea_text->get_textAtOffset(
|
| + IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_ALL,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| + EXPECT_EQ(0, start_offset);
|
| + EXPECT_EQ(0, end_offset);
|
| + EXPECT_EQ(nullptr, static_cast<BSTR>(text));
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestTextAtOffsetWithBoundaryCharacter) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| + for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) {
|
| + std::wstring expected_text(1, INPUT_CONTENTS[offset]);
|
| + LONG expected_start_offset = offset;
|
| + LONG expected_end_offset = offset + 1;
|
| + CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + expected_start_offset, expected_end_offset, expected_text);
|
| + }
|
| +
|
| + for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) {
|
| + std::wstring expected_text(1, INPUT_CONTENTS[offset]);
|
| + LONG expected_start_offset = offset;
|
| + LONG expected_end_offset = offset + 1;
|
| + CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + expected_start_offset, expected_end_offset, expected_text);
|
| + }
|
| +
|
| + CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET,
|
| + IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L".");
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + DISABLED_TestMultiLineTextAtOffsetWithBoundaryCharacter) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| + for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) {
|
| + std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]);
|
| + LONG expected_start_offset = offset;
|
| + LONG expected_end_offset = offset + 1;
|
| + CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + expected_start_offset, expected_end_offset, expected_text);
|
| + }
|
| +
|
| + for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) {
|
| + std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]);
|
| + LONG expected_start_offset = offset;
|
| + LONG expected_end_offset = offset + 1;
|
| + CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR,
|
| + expected_start_offset, expected_end_offset, expected_text);
|
| + }
|
| +
|
| + CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
|
| + IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L".");
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestTextAtOffsetWithBoundaryWord) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| +
|
| + // Trailing punctuation should be included as part of the previous word.
|
| + CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD,
|
| + 0, 4, L"Moz/");
|
| + CheckTextAtOffset(input_text, 2, IA2_TEXT_BOUNDARY_WORD,
|
| + 0, 4, L"Moz/");
|
| +
|
| + // If the offset is at the punctuation, it should return
|
| + // the previous word.
|
| + CheckTextAtOffset(input_text, 3, IA2_TEXT_BOUNDARY_WORD,
|
| + 0, 4, L"Moz/");
|
| +
|
| + // Numbers with a decimal point ("." for U.S), should be treated as one word.
|
| + // Also, trailing punctuation that occurs after empty space should be part of
|
| + // the word. ("5.0 (" and not "5.0 ".)
|
| + CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(input_text, 5, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(input_text, 7, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| +
|
| + // Leading punctuation should not be included with the word after it.
|
| + CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(input_text, 11, IA2_TEXT_BOUNDARY_WORD,
|
| + 9, 12, L"ST ");
|
| +
|
| + // Numbers separated from letters with trailing punctuation should
|
| + // be split into two words. Same for abreviations like "i.e.".
|
| + CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD,
|
| + 12, 14, L"6.");
|
| + CheckTextAtOffset(input_text, 15, IA2_TEXT_BOUNDARY_WORD,
|
| + 14, 17, L"x; ");
|
| +
|
| + // Words with numbers should be treated like ordinary words.
|
| + CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD,
|
| + 17, 24, L"WWW33) ");
|
| + CheckTextAtOffset(input_text, 23, IA2_TEXT_BOUNDARY_WORD,
|
| + 17, 24, L"WWW33) ");
|
| +
|
| + // Multiple trailing empty spaces should be part of the word preceding it.
|
| + CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD,
|
| + 24, 33, L"WebKit \"");
|
| + CheckTextAtOffset(input_text, 31, IA2_TEXT_BOUNDARY_WORD,
|
| + 24, 33, L"WebKit \"");
|
| + CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD,
|
| + 24, 33, L"WebKit \"");
|
| +
|
| + // Leading punctuation such as quotation marks should not be part of the word.
|
| + CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD,
|
| + 33, 40, L"KHTML, ");
|
| + CheckTextAtOffset(input_text, 38, IA2_TEXT_BOUNDARY_WORD,
|
| + 33, 40, L"KHTML, ");
|
| +
|
| + // Trailing final punctuation should be part of the last word.
|
| + CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD,
|
| + 40, CONTENTS_LENGTH, L"like\".");
|
| + CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD,
|
| + 40, CONTENTS_LENGTH, L"like\".");
|
| +
|
| + // Test special offsets.
|
| + CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET,
|
| + IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\".");
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + DISABLED_TestMultiLineTextAtOffsetWithBoundaryWord) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| +
|
| + // Trailing punctuation should be included as part of the previous word.
|
| + CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_WORD,
|
| + 0, 4, L"Moz/");
|
| + CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD,
|
| + 0, 4, L"Moz/");
|
| +
|
| + // If the offset is at the punctuation, it should return
|
| + // the previous word.
|
| + CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD,
|
| + 0, 4, L"Moz/");
|
| +
|
| + // Numbers with a decimal point ("." for U.S), should be treated as one word.
|
| + // Also, trailing punctuation that occurs after empty space should be part of
|
| + // the word. ("5.0 (" and not "5.0 ".)
|
| + CheckTextAtOffset(textarea_text, 4, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| +
|
| + // Leading punctuation should not be included with the word after it.
|
| + CheckTextAtOffset(textarea_text, 8, IA2_TEXT_BOUNDARY_WORD,
|
| + 4, 9, L"5.0 (");
|
| + CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD,
|
| + 9, 12, L"ST ");
|
| +
|
| + // Numbers separated from letters with trailing punctuation should
|
| + // be split into two words. Same for abreviations like "i.e.".
|
| + CheckTextAtOffset(textarea_text, 12, IA2_TEXT_BOUNDARY_WORD,
|
| + 12, 14, L"6.");
|
| + CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD,
|
| + 14, 17, L"x; ");
|
| +
|
| + // Words with numbers should be treated like ordinary words.
|
| + CheckTextAtOffset(textarea_text, 17, IA2_TEXT_BOUNDARY_WORD,
|
| + 17, 24, L"WWW33)\n");
|
| + CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD,
|
| + 17, 24, L"WWW33)\n");
|
| +
|
| + // Multiple trailing empty spaces should be part of the word preceding it.
|
| + CheckTextAtOffset(textarea_text, 28, IA2_TEXT_BOUNDARY_WORD,
|
| + 24, 33, L"WebKit \n\"");
|
| + CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD,
|
| + 24, 33, L"WebKit \n\"");
|
| + CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD,
|
| + 24, 33, L"WebKit \n\"");
|
| +
|
| + // Leading punctuation such as quotation marks should not be part of the word.
|
| + CheckTextAtOffset(textarea_text, 33, IA2_TEXT_BOUNDARY_WORD,
|
| + 33, 40, L"KHTML, ");
|
| + CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD,
|
| + 33, 40, L"KHTML, ");
|
| +
|
| + // Trailing final punctuation should be part of the last word.
|
| + CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD,
|
| + 40, CONTENTS_LENGTH, L"like\".");
|
| + CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD,
|
| + 40, CONTENTS_LENGTH, L"like\".");
|
| +
|
| + // Test special offsets.
|
| + CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
|
| + IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\".");
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestTextAtOffsetWithBoundarySentence) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| +
|
| + // Sentence navigation is not currently implemented.
|
| + LONG start_offset = 0;
|
| + LONG end_offset = 0;
|
| + base::win::ScopedBstr text;
|
| + HRESULT hr = input_text->get_textAtOffset(
|
| + 5, IA2_TEXT_BOUNDARY_SENTENCE,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestMultiLineTextAtOffsetWithBoundarySentence) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| +
|
| + // Sentence navigation is not currently implemented.
|
| + LONG start_offset = 0;
|
| + LONG end_offset = 0;
|
| + base::win::ScopedBstr text;
|
| + HRESULT hr = textarea_text->get_textAtOffset(
|
| + 25, IA2_TEXT_BOUNDARY_SENTENCE,
|
| + &start_offset, &end_offset, text.Receive());
|
| + EXPECT_EQ(S_FALSE, hr);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestTextAtOffsetWithBoundaryLine) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| +
|
| + // Single line text fields should return the whole text.
|
| + CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_LINE,
|
| + 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
|
| +
|
| + // Test special offsets.
|
| + CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_LINE,
|
| + 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
|
| + CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, IA2_TEXT_BOUNDARY_LINE,
|
| + 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + DISABLED_TestMultiLineTextAtOffsetWithBoundaryLine) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| +
|
| + CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE,
|
| + 0, 24, L"Moz/5.0 (ST 6.x; WWW33)\n");
|
| +
|
| + // If the offset is at the newline, return the line preceding it.
|
| + CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_LINE,
|
| + 24, 32, L"WebKit \n");
|
| +
|
| + // Last line does not have a trailing newline.
|
| + CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_LINE,
|
| + 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
|
| +
|
| + // An offset one past the last character should return the last line.
|
| + CheckTextAtOffset(textarea_text, CONTENTS_LENGTH, IA2_TEXT_BOUNDARY_LINE,
|
| + 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
|
| +
|
| + // Test special offsets.
|
| + CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH,
|
| + IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
|
| + CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
|
| + IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestTextAtOffsetWithBoundaryAll) {
|
| + base::win::ScopedComPtr<IAccessibleText> input_text;
|
| + SetUpInputField(&input_text);
|
| +
|
| + CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL,
|
| + 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
|
| + TestMultiLineTextAtOffsetWithBoundaryAll) {
|
| + base::win::ScopedComPtr<IAccessibleText> textarea_text;
|
| + SetUpTextareaField(&textarea_text);
|
| +
|
| + CheckTextAtOffset(textarea_text, CONTENTS_LENGTH - 1, IA2_TEXT_BOUNDARY_ALL,
|
| + 0, CONTENTS_LENGTH, base::SysUTF8ToWide(TEXTAREA_CONTENTS));
|
| +}
|
| +
|
| } // namespace content
|
|
|