summaryrefslogtreecommitdiffstats
path: root/chrome/browser/accessibility
diff options
context:
space:
mode:
authordtseng@chromium.org <dtseng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-24 03:09:44 +0000
committerdtseng@chromium.org <dtseng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-24 03:09:44 +0000
commit5f5d58a9635023d87a8acbe11c4aacc4fb387e14 (patch)
treeb0d17bb1f5e424e60d08709d9d9fbdae551c9416 /chrome/browser/accessibility
parentce163a942cce41d1774eac0bee0056b90464fd15 (diff)
downloadchromium_src-5f5d58a9635023d87a8acbe11c4aacc4fb387e14.zip
chromium_src-5f5d58a9635023d87a8acbe11c4aacc4fb387e14.tar.gz
chromium_src-5f5d58a9635023d87a8acbe11c4aacc4fb387e14.tar.bz2
Reland 66893.
TBR=dtseng Review URL: http://codereview.chromium.org/5326003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67208 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/accessibility')
-rw-r--r--chrome/browser/accessibility/accessibility_mac_uitest.mm202
1 files changed, 202 insertions, 0 deletions
diff --git a/chrome/browser/accessibility/accessibility_mac_uitest.mm b/chrome/browser/accessibility/accessibility_mac_uitest.mm
new file mode 100644
index 0000000..45cdd11
--- /dev/null
+++ b/chrome/browser/accessibility/accessibility_mac_uitest.mm
@@ -0,0 +1,202 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/ui/ui_test.h"
+
+// The following tests exercise the Chrome Mac accessibility implementation
+// similarly to the way in which VoiceOver would.
+// We achieve this by utilizing the same carbon API (HIServices) as do
+// other assistive technologies.
+// Note that the tests must be UITests since these API's only work if not
+// called within the same process begin examined.
+class AccessibilityMacUITest : public UITest {
+ public:
+ AccessibilityMacUITest() {
+ // TODO(dtseng): fake the VoiceOver defaults value?
+ launch_arguments_.AppendSwitch(switches::kForceRendererAccessibility);
+ }
+
+ virtual void SetUp() {
+ UITest::SetUp();
+ SetupObservedNotifications();
+ Initialize();
+ }
+
+ // Called to insert an event for validation.
+ // This is a order sensitive expectation.
+ void AddExpectedEvent(NSString* notificationName) {
+ [AccessibilityMacUITest::expectedEvents addObject:notificationName];
+ }
+
+ // Assert that there are no remaining expected events.
+ // CFRunLoop necessary to receive AX callbacks.
+ // Assumes that there is at least one expected event.
+ // The runloop stops only if we receive all expected notifications.
+ void WaitAndAssertAllEventsObserved() {
+ ASSERT_GE([expectedEvents count], 1U);
+ CFRunLoopRunInMode(
+ kCFRunLoopDefaultMode, action_max_timeout_ms()/1000, false);
+ ASSERT_EQ(0U, [AccessibilityMacUITest::expectedEvents count]);
+ }
+
+ // The Callback handler added to each AXUIElement.
+ static void EventReceiver(
+ AXObserverRef observerRef,
+ AXUIElementRef element,
+ CFStringRef notificationName,
+ void *refcon) {
+ if ([[AccessibilityMacUITest::expectedEvents objectAtIndex:0]
+ isEqualToString:(NSString*)notificationName]) {
+ [AccessibilityMacUITest::expectedEvents removeObjectAtIndex:0];
+ }
+
+ if ([AccessibilityMacUITest::expectedEvents count] == 0) {
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ }
+
+ // TODO(dtseng): currently refreshing on all notifications; scope later.
+ AccessibilityMacUITest::SetAllObserversOnDescendants(
+ element, observerRef);
+ }
+
+ private:
+ // Perform AX setup.
+ void Initialize() {
+ AccessibilityMacUITest::expectedEvents.reset([[NSMutableArray alloc] init]);
+
+ // Construct the Chrome AXUIElementRef.
+ ASSERT_NE(-1, browser_process_id());
+ AXUIElementRef browserUiElement =
+ AXUIElementCreateApplication(browser_process_id());
+ ASSERT_TRUE(browserUiElement);
+
+ // Setup our callbacks.
+ AXObserverRef observerRef;
+ ASSERT_EQ(kAXErrorSuccess,
+ AXObserverCreate(browser_process_id(),
+ AccessibilityMacUITest::EventReceiver,
+ &observerRef));
+ SetAllObserversOnDescendants(browserUiElement, observerRef);
+
+ // Add the observer to the current message loop.
+ CFRunLoopAddSource(
+ [[NSRunLoop currentRunLoop] getCFRunLoop],
+ AXObserverGetRunLoopSource(observerRef),
+ kCFRunLoopDefaultMode);
+ }
+
+ // Taken largely from AXNotificationConstants.h
+ // (substituted NSAccessibility* to avoid casting).
+ static void SetupObservedNotifications() {
+ AccessibilityMacUITest::observedNotifications.reset(
+ [[NSArray alloc] initWithObjects:
+
+ // focus notifications
+ NSAccessibilityMainWindowChangedNotification,
+ NSAccessibilityFocusedWindowChangedNotification,
+ NSAccessibilityFocusedUIElementChangedNotification,
+
+ // application notifications
+ NSAccessibilityApplicationActivatedNotification,
+ NSAccessibilityApplicationDeactivatedNotification,
+ NSAccessibilityApplicationHiddenNotification,
+ NSAccessibilityApplicationShownNotification,
+
+ // window notifications
+ NSAccessibilityWindowCreatedNotification,
+ NSAccessibilityWindowMovedNotification,
+ NSAccessibilityWindowResizedNotification,
+ NSAccessibilityWindowMiniaturizedNotification,
+ NSAccessibilityWindowDeminiaturizedNotification,
+
+ // new drawer, sheet, and help tag notifications
+ NSAccessibilityDrawerCreatedNotification,
+ NSAccessibilitySheetCreatedNotification,
+ NSAccessibilityHelpTagCreatedNotification,
+
+ // element notifications
+ NSAccessibilityValueChangedNotification,
+ NSAccessibilityUIElementDestroyedNotification,
+
+ // menu notifications
+ (NSString*)kAXMenuOpenedNotification,
+ (NSString*)kAXMenuClosedNotification,
+ (NSString*)kAXMenuItemSelectedNotification,
+
+ // table/outline notifications
+ NSAccessibilityRowCountChangedNotification,
+
+ // other notifications
+ NSAccessibilitySelectedChildrenChangedNotification,
+ NSAccessibilityResizedNotification,
+ NSAccessibilityMovedNotification,
+ NSAccessibilityCreatedNotification,
+ NSAccessibilitySelectedRowsChangedNotification,
+ NSAccessibilitySelectedColumnsChangedNotification,
+ NSAccessibilitySelectedTextChangedNotification,
+ NSAccessibilityTitleChangedNotification,
+
+ // Webkit specific notifications.
+ @"AXLoadComplete",
+ nil]);
+ }
+
+ // Observe AX notifications on element and all descendants.
+ static void SetAllObserversOnDescendants(
+ AXUIElementRef element,
+ AXObserverRef observerRef) {
+ SetAllObservers(element, observerRef);
+ CFTypeRef childrenRef;
+ if ((AXUIElementCopyAttributeValue(
+ element, kAXChildrenAttribute, &childrenRef)) == kAXErrorSuccess) {
+ NSArray* children = (NSArray*)childrenRef;
+ for (uint32 i = 0; i < [children count]; ++i) {
+ SetAllObserversOnDescendants(
+ (AXUIElementRef)[children objectAtIndex:i], observerRef);
+ }
+ }
+ }
+
+ // Add observers for all notifications we know about.
+ static void SetAllObservers(
+ AXUIElementRef element,
+ AXObserverRef observerRef) {
+ for (NSString* notification in
+ AccessibilityMacUITest::observedNotifications.get()) {
+ AXObserverAddNotification(
+ observerRef, element, (CFStringRef)notification, nil);
+ }
+ }
+
+ // Used to keep track of events received during the lifetime of the tests.
+ static scoped_nsobject<NSMutableArray> expectedEvents;
+ // NSString collection of all AX notifications.
+ static scoped_nsobject<NSArray> observedNotifications;
+};
+
+scoped_nsobject<NSMutableArray> AccessibilityMacUITest::expectedEvents;
+scoped_nsobject<NSArray> AccessibilityMacUITest::observedNotifications;
+
+TEST_F(AccessibilityMacUITest, TestInitialPageNotifications) {
+ // Test for initial page load.
+ AddExpectedEvent(@"AXLoadComplete");
+ WaitAndAssertAllEventsObserved();
+
+ // Browse to a new page.
+ GURL tree_url(
+ "data:text/html,<html><head><title>Accessibility Mac Test</title></head>"
+ "<body><input type='button' value='push' /><input type='checkbox' />"
+ "</body></html>");
+ NavigateToURLAsync(tree_url);
+
+ // Test for navigation.
+ AddExpectedEvent(@"AXLoadComplete");
+
+ // Check all the expected Mac notifications.
+ WaitAndAssertAllEventsObserved();
+}