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;
  }
}