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

Add a context field to the accessibility extension API.

This makes it possible to provide more helpful spoken feedback when focusing
a toolbar button or infobar button - e.g. it can now read the full text of
the infobar when you move focus to any of its buttons.

BUG=106724
TEST=Adds new unit tests; will need new ChromeVox push to test manually.
Review URL: http://codereview.chromium.org/8850004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114640 0039d316-1c4b-4281-b951-d872f2087c98
parent b7544d08
...@@ -33,8 +33,9 @@ void SendAccessibilityVolumeNotification(double volume, bool is_muted) { ...@@ -33,8 +33,9 @@ void SendAccessibilityVolumeNotification(double volume, bool is_muted) {
} }
AccessibilityControlInfo::AccessibilityControlInfo( AccessibilityControlInfo::AccessibilityControlInfo(
Profile* profile, const std::string& control_name) Profile* profile, const std::string& name)
: AccessibilityEventInfo(profile), name_(control_name) { : AccessibilityEventInfo(profile),
name_(name) {
} }
AccessibilityControlInfo::~AccessibilityControlInfo() { AccessibilityControlInfo::~AccessibilityControlInfo() {
...@@ -43,6 +44,8 @@ AccessibilityControlInfo::~AccessibilityControlInfo() { ...@@ -43,6 +44,8 @@ AccessibilityControlInfo::~AccessibilityControlInfo() {
void AccessibilityControlInfo::SerializeToDict(DictionaryValue *dict) const { void AccessibilityControlInfo::SerializeToDict(DictionaryValue *dict) const {
dict->SetString(keys::kNameKey, name_); dict->SetString(keys::kNameKey, name_);
dict->SetString(keys::kTypeKey, type()); dict->SetString(keys::kTypeKey, type());
if (!context_.empty())
dict->SetString(keys::kContextKey, context_);
} }
AccessibilityWindowInfo::AccessibilityWindowInfo(Profile* profile, AccessibilityWindowInfo::AccessibilityWindowInfo(Profile* profile,
...@@ -55,8 +58,10 @@ const char* AccessibilityWindowInfo::type() const { ...@@ -55,8 +58,10 @@ const char* AccessibilityWindowInfo::type() const {
} }
AccessibilityButtonInfo::AccessibilityButtonInfo(Profile* profile, AccessibilityButtonInfo::AccessibilityButtonInfo(Profile* profile,
const std::string& button_name) const std::string& button_name,
const std::string& context)
: AccessibilityControlInfo(profile, button_name) { : AccessibilityControlInfo(profile, button_name) {
set_context(context);
} }
const char* AccessibilityButtonInfo::type() const { const char* AccessibilityButtonInfo::type() const {
...@@ -64,8 +69,11 @@ const char* AccessibilityButtonInfo::type() const { ...@@ -64,8 +69,11 @@ const char* AccessibilityButtonInfo::type() const {
} }
AccessibilityLinkInfo::AccessibilityLinkInfo(Profile* profile, AccessibilityLinkInfo::AccessibilityLinkInfo(Profile* profile,
const std::string& link_name) const std::string& link_name,
: AccessibilityControlInfo(profile, link_name) { } const std::string& context)
: AccessibilityControlInfo(profile, link_name) {
set_context(context);
}
const char* AccessibilityLinkInfo::type() const { const char* AccessibilityLinkInfo::type() const {
return keys::kTypeLink; return keys::kTypeLink;
...@@ -74,6 +82,7 @@ const char* AccessibilityLinkInfo::type() const { ...@@ -74,6 +82,7 @@ const char* AccessibilityLinkInfo::type() const {
AccessibilityRadioButtonInfo::AccessibilityRadioButtonInfo( AccessibilityRadioButtonInfo::AccessibilityRadioButtonInfo(
Profile* profile, Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool checked, bool checked,
int item_index, int item_index,
int item_count) int item_count)
...@@ -81,6 +90,7 @@ AccessibilityRadioButtonInfo::AccessibilityRadioButtonInfo( ...@@ -81,6 +90,7 @@ AccessibilityRadioButtonInfo::AccessibilityRadioButtonInfo(
checked_(checked), checked_(checked),
item_index_(item_index), item_index_(item_index),
item_count_(item_count) { item_count_(item_count) {
set_context(context);
} }
const char* AccessibilityRadioButtonInfo::type() const { const char* AccessibilityRadioButtonInfo::type() const {
...@@ -97,9 +107,11 @@ void AccessibilityRadioButtonInfo::SerializeToDict( ...@@ -97,9 +107,11 @@ void AccessibilityRadioButtonInfo::SerializeToDict(
AccessibilityCheckboxInfo::AccessibilityCheckboxInfo(Profile* profile, AccessibilityCheckboxInfo::AccessibilityCheckboxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool checked) bool checked)
: AccessibilityControlInfo(profile, name), : AccessibilityControlInfo(profile, name),
checked_(checked) { checked_(checked) {
set_context(context);
} }
const char* AccessibilityCheckboxInfo::type() const { const char* AccessibilityCheckboxInfo::type() const {
...@@ -113,11 +125,13 @@ void AccessibilityCheckboxInfo::SerializeToDict(DictionaryValue *dict) const { ...@@ -113,11 +125,13 @@ void AccessibilityCheckboxInfo::SerializeToDict(DictionaryValue *dict) const {
AccessibilityTabInfo::AccessibilityTabInfo(Profile* profile, AccessibilityTabInfo::AccessibilityTabInfo(Profile* profile,
const std::string& tab_name, const std::string& tab_name,
const std::string& context,
int tab_index, int tab_index,
int tab_count) int tab_count)
: AccessibilityControlInfo(profile, tab_name), : AccessibilityControlInfo(profile, tab_name),
tab_index_(tab_index), tab_index_(tab_index),
tab_count_(tab_count) { tab_count_(tab_count) {
set_context(context);
} }
const char* AccessibilityTabInfo::type() const { const char* AccessibilityTabInfo::type() const {
...@@ -132,6 +146,7 @@ void AccessibilityTabInfo::SerializeToDict(DictionaryValue *dict) const { ...@@ -132,6 +146,7 @@ void AccessibilityTabInfo::SerializeToDict(DictionaryValue *dict) const {
AccessibilityComboBoxInfo::AccessibilityComboBoxInfo(Profile* profile, AccessibilityComboBoxInfo::AccessibilityComboBoxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
const std::string& value, const std::string& value,
int item_index, int item_index,
int item_count) int item_count)
...@@ -139,6 +154,7 @@ AccessibilityComboBoxInfo::AccessibilityComboBoxInfo(Profile* profile, ...@@ -139,6 +154,7 @@ AccessibilityComboBoxInfo::AccessibilityComboBoxInfo(Profile* profile,
value_(value), value_(value),
item_index_(item_index), item_index_(item_index),
item_count_(item_count) { item_count_(item_count) {
set_context(context);
} }
const char* AccessibilityComboBoxInfo::type() const { const char* AccessibilityComboBoxInfo::type() const {
...@@ -154,12 +170,14 @@ void AccessibilityComboBoxInfo::SerializeToDict(DictionaryValue *dict) const { ...@@ -154,12 +170,14 @@ void AccessibilityComboBoxInfo::SerializeToDict(DictionaryValue *dict) const {
AccessibilityTextBoxInfo::AccessibilityTextBoxInfo(Profile* profile, AccessibilityTextBoxInfo::AccessibilityTextBoxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool password) bool password)
: AccessibilityControlInfo(profile, name), : AccessibilityControlInfo(profile, name),
value_(""), value_(""),
password_(password), password_(password),
selection_start_(0), selection_start_(0),
selection_end_(0) { selection_end_(0) {
set_context(context);
} }
const char* AccessibilityTextBoxInfo::type() const { const char* AccessibilityTextBoxInfo::type() const {
...@@ -176,6 +194,7 @@ void AccessibilityTextBoxInfo::SerializeToDict(DictionaryValue *dict) const { ...@@ -176,6 +194,7 @@ void AccessibilityTextBoxInfo::SerializeToDict(DictionaryValue *dict) const {
AccessibilityListBoxInfo::AccessibilityListBoxInfo(Profile* profile, AccessibilityListBoxInfo::AccessibilityListBoxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
const std::string& value, const std::string& value,
int item_index, int item_index,
int item_count) int item_count)
...@@ -183,6 +202,7 @@ AccessibilityListBoxInfo::AccessibilityListBoxInfo(Profile* profile, ...@@ -183,6 +202,7 @@ AccessibilityListBoxInfo::AccessibilityListBoxInfo(Profile* profile,
value_(value), value_(value),
item_index_(item_index), item_index_(item_index),
item_count_(item_count) { item_count_(item_count) {
set_context(context);
} }
const char* AccessibilityListBoxInfo::type() const { const char* AccessibilityListBoxInfo::type() const {
...@@ -237,6 +257,7 @@ const char* AccessibilityMenuInfo::type() const { ...@@ -237,6 +257,7 @@ const char* AccessibilityMenuInfo::type() const {
AccessibilityMenuItemInfo::AccessibilityMenuItemInfo(Profile* profile, AccessibilityMenuItemInfo::AccessibilityMenuItemInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool has_submenu, bool has_submenu,
int item_index, int item_index,
int item_count) int item_count)
...@@ -244,6 +265,7 @@ AccessibilityMenuItemInfo::AccessibilityMenuItemInfo(Profile* profile, ...@@ -244,6 +265,7 @@ AccessibilityMenuItemInfo::AccessibilityMenuItemInfo(Profile* profile,
has_submenu_(has_submenu), has_submenu_(has_submenu),
item_index_(item_index), item_index_(item_index),
item_count_(item_count) { item_count_(item_count) {
set_context(context);
} }
const char* AccessibilityMenuItemInfo::type() const { const char* AccessibilityMenuItemInfo::type() const {
......
...@@ -59,11 +59,20 @@ class AccessibilityControlInfo : public AccessibilityEventInfo { ...@@ -59,11 +59,20 @@ class AccessibilityControlInfo : public AccessibilityEventInfo {
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
const std::string& context() const { return context_; }
protected: protected:
AccessibilityControlInfo(Profile* profile, const std::string& control_name); AccessibilityControlInfo(Profile* profile,
const std::string& name);
void set_context(const std::string& context) { context_ = context; }
// The name of the control, like "OK" or "Password". // The name of the control, like "OK" or "Password".
std::string name_; std::string name_;
// A string describing the context of the control, such as the name of
// the group or toolbar it's contained in.
std::string context_;
}; };
// Accessibility information about a window passed to onWindowOpened // Accessibility information about a window passed to onWindowOpened
...@@ -79,7 +88,9 @@ class AccessibilityWindowInfo : public AccessibilityControlInfo { ...@@ -79,7 +88,9 @@ class AccessibilityWindowInfo : public AccessibilityControlInfo {
// and onControlAction event listeners. // and onControlAction event listeners.
class AccessibilityButtonInfo : public AccessibilityControlInfo { class AccessibilityButtonInfo : public AccessibilityControlInfo {
public: public:
AccessibilityButtonInfo(Profile* profile, const std::string& button_name); AccessibilityButtonInfo(Profile* profile,
const std::string& button_name,
const std::string& context);
virtual const char* type() const OVERRIDE; virtual const char* type() const OVERRIDE;
}; };
...@@ -88,7 +99,9 @@ class AccessibilityButtonInfo : public AccessibilityControlInfo { ...@@ -88,7 +99,9 @@ class AccessibilityButtonInfo : public AccessibilityControlInfo {
// and onControlAction event listeners. // and onControlAction event listeners.
class AccessibilityLinkInfo : public AccessibilityControlInfo { class AccessibilityLinkInfo : public AccessibilityControlInfo {
public: public:
AccessibilityLinkInfo(Profile* profile, const std::string& link_name); AccessibilityLinkInfo(Profile* profile,
const std::string& link_name,
const std::string& context);
virtual const char* type() const OVERRIDE; virtual const char* type() const OVERRIDE;
}; };
...@@ -99,6 +112,7 @@ class AccessibilityRadioButtonInfo : public AccessibilityControlInfo { ...@@ -99,6 +112,7 @@ class AccessibilityRadioButtonInfo : public AccessibilityControlInfo {
public: public:
AccessibilityRadioButtonInfo(Profile* profile, AccessibilityRadioButtonInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool checked, bool checked,
int item_index, int item_index,
int item_count); int item_count);
...@@ -126,6 +140,7 @@ class AccessibilityCheckboxInfo : public AccessibilityControlInfo { ...@@ -126,6 +140,7 @@ class AccessibilityCheckboxInfo : public AccessibilityControlInfo {
public: public:
AccessibilityCheckboxInfo(Profile* profile, AccessibilityCheckboxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool checked); bool checked);
virtual const char* type() const OVERRIDE; virtual const char* type() const OVERRIDE;
...@@ -146,6 +161,7 @@ class AccessibilityTabInfo : public AccessibilityControlInfo { ...@@ -146,6 +161,7 @@ class AccessibilityTabInfo : public AccessibilityControlInfo {
public: public:
AccessibilityTabInfo(Profile* profile, AccessibilityTabInfo(Profile* profile,
const std::string& tab_name, const std::string& tab_name,
const std::string& context,
int tab_index, int tab_index,
int tab_count); int tab_count);
...@@ -173,6 +189,7 @@ class AccessibilityComboBoxInfo : public AccessibilityControlInfo { ...@@ -173,6 +189,7 @@ class AccessibilityComboBoxInfo : public AccessibilityControlInfo {
public: public:
AccessibilityComboBoxInfo(Profile* profile, AccessibilityComboBoxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
const std::string& value, const std::string& value,
int item_index, int item_index,
int item_count); int item_count);
...@@ -205,6 +222,7 @@ class AccessibilityTextBoxInfo : public AccessibilityControlInfo { ...@@ -205,6 +222,7 @@ class AccessibilityTextBoxInfo : public AccessibilityControlInfo {
public: public:
AccessibilityTextBoxInfo(Profile* profile, AccessibilityTextBoxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool password); bool password);
virtual const char* type() const OVERRIDE; virtual const char* type() const OVERRIDE;
...@@ -236,6 +254,7 @@ class AccessibilityListBoxInfo : public AccessibilityControlInfo { ...@@ -236,6 +254,7 @@ class AccessibilityListBoxInfo : public AccessibilityControlInfo {
public: public:
AccessibilityListBoxInfo(Profile* profile, AccessibilityListBoxInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
const std::string& value, const std::string& value,
int item_index, int item_index,
int item_count); int item_count);
...@@ -305,6 +324,7 @@ class AccessibilityMenuItemInfo : public AccessibilityControlInfo { ...@@ -305,6 +324,7 @@ class AccessibilityMenuItemInfo : public AccessibilityControlInfo {
public: public:
AccessibilityMenuItemInfo(Profile* profile, AccessibilityMenuItemInfo(Profile* profile,
const std::string& name, const std::string& name,
const std::string& context,
bool has_submenu, bool has_submenu,
int item_index, int item_index,
int item_count); int item_count);
......
...@@ -9,6 +9,7 @@ namespace extension_accessibility_api_constants { ...@@ -9,6 +9,7 @@ namespace extension_accessibility_api_constants {
// String keys for AccessibilityObject properties. // String keys for AccessibilityObject properties.
const char kTypeKey[] = "type"; const char kTypeKey[] = "type";
const char kNameKey[] = "name"; const char kNameKey[] = "name";
const char kContextKey[] = "context";
const char kDetailsKey[] = "details"; const char kDetailsKey[] = "details";
const char kValueKey[] = "details.value"; const char kValueKey[] = "details.value";
const char kPasswordKey[] = "details.isPassword"; const char kPasswordKey[] = "details.isPassword";
......
...@@ -13,6 +13,7 @@ namespace extension_accessibility_api_constants { ...@@ -13,6 +13,7 @@ namespace extension_accessibility_api_constants {
// Keys. // Keys.
extern const char kTypeKey[]; extern const char kTypeKey[];
extern const char kNameKey[]; extern const char kNameKey[];
extern const char kContextKey[];
extern const char kDetailsKey[]; extern const char kDetailsKey[];
extern const char kValueKey[]; extern const char kValueKey[];
extern const char kPasswordKey[]; extern const char kPasswordKey[];
......
...@@ -44,7 +44,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestFocusEvents) { ...@@ -44,7 +44,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestFocusEvents) {
// Test a simple control. // Test a simple control.
std::string button_name = "Save"; std::string button_name = "Save";
AccessibilityButtonInfo button_info(NULL, button_name); AccessibilityButtonInfo button_info(NULL, button_name, "");
handler.DescribeAccessibilityEvent( handler.DescribeAccessibilityEvent(
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
&button_info, &button_info,
...@@ -55,7 +55,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestFocusEvents) { ...@@ -55,7 +55,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestFocusEvents) {
// Test a control with multiple states. // Test a control with multiple states.
std::string checkbox_name = "Accessibility"; std::string checkbox_name = "Accessibility";
AccessibilityCheckboxInfo checkbox_info(NULL, checkbox_name, false); AccessibilityCheckboxInfo checkbox_info(NULL, checkbox_name, "", false);
handler.DescribeAccessibilityEvent( handler.DescribeAccessibilityEvent(
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
&checkbox_info, &checkbox_info,
...@@ -76,7 +76,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestFocusEvents) { ...@@ -76,7 +76,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestFocusEvents) {
std::string combobox_name = "Language"; std::string combobox_name = "Language";
std::string combobox_value = "English"; std::string combobox_value = "English";
AccessibilityComboBoxInfo combobox_info( AccessibilityComboBoxInfo combobox_info(
NULL, combobox_name, combobox_value, 12, 35); NULL, combobox_name, "", combobox_value, 12, 35);
handler.DescribeAccessibilityEvent( handler.DescribeAccessibilityEvent(
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
&combobox_info, &combobox_info,
...@@ -92,7 +92,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestTextEvents) { ...@@ -92,7 +92,7 @@ TEST_F(WizardAccessibilityHandlerTest, TestTextEvents) {
std::string description; std::string description;
EarconType earcon; EarconType earcon;
AccessibilityTextBoxInfo textbox_info(NULL, "", false); AccessibilityTextBoxInfo textbox_info(NULL, "", "", false);
handler.DescribeAccessibilityEvent( handler.DescribeAccessibilityEvent(
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
&textbox_info, &textbox_info,
......
...@@ -551,8 +551,11 @@ void LocationBarViewGtk::OnKillFocus() { ...@@ -551,8 +551,11 @@ void LocationBarViewGtk::OnKillFocus() {
void LocationBarViewGtk::OnSetFocus() { void LocationBarViewGtk::OnSetFocus() {
Profile* profile = browser_->profile(); Profile* profile = browser_->profile();
AccessibilityTextBoxInfo info(profile, AccessibilityTextBoxInfo info(
l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION), false); profile,
l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION),
std::string(),
false);
content::NotificationService::current()->Notify( content::NotificationService::current()->Notify(
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
content::Source<Profile>(profile), content::Source<Profile>(profile),
......
...@@ -91,6 +91,7 @@ void AccessibilityEventRouterViews::HandleMenuItemFocused( ...@@ -91,6 +91,7 @@ void AccessibilityEventRouterViews::HandleMenuItemFocused(
AccessibilityMenuItemInfo info(most_recent_profile_, AccessibilityMenuItemInfo info(most_recent_profile_,
UTF16ToUTF8(menu_item_name), UTF16ToUTF8(menu_item_name),
UTF16ToUTF8(menu_name),
has_submenu, has_submenu,
item_index, item_index,
item_count); item_count);
...@@ -170,22 +171,26 @@ void AccessibilityEventRouterViews::DispatchAccessibilityNotification( ...@@ -170,22 +171,26 @@ void AccessibilityEventRouterViews::DispatchAccessibilityNotification(
} }
} }
// static
void AccessibilityEventRouterViews::SendButtonNotification( void AccessibilityEventRouterViews::SendButtonNotification(
views::View* view, views::View* view,
int type, int type,
Profile* profile) { Profile* profile) {
AccessibilityButtonInfo info(profile, GetViewName(view)); AccessibilityButtonInfo info(
profile, GetViewName(view), GetViewContext(view));
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendLinkNotification( void AccessibilityEventRouterViews::SendLinkNotification(
views::View* view, views::View* view,
int type, int type,
Profile* profile) { Profile* profile) {
AccessibilityLinkInfo info(profile, GetViewName(view)); AccessibilityLinkInfo info(profile, GetViewName(view), GetViewContext(view));
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendMenuNotification( void AccessibilityEventRouterViews::SendMenuNotification(
views::View* view, views::View* view,
int type, int type,
...@@ -194,11 +199,13 @@ void AccessibilityEventRouterViews::SendMenuNotification( ...@@ -194,11 +199,13 @@ void AccessibilityEventRouterViews::SendMenuNotification(
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendMenuItemNotification( void AccessibilityEventRouterViews::SendMenuItemNotification(
views::View* view, views::View* view,
int type, int type,
Profile* profile) { Profile* profile) {
std::string name = GetViewName(view); std::string name = GetViewName(view);
std::string context = GetViewContext(view);
bool has_submenu = false; bool has_submenu = false;
int index = -1; int index = -1;
...@@ -217,10 +224,12 @@ void AccessibilityEventRouterViews::SendMenuItemNotification( ...@@ -217,10 +224,12 @@ void AccessibilityEventRouterViews::SendMenuItemNotification(
RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count); RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count);
} }
AccessibilityMenuItemInfo info(profile, name, has_submenu, index, count); AccessibilityMenuItemInfo info(
profile, name, context, has_submenu, index, count);
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendTextfieldNotification( void AccessibilityEventRouterViews::SendTextfieldNotification(
views::View* view, views::View* view,
int type, int type,
...@@ -228,14 +237,16 @@ void AccessibilityEventRouterViews::SendTextfieldNotification( ...@@ -228,14 +237,16 @@ void AccessibilityEventRouterViews::SendTextfieldNotification(
ui::AccessibleViewState state; ui::AccessibleViewState state;
view->GetAccessibleState(&state); view->GetAccessibleState(&state);
std::string name = UTF16ToUTF8(state.name); std::string name = UTF16ToUTF8(state.name);
std::string context = GetViewContext(view);
bool password = bool password =
(state.state & ui::AccessibilityTypes::STATE_PROTECTED) != 0; (state.state & ui::AccessibilityTypes::STATE_PROTECTED) != 0;
AccessibilityTextBoxInfo info(profile, name, password); AccessibilityTextBoxInfo info(profile, name, context, password);
std::string value = UTF16ToUTF8(state.value); std::string value = UTF16ToUTF8(state.value);
info.SetValue(value, state.selection_start, state.selection_end); info.SetValue(value, state.selection_start, state.selection_end);
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendComboboxNotification( void AccessibilityEventRouterViews::SendComboboxNotification(
views::View* view, views::View* view,
int type, int type,
...@@ -244,11 +255,13 @@ void AccessibilityEventRouterViews::SendComboboxNotification( ...@@ -244,11 +255,13 @@ void AccessibilityEventRouterViews::SendComboboxNotification(
view->GetAccessibleState(&state); view->GetAccessibleState(&state);
std::string name = UTF16ToUTF8(state.name); std::string name = UTF16ToUTF8(state.name);
std::string value = UTF16ToUTF8(state.value); std::string value = UTF16ToUTF8(state.value);
std::string context = GetViewContext(view);
AccessibilityComboBoxInfo info( AccessibilityComboBoxInfo info(
profile, name, value, state.index, state.count); profile, name, context, value, state.index, state.count);
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendCheckboxNotification( void AccessibilityEventRouterViews::SendCheckboxNotification(
views::View* view, views::View* view,
int type, int type,
...@@ -257,11 +270,16 @@ void AccessibilityEventRouterViews::SendCheckboxNotification( ...@@ -257,11 +270,16 @@ void AccessibilityEventRouterViews::SendCheckboxNotification(
view->GetAccessibleState(&state); view->GetAccessibleState(&state);
std::string name = UTF16ToUTF8(state.name); std::string name = UTF16ToUTF8(state.name);
std::string value = UTF16ToUTF8(state.value); std::string value = UTF16ToUTF8(state.value);
std::string context = GetViewContext(view);
AccessibilityCheckboxInfo info( AccessibilityCheckboxInfo info(
profile, name, state.state == ui::AccessibilityTypes::STATE_CHECKED); profile,
name,
context,
state.state == ui::AccessibilityTypes::STATE_CHECKED);
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
void AccessibilityEventRouterViews::SendWindowNotification( void AccessibilityEventRouterViews::SendWindowNotification(
views::View* view, views::View* view,
int type, int type,
...@@ -283,12 +301,68 @@ void AccessibilityEventRouterViews::SendWindowNotification( ...@@ -283,12 +301,68 @@ void AccessibilityEventRouterViews::SendWindowNotification(
SendAccessibilityNotification(type, &info); SendAccessibilityNotification(type, &info);
} }
// static
std::string AccessibilityEventRouterViews::GetViewName(views::View* view) { std::string AccessibilityEventRouterViews::GetViewName(views::View* view) {
ui::AccessibleViewState state; ui::AccessibleViewState state;
view->GetAccessibleState(&state); view->GetAccessibleState(&state);
return UTF16ToUTF8(state.name); return UTF16ToUTF8(state.name);
} }
// static
std::string AccessibilityEventRouterViews::GetViewContext(views::View* view) {
for (views::View* parent = view->parent();
parent;
parent = parent->parent()) {
ui::AccessibleViewState state;
parent->GetAccessibleState(&state);
// Two cases are handled right now. More could be added in the future
// depending on how the UI evolves.
// A control in a toolbar should use the toolbar's accessible name
// as the context.
if (state.role == ui::AccessibilityTypes::ROLE_TOOLBAR &&
!state.name.empty()) {
return UTF16ToUTF8(state.name);
}
// A control inside of an alert (like an infobar) should grab the
// first static text descendant as the context; that's the prompt.
if (state.role == ui::AccessibilityTypes::ROLE_ALERT) {
views::View* static_text_child = FindDescendantWithAccessibleRole(
parent, ui::AccessibilityTypes::ROLE_STATICTEXT);
if (static_text_child) {
ui::AccessibleViewState state;
static_text_child->GetAccessibleState(&state);
if (!state.name.empty())
return UTF16ToUTF8(state.name);
}
return std::string();
}
}
return std::string();
}
// static
views::View* AccessibilityEventRouterViews::FindDescendantWithAccessibleRole(
views::View* view, ui::AccessibilityTypes::Role role) {
ui::AccessibleViewState state;
view->GetAccessibleState(&state);
if (state.role == role)
return view;
for (int i = 0; i < view->child_count(); i++) {
views::View* child = view->child_at(i);
views::View* result = FindDescendantWithAccessibleRole(child, role);
if (result)
return result;
}
return NULL;
}
// static
bool AccessibilityEventRouterViews::IsMenuEvent( bool AccessibilityEventRouterViews::IsMenuEvent(
views::View* view, views::View* view,
int type) { int type) {
...@@ -310,6 +384,7 @@ bool AccessibilityEventRouterViews::IsMenuEvent( ...@@ -310,6 +384,7 @@ bool AccessibilityEventRouterViews::IsMenuEvent(
return false; return false;
} }
// static
void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount( void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount(
views::View* menu, views::View* menu,
views::View* item, views::View* item,
...@@ -332,6 +407,7 @@ void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount( ...@@ -332,6 +407,7 @@ void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount(
} }
} }
// static
std::string AccessibilityEventRouterViews::RecursiveGetStaticText( std::string AccessibilityEventRouterViews::RecursiveGetStaticText(
views::View* view) { views::View* view) {
ui::AccessibleViewState state; ui::AccessibleViewState state;
......
...@@ -77,44 +77,72 @@ class AccessibilityEventRouterViews { ...@@ -77,44 +77,72 @@ class AccessibilityEventRouterViews {
// Checks the type of the view and calls one of the more specific // Checks the type of the view and calls one of the more specific
// Send*Notification methods, below. // Send*Notification methods, below.
void DispatchAccessibilityNotification( void DispatchAccessibilityNotification(
views::View* view, int type); views::View* view,
int type);
// Each of these methods constructs an AccessibilityControlInfo object // Each of these methods constructs an AccessibilityControlInfo object
// and sends a notification of a specific accessibility event. // and sends a notification of a specific accessibility event.
void SendButtonNotification( static void SendButtonNotification(
views::View* view, int type, Profile* profile); views::View* view,
void SendLinkNotification( int type,
views::View* view, int type, Profile* profile); Profile* profile);
void SendMenuNotification( static void SendLinkNotification(
views::View* view, int type, Profile* profile); views::View* view,
void SendMenuItemNotification( int type,
views::View* view, int type, Profile* profile); Profile* profile);
void SendTextfieldNotification( static void SendMenuNotification(
views::View* view, int type, Profile* profile); views::View* view,
void SendComboboxNotification( int type,
views::View* view, int type, Profile* profile); Profile* profile);
void SendCheckboxNotification( static void SendMenuItemNotification(
views::View* view, int type, Profile* profile); views::View* view,
void SendWindowNotification( int type,
views::View* view, int type, Profile* profile); Profile* profile);
static void SendTextfieldNotification(
views::View* view,
int type,
Profile* profile);
static void SendComboboxNotification(
views::View* view,
int type,
Profile* profile);
static void SendCheckboxNotification(
views::View* view,
int type,
Profile* profile);
static void SendWindowNotification(
views::View* view,
int type,
Profile* profile);
// Return the name of a view. // Return the name of a view.
std::string GetViewName(views::View* view); static std::string GetViewName(views::View* view);
// Get the context of a view - the name of the enclosing group, toolbar, etc.
static std::string GetViewContext(views::View* view);
// Return a descendant of this view with a given accessible role, if found.
static views::View* FindDescendantWithAccessibleRole(
views::View* view,
ui::AccessibilityTypes::Role role);
// Return true if it's an event on a menu. // Return true if it's an event on a menu.
bool IsMenuEvent(views::View* view, int type); static bool IsMenuEvent(views::View* view,
int type);
// Recursively explore all menu items of |menu| and return in |count| // Recursively explore all menu items of |menu| and return in |count|
// the total number of items, and in |index| the 0-based index of // the total number of items, and in |index| the 0-based index of
// |item|, if found. Initialize |count| to zero before calling this // |item|, if found. Initialize |count| to zero before calling this
// method. |index| will be unchanged if the item is not found, so // method. |index| will be unchanged if the item is not found, so
// initialize it to -1 to detect this case. // initialize it to -1 to detect this case.
void RecursiveGetMenuItemIndexAndCount( static void RecursiveGetMenuItemIndexAndCount(views::View* menu,
views::View* menu, views::View* item, int* index, int* count); views::View* item,
int* index,
int* count);
// Recursively explore the subviews and return the text from the first // Recursively explore the subviews and return the text from the first
// subview with a role of STATIC_TEXT. // subview with a role of STATIC_TEXT.
std::string RecursiveGetStaticText(views::View* view); static std::string RecursiveGetStaticText(views::View* view);
// The profile associated with the most recent window event - used to // The profile associated with the most recent window event - used to
// figure out where to route a few events that can't be directly traced // figure out where to route a few events that can't be directly traced
......
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/views/controls/button/text_button.h" #include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/grid_layout.h" #include "ui/views/layout/grid_layout.h"
#include "ui/views/views_delegate.h" #include "ui/views/views_delegate.h"
#include "ui/views/widget/native_widget.h" #include "ui/views/widget/native_widget.h"
...@@ -84,6 +86,25 @@ class AccessibilityWindowDelegate : public views::WidgetDelegate { ...@@ -84,6 +86,25 @@ class AccessibilityWindowDelegate : public views::WidgetDelegate {
views::View* contents_; views::View* contents_;
}; };
class ViewWithNameAndRole : public views::View {
public:
explicit ViewWithNameAndRole(const string16& name,
ui::AccessibilityTypes::Role role)
: name_(name),
role_(role) {
}
void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE {
views::View::GetAccessibleState(state);
state->name = name_;
state->role = role_;
}
private:
string16 name_;
ui::AccessibilityTypes::Role role_;
};
class AccessibilityEventRouterViewsTest class AccessibilityEventRouterViewsTest
: public testing::Test, : public testing::Test,
public content::NotificationObserver { public content::NotificationObserver {
...@@ -114,11 +135,13 @@ class AccessibilityEventRouterViewsTest ...@@ -114,11 +135,13 @@ class AccessibilityEventRouterViewsTest
content::Details<const AccessibilityControlInfo>(details).ptr(); content::Details<const AccessibilityControlInfo>(details).ptr();
focus_event_count_++; focus_event_count_++;
last_control_name_ = info->name(); last_control_name_ = info->name();
last_control_context_ = info->context();
} }
MessageLoopForUI message_loop_; MessageLoopForUI message_loop_;
int focus_event_count_; int focus_event_count_;
std::string last_control_name_; std::string last_control_name_;
std::string last_control_context_;
}; };
TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) { TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
...@@ -184,4 +207,90 @@ TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) { ...@@ -184,4 +207,90 @@ TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
window->CloseNow(); window->CloseNow();
} }
TEST_F(AccessibilityEventRouterViewsTest, TestToolbarContext) {
const char kToolbarNameASCII[] = "MyToolbar";
const char kButtonNameASCII[] = "MyButton";
// Create a toolbar with a button.
views::View* contents = new ViewWithNameAndRole(
ASCIIToUTF16(kToolbarNameASCII),
ui::AccessibilityTypes::ROLE_TOOLBAR);
views::NativeTextButton* button = new views::NativeTextButton(
NULL, ASCIIToUTF16(kButtonNameASCII));
contents->AddChildView(button);
// Put the view in a window.
views::Widget* window = CreateWindowWithContents(contents);
// Start listening to ACCESSIBILITY_CONTROL_FOCUSED notifications.
content::NotificationRegistrar registrar;
registrar.Add(this,
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
content::NotificationService::AllSources());
// Switch on accessibility event notifications.
ExtensionAccessibilityEventRouter* accessibility_event_router =
ExtensionAccessibilityEventRouter::GetInstance();
accessibility_event_router->SetAccessibilityEnabled(true);
// Create a profile and associate it with this window.
TestingProfile profile;
window->SetNativeWindowProperty(Profile::kProfileKey, &profile);
// Set focus to the button.
focus_event_count_ = 0;
button->RequestFocus();
// Test that we got the event with the expected name and context.
EXPECT_EQ(1, focus_event_count_);
EXPECT_EQ(kButtonNameASCII, last_control_name_);
EXPECT_EQ(kToolbarNameASCII, last_control_context_);
window->CloseNow();
}
TEST_F(AccessibilityEventRouterViewsTest, TestAlertContext) {
const char kAlertTextASCII[] = "MyAlertText";
const char kButtonNameASCII[] = "MyButton";
// Create an alert with static text and a button, similar to an infobar.
views::View* contents = new ViewWithNameAndRole(
string16(),
ui::AccessibilityTypes::ROLE_ALERT);
views::Label* label = new views::Label(ASCIIToUTF16(kAlertTextASCII));
contents->AddChildView(label);
views::NativeTextButton* button = new views::NativeTextButton(
NULL, ASCIIToUTF16(kButtonNameASCII));
contents->AddChildView(button);
// Put the view in a window.
views::Widget* window = CreateWindowWithContents(contents);
// Start listening to ACCESSIBILITY_CONTROL_FOCUSED notifications.
content::NotificationRegistrar registrar;
registrar.Add(this,
chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED,
content::NotificationService::AllSources());
// Switch on accessibility event notifications.
ExtensionAccessibilityEventRouter* accessibility_event_router =
ExtensionAccessibilityEventRouter::GetInstance();
accessibility_event_router->SetAccessibilityEnabled(true);
// Create a profile and associate it with this window.
TestingProfile profile;
window->SetNativeWindowProperty(Profile::kProfileKey, &profile);
// Set focus to the button.
focus_event_count_ = 0;
button->RequestFocus();
// Test that we got the event with the expected name and context.
EXPECT_EQ(1, focus_event_count_);
EXPECT_EQ(kButtonNameASCII, last_control_name_);
EXPECT_EQ(kAlertTextASCII, last_control_context_);
window->CloseNow();
}
#endif // defined(TOOLKIT_VIEWS) #endif // defined(TOOLKIT_VIEWS)
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
"type": "string", "type": "string",
"description": "The localized name of the object, like OK or Password. Do not rely on an exact string match because the text will be in the user's language and may change in the future." "description": "The localized name of the object, like OK or Password. Do not rely on an exact string match because the text will be in the user's language and may change in the future."
}, },
"context": {
"type": "string",
"description": "The localized name of the context for the object, like the name of the surrounding toolbar or group of controls.",
"optional": true
},
"details": { "details": {
"description": "Other details like the state, depending on the type of object.", "description": "Other details like the state, depending on the type of object.",
"optional": true, "optional": true,
......
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