Commit c93c9c32 authored by dmazzoni@chromium.org's avatar dmazzoni@chromium.org

Implement put_accvalue for textfields and location bar.

All interactive views implement GetAccessibleState
to provide accessibility information about the current
state of the view. This struct now includes a callback
that can be used to change the string value, since
automation software wants to fill in text fields,
and this interface is implemented for Textfield
and LocationBarView, and hooked up to put_accValue.

BUG=260266

Review URL: https://chromiumcodereview.appspot.com/23441024

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221688 0039d316-1c4b-4281-b951-d872f2087c98
parent 70bd4e54
......@@ -9,6 +9,7 @@
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/prefs/pref_member.h"
#include "chrome/browser/extensions/extension_context_menu_model.h"
#include "chrome/browser/search_engines/template_url_service_observer.h"
......@@ -413,9 +414,6 @@ class LocationBarView : public LocationBar,
// Update the view for the zoom icon based on the current tab's zoom.
void RefreshZoomView();
// Sets the visibility of view to new_vis.
void ToggleVisibility(bool new_vis, views::View* view);
#if !defined(USE_AURA)
// Helper for the Mouse event handlers that does all the real work.
void OnMouseEvent(const ui::MouseEvent& event, UINT msg);
......@@ -431,6 +429,11 @@ class LocationBarView : public LocationBar,
// after layout, so the |page_action_views_| have their bounds.
void PaintPageActionBackgrounds(gfx::Canvas* canvas);
// Handles a request to change the value of this text field from software
// using an accessibility API (typically automation software, screen readers
// don't normally use this). Sets the value and clears the selection.
void AccessibilitySetValue(const string16& new_value);
// The Browser this LocationBarView is in. Note that at least
// chromeos::SimpleWebViewDialog uses a LocationBarView outside any browser
// window, so this may be NULL.
......@@ -543,6 +546,9 @@ class LocationBarView : public LocationBar,
// Used to register for notifications received by NotificationObserver.
content::NotificationRegistrar registrar_;
// Used to bind callback functions to this object.
base::WeakPtrFactory<LocationBarView> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(LocationBarView);
};
......
......@@ -6,6 +6,7 @@
#define UI_BASE_ACCESSIBILITY_ACCESSIBLE_VIEW_STATE_H_
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/strings/string16.h"
#include "ui/base/accessibility/accessibility_types.h"
#include "ui/base/ui_export.h"
......@@ -54,6 +55,17 @@ struct UI_EXPORT AccessibleViewState {
// index and count should be -1 otherwise.
int index;
int count;
// An optional callback that can be used by accessibility clients to
// set the string value of this view. This only applies to roles where
// setting the value makes sense, like a text box. Not often used by
// screen readers, but often used by automation software to script
// things like logging into portals or filling forms.
//
// This callback is only valid for the lifetime of the view, and should
// be a safe no-op if the view is deleted. Typically, accessible views
// should use a WeakPtr when binding the callback.
base::Callback<void(const base::string16&)> set_value_callback;
};
} // namespace ui
......
......@@ -582,8 +582,8 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accState(
return S_OK;
}
STDMETHODIMP NativeViewAccessibilityWin::get_accValue(
VARIANT var_id, BSTR* value) {
STDMETHODIMP NativeViewAccessibilityWin::get_accValue(VARIANT var_id,
BSTR* value) {
if (!IsValidId(var_id) || !value)
return E_INVALIDARG;
......@@ -607,6 +607,24 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accValue(
return S_OK;
}
STDMETHODIMP NativeViewAccessibilityWin::put_accValue(VARIANT var_id,
BSTR new_value) {
if (!IsValidId(var_id) || !new_value)
return E_INVALIDARG;
if (!view_)
return E_FAIL;
// Return an error if the view can't set the value.
ui::AccessibleViewState state;
view_->GetAccessibleState(&state);
if (state.set_value_callback.is_null())
return E_FAIL;
state.set_value_callback.Run(new_value);
return S_OK;
}
// IAccessible functions not supported.
STDMETHODIMP NativeViewAccessibilityWin::get_accSelection(VARIANT* selected) {
......@@ -644,12 +662,6 @@ STDMETHODIMP NativeViewAccessibilityWin::put_accName(
return E_NOTIMPL;
}
STDMETHODIMP NativeViewAccessibilityWin::put_accValue(
VARIANT var_id, BSTR put_val) {
// Deprecated.
return E_NOTIMPL;
}
//
// IAccessible2
//
......
......@@ -114,10 +114,11 @@ NativeViewAccessibilityWin
// Retrieves the current state of the specified object.
STDMETHODIMP get_accState(VARIANT var_id, VARIANT* state);
// Retrieves the current value associated with the specified object.
// Retrieve or set the string value associated with the specified object.
// Setting the value is not typically used by screen readers, but it's
// used frequently by automation software.
STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value);
// Non-supported IAccessible methods.
STDMETHODIMP put_accValue(VARIANT var_id, BSTR new_value);
// Selections not applicable to views.
STDMETHODIMP get_accSelection(VARIANT* selected);
......@@ -131,7 +132,6 @@ NativeViewAccessibilityWin
// Deprecated functions, not implemented here.
STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name);
STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val);
//
// IAccessible2
......
// Copyright 2013 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 <oleacc.h>
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/test/views_test_base.h"
namespace views {
namespace test {
typedef ViewsTestBase NativeViewAcccessibilityWinTest;
TEST_F(NativeViewAcccessibilityWinTest, TextfieldAccessibility) {
Widget widget;
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget.Init(init_params);
View* content = new View;
widget.SetContentsView(content);
Textfield* textfield = new Textfield;
textfield->SetAccessibleName(L"Name");
textfield->SetText(L"Value");
content->AddChildView(textfield);
base::win::ScopedComPtr<IAccessible> content_accessible(
content->GetNativeViewAccessible());
LONG child_count = 0;
ASSERT_EQ(S_OK, content_accessible->get_accChildCount(&child_count));
ASSERT_EQ(1L, child_count);
base::win::ScopedComPtr<IDispatch> textfield_dispatch;
base::win::ScopedComPtr<IAccessible> textfield_accessible;
base::win::ScopedVariant child_index(1);
ASSERT_EQ(S_OK, content_accessible->get_accChild(
child_index, textfield_dispatch.Receive()));
ASSERT_EQ(S_OK, textfield_dispatch.QueryInterface(
textfield_accessible.Receive()));
base::win::ScopedBstr name;
base::win::ScopedVariant childid_self(CHILDID_SELF);
ASSERT_EQ(S_OK, textfield_accessible->get_accName(
childid_self, name.Receive()));
ASSERT_STREQ(L"Name", name);
base::win::ScopedBstr value;
ASSERT_EQ(S_OK, textfield_accessible->get_accValue(
childid_self, value.Receive()));
ASSERT_STREQ(L"Value", value);
base::win::ScopedBstr new_value(L"New value");
ASSERT_EQ(S_OK, textfield_accessible->put_accValue(childid_self, new_value));
ASSERT_STREQ(L"New value", textfield->text().c_str());
}
} // namespace test
} // namespace views
......@@ -85,7 +85,8 @@ Textfield::Textfield()
vertical_margins_were_set_(false),
vertical_alignment_(gfx::ALIGN_VCENTER),
placeholder_text_color_(kDefaultPlaceholderTextColor),
text_input_type_(ui::TEXT_INPUT_TYPE_TEXT) {
text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
weak_ptr_factory_(this) {
set_focusable(true);
if (ViewsDelegate::views_delegate) {
......@@ -110,7 +111,8 @@ Textfield::Textfield(StyleFlags style)
vertical_margins_were_set_(false),
vertical_alignment_(gfx::ALIGN_VCENTER),
placeholder_text_color_(kDefaultPlaceholderTextColor),
text_input_type_(ui::TEXT_INPUT_TYPE_TEXT) {
text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
weak_ptr_factory_(this) {
set_focusable(true);
if (IsObscured())
SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
......@@ -502,6 +504,12 @@ void Textfield::GetAccessibleState(ui::AccessibleViewState* state) {
const ui::Range range = native_wrapper_->GetSelectedRange();
state->selection_start = range.start();
state->selection_end = range.end();
if (!read_only()) {
state->set_value_callback =
base::Bind(&Textfield::AccessibilitySetValue,
weak_ptr_factory_.GetWeakPtr());
}
}
ui::TextInputClient* Textfield::GetTextInputClient() {
......@@ -543,6 +551,9 @@ const char* Textfield::GetClassName() const {
return kViewClassName;
}
////////////////////////////////////////////////////////////////////////////////
// Textfield, private:
gfx::Insets Textfield::GetTextInsets() const {
gfx::Insets insets = GetInsets();
if (draw_border_ && native_wrapper_)
......@@ -550,6 +561,13 @@ gfx::Insets Textfield::GetTextInsets() const {
return insets;
}
void Textfield::AccessibilitySetValue(const string16& new_value) {
if (!read_only()) {
SetText(new_value);
ClearSelection();
}
}
////////////////////////////////////////////////////////////////////////////////
// NativeTextfieldWrapper, public:
......
......@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "build/build_config.h"
......@@ -285,6 +286,11 @@ class VIEWS_EXPORT Textfield : public View {
// Returns the insets to the rectangle where text is actually painted.
gfx::Insets GetTextInsets() const;
// Handles a request to change the value of this text field from software
// using an accessibility API (typically automation software, screen readers
// don't normally use this). Sets the value and clears the selection.
void AccessibilitySetValue(const string16& new_value);
// This is the current listener for events from this Textfield.
TextfieldController* controller_;
......@@ -344,6 +350,9 @@ class VIEWS_EXPORT Textfield : public View {
// The duration to reveal the last typed char for obscured textfields.
base::TimeDelta obscured_reveal_duration_;
// Used to bind callback functions to this object.
base::WeakPtrFactory<Textfield> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(Textfield);
};
......
......@@ -696,6 +696,7 @@
'..',
],
'sources': [
'accessibility/native_view_accessibility_win_unittest.cc',
'accessible_pane_view_unittest.cc',
'animation/bounds_animator_unittest.cc',
'bubble/bubble_border_unittest.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment