1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #import "config.h" 27 #import "AccessibilityWebPageObject.h" 28 29 #import "WebFrame.h" 30 #import "WebPage.h" 31 #import <WebCore/AXObjectCache.h> 32 #import <WebCore/Frame.h> 33 #import <WebCore/FrameView.h> 34 #import <WebCore/ScrollView.h> 35 #import <WebCore/Scrollbar.h> 36 #import <WebKitSystemInterface.h> 37 38 using namespace WebCore; 39 using namespace WebKit; 40 41 @implementation AccessibilityWebPageObject 42 43 - (id)accessibilityRootObjectWrapper 44 { 45 WebCore::Page* page = m_page->corePage(); 46 if (!page) 47 return nil; 48 49 WebCore::Frame* core = page->mainFrame(); 50 if (!core || !core->document()) 51 return nil; 52 53 AccessibilityObject* root = core->document()->axObjectCache()->rootObject(); 54 if (!root) 55 return nil; 56 57 return root->wrapper(); 58 } 59 60 - (void)setWebPage:(WebPage*)page 61 { 62 m_page = page; 63 } 64 65 - (void)setRemoteParent:(id)parent 66 { 67 if (parent != m_parent) { 68 [m_parent release]; 69 m_parent = [parent retain]; 70 } 71 } 72 73 - (void)dealloc 74 { 75 WKUnregisterUniqueIdForElement(self); 76 [m_accessibilityChildren release]; 77 [m_attributeNames release]; 78 [m_parent release]; 79 [super dealloc]; 80 } 81 82 - (BOOL)accessibilityIsIgnored 83 { 84 return NO; 85 } 86 87 - (NSArray *)accessibilityAttributeNames 88 { 89 if (!m_attributeNames) 90 m_attributeNames = [[NSArray alloc] initWithObjects: 91 NSAccessibilityRoleAttribute, NSAccessibilityRoleDescriptionAttribute, NSAccessibilityFocusedAttribute, 92 NSAccessibilityParentAttribute, NSAccessibilityWindowAttribute, NSAccessibilityTopLevelUIElementAttribute, 93 NSAccessibilityPositionAttribute, NSAccessibilitySizeAttribute, NSAccessibilityChildrenAttribute, nil]; 94 95 return m_attributeNames; 96 } 97 98 - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute 99 { 100 return NO; 101 } 102 103 - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute 104 { 105 return; 106 } 107 108 - (NSArray *)accessibilityActionNames 109 { 110 return [NSArray array]; 111 } 112 113 - (NSArray *)accessibilityChildren 114 { 115 id wrapper = [self accessibilityRootObjectWrapper]; 116 if (!wrapper) 117 return [NSArray array]; 118 119 return [NSArray arrayWithObject:wrapper]; 120 } 121 122 - (id)accessibilityAttributeValue:(NSString *)attribute 123 { 124 if (!WebCore::AXObjectCache::accessibilityEnabled()) 125 WebCore::AXObjectCache::enableAccessibility(); 126 127 if ([attribute isEqualToString:NSAccessibilityParentAttribute]) 128 return m_parent; 129 if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) 130 return [m_parent accessibilityAttributeValue:NSAccessibilityWindowAttribute]; 131 if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) 132 return [m_parent accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; 133 if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) 134 return NSAccessibilityGroupRole; 135 if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) 136 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, nil); 137 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) 138 return [NSNumber numberWithBool:NO]; 139 140 if (!m_page) 141 return nil; 142 143 if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) { 144 WebCore::IntPoint point = m_page->accessibilityPosition(); 145 return [NSValue valueWithPoint:NSMakePoint(point.x(), point.y())]; 146 } 147 if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) { 148 const IntSize& s = m_page->size(); 149 return [NSValue valueWithSize:NSMakeSize(s.width(), s.height())]; 150 } 151 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) 152 return [self accessibilityChildren]; 153 154 return [super accessibilityAttributeValue:attribute]; 155 } 156 157 - (BOOL)accessibilityShouldUseUniqueId 158 { 159 return YES; 160 } 161 162 - (id)accessibilityHitTest:(NSPoint)point 163 { 164 // Hit-test point comes in as bottom-screen coordinates. Needs to be normalized to the frame of the web page. 165 NSPoint remotePosition = [[self accessibilityAttributeValue:NSAccessibilityPositionAttribute] pointValue]; 166 NSSize remoteSize = [[self accessibilityAttributeValue:NSAccessibilitySizeAttribute] sizeValue]; 167 168 // Get the y position of the WKView (we have to screen-flip and go from bottom left to top left). 169 CGFloat screenHeight = [[[NSScreen screens] objectAtIndex:0] frame].size.height; 170 remotePosition.y = (screenHeight - remotePosition.y) - remoteSize.height; 171 172 point.y = screenHeight - point.y; 173 174 // Re-center point into the web page's frame. 175 point.y -= remotePosition.y; 176 point.x -= remotePosition.x; 177 178 if (m_page && m_page->mainFrame() && m_page->mainFrame()->coreFrame()) { 179 WebCore::FrameView* fv = m_page->mainFrame()->coreFrame()->view(); 180 if (fv) { 181 point.y += fv->scrollPosition().y(); 182 point.x += fv->scrollPosition().x(); 183 } 184 } 185 186 return [[self accessibilityRootObjectWrapper] accessibilityHitTest:point]; 187 } 188 189 - (id)accessibilityFocusedUIElement 190 { 191 return [[self accessibilityRootObjectWrapper] accessibilityFocusedUIElement]; 192 } 193 194 195 @end 196