summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/browser_accessibility_qt.cpp82
-rw-r--r--src/core/browser_accessibility_qt.h3
-rw-r--r--tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp70
3 files changed, 136 insertions, 19 deletions
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index d2710b0ea..405bafb94 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -34,6 +34,10 @@
**
****************************************************************************/
+// 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 "browser_accessibility_qt.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
@@ -52,6 +56,82 @@ BrowserAccessibilityQt::BrowserAccessibilityQt()
QAccessible::registerAccessibleInterface(this);
}
+// This function is taken from chromium/content/browser/accessibility/browser_accessibility_win.cc
+// see also http://www.w3.org/TR/html-aapi
+void BrowserAccessibilityQt::OnDataChanged()
+{
+ BrowserAccessibility::OnDataChanged();
+
+ // The calculation of the accessible name of an element has been
+ // standardized in the HTML to Platform Accessibility APIs Implementation
+ // Guide (http://www.w3.org/TR/html-aapi/). In order to return the
+ // appropriate accessible name on Windows, we need to apply some logic
+ // to the fields we get from WebKit.
+ //
+ // TODO(dmazzoni): move most of this logic into WebKit.
+ //
+ // WebKit gives us:
+ //
+ // name: the default name, e.g. inner text
+ // title ui element: a reference to a <label> element on the same
+ // page that labels this node.
+ // description: accessible labels that override the default name:
+ // aria-label or aria-labelledby or aria-describedby
+ // help: the value of the "title" attribute
+ //
+ // On Windows, the logic we apply lets some fields take precedence and
+ // always returns the primary name in "name" and the secondary name,
+ // if any, in "description".
+
+ int title_elem_id = GetIntAttribute(
+ ui::AX_ATTR_TITLE_UI_ELEMENT);
+ std::string help = GetStringAttribute(ui::AX_ATTR_HELP);
+ std::string description = GetStringAttribute(
+ ui::AX_ATTR_DESCRIPTION);
+
+ // WebKit annoyingly puts the title in the description if there's no other
+ // description, which just confuses the rest of the logic. Put it back.
+ // Now "help" is always the value of the "title" attribute, if present.
+ std::string title_attr;
+ if (GetHtmlAttribute("title", &title_attr) &&
+ description == title_attr &&
+ help.empty()) {
+ help = description;
+ description.clear();
+ }
+
+ // Now implement the main logic: the descripion should become the name if
+ // it's nonempty, and the help should become the description if
+ // there's no description - or the name if there's no name or description.
+ if (!description.empty()) {
+ set_name(description);
+ description.clear();
+ }
+ if (!help.empty() && description.empty()) {
+ description = help;
+ help.clear();
+ }
+ if (!description.empty() && name().empty() && !title_elem_id) {
+ set_name(description);
+ description.clear();
+ }
+
+ // If it's a text field, also consider the placeholder.
+ std::string placeholder;
+ if (GetRole() == ui::AX_ROLE_TEXT_FIELD &&
+ HasState(ui::AX_STATE_FOCUSABLE) &&
+ GetHtmlAttribute("placeholder", &placeholder)) {
+ if (name().empty() && !title_elem_id) {
+ set_name(placeholder);
+ } else if (description.empty()) {
+ description = placeholder;
+ }
+ }
+
+ SetStringAttribute(ui::AX_ATTR_DESCRIPTION, description);
+ SetStringAttribute(ui::AX_ATTR_HELP, help);
+}
+
bool BrowserAccessibilityQt::isValid() const
{
return true;
@@ -128,7 +208,7 @@ QString BrowserAccessibilityQt::text(QAccessible::Text t) const
{
switch (t) {
case QAccessible::Name:
- return toQt(GetStringAttribute(ui::AX_ATTR_NAME));
+ return toQt(name());
case QAccessible::Description:
return toQt(GetStringAttribute(ui::AX_ATTR_DESCRIPTION));
case QAccessible::Help:
diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h
index b8cd9e67d..8dfffdcff 100644
--- a/src/core/browser_accessibility_qt.h
+++ b/src/core/browser_accessibility_qt.h
@@ -52,6 +52,9 @@ class BrowserAccessibilityQt
public:
BrowserAccessibilityQt();
+ // BrowserAccessibility
+ virtual void OnDataChanged() Q_DECL_OVERRIDE;
+
// QAccessibleInterface
virtual bool isValid() const Q_DECL_OVERRIDE;
virtual QObject *object() const Q_DECL_OVERRIDE;
diff --git a/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp b/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp
index 7668a12ab..c61b5eff7 100644
--- a/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp
+++ b/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp
@@ -144,33 +144,67 @@ void tst_QWebEngineView::text()
QWebEngineView webView;
webView.setHtml("<html><body>" \
"<input type='text' value='Good morning!'></input>" \
+ "<p id='labelName'>Enter your name here:</p>" \
+ "<input type='text' value='my name' aria-labelledby='labelName' aria-describedby='explanation'></input>" \
+ "<p id='explanation'>Provide both first and last name.</p>" \
+ "<input type='text' value='Good day!' placeholder='day'></input>" \
"</body></html>");
webView.show();
::waitForSignal(&webView, SIGNAL(loadFinished(bool)));
QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView);
// Wait for accessibility to be fully initialized
- QTRY_VERIFY(view->child(0)->childCount() == 1);
- QAccessibleInterface *document = view->child(0);
- QAccessibleInterface *grouping = document->child(0);
- QVERIFY(grouping);
- QAccessibleInterface *input = grouping->child(0);
- QCOMPARE(input->role(), QAccessible::EditableText);
- QCOMPARE(input->text(QAccessible::Name), QString());
- QCOMPARE(input->text(QAccessible::Description), QString());
- QCOMPARE(input->text(QAccessible::Value), QStringLiteral("Good morning!"));
-
- QAccessibleTextInterface *textInterface = input->textInterface();
- QVERIFY(textInterface);
- QCOMPARE(textInterface->characterCount(), 13);
- QCOMPARE(textInterface->selectionCount(), 0);
- QCOMPARE(textInterface->text(2, 9), QStringLiteral("od morn"));
+ QTRY_VERIFY(view->child(0)->childCount() == 5);
+ QAccessibleInterface *document = view->child(0);
+ QVERIFY(document);
+
+ // Good morning! [edit]
+ QAccessibleInterface *grouping1 = document->child(0);
+ QAccessibleInterface *input1 = grouping1->child(0);
+ QCOMPARE(input1->role(), QAccessible::EditableText);
+ QCOMPARE(input1->text(QAccessible::Name), QString());
+ QCOMPARE(input1->text(QAccessible::Description), QString());
+ QCOMPARE(input1->text(QAccessible::Value), QStringLiteral("Good morning!"));
+
+ QAccessibleTextInterface *textInterface1 = input1->textInterface();
+ QVERIFY(textInterface1);
+ QCOMPARE(textInterface1->characterCount(), 13);
+ QCOMPARE(textInterface1->selectionCount(), 0);
+ QCOMPARE(textInterface1->text(2, 9), QStringLiteral("od morn"));
int start = -1;
int end = -1;
- QCOMPARE(textInterface->textAtOffset(8, QAccessible::WordBoundary, &start, &end), QStringLiteral("morning"));
- textInterface->setCursorPosition(3);
- QTRY_COMPARE(textInterface->cursorPosition(), 3);
+ QCOMPARE(textInterface1->textAtOffset(8, QAccessible::WordBoundary, &start, &end), QStringLiteral("morning"));
+
+ // Enter your name here:
+ // my name [edit]
+ // Provide both first and last name here.
+ QAccessibleInterface *grouping2 = document->child(1);
+ QAccessibleInterface *label1 = grouping2->child(0);
+ QCOMPARE(label1->role(), QAccessible::StaticText);
+ QCOMPARE(label1->text(QAccessible::Name), QString());
+ QCOMPARE(label1->text(QAccessible::Description), QString());
+ QCOMPARE(label1->text(QAccessible::Value), QStringLiteral("Enter your name here:"));
+ QAccessibleInterface *grouping3 = document->child(2);
+ QAccessibleInterface *input2 = grouping3->child(0);
+ QCOMPARE(input2->role(), QAccessible::EditableText);
+ QCOMPARE(input2->text(QAccessible::Name), QStringLiteral("Enter your name here:"));
+ QCOMPARE(input2->text(QAccessible::Description), QStringLiteral("Provide both first and last name."));
+ QCOMPARE(input2->text(QAccessible::Value), QStringLiteral("my name"));
+ QAccessibleInterface *grouping4 = document->child(3);
+ QAccessibleInterface *label2 = grouping4->child(0);
+ QCOMPARE(label2->role(), QAccessible::StaticText);
+ QCOMPARE(label2->text(QAccessible::Name), QString());
+ QCOMPARE(label2->text(QAccessible::Description), QString());
+ QCOMPARE(label2->text(QAccessible::Value), QStringLiteral("Provide both first and last name."));
+
+ // Good day! [edit]
+ QAccessibleInterface *grouping5 = document->child(4);
+ QAccessibleInterface *input3 = grouping5->child(0);
+ QCOMPARE(input3->role(), QAccessible::EditableText);
+ QCOMPARE(input3->text(QAccessible::Name), QStringLiteral("day"));
+ QCOMPARE(input3->text(QAccessible::Description), QString());
+ QCOMPARE(input3->text(QAccessible::Value), QStringLiteral("Good day!"));
}
void tst_QWebEngineView::value()