diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-19 14:33:09 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-19 14:33:09 +0000 |
commit | 521d76f78a831a4465e25649f39b1315726b28df (patch) | |
tree | b6e19a2f7683d32537781512247cd3066853c46e | |
parent | 0b55e380036cc1fb3391efeca7dda9bdab49a119 (diff) | |
download | chromium_src-521d76f78a831a4465e25649f39b1315726b28df.zip chromium_src-521d76f78a831a4465e25649f39b1315726b28df.tar.gz chromium_src-521d76f78a831a4465e25649f39b1315726b28df.tar.bz2 |
Add infrastructure for supporting Views to the accessibility extension api.
Only a few controls actually generate accessibility events to make sure
it works, this is mostly to get the infrastructure in place.
Note that the new files are analogous to:
chrome/browser/gtk/accessibility_event_router_gtk.cc
chrome/browser/gtk/accessibility_event_router_gtk.h
chrome/browser/gtk/accessibile_widget_helper_gtk.cc
chrome/browser/gtk/accessibile_widget_helper_gtk.h
Any design changes should be made to both sets of classes.
BUG=none
TEST=Added new unit test.
Review URL: http://codereview.chromium.org/1518029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44907 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/views/about_chrome_view.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/about_chrome_view.h | 3 | ||||
-rw-r--r-- | chrome/browser/views/accessibility_event_router_views.cc | 178 | ||||
-rw-r--r-- | chrome/browser/views/accessibility_event_router_views.h | 143 | ||||
-rw-r--r-- | chrome/browser/views/accessibility_event_router_views_unittest.cc | 126 | ||||
-rw-r--r-- | chrome/browser/views/accessible_view_helper.cc | 73 | ||||
-rw-r--r-- | chrome/browser/views/accessible_view_helper.h | 69 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.h | 2 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 12 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 |
11 files changed, 615 insertions, 2 deletions
diff --git a/chrome/browser/views/about_chrome_view.cc b/chrome/browser/views/about_chrome_view.cc index 4885b07..96e284d 100644 --- a/chrome/browser/views/about_chrome_view.cc +++ b/chrome/browser/views/about_chrome_view.cc @@ -13,6 +13,7 @@ #include "chrome/app/chrome_version_info.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/views/accessible_view_helper.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/platform_util.h" #include "chrome/common/url_constants.h" @@ -408,6 +409,10 @@ void AboutChromeView::Layout() { throbber_topleft_y + 1, parent_bounds.width() - update_label_x, sz.height()); + + if (!accessible_view_helper_.get()) + accessible_view_helper_.reset( + new AccessibleViewHelper(GetParent(), profile_)); } diff --git a/chrome/browser/views/about_chrome_view.h b/chrome/browser/views/about_chrome_view.h index 5bee7a9..56decd3 100644 --- a/chrome/browser/views/about_chrome_view.h +++ b/chrome/browser/views/about_chrome_view.h @@ -24,6 +24,7 @@ class Throbber; class Window; } +class AccessibleViewHelper; class Profile; //////////////////////////////////////////////////////////////////////////////// @@ -169,6 +170,8 @@ class AboutChromeView : public views::View, CancelableRequestConsumer consumer_; #endif + scoped_ptr<AccessibleViewHelper> accessible_view_helper_; + DISALLOW_COPY_AND_ASSIGN(AboutChromeView); }; diff --git a/chrome/browser/views/accessibility_event_router_views.cc b/chrome/browser/views/accessibility_event_router_views.cc new file mode 100644 index 0000000..32dfaeb --- /dev/null +++ b/chrome/browser/views/accessibility_event_router_views.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2010 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 "chrome/browser/views/accessibility_event_router_views.h" + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/message_loop.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/extensions/extension_accessibility_api.h" +#include "chrome/browser/profile.h" +#include "chrome/common/notification_type.h" +#include "views/controls/button/image_button.h" +#include "views/controls/button/menu_button.h" +#include "views/controls/button/native_button.h" +#include "views/controls/link.h" + +using views::FocusManager; +using views::View; + +AccessibilityEventRouterViews::AccessibilityEventRouterViews() + : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { +} + +AccessibilityEventRouterViews::~AccessibilityEventRouterViews() { +} + +// static +AccessibilityEventRouterViews* AccessibilityEventRouterViews::GetInstance() { + return Singleton<AccessibilityEventRouterViews>::get(); +} + +bool AccessibilityEventRouterViews::AddViewTree(View* view, Profile* profile) { + if (view_tree_profile_map_[view] != NULL) + return false; + + view_tree_profile_map_[view] = profile; + FocusManager* focus_manager = view->GetFocusManager(); + + // Add this object as a listener for this focus manager, but use a ref + // count to ensure we only call AddFocusChangeListener on any given + // focus manager once. Note that hash_map<FocusManager*, int>::operator[] + // will initialize the ref count to zero if it's not already in the map. + if (focus_manager_ref_count_[focus_manager] == 0) { + focus_manager->AddFocusChangeListener(this); + } + focus_manager_ref_count_[focus_manager]++; + + view_info_map_[view].focus_manager = focus_manager; + return true; +} + +void AccessibilityEventRouterViews::RemoveViewTree(View* view) { + DCHECK(view_tree_profile_map_.find(view) != + view_tree_profile_map_.end()); + view_tree_profile_map_.erase(view); + + // Decrement the ref count of the focus manager, and remove this object + // as a listener if the count reaches zero. + FocusManager* focus_manager = view_info_map_[view].focus_manager; + DCHECK(focus_manager); + focus_manager_ref_count_[focus_manager]--; + if (focus_manager_ref_count_[focus_manager] == 0) { + focus_manager->RemoveFocusChangeListener(this); + } +} + +void AccessibilityEventRouterViews::IgnoreView(View* view) { + view_info_map_[view].ignore = true; +} + +void AccessibilityEventRouterViews::SetViewName(View* view, std::string name) { + view_info_map_[view].name = name; +} + +void AccessibilityEventRouterViews::RemoveView(View* view) { + DCHECK(view_info_map_.find(view) != view_info_map_.end()); + view_info_map_.erase(view); +} + +// +// views::FocusChangeListener +// + +void AccessibilityEventRouterViews::FocusWillChange( + View* focused_before, View* focused_now) { + if (focused_now) { + DispatchAccessibilityNotification( + focused_now, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); + } +} + +// +// Private methods +// + +void AccessibilityEventRouterViews::FindView( + View* view, Profile** profile, bool* is_accessible) { + *is_accessible = false; + + // First see if it's a descendant of an accessible view. + for (base::hash_map<View*, Profile*>::const_iterator iter = + view_tree_profile_map_.begin(); + iter != view_tree_profile_map_.end(); + ++iter) { + if (iter->first->IsParentOf(view)) { + *is_accessible = true; + if (profile) + *profile = iter->second; + break; + } + } + if (!*is_accessible) + return; + + // Now make sure it's not marked as a widget to be ignored. + base::hash_map<View*, ViewInfo>::const_iterator iter = + view_info_map_.find(view); + if (iter != view_info_map_.end() && iter->second.ignore) + *is_accessible = false; +} + +std::string AccessibilityEventRouterViews::GetViewName(View* view) { + std::string name; + + // First see if we have a name registered for this view. + base::hash_map<View*, ViewInfo>::const_iterator iter = + view_info_map_.find(view); + if (iter != view_info_map_.end()) + name = iter->second.name; + + // Otherwise ask the view for its accessible name. + if (name.empty()) { + std::wstring wname; + view->GetAccessibleName(&wname); + name = WideToUTF8(wname); + } + + return name; +} + +void AccessibilityEventRouterViews::DispatchAccessibilityNotification( + View* view, NotificationType type) { + Profile* profile = NULL; + bool is_accessible; + FindView(view, &profile, &is_accessible); + if (!is_accessible) + return; + + if (view->GetClassName() == views::ImageButton::kViewClassName) { + SendButtonNotification(view, type, profile); + } else if (view->GetClassName() == views::NativeButton::kViewClassName) { + SendButtonNotification(view, type, profile); + } else if (view->GetClassName() == views::Link::kViewClassName) { + SendLinkNotification(view, type, profile); + } else if (view->GetClassName() == views::MenuButton::kViewClassName) { + SendMenuNotification(view, type, profile); + } +} + +void AccessibilityEventRouterViews::SendButtonNotification( + View* view, NotificationType type, Profile* profile) { + AccessibilityButtonInfo info(profile, GetViewName(view)); + SendAccessibilityNotification(type, &info); +} + +void AccessibilityEventRouterViews::SendLinkNotification( + View* view, NotificationType type, Profile* profile) { + AccessibilityLinkInfo info(profile, GetViewName(view)); + SendAccessibilityNotification(type, &info); +} + +void AccessibilityEventRouterViews::SendMenuNotification( + View* view, NotificationType type, Profile* profile) { + AccessibilityMenuInfo info(profile, GetViewName(view)); + SendAccessibilityNotification(type, &info); +} diff --git a/chrome/browser/views/accessibility_event_router_views.h b/chrome/browser/views/accessibility_event_router_views.h new file mode 100644 index 0000000..024faf1 --- /dev/null +++ b/chrome/browser/views/accessibility_event_router_views.h @@ -0,0 +1,143 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_ +#define CHROME_BROWSER_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/singleton.h" +#include "base/task.h" +#include "chrome/browser/accessibility_events.h" +#include "views/view.h" +#include "views/widget/root_view.h" + +class Profile; + +// Allows us to use (View*) and (FocusManager*) in a hash_map with gcc. +#if defined(COMPILER_GCC) +namespace __gnu_cxx { +template<> +struct hash<views::FocusManager*> { + size_t operator()(views::FocusManager* focus_manager) const { + return reinterpret_cast<size_t>(focus_manager); + } +}; +template<> +struct hash<views::View*> { + size_t operator()(views::View* view) const { + return reinterpret_cast<size_t>(view); + } +}; +} // namespace __gnu_cxx +#endif // defined(COMPILER_GCC) + +// NOTE: This class is part of the Accessibility Extension API, which lets +// extensions receive accessibility events. It's distinct from code that +// implements platform accessibility APIs like MSAA or ATK. +// +// Singleton class that adds listeners to many views, then sends an +// accessibility notification whenever a relevant event occurs in an +// accessible view. +// +// Views are not accessible by default. When you register a root widget, +// that widget and all of its descendants will start sending accessibility +// event notifications. You can then override the default behavior for +// specific descendants using other methods. +// +// You can use Profile::PauseAccessibilityEvents to prevent a flurry +// of accessibility events when a window is being created or initialized. +class AccessibilityEventRouterViews + : public views::FocusChangeListener { + public: + // Internal information about a particular view to override the + // information we get directly from the view. + struct ViewInfo { + ViewInfo() : ignore(false), focus_manager(NULL) {} + + // If nonempty, will use this name instead of the view's label. + std::string name; + + // If true, will ignore this widget and not send accessibility events. + bool ignore; + + // The focus manager that this view is part of - saved because + // GetFocusManager may not succeed while a view is being deleted. + views::FocusManager* focus_manager; + }; + + // Get the single instance of this class. + static AccessibilityEventRouterViews* GetInstance(); + + // Start sending accessibility events for this view and all of its + // descendants. Notifications will go to the specified profile. + // Returns true on success, false if "view" was already registered. + // It is the responsibility of the caller to call RemoveViewTree if + // this view is ever deleted; consider using AccessibleViewHelper. + bool AddViewTree(views::View* view, Profile* profile); + + // Stop sending accessibility events for this view and all of its + // descendants. + void RemoveViewTree(views::View* view); + + // Don't send any events for this view. + void IgnoreView(views::View* view); + + // Use the following string as the name of this view, instead of the + // gtk label associated with the view. + void SetViewName(views::View* view, std::string name); + + // Forget all information about this view. + void RemoveView(views::View* view); + + // Implementation of views::FocusChangeListener: + virtual void FocusWillChange( + views::View* focused_before, views::View* focused_now); + + private: + // Given a view, determine if it's part of a view tree that's mapped to + // a profile and if so, if it's marked as accessible. + void FindView(views::View* view, Profile** profile, bool* is_accessible); + + // Checks the type of the view and calls one of the more specific + // Send*Notification methods, below. + void DispatchAccessibilityNotification( + views::View* view, NotificationType type); + + // Return the name of a view. + std::string GetViewName(views::View* view); + + // Each of these methods constructs an AccessibilityControlInfo object + // and sends a notification of a specific accessibility event. + void SendButtonNotification( + views::View* view, NotificationType type, Profile* profile); + void SendLinkNotification( + views::View* view, NotificationType type, Profile* profile); + void SendMenuNotification( + views::View* view, NotificationType type, Profile* profile); + + private: + AccessibilityEventRouterViews(); + virtual ~AccessibilityEventRouterViews(); + + friend struct DefaultSingletonTraits<AccessibilityEventRouterViews>; + + // The set of all view tree roots; only descendants of these will generate + // accessibility notifications. + base::hash_map<views::View*, Profile*> view_tree_profile_map_; + + // Extra information about specific views. + base::hash_map<views::View*, ViewInfo> view_info_map_; + + // Count of the number of references to each focus manager. + base::hash_map<views::FocusManager*, int> focus_manager_ref_count_; + + // Used to defer handling of some events until the next time + // through the event loop. + ScopedRunnableMethodFactory<AccessibilityEventRouterViews> method_factory_; +}; + +#endif // CHROME_BROWSER_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_ diff --git a/chrome/browser/views/accessibility_event_router_views_unittest.cc b/chrome/browser/views/accessibility_event_router_views_unittest.cc new file mode 100644 index 0000000..11b5303c --- /dev/null +++ b/chrome/browser/views/accessibility_event_router_views_unittest.cc @@ -0,0 +1,126 @@ +// Copyright (c) 2010 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 <string> + +#include "base/message_loop.h" +#include "chrome/browser/extensions/extension_accessibility_api.h" +#include "chrome/browser/views/accessibility_event_router_views.h" +#include "chrome/browser/views/accessible_view_helper.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_service.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "views/controls/button/native_button.h" +#include "views/grid_layout.h" +#include "views/widget/root_view.h" +#include "views/window/window.h" + +#if defined(OS_WIN) +#include "views/widget/widget_win.h" +#elif defined(OS_LINUX) +#include "views/widget/widget_gtk.h" +#endif + +#if defined(TOOLKIT_VIEWS) + +class AccessibilityEventRouterViewsTest + : public testing::Test, + public NotificationObserver { + public: + views::Widget* CreateWidget() { +#if defined(OS_WIN) + return new views::WidgetWin(); +#elif defined(OS_LINUX) + return new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); +#endif + } + protected: + // Implement NotificationObserver::Observe and store information about a + // ACCESSIBILITY_CONTROL_FOCUSED event. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + ASSERT_EQ(type.value, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); + const AccessibilityControlInfo* info = + Details<const AccessibilityControlInfo>(details).ptr(); + focus_event_count_++; + last_control_name_ = info->name(); + } + + MessageLoopForUI message_loop_; + int focus_event_count_; + std::string last_control_name_; +}; + +TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) { + const char kButton1ASCII[] = "Button1"; + const char kButton2ASCII[] = "Button2"; + const char kButton3ASCII[] = "Button3"; + + // Create a window and layout. + views::Widget* window = CreateWidget(); + window->Init(NULL, gfx::Rect(0, 0, 100, 100)); + views::RootView* root_view = window->GetRootView(); + views::GridLayout* layout = new views::GridLayout(root_view); + root_view->SetLayoutManager(layout); + views::ColumnSet* column_set = layout->AddColumnSet(0); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + + // Add 3 buttons. + views::NativeButton* button1 = new views::NativeButton( + NULL, ASCIIToWide(kButton1ASCII)); + layout->StartRow(0, 0); + layout->AddView(button1); + views::NativeButton* button2 = new views::NativeButton( + NULL, ASCIIToWide(kButton2ASCII)); + layout->StartRow(0, 0); + layout->AddView(button2); + views::NativeButton* button3 = new views::NativeButton( + NULL, ASCIIToWide(kButton3ASCII)); + layout->StartRow(0, 0); + layout->AddView(button3); + + // Set focus to the first button initially. + button1->RequestFocus(); + + // Start listening to ACCESSIBILITY_CONTROL_FOCUSED notifications. + NotificationRegistrar registrar; + registrar.Add(this, + NotificationType::ACCESSIBILITY_CONTROL_FOCUSED, + NotificationService::AllSources()); + + // Switch on accessibility event notifications. + TestingProfile profile; + ExtensionAccessibilityEventRouter* accessibility_event_router = + ExtensionAccessibilityEventRouter::GetInstance(); + accessibility_event_router->SetAccessibilityEnabled(true); + + // Create an AccessibleViewHelper for this window, which will send + // accessibility notifications for all events that happen in child views. + // Tell it to ignore button 3. + AccessibleViewHelper accessible_view_helper(root_view, &profile); + accessible_view_helper.IgnoreView(button3); + + // Advance focus to the next button and test that we got the + // expected notification with the name of button 2. + views::FocusManager* focus_manager = window->GetFocusManager(); + focus_event_count_ = 0; + focus_manager->AdvanceFocus(false); + EXPECT_EQ(1, focus_event_count_); + EXPECT_EQ(kButton2ASCII, last_control_name_); + + // Advance to button 3. We expect no notification because we told it + // to ignore this view. + focus_manager->AdvanceFocus(false); + EXPECT_EQ(1, focus_event_count_); + + // Advance to button 1 and check the notification. + focus_manager->AdvanceFocus(false); + EXPECT_EQ(2, focus_event_count_); + EXPECT_EQ(kButton1ASCII, last_control_name_); +} + +#endif // defined(TOOLKIT_VIEWS) diff --git a/chrome/browser/views/accessible_view_helper.cc b/chrome/browser/views/accessible_view_helper.cc new file mode 100644 index 0000000..8a42515 --- /dev/null +++ b/chrome/browser/views/accessible_view_helper.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2010 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 "chrome/browser/views/accessible_view_helper.h" + +#include "app/l10n_util.h" +#include "chrome/browser/accessibility_events.h" +#include "chrome/browser/profile.h" +#include "chrome/common/notification_service.h" + +using views::View; + +AccessibleViewHelper::AccessibleViewHelper( + View* view_tree, Profile* profile) + : accessibility_event_router_(AccessibilityEventRouterViews::GetInstance()), + profile_(profile), + view_tree_(view_tree) { + if (!accessibility_event_router_->AddViewTree(view_tree_, profile)) + view_tree_ = NULL; +} + +AccessibleViewHelper::~AccessibleViewHelper() { + if (!window_title_.empty()) { + AccessibilityWindowInfo info(profile_, window_title_); + NotificationService::current()->Notify( + NotificationType::ACCESSIBILITY_WINDOW_CLOSED, + Source<Profile>(profile_), + Details<AccessibilityWindowInfo>(&info)); + } + + if (view_tree_) { + accessibility_event_router_->RemoveViewTree(view_tree_); + for (std::vector<views::View*>::iterator iter = managed_views_.begin(); + iter != managed_views_.end(); ++iter) + accessibility_event_router_->RemoveView(*iter); + } +} + +void AccessibleViewHelper::SendOpenWindowNotification( + const std::string& window_title) { + window_title_ = window_title; + AccessibilityWindowInfo info(profile_, window_title); + NotificationService::current()->Notify( + NotificationType::ACCESSIBILITY_WINDOW_OPENED, + Source<Profile>(profile_), + Details<AccessibilityWindowInfo>(&info)); +} + +void AccessibleViewHelper::IgnoreView(View* view) { + if (!view_tree_) + return; + + accessibility_event_router_->IgnoreView(view); + managed_views_.push_back(view); +} + +void AccessibleViewHelper::SetViewName(View* view, std::string name) { + if (!view_tree_) + return; + + accessibility_event_router_->SetViewName(view, name); + managed_views_.push_back(view); +} + +void AccessibleViewHelper::SetViewName(View* view, int string_id) { + if (!view_tree_) + return; + + std::string name = l10n_util::GetStringUTF8(string_id); + accessibility_event_router_->SetViewName(view, name); + managed_views_.push_back(view); +} diff --git a/chrome/browser/views/accessible_view_helper.h b/chrome/browser/views/accessible_view_helper.h new file mode 100644 index 0000000..c5c1e15 --- /dev/null +++ b/chrome/browser/views/accessible_view_helper.h @@ -0,0 +1,69 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_VIEWS_ACCESSIBLE_VIEW_HELPER_H_ +#define CHROME_BROWSER_VIEWS_ACCESSIBLE_VIEW_HELPER_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/singleton.h" +#include "chrome/browser/accessibility_events.h" +#include "chrome/browser/views/accessibility_event_router_views.h" + +class Profile; + +// NOTE: This class is part of the Accessibility Extension API, which lets +// extensions receive accessibility events. It's distinct from code that +// implements platform accessibility APIs like MSAA or ATK. +// +// Helper class that helps to manage the accessibility information for a +// view and all of its descendants. Create an instance of this class for +// the root of a tree of views (like a dialog) that should send accessibility +// events for all of its descendants. +// +// Most controls have default behavior for accessibility; when this needs +// to be augmented, call one of the methods below to ignore a particular +// view or change its details. +// +// All of the information managed by this class is registered with the +// (global) AccessibilityEventRouterViews and unregistered when this object is +// destroyed. +class AccessibleViewHelper { + public: + // Constructs an AccessibleViewHelper that makes the given view and all + // of its descendants accessible for the lifetime of this object, + // sending accessibility notifications to the given profile. + AccessibleViewHelper(views::View* view_tree, Profile* profile); + + virtual ~AccessibleViewHelper(); + + // Sends a notification that a new window was opened now, and a + // corresponding close window notification when this object + // goes out of scope. + void SendOpenWindowNotification(const std::string& window_title); + + // Will not send accessibility events for this view. + void IgnoreView(views::View* view); + + // Uses the following string as the name of this view, instead of + // view->GetAccessibleName(). + void SetViewName(views::View* view, std::string name); + + // Uses the following string id as the name of this view, instead of + // view->GetAccessibleName(). + void SetViewName(views::View* view, int string_id); + + private: + AccessibilityEventRouterViews* accessibility_event_router_; + Profile* profile_; + views::View* view_tree_; + std::string window_title_; + std::vector<views::View*> managed_views_; + + DISALLOW_COPY_AND_ASSIGN(AccessibleViewHelper); +}; + +#endif // CHROME_BROWSER_VIEWS_ACCESSIBLE_VIEW_HELPER_H_ diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index dba7844..f96964a 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -27,6 +27,7 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/view_ids.h" +#include "chrome/browser/views/accessible_view_helper.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/browser/views/browser_dialogs.h" #include "chrome/browser/views/download_shelf_view.h" @@ -640,6 +641,9 @@ bool BrowserView::IsPositionInWindowCaption(const gfx::Point& point) { // BrowserView, BrowserWindow implementation: void BrowserView::Show() { + accessible_view_helper_.reset(new AccessibleViewHelper( + this, browser_->profile())); + #if defined(OS_LINUX) if (!accessible_widget_helper_.get()) { accessible_widget_helper_.reset(new AccessibleWidgetHelper( diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 8b6c120..1e5b361 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -35,6 +35,7 @@ // NOTE: For more information about the objects and files in this directory, // view: http://dev.chromium.org/developers/design-documents/browser-window +class AccessibleViewHelper; class BookmarkBarView; class Browser; class BrowserBubble; @@ -573,6 +574,7 @@ class BrowserView : public BrowserBubbleHost, UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; + scoped_ptr<AccessibleViewHelper> accessible_view_helper_; #if defined(OS_LINUX) scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; #endif diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 2d96990..3f84b65 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2121,8 +2121,12 @@ 'browser/views/about_network_dialog.h', 'browser/views/accelerator_table_gtk.cc', 'browser/views/accelerator_table_gtk.h', + 'browser/views/accessibility_event_router_views.cc', + 'browser/views/accessibility_event_router_views.h', 'browser/views/accessible_toolbar_view.cc', 'browser/views/accessible_toolbar_view.h', + 'browser/views/accessible_view_helper.cc', + 'browser/views/accessible_view_helper.h', 'browser/views/app_launcher.cc', 'browser/views/app_launcher.h', 'browser/views/appcache_info_view.cc', @@ -2777,13 +2781,17 @@ ['include', '^browser/extensions/'], ['include', '^browser/views/about_chrome_view.cc'], ['include', '^browser/views/about_chrome_view.h'], - ['include', '^browser/views/app_launcher.cc'], - ['include', '^browser/views/app_launcher.h'], ['include', '^browser/views/accelerator_table_gtk.cc'], ['include', '^browser/views/accelerator_table_gtk.h'], + ['include', '^browser/views/accessibility_event_router_views.cc'], + ['include', '^browser/views/accessibility_event_router_views.h'], ['include', '^browser/views/accessible_toolbar_view.cc'], ['include', '^browser/views/accessible_toolbar_view.h'], + ['include', '^browser/views/accessible_view_helper.cc'], + ['include', '^browser/views/accessible_view_helper.h'], ['include', '^browser/views/app_launcher.cc'], + ['include', '^browser/views/app_launcher.cc'], + ['include', '^browser/views/app_launcher.h'], ['include', '^browser/views/app_launcher.h'], ['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.cc'], ['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.h'], diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index dc8cb1e..2c2a577 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -933,6 +933,7 @@ 'browser/translate/translate_manager_unittest.cc', 'browser/theme_resources_util_unittest.cc', 'browser/user_style_sheet_watcher_unittest.cc', + 'browser/views/accessibility_event_router_views_unittest.cc', 'browser/views/bookmark_context_menu_test.cc', 'browser/views/bookmark_editor_view_unittest.cc', 'browser/views/extensions/browser_action_drag_data_unittest.cc', @@ -1085,6 +1086,7 @@ 'sources!': [ # Blocked on bookmark manager. 'browser/bookmarks/bookmark_context_menu_controller_unittest.cc', + 'browser/views/accessibility_event_router_views_unittest.cc', 'browser/views/bookmark_context_menu_test.cc', 'browser/gtk/go_button_gtk_unittest.cc', 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', |