| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
| 6 | 6 |
| 7 #include "base/memory/scoped_nsobject.h" | 7 #include "base/memory/scoped_nsobject.h" |
| 8 #include "base/test/test_timeouts.h" | 8 #include "base/test/test_timeouts.h" |
| 9 #include "chrome/common/chrome_switches.h" | 9 #include "chrome/common/chrome_switches.h" |
| 10 #include "chrome/test/ui/ui_test.h" | 10 #include "chrome/test/ui/ui_test.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 virtual void SetUp() { | 25 virtual void SetUp() { |
| 26 UITest::SetUp(); | 26 UITest::SetUp(); |
| 27 SetupObservedNotifications(); | 27 SetupObservedNotifications(); |
| 28 Initialize(); | 28 Initialize(); |
| 29 } | 29 } |
| 30 | 30 |
| 31 // Called to insert an event for validation. | 31 // Called to insert an event for validation. |
| 32 // This is a order sensitive expectation. | 32 // This is a order sensitive expectation. |
| 33 void AddExpectedEvent(NSString* notificationName) { | 33 void AddExpectedEvent(NSString* notificationName) { |
| 34 [AccessibilityMacUITest::expectedEvents addObject:notificationName]; | 34 [expectedEvents_ addObject:notificationName]; |
| 35 } | 35 } |
| 36 | 36 |
| 37 // Assert that there are no remaining expected events. | 37 // Assert that there are no remaining expected events. |
| 38 // CFRunLoop necessary to receive AX callbacks. | 38 // CFRunLoop necessary to receive AX callbacks. |
| 39 // Assumes that there is at least one expected event. | 39 // Assumes that there is at least one expected event. |
| 40 // The runloop stops only if we receive all expected notifications. | 40 // The runloop stops only if we receive all expected notifications. |
| 41 void WaitAndAssertAllEventsObserved() { | 41 void WaitAndAssertAllEventsObserved() { |
| 42 ASSERT_GE([expectedEvents count], 1U); | 42 ASSERT_GE([expectedEvents_ count], 1U); |
| 43 CFRunLoopRunInMode( | 43 CFRunLoopRunInMode( |
| 44 kCFRunLoopDefaultMode, | 44 kCFRunLoopDefaultMode, |
| 45 TestTimeouts::action_max_timeout_ms() / 1000, false); | 45 TestTimeouts::action_max_timeout_ms() / 1000, false); |
| 46 ASSERT_EQ(0U, [AccessibilityMacUITest::expectedEvents count]); | 46 ASSERT_EQ(0U, [expectedEvents_ count]); |
| 47 } | 47 } |
| 48 | 48 |
| 49 // The Callback handler added to each AXUIElement. | 49 // The Callback handler added to each AXUIElement. |
| 50 static void EventReceiver( | 50 static void EventReceiver( |
| 51 AXObserverRef observerRef, | 51 AXObserverRef observerRef, |
| 52 AXUIElementRef element, | 52 AXUIElementRef element, |
| 53 CFStringRef notificationName, | 53 CFStringRef notificationName, |
| 54 void *refcon) { | 54 void *refcon) { |
| 55 if ([[AccessibilityMacUITest::expectedEvents objectAtIndex:0] | 55 AccessibilityMacUITest* this_pointer = |
| 56 reinterpret_cast<AccessibilityMacUITest*>(refcon); |
| 57 if ([[this_pointer->expectedEvents_ objectAtIndex:0] |
| 56 isEqualToString:(NSString*)notificationName]) { | 58 isEqualToString:(NSString*)notificationName]) { |
| 57 [AccessibilityMacUITest::expectedEvents removeObjectAtIndex:0]; | 59 [this_pointer->expectedEvents_ removeObjectAtIndex:0]; |
| 58 } | 60 } |
| 59 | 61 |
| 60 if ([AccessibilityMacUITest::expectedEvents count] == 0) { | 62 if ([this_pointer->expectedEvents_ count] == 0) { |
| 61 CFRunLoopStop(CFRunLoopGetCurrent()); | 63 CFRunLoopStop(CFRunLoopGetCurrent()); |
| 62 } | 64 } |
| 63 | 65 |
| 64 // TODO(dtseng): currently refreshing on all notifications; scope later. | 66 // TODO(dtseng): currently refreshing on all notifications; scope later. |
| 65 AccessibilityMacUITest::SetAllObserversOnDescendants( | 67 this_pointer->SetAllObserversOnDescendants(element, observerRef); |
| 66 element, observerRef); | |
| 67 } | 68 } |
| 68 | 69 |
| 69 private: | 70 private: |
| 70 // Perform AX setup. | 71 // Perform AX setup. |
| 71 void Initialize() { | 72 void Initialize() { |
| 72 AccessibilityMacUITest::expectedEvents.reset([[NSMutableArray alloc] init]); | 73 expectedEvents_.reset([[NSMutableArray alloc] init]); |
| 73 | 74 |
| 74 // Construct the Chrome AXUIElementRef. | 75 // Construct the Chrome AXUIElementRef. |
| 75 ASSERT_NE(-1, browser_process_id()); | 76 ASSERT_NE(-1, browser_process_id()); |
| 76 AXUIElementRef browserUiElement = | 77 AXUIElementRef browserUiElement = |
| 77 AXUIElementCreateApplication(browser_process_id()); | 78 AXUIElementCreateApplication(browser_process_id()); |
| 78 ASSERT_TRUE(browserUiElement); | 79 ASSERT_TRUE(browserUiElement); |
| 79 | 80 |
| 80 // Setup our callbacks. | 81 // Setup our callbacks. |
| 81 AXObserverRef observerRef; | 82 AXObserverRef observerRef; |
| 82 ASSERT_EQ(kAXErrorSuccess, | 83 ASSERT_EQ(kAXErrorSuccess, |
| 83 AXObserverCreate(browser_process_id(), | 84 AXObserverCreate(browser_process_id(), |
| 84 AccessibilityMacUITest::EventReceiver, | 85 AccessibilityMacUITest::EventReceiver, |
| 85 &observerRef)); | 86 &observerRef)); |
| 86 SetAllObserversOnDescendants(browserUiElement, observerRef); | 87 SetAllObserversOnDescendants(browserUiElement, observerRef); |
| 87 | 88 |
| 88 // Add the observer to the current message loop. | 89 // Add the observer to the current message loop. |
| 89 CFRunLoopAddSource( | 90 CFRunLoopAddSource( |
| 90 [[NSRunLoop currentRunLoop] getCFRunLoop], | 91 [[NSRunLoop currentRunLoop] getCFRunLoop], |
| 91 AXObserverGetRunLoopSource(observerRef), | 92 AXObserverGetRunLoopSource(observerRef), |
| 92 kCFRunLoopDefaultMode); | 93 kCFRunLoopDefaultMode); |
| 93 } | 94 } |
| 94 | 95 |
| 95 // Taken largely from AXNotificationConstants.h | 96 // Taken largely from AXNotificationConstants.h |
| 96 // (substituted NSAccessibility* to avoid casting). | 97 // (substituted NSAccessibility* to avoid casting). |
| 97 static void SetupObservedNotifications() { | 98 void SetupObservedNotifications() { |
| 98 AccessibilityMacUITest::observedNotifications.reset( | 99 observedNotifications_.reset( |
| 99 [[NSArray alloc] initWithObjects: | 100 [[NSArray alloc] initWithObjects: |
| 100 | 101 |
| 101 // focus notifications | 102 // focus notifications |
| 102 NSAccessibilityMainWindowChangedNotification, | 103 NSAccessibilityMainWindowChangedNotification, |
| 103 NSAccessibilityFocusedWindowChangedNotification, | 104 NSAccessibilityFocusedWindowChangedNotification, |
| 104 NSAccessibilityFocusedUIElementChangedNotification, | 105 NSAccessibilityFocusedUIElementChangedNotification, |
| 105 | 106 |
| 106 // application notifications | 107 // application notifications |
| 107 NSAccessibilityApplicationActivatedNotification, | 108 NSAccessibilityApplicationActivatedNotification, |
| 108 NSAccessibilityApplicationDeactivatedNotification, | 109 NSAccessibilityApplicationDeactivatedNotification, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 NSAccessibilitySelectedColumnsChangedNotification, | 143 NSAccessibilitySelectedColumnsChangedNotification, |
| 143 NSAccessibilitySelectedTextChangedNotification, | 144 NSAccessibilitySelectedTextChangedNotification, |
| 144 NSAccessibilityTitleChangedNotification, | 145 NSAccessibilityTitleChangedNotification, |
| 145 | 146 |
| 146 // Webkit specific notifications. | 147 // Webkit specific notifications. |
| 147 @"AXLoadComplete", | 148 @"AXLoadComplete", |
| 148 nil]); | 149 nil]); |
| 149 } | 150 } |
| 150 | 151 |
| 151 // Observe AX notifications on element and all descendants. | 152 // Observe AX notifications on element and all descendants. |
| 152 static void SetAllObserversOnDescendants( | 153 void SetAllObserversOnDescendants( |
| 153 AXUIElementRef element, | 154 AXUIElementRef element, |
| 154 AXObserverRef observerRef) { | 155 AXObserverRef observerRef) { |
| 155 SetAllObservers(element, observerRef); | 156 SetAllObservers(element, observerRef); |
| 156 CFTypeRef childrenRef; | 157 CFTypeRef childrenRef; |
| 157 if ((AXUIElementCopyAttributeValue( | 158 if ((AXUIElementCopyAttributeValue( |
| 158 element, kAXChildrenAttribute, &childrenRef)) == kAXErrorSuccess) { | 159 element, kAXChildrenAttribute, &childrenRef)) == kAXErrorSuccess) { |
| 159 NSArray* children = (NSArray*)childrenRef; | 160 NSArray* children = (NSArray*)childrenRef; |
| 160 for (uint32 i = 0; i < [children count]; ++i) { | 161 for (uint32 i = 0; i < [children count]; ++i) { |
| 161 SetAllObserversOnDescendants( | 162 SetAllObserversOnDescendants( |
| 162 (AXUIElementRef)[children objectAtIndex:i], observerRef); | 163 (AXUIElementRef)[children objectAtIndex:i], observerRef); |
| 163 } | 164 } |
| 164 } | 165 } |
| 165 } | 166 } |
| 166 | 167 |
| 167 // Add observers for all notifications we know about. | 168 // Add observers for all notifications we know about. |
| 168 static void SetAllObservers( | 169 void SetAllObservers( |
| 169 AXUIElementRef element, | 170 AXUIElementRef element, |
| 170 AXObserverRef observerRef) { | 171 AXObserverRef observerRef) { |
| 171 for (NSString* notification in | 172 for (NSString* notification in observedNotifications_.get()) { |
| 172 AccessibilityMacUITest::observedNotifications.get()) { | |
| 173 AXObserverAddNotification( | 173 AXObserverAddNotification( |
| 174 observerRef, element, (CFStringRef)notification, nil); | 174 observerRef, element, (CFStringRef)notification, this); |
| 175 } | 175 } |
| 176 } | 176 } |
| 177 | 177 |
| 178 // Used to keep track of events received during the lifetime of the tests. | 178 // Used to keep track of events received during the lifetime of the tests. |
| 179 static scoped_nsobject<NSMutableArray> expectedEvents; | 179 scoped_nsobject<NSMutableArray> expectedEvents_; |
| 180 // NSString collection of all AX notifications. | 180 // NSString collection of all AX notifications. |
| 181 static scoped_nsobject<NSArray> observedNotifications; | 181 scoped_nsobject<NSArray> observedNotifications_; |
| 182 }; | 182 }; |
| 183 | 183 |
| 184 scoped_nsobject<NSMutableArray> AccessibilityMacUITest::expectedEvents; | |
| 185 scoped_nsobject<NSArray> AccessibilityMacUITest::observedNotifications; | |
| 186 | |
| 187 TEST_F(AccessibilityMacUITest, TestInitialPageNotifications) { | 184 TEST_F(AccessibilityMacUITest, TestInitialPageNotifications) { |
| 188 // Browse to a new page. | 185 // Browse to a new page. |
| 189 GURL tree_url( | 186 GURL tree_url( |
| 190 "data:text/html,<html><head><title>Accessibility Mac Test</title></head>" | 187 "data:text/html,<html><head><title>Accessibility Mac Test</title></head>" |
| 191 "<body><input type='button' value='push' /><input type='checkbox' />" | 188 "<body><input type='button' value='push' /><input type='checkbox' />" |
| 192 "</body></html>"); | 189 "</body></html>"); |
| 193 NavigateToURLAsync(tree_url); | 190 NavigateToURLAsync(tree_url); |
| 194 | 191 |
| 195 // Test for navigation. | 192 // Test for navigation. |
| 196 AddExpectedEvent(@"AXLoadComplete"); | 193 AddExpectedEvent(@"AXLoadComplete"); |
| 197 | 194 |
| 198 // Check all the expected Mac notifications. | 195 // Check all the expected Mac notifications. |
| 199 WaitAndAssertAllEventsObserved(); | 196 WaitAndAssertAllEventsObserved(); |
| 200 } | 197 } |
| OLD | NEW |