This source file includes following definitions.
- NotifyAccessibilityEvent
- DeleteDelegate
- GetContentsView
- GetWidget
- GetWidget
- role_
- GetAccessibleState
- set_name
- SetUp
- TearDown
- CreateWindowWithContents
- EnableAccessibilityAndListenToFocusNotifications
- ClearCallback
- OnControlEvent
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BuildMenu
- IsCommandIdChecked
- IsCommandIdEnabled
- IsCommandIdVisible
- GetAcceleratorForCommandId
- ExecuteCommand
- TEST_F
#include <string>
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/accessibility/accessibility_extension_api.h"
#include "chrome/browser/accessibility/accessibility_extension_api_constants.h"
#include "chrome/browser/ui/views/accessibility/accessibility_event_router_views.h"
#include "chrome/test/base/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#if defined(OS_WIN)
#include "ui/base/win/scoped_ole_initializer.h"
#endif
#if defined(USE_AURA)
#include "ui/aura/test/aura_test_helper.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/compositor/test/context_factories_for_test.h"
#endif
using base::ASCIIToUTF16;
class AccessibilityViewsDelegate : public views::TestViewsDelegate {
public:
AccessibilityViewsDelegate() {}
virtual ~AccessibilityViewsDelegate() {}
virtual void NotifyAccessibilityEvent(
views::View* view, ui::AXEvent event_type) OVERRIDE {
AccessibilityEventRouterViews::GetInstance()->HandleAccessibilityEvent(
view, event_type);
}
DISALLOW_COPY_AND_ASSIGN(AccessibilityViewsDelegate);
};
class AccessibilityWindowDelegate : public views::WidgetDelegate {
public:
explicit AccessibilityWindowDelegate(views::View* contents)
: contents_(contents) { }
virtual void DeleteDelegate() OVERRIDE { delete this; }
virtual views::View* GetContentsView() OVERRIDE { return contents_; }
virtual const views::Widget* GetWidget() const OVERRIDE {
return contents_->GetWidget();
}
virtual views::Widget* GetWidget() OVERRIDE { return contents_->GetWidget(); }
private:
views::View* contents_;
DISALLOW_COPY_AND_ASSIGN(AccessibilityWindowDelegate);
};
class ViewWithNameAndRole : public views::View {
public:
explicit ViewWithNameAndRole(const base::string16& name,
ui::AXRole role)
: name_(name),
role_(role) {
}
virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
views::View::GetAccessibleState(state);
state->name = name_;
state->role = role_;
}
void set_name(const base::string16& name) { name_ = name; }
private:
base::string16 name_;
ui::AXRole role_;
DISALLOW_COPY_AND_ASSIGN(ViewWithNameAndRole);
};
class AccessibilityEventRouterViewsTest
: public testing::Test {
public:
AccessibilityEventRouterViewsTest() : control_event_count_(0) {
}
virtual void SetUp() {
#if defined(OS_WIN)
ole_initializer_.reset(new ui::ScopedOleInitializer());
#endif
views::ViewsDelegate::views_delegate = new AccessibilityViewsDelegate();
#if defined(USE_AURA)
bool enable_pixel_output = false;
ui::InitializeContextFactoryForTests(enable_pixel_output);
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
aura_test_helper_->SetUp();
#endif
EnableAccessibilityAndListenToFocusNotifications();
}
virtual void TearDown() {
ClearCallback();
#if defined(USE_AURA)
aura_test_helper_->TearDown();
ui::TerminateContextFactoryForTests();
#endif
delete views::ViewsDelegate::views_delegate;
views::ViewsDelegate::views_delegate = NULL;
base::MessageLoop::current()->RunUntilIdle();
#if defined(OS_WIN)
ole_initializer_.reset();
#endif
}
views::Widget* CreateWindowWithContents(views::View* contents) {
gfx::NativeView context = NULL;
#if defined(USE_AURA)
context = aura_test_helper_->root_window();
#endif
views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
new AccessibilityWindowDelegate(contents),
context,
gfx::Rect(0, 0, 500, 500));
widget->SetNativeWindowProperty(Profile::kProfileKey, &profile_);
return widget;
}
void EnableAccessibilityAndListenToFocusNotifications() {
ExtensionAccessibilityEventRouter* accessibility_event_router =
ExtensionAccessibilityEventRouter::GetInstance();
accessibility_event_router->SetAccessibilityEnabled(true);
accessibility_event_router->SetControlEventCallbackForTesting(base::Bind(
&AccessibilityEventRouterViewsTest::OnControlEvent,
base::Unretained(this)));
}
void ClearCallback() {
ExtensionAccessibilityEventRouter* accessibility_event_router =
ExtensionAccessibilityEventRouter::GetInstance();
accessibility_event_router->ClearControlEventCallback();
}
protected:
virtual void OnControlEvent(ui::AXEvent event,
const AccessibilityControlInfo* info) {
control_event_count_++;
last_control_type_ = info->type();
last_control_name_ = info->name();
last_control_context_ = info->context();
}
base::MessageLoopForUI message_loop_;
int control_event_count_;
std::string last_control_type_;
std::string last_control_name_;
std::string last_control_context_;
TestingProfile profile_;
#if defined(OS_WIN)
scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
#endif
#if defined(USE_AURA)
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
#endif
};
TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
const char kButton1ASCII[] = "Button1";
const char kButton2ASCII[] = "Button2";
const char kButton3ASCII[] = "Button3";
const char kButton3NewASCII[] = "Button3New";
views::View* contents = new views::View();
views::LabelButton* button1 = new views::LabelButton(
NULL, ASCIIToUTF16(kButton1ASCII));
button1->SetStyle(views::Button::STYLE_BUTTON);
contents->AddChildView(button1);
views::LabelButton* button2 = new views::LabelButton(
NULL, ASCIIToUTF16(kButton2ASCII));
button2->SetStyle(views::Button::STYLE_BUTTON);
contents->AddChildView(button2);
views::LabelButton* button3 = new views::LabelButton(
NULL, ASCIIToUTF16(kButton3ASCII));
button3->SetStyle(views::Button::STYLE_BUTTON);
contents->AddChildView(button3);
views::Widget* window = CreateWindowWithContents(contents);
window->Show();
button1->RequestFocus();
base::MessageLoop::current()->RunUntilIdle();
button3->SetAccessibleName(ASCIIToUTF16(kButton3NewASCII));
views::FocusManager* focus_manager = contents->GetWidget()->GetFocusManager();
control_event_count_ = 0;
focus_manager->AdvanceFocus(false);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, control_event_count_);
EXPECT_EQ(kButton2ASCII, last_control_name_);
focus_manager->AdvanceFocus(false);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(2, control_event_count_);
EXPECT_EQ(kButton3NewASCII, last_control_name_);
focus_manager->AdvanceFocus(false);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(3, control_event_count_);
EXPECT_EQ(kButton1ASCII, last_control_name_);
window->CloseNow();
}
TEST_F(AccessibilityEventRouterViewsTest, TestToolbarContext) {
const char kToolbarNameASCII[] = "MyToolbar";
const char kButtonNameASCII[] = "MyButton";
views::View* contents = new ViewWithNameAndRole(
ASCIIToUTF16(kToolbarNameASCII),
ui::AX_ROLE_TOOLBAR);
views::LabelButton* button = new views::LabelButton(
NULL, ASCIIToUTF16(kButtonNameASCII));
button->SetStyle(views::Button::STYLE_BUTTON);
contents->AddChildView(button);
views::Widget* window = CreateWindowWithContents(contents);
control_event_count_ = 0;
button->RequestFocus();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, control_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";
views::View* contents = new ViewWithNameAndRole(
base::string16(),
ui::AX_ROLE_ALERT);
views::Label* label = new views::Label(ASCIIToUTF16(kAlertTextASCII));
contents->AddChildView(label);
views::LabelButton* button = new views::LabelButton(
NULL, ASCIIToUTF16(kButtonNameASCII));
button->SetStyle(views::Button::STYLE_BUTTON);
contents->AddChildView(button);
views::Widget* window = CreateWindowWithContents(contents);
control_event_count_ = 0;
button->RequestFocus();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, control_event_count_);
EXPECT_EQ(kButtonNameASCII, last_control_name_);
EXPECT_EQ(kAlertTextASCII, last_control_context_);
window->CloseNow();
}
TEST_F(AccessibilityEventRouterViewsTest, StateChangeAfterNotification) {
const char kContentsNameASCII[] = "Contents";
const char kOldNameASCII[] = "OldName";
const char kNewNameASCII[] = "NewName";
views::View* contents = new ViewWithNameAndRole(
ASCIIToUTF16(kContentsNameASCII),
ui::AX_ROLE_CLIENT);
ViewWithNameAndRole* child = new ViewWithNameAndRole(
ASCIIToUTF16(kOldNameASCII),
ui::AX_ROLE_BUTTON);
child->SetFocusable(true);
contents->AddChildView(child);
views::Widget* window = CreateWindowWithContents(contents);
control_event_count_ = 0;
child->RequestFocus();
child->set_name(ASCIIToUTF16(kNewNameASCII));
EXPECT_EQ(0, control_event_count_);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, control_event_count_);
EXPECT_EQ(kNewNameASCII, last_control_name_);
window->CloseNow();
}
TEST_F(AccessibilityEventRouterViewsTest, NotificationOnDeletedObject) {
const char kContentsNameASCII[] = "Contents";
const char kNameASCII[] = "OldName";
views::View* contents = new ViewWithNameAndRole(
ASCIIToUTF16(kContentsNameASCII),
ui::AX_ROLE_CLIENT);
ViewWithNameAndRole* child = new ViewWithNameAndRole(
ASCIIToUTF16(kNameASCII),
ui::AX_ROLE_BUTTON);
child->SetFocusable(true);
contents->AddChildView(child);
views::Widget* window = CreateWindowWithContents(contents);
control_event_count_ = 0;
child->RequestFocus();
delete child;
EXPECT_EQ(0, control_event_count_);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(0, control_event_count_);
window->CloseNow();
}
TEST_F(AccessibilityEventRouterViewsTest, AlertsFromWindowAndControl) {
const char kButtonASCII[] = "Button";
const char* kTypeAlert = extension_accessibility_api_constants::kTypeAlert;
const char* kTypeWindow = extension_accessibility_api_constants::kTypeWindow;
views::View* contents = new views::View();
views::LabelButton* button = new views::LabelButton(
NULL, ASCIIToUTF16(kButtonASCII));
button->SetStyle(views::Button::STYLE_BUTTON);
contents->AddChildView(button);
views::Widget* window = CreateWindowWithContents(contents);
window->Show();
control_event_count_ = 0;
button->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(kTypeAlert, last_control_type_);
EXPECT_EQ(1, control_event_count_);
EXPECT_EQ(kButtonASCII, last_control_name_);
control_event_count_ = 0;
window->GetRootView()->NotifyAccessibilityEvent(
ui::AX_EVENT_ALERT, true);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, control_event_count_);
EXPECT_EQ(kTypeWindow, last_control_type_);
window->CloseNow();
}
namespace {
class SimpleMenuDelegate : public ui::SimpleMenuModel::Delegate {
public:
enum {
IDC_MENU_ITEM_1,
IDC_MENU_ITEM_2,
IDC_MENU_INVISIBLE,
IDC_MENU_ITEM_3,
};
SimpleMenuDelegate() {}
virtual ~SimpleMenuDelegate() {}
views::MenuItemView* BuildMenu() {
menu_model_.reset(new ui::SimpleMenuModel(this));
menu_model_->AddItem(IDC_MENU_ITEM_1, ASCIIToUTF16("Item 1"));
menu_model_->AddItem(IDC_MENU_ITEM_2, ASCIIToUTF16("Item 2"));
menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
menu_model_->AddItem(IDC_MENU_INVISIBLE, ASCIIToUTF16("Invisible"));
menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
menu_model_->AddItem(IDC_MENU_ITEM_3, ASCIIToUTF16("Item 3"));
menu_runner_.reset(new views::MenuRunner(menu_model_.get()));
return menu_runner_->GetMenu();
}
virtual bool IsCommandIdChecked(int command_id) const OVERRIDE {
return false;
}
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
return true;
}
virtual bool IsCommandIdVisible(int command_id) const OVERRIDE {
return command_id != IDC_MENU_INVISIBLE;
}
virtual bool GetAcceleratorForCommandId(
int command_id,
ui::Accelerator* accelerator) OVERRIDE {
return false;
}
virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE {
}
private:
scoped_ptr<ui::SimpleMenuModel> menu_model_;
scoped_ptr<views::MenuRunner> menu_runner_;
DISALLOW_COPY_AND_ASSIGN(SimpleMenuDelegate);
};
}
TEST_F(AccessibilityEventRouterViewsTest, MenuIndexAndCountForInvisibleMenu) {
SimpleMenuDelegate menu_delegate;
views::MenuItemView* menu = menu_delegate.BuildMenu();
views::View* menu_container = menu->CreateSubmenu();
struct TestCase {
int command_id;
int expected_index;
int expected_count;
} kTestCases[] = {
{ SimpleMenuDelegate::IDC_MENU_ITEM_1, 0, 3 },
{ SimpleMenuDelegate::IDC_MENU_ITEM_2, 1, 3 },
{ SimpleMenuDelegate::IDC_MENU_INVISIBLE, 0, 3 },
{ SimpleMenuDelegate::IDC_MENU_ITEM_3, 2, 3 },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
int index = 0;
int count = 0;
AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount(
menu_container,
menu->GetMenuItemByID(kTestCases[i].command_id),
&index,
&count);
EXPECT_EQ(kTestCases[i].expected_index, index) << "Case " << i;
EXPECT_EQ(kTestCases[i].expected_count, count) << "Case " << i;
}
}