Home | History | Annotate | Download | only in views
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 
      7 #include "base/message_loop.h"
      8 #include "base/string_util.h"
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/browser/extensions/extension_accessibility_api.h"
     11 #include "chrome/browser/ui/views/accessibility_event_router_views.h"
     12 #include "chrome/test/testing_profile.h"
     13 #include "content/common/notification_registrar.h"
     14 #include "content/common/notification_service.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "views/controls/button/native_button.h"
     17 #include "views/layout/grid_layout.h"
     18 #include "views/views_delegate.h"
     19 #include "views/widget/native_widget.h"
     20 #include "views/widget/root_view.h"
     21 #include "views/widget/widget.h"
     22 #include "views/window/window.h"
     23 #include "views/window/window_delegate.h"
     24 
     25 #if defined(TOOLKIT_VIEWS)
     26 
     27 class AccessibilityViewsDelegate : public views::ViewsDelegate {
     28  public:
     29   AccessibilityViewsDelegate() {}
     30   virtual ~AccessibilityViewsDelegate() {}
     31 
     32   // Overridden from views::ViewsDelegate:
     33   virtual ui::Clipboard* GetClipboard() const { return NULL; }
     34   virtual void SaveWindowPlacement(views::Window* window,
     35                                    const std::wstring& window_name,
     36                                    const gfx::Rect& bounds,
     37                                    bool maximized) {
     38   }
     39   virtual bool GetSavedWindowBounds(views::Window* window,
     40                                     const std::wstring& window_name,
     41                                     gfx::Rect* bounds) const {
     42     return false;
     43   }
     44   virtual bool GetSavedMaximizedState(views::Window* window,
     45                                       const std::wstring& window_name,
     46                                       bool* maximized) const {
     47     return false;
     48   }
     49   virtual void NotifyAccessibilityEvent(
     50       views::View* view, ui::AccessibilityTypes::Event event_type) {
     51     AccessibilityEventRouterViews::GetInstance()->HandleAccessibilityEvent(
     52         view, event_type);
     53   }
     54   virtual void NotifyMenuItemFocused(
     55       const std::wstring& menu_name,
     56       const std::wstring& menu_item_name,
     57       int item_index,
     58       int item_count,
     59       bool has_submenu) {}
     60 #if defined(OS_WIN)
     61   virtual HICON GetDefaultWindowIcon() const {
     62     return NULL;
     63   }
     64 #endif
     65   virtual void AddRef() {}
     66   virtual void ReleaseRef() {}
     67 
     68   DISALLOW_COPY_AND_ASSIGN(AccessibilityViewsDelegate);
     69 };
     70 
     71 class AccessibilityWindowDelegate : public views::WindowDelegate {
     72  public:
     73   explicit AccessibilityWindowDelegate(views::View* contents)
     74       : contents_(contents) { }
     75 
     76   virtual void DeleteDelegate() { delete this; }
     77 
     78   virtual views::View* GetContentsView() { return contents_; }
     79 
     80  private:
     81   views::View* contents_;
     82 };
     83 
     84 class AccessibilityEventRouterViewsTest
     85     : public testing::Test,
     86       public NotificationObserver {
     87  public:
     88   virtual void SetUp() {
     89     views::ViewsDelegate::views_delegate = new AccessibilityViewsDelegate();
     90     window_delegate_ = NULL;
     91   }
     92 
     93   virtual void TearDown() {
     94     delete views::ViewsDelegate::views_delegate;
     95     views::ViewsDelegate::views_delegate = NULL;
     96     if (window_delegate_)
     97       delete window_delegate_;
     98   }
     99 
    100   views::Window* CreateWindowWithContents(views::View* contents) {
    101     window_delegate_ = new AccessibilityWindowDelegate(contents);
    102     return views::Window::CreateChromeWindow(
    103         NULL, gfx::Rect(0, 0, 500, 500), window_delegate_);
    104   }
    105 
    106  protected:
    107   // Implement NotificationObserver::Observe and store information about a
    108   // ACCESSIBILITY_CONTROL_FOCUSED event.
    109   virtual void Observe(NotificationType type,
    110                        const NotificationSource& source,
    111                        const NotificationDetails& details) {
    112     ASSERT_EQ(type.value, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
    113     const AccessibilityControlInfo* info =
    114         Details<const AccessibilityControlInfo>(details).ptr();
    115     focus_event_count_++;
    116     last_control_name_ = info->name();
    117   }
    118 
    119   MessageLoopForUI message_loop_;
    120   int focus_event_count_;
    121   std::string last_control_name_;
    122   AccessibilityWindowDelegate* window_delegate_;
    123 };
    124 
    125 TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
    126   const char kButton1ASCII[] = "Button1";
    127   const char kButton2ASCII[] = "Button2";
    128   const char kButton3ASCII[] = "Button3";
    129   const char kButton3NewASCII[] = "Button3New";
    130 
    131   // Create a contents view with 3 buttons.
    132   views::View* contents = new views::View();
    133   views::NativeButton* button1 = new views::NativeButton(
    134       NULL, ASCIIToWide(kButton1ASCII));
    135   contents->AddChildView(button1);
    136   views::NativeButton* button2 = new views::NativeButton(
    137       NULL, ASCIIToWide(kButton2ASCII));
    138   contents->AddChildView(button2);
    139   views::NativeButton* button3 = new views::NativeButton(
    140       NULL, ASCIIToWide(kButton3ASCII));
    141   contents->AddChildView(button3);
    142 
    143   // Put the view in a window.
    144   views::Window* window = CreateWindowWithContents(contents);
    145 
    146   // Set focus to the first button initially.
    147   button1->RequestFocus();
    148 
    149   // Start listening to ACCESSIBILITY_CONTROL_FOCUSED notifications.
    150   NotificationRegistrar registrar;
    151   registrar.Add(this,
    152                 NotificationType::ACCESSIBILITY_CONTROL_FOCUSED,
    153                 NotificationService::AllSources());
    154 
    155   // Switch on accessibility event notifications.
    156   ExtensionAccessibilityEventRouter* accessibility_event_router =
    157       ExtensionAccessibilityEventRouter::GetInstance();
    158   accessibility_event_router->SetAccessibilityEnabled(true);
    159 
    160   // Create a profile and associate it with this window.
    161   TestingProfile profile;
    162   window->AsWidget()->native_widget()->SetNativeWindowProperty(
    163       Profile::kProfileKey, &profile);
    164 
    165   // Change the accessible name of button3.
    166   button3->SetAccessibleName(ASCIIToUTF16(kButton3NewASCII));
    167 
    168   // Advance focus to the next button and test that we got the
    169   // expected notification with the name of button 2.
    170   views::FocusManager* focus_manager = contents->GetWidget()->GetFocusManager();
    171   focus_event_count_ = 0;
    172   focus_manager->AdvanceFocus(false);
    173   EXPECT_EQ(1, focus_event_count_);
    174   EXPECT_EQ(kButton2ASCII, last_control_name_);
    175 
    176   // Advance to button 3. Expect the new accessible name we assigned.
    177   focus_manager->AdvanceFocus(false);
    178   EXPECT_EQ(2, focus_event_count_);
    179   EXPECT_EQ(kButton3NewASCII, last_control_name_);
    180 
    181   // Advance to button 1 and check the notification.
    182   focus_manager->AdvanceFocus(false);
    183   EXPECT_EQ(3, focus_event_count_);
    184   EXPECT_EQ(kButton1ASCII, last_control_name_);
    185 }
    186 
    187 #endif  // defined(TOOLKIT_VIEWS)
    188