diff options
author | dtseng@chromium.org <dtseng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-13 18:50:10 +0000 |
---|---|---|
committer | dtseng@chromium.org <dtseng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-13 18:50:10 +0000 |
commit | 1dbadbd465e5cce4031dd20eb901ac7da2d67668 (patch) | |
tree | 83f16e5657ccc3a17c6059f72dbba171fce8c478 /chrome | |
parent | fd21468f5e0b3d8523a6ad93e337e27632c2b1b6 (diff) | |
download | chromium_src-1dbadbd465e5cce4031dd20eb901ac7da2d67668.zip chromium_src-1dbadbd465e5cce4031dd20eb901ac7da2d67668.tar.gz chromium_src-1dbadbd465e5cce4031dd20eb901ac7da2d67668.tar.bz2 |
Refactoring of BrowserAccessibility (Mac) to use cross platform base classes.
BUG=none
TEST=passing unit tests.
Review URL: http://codereview.chromium.org/3696003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62431 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
13 files changed, 407 insertions, 131 deletions
diff --git a/chrome/browser/accessibility/browser_accessibility.h b/chrome/browser/accessibility/browser_accessibility.h index bdf374e..62cffb5 100644 --- a/chrome/browser/accessibility/browser_accessibility.h +++ b/chrome/browser/accessibility/browser_accessibility.h @@ -15,7 +15,9 @@ #include "webkit/glue/webaccessibility.h" class BrowserAccessibilityManager; -#if defined(OS_WIN) +#if defined(OS_MACOSX) +class BrowserAccessibilityMac; +#elif defined(OS_WIN) class BrowserAccessibilityWin; #endif @@ -97,7 +99,9 @@ class BrowserAccessibility { int32 index_in_parent() const { return index_in_parent_; } WebKit::WebRect location() const { return location_; } -#if defined(OS_WIN) +#if defined(OS_MACOSX) + BrowserAccessibilityMac* toBrowserAccessibilityMac(); +#elif defined(OS_WIN) BrowserAccessibilityWin* toBrowserAccessibilityWin(); #endif diff --git a/chrome/browser/accessibility/browser_accessibility_mac.h b/chrome/browser/accessibility/browser_accessibility_mac.h new file mode 100644 index 0000000..136be99 --- /dev/null +++ b/chrome/browser/accessibility/browser_accessibility_mac.h @@ -0,0 +1,59 @@ +// 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_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MAC_H_ +#define CHROME_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MAC_H_ +#pragma once + +#include <map> +#include <utility> +#include <vector> + +#include "chrome/browser/accessibility/browser_accessibility.h" + +@class BrowserAccessibilityCocoa; + +class BrowserAccessibilityMac : public BrowserAccessibility { + public: + // Implementation of BrowserAccessibility. + virtual void Initialize(); + virtual void ReleaseReference(); + + // Accessers that allow the cocoa wrapper to read these values. + const string16& name() const { return name_; } + const string16& value() const { return value_; } + const std::map<int32, string16>& attributes() const { return attributes_; } + + const std::vector<std::pair<string16, string16> >& html_attributes() const { + return html_attributes_; + } + + int32 role() const { return role_; } + int32 state() const { return state_; } + const string16& role_name() const { return role_name_; } + + // Accesser and setter for + // the BrowserAccessibilityCocoa associated with us. + BrowserAccessibilityCocoa* native_view() const { + return browser_accessibility_cocoa_; + } + + void native_view(BrowserAccessibilityCocoa* v) { + browser_accessibility_cocoa_ = v; + } + + private: + // This gives BrowserAccessibility::Create access to the class constructor. + friend class BrowserAccessibility; + + BrowserAccessibilityMac(); + + // Allows access to the BrowserAccessibilityCocoa which wraps this. + // BrowserAccessibility. We only initialize this member if the accessibility + // API requests this object. + BrowserAccessibilityCocoa* browser_accessibility_cocoa_; + DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityMac); +}; + +#endif // CHROME_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MAC_H_ diff --git a/chrome/browser/accessibility/browser_accessibility_mac.mm b/chrome/browser/accessibility/browser_accessibility_mac.mm new file mode 100644 index 0000000..1a6c1d4 --- /dev/null +++ b/chrome/browser/accessibility/browser_accessibility_mac.mm @@ -0,0 +1,27 @@ +// 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 "chrome/browser/accessibility/browser_accessibility_mac.h" + +// Static. +BrowserAccessibility* BrowserAccessibility::Create() { + return new BrowserAccessibilityMac(); +} + +BrowserAccessibilityMac::BrowserAccessibilityMac() { +} + +// TODO(dtseng): ensure we create BrowserAccessibilityCocoa here +// (RenderWidgetHostViewCocoa to BrowserAccessibilityManagerMac refactoring). +void BrowserAccessibilityMac::Initialize() { +} + +// TODO(dtseng): ensure we cleanup BrowserAccessibilityCocoa and this class. +// (RenderWidgetHostViewCocoa to BrowserAccessibilityManagerMac refactoring). +void BrowserAccessibilityMac::ReleaseReference() { +} + +BrowserAccessibilityMac* BrowserAccessibility::toBrowserAccessibilityMac() { + return static_cast<BrowserAccessibilityMac*>(this); +} diff --git a/chrome/browser/accessibility/browser_accessibility_manager.cc b/chrome/browser/accessibility/browser_accessibility_manager.cc index c663666..eb17e6e 100644 --- a/chrome/browser/accessibility/browser_accessibility_manager.cc +++ b/chrome/browser/accessibility/browser_accessibility_manager.cc @@ -140,6 +140,13 @@ void BrowserAccessibilityManager::OnAccessibilityObjectFocusChange( focus_ = new_browser_acc; if (delegate_ && delegate_->HasFocus()) GotFocus(); + // Mac currently does not have a BrowserAccessibilityDelegate. + else if (!delegate_) { + NotifyAccessibilityEvent( + ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_FOCUS_CHANGED, + focus_); + } } void BrowserAccessibilityManager::OnAccessibilityObjectLoadComplete( diff --git a/chrome/browser/accessibility/browser_accessibility_manager_mac.h b/chrome/browser/accessibility/browser_accessibility_manager_mac.h new file mode 100644 index 0000000..892de15 --- /dev/null +++ b/chrome/browser/accessibility/browser_accessibility_manager_mac.h @@ -0,0 +1,33 @@ +// 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_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_MAC_H_ +#define CHROME_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_MAC_H_ +#pragma once + +#import <Cocoa/Cocoa.h> + +#include "chrome/browser/accessibility/browser_accessibility_manager.h" + +class BrowserAccessibilityManagerMac : public BrowserAccessibilityManager { + public: + // Implementation of BrowserAccessibilityManager. + virtual void NotifyAccessibilityEvent( + ViewHostMsg_AccessibilityNotification_Params::NotificationType n, + BrowserAccessibility* node); + + private: + // This gives BrowserAccessibilityManager::Create access to the class + // constructor. + friend class BrowserAccessibilityManager; + + BrowserAccessibilityManagerMac(gfx::NativeView parent_view, + const webkit_glue::WebAccessibility& src, + BrowserAccessibilityDelegate* delegate, + BrowserAccessibilityFactory* factory); + + DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerMac); +}; + +#endif // CHROME_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_MAC_H_ diff --git a/chrome/browser/accessibility/browser_accessibility_manager_mac.mm b/chrome/browser/accessibility/browser_accessibility_manager_mac.mm new file mode 100644 index 0000000..8aadf8b --- /dev/null +++ b/chrome/browser/accessibility/browser_accessibility_manager_mac.mm @@ -0,0 +1,80 @@ +// 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/accessibility/browser_accessibility_manager_mac.h" + +#include "chrome/browser/accessibility/browser_accessibility_mac.h" +#import "chrome/browser/cocoa/browser_accessibility.h" +// TODO(dtseng): move to delegate? +#import "chrome/browser/renderer_host/render_widget_host_view_mac.h" + +// static +BrowserAccessibilityManager* BrowserAccessibilityManager::Create( + gfx::NativeView parent_view, + const WebAccessibility& src, + BrowserAccessibilityDelegate* delegate, + BrowserAccessibilityFactory* factory) { + return new BrowserAccessibilityManagerMac( + parent_view, src, delegate, factory); +} + +BrowserAccessibility* BrowserAccessibilityFactory::Create() { + return BrowserAccessibility::Create(); +} + +BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac( + gfx::NativeView parent_window, + const webkit_glue::WebAccessibility& src, + BrowserAccessibilityDelegate* delegate, + BrowserAccessibilityFactory* factory) + : BrowserAccessibilityManager(parent_window, src, delegate, factory) { +} + +void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent( + ViewHostMsg_AccessibilityNotification_Params::NotificationType n, + BrowserAccessibility* node) { + // TODO(dtseng): support all notifications. + NSString* event_id = @""; + switch (n) { + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_CHECK_STATE_CHANGED: + return; + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_CHILDREN_CHANGED: + event_id = NSAccessibilityValueChangedNotification; + if (GetRoot() == node) + [((RenderWidgetHostViewCocoa*)GetParentView()) + setAccessibilityTreeRoot:GetRoot()]; + else + [node->GetParent()->toBrowserAccessibilityMac()->native_view() + updateDescendants]; + break; + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_FOCUS_CHANGED: + event_id = NSAccessibilityFocusedUIElementChangedNotification; + if (GetRoot() == node) + [((RenderWidgetHostViewCocoa*)GetParentView()) + setAccessibilityTreeRoot:GetRoot()]; + else + [node->GetParent()->toBrowserAccessibilityMac()->native_view() + updateDescendants]; + break; + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_LOAD_COMPLETE: + [((RenderWidgetHostViewCocoa*)GetParentView()) + setAccessibilityTreeRoot:GetRoot()]; + return; + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_VALUE_CHANGED: + event_id = NSAccessibilityValueChangedNotification; + break; + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED: + return; + } + BrowserAccessibilityCocoa* native_node = node->toBrowserAccessibilityMac()-> + native_view(); + DCHECK(native_node); + NSAccessibilityPostNotification(native_node, event_id); +} diff --git a/chrome/browser/cocoa/browser_accessibility.h b/chrome/browser/cocoa/browser_accessibility.h index 32af50e..7a6fdb4 100644 --- a/chrome/browser/cocoa/browser_accessibility.h +++ b/chrome/browser/cocoa/browser_accessibility.h @@ -2,40 +2,45 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_H -#define CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_H +#ifndef CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_H_ +#define CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_H_ #pragma once #import <Cocoa/Cocoa.h> #import "base/scoped_nsobject.h" +#include "chrome/browser/accessibility/browser_accessibility_mac.h" #import "chrome/browser/cocoa/browser_accessibility_delegate.h" -#include "webkit/glue/webaccessibility.h" -using webkit_glue::WebAccessibility; - -// BrowserAccessibility is a cocoa wrapper around the WebAccessibility +// BrowserAccessibilityCocoa is a cocoa wrapper around the BrowserAccessibility // object. The renderer converts webkit's accessibility tree into a // WebAccessibility tree and passes it to the browser process over IPC. // This class converts it into a format Cocoa can query. -@interface BrowserAccessibility : NSObject { +@interface BrowserAccessibilityCocoa : NSObject { @private - WebAccessibility webAccessibility_; - id<BrowserAccessibilityDelegate> delegate_; + BrowserAccessibility* browserAccessibility_; + id<BrowserAccessibilityDelegateCocoa> delegate_; scoped_nsobject<NSMutableArray> children_; // The parent of the accessibility object. This can be another - // BrowserAccessibility or a RenderWidgetHostViewCocoa. + // BrowserAccessibilityCocoa or a RenderWidgetHostViewCocoa. id parent_; // weak } // This creates a cocoa browser accessibility object around -// the webkit glue WebAccessibility object. The delegate is +// the cross platform BrowserAccessibility object. The delegate is // used to communicate with the host renderer. None of these // parameters can be null. -- (id)initWithObject:(const WebAccessibility&)accessibility - delegate:(id<BrowserAccessibilityDelegate>)delegate +- (id)initWithObject:(BrowserAccessibility*)accessibility + delegate:(id<BrowserAccessibilityDelegateCocoa>)delegate parent:(id)parent; +// Updates children from backing BrowserAccessibility. +- (NSArray*)updateChildren; +// Updates all descendants from the backing BrowserAccessibility. +- (void)updateDescendants; + +@property(nonatomic, readonly) BrowserAccessibility* browserAccessibility; + // Children is an array of BrowserAccessibility objects, representing // the accessibility children of this object. @property(nonatomic, readonly) NSArray* children; @@ -54,4 +59,4 @@ using webkit_glue::WebAccessibility; @end -#endif // CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_H +#endif // CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_H_ diff --git a/chrome/browser/cocoa/browser_accessibility.mm b/chrome/browser/cocoa/browser_accessibility.mm index 06b9cfb..abef731 100644 --- a/chrome/browser/cocoa/browser_accessibility.mm +++ b/chrome/browser/cocoa/browser_accessibility.mm @@ -13,8 +13,6 @@ #include "grit/webkit_strings.h" #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" -using webkit_glue::WebAccessibility; - namespace { // Returns an autoreleased copy of the WebAccessibility's attribute. @@ -59,67 +57,89 @@ static const RoleEntry roles[] = { // GetState checks the bitmask used in webaccessibility.h to check // if the given state was set on the accessibility object. -bool GetState(WebAccessibility accessibility, int state) { - return ((accessibility.state >> state) & 1); +bool GetState(BrowserAccessibility* accessibility, int state) { + // TODO(dtseng): add accesser. + return ((accessibility->toBrowserAccessibilityMac()->state() >> + state) & 1); } } // namespace -@implementation BrowserAccessibility +@implementation BrowserAccessibilityCocoa -- (id)initWithObject:(const WebAccessibility&)accessibility - delegate:(id<BrowserAccessibilityDelegate>)delegate +- (id)initWithObject:(BrowserAccessibility*)accessibility + delegate:(id<BrowserAccessibilityDelegateCocoa>)delegate parent:(id)parent { if ((self = [super init])) { - webAccessibility_ = accessibility; + browserAccessibility_ = accessibility; parent_ = parent; delegate_ = delegate; + // Set the proper native view for the new object? + browserAccessibility_->toBrowserAccessibilityMac()->native_view(self); } return self; } -// Returns an array of BrowserAccessibility objects, representing the +- (BrowserAccessibility*)browserAccessibility { + return browserAccessibility_; +} + +// Returns an array of BrowserAccessibilityCocoa objects, representing the // accessibility children of this object. - (NSArray*)children { if (!children_.get()) { - const std::vector<WebAccessibility>& accessibilityChildren = - webAccessibility_.children; - children_.reset( - [[NSMutableArray alloc] - initWithCapacity:accessibilityChildren.size()]); - std::vector<WebAccessibility>::const_iterator iterator; - for (iterator = accessibilityChildren.begin(); - iterator != accessibilityChildren.end(); - ++iterator) { - scoped_nsobject<BrowserAccessibility> child( - [[BrowserAccessibility alloc] - initWithObject:*iterator - delegate:delegate_ - parent:self]); - [children_ addObject:child]; - } + return [self updateChildren]; + } else { + return children_.get(); } +} + +- (NSArray*)updateChildren { + children_.reset( + [[NSMutableArray alloc] + initWithCapacity:browserAccessibility_->GetChildCount()]); + for (uint32 index = 0; + index < browserAccessibility_->GetChildCount(); + ++index) { + scoped_nsobject<BrowserAccessibilityCocoa> child( + [[BrowserAccessibilityCocoa alloc] + initWithObject:browserAccessibility_->GetChild(index) + delegate:delegate_ + parent:self]); + [children_ addObject:child]; + } return children_; } +- (void)updateDescendants { + NSArray* newChildren = [self updateChildren]; + for (uint32 i = 0; i < [newChildren count]; ++i) { + [(BrowserAccessibilityCocoa*)[newChildren objectAtIndex:i] + updateDescendants]; + } +} + // Returns whether or not this node should be ignored in the // accessibility tree. - (BOOL)isIgnored { - return webAccessibility_.role == WebAccessibility::ROLE_IGNORED; + return browserAccessibility_->toBrowserAccessibilityMac()->role() == + WebAccessibility::ROLE_IGNORED; } // The origin of this accessibility object in the page's document. // This is relative to webkit's top-left origin, not Cocoa's // bottom-left origin. - (NSPoint)origin { - return NSMakePoint(webAccessibility_.location.x, - webAccessibility_.location.y); + return NSMakePoint(browserAccessibility_->location().x, + browserAccessibility_->location().y); } // Returns a string indicating the role of this object. - (NSString*)role { NSString* role = NSAccessibilityUnknownRole; - WebAccessibility::Role value = webAccessibility_.role; + WebAccessibility::Role value = + static_cast<WebAccessibility::Role>( browserAccessibility_-> + toBrowserAccessibilityMac()->role()); const size_t numRoles = sizeof(roles) / sizeof(roles[0]); for (size_t i = 0; i < numRoles; ++i) { if (roles[i].value == value) { @@ -147,18 +167,21 @@ bool GetState(WebAccessibility accessibility, int state) { // Returns the size of this object. - (NSSize)size { - return NSMakeSize(webAccessibility_.location.width, - webAccessibility_.location.height); + return NSMakeSize(browserAccessibility_->location().width, + browserAccessibility_->location().height); } // Returns the accessibility value for the given attribute. If the value isn't // supported this will return nil. - (id)accessibilityAttributeValue:(NSString*)attribute { + BrowserAccessibilityMac* browserAccessibilityMac = browserAccessibility_-> + toBrowserAccessibilityMac(); if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) { return [self role]; } if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) { - return NSStringForWebAccessibilityAttribute(webAccessibility_.attributes, + return NSStringForWebAccessibilityAttribute( + browserAccessibilityMac->attributes(), WebAccessibility::ATTR_DESCRIPTION); } if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) { @@ -180,23 +203,25 @@ bool GetState(WebAccessibility accessibility, int state) { } } if ([attribute isEqualToString:NSAccessibilityTitleAttribute]) { - return base::SysUTF16ToNSString(webAccessibility_.name); + return base::SysUTF16ToNSString(browserAccessibilityMac->name()); } if ([attribute isEqualToString:NSAccessibilityHelpAttribute]) { - return NSStringForWebAccessibilityAttribute(webAccessibility_.attributes, - WebAccessibility::ATTR_HELP); + return NSStringForWebAccessibilityAttribute( + browserAccessibilityMac->attributes(), + WebAccessibility::ATTR_HELP); } if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { - return base::SysUTF16ToNSString(webAccessibility_.value); + return base::SysUTF16ToNSString(browserAccessibilityMac->value()); } if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) { return [self roleDescription]; } if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { NSNumber* ret = [NSNumber numberWithBool: - GetState(webAccessibility_, WebAccessibility::STATE_FOCUSED)]; + GetState(browserAccessibility_, WebAccessibility::STATE_FOCUSED)]; return ret; } + // TODO(dtseng): provide complete implementations for the following. if ([attribute isEqualToString:NSAccessibilityEnabledAttribute] || [attribute isEqualToString:@"AXVisited"] || [attribute isEqualToString:@"AXLoaded"]) { @@ -261,16 +286,10 @@ bool GetState(WebAccessibility accessibility, int state) { nil]; } -// Returns the deepest child that has user focus. -// TODO(feldstein): This does not work yet. -- (id)accessibilityFocusedUIElement { - return self; -} - // Returns the index of the child in this objects array of children. - (NSUInteger)accessibilityIndexOfChild:(id)child { NSUInteger index = 0; - for (BrowserAccessibility* childToCheck in [self children]) { + for (BrowserAccessibilityCocoa* childToCheck in [self children]) { if ([child isEqual:childToCheck]) return index; if (![childToCheck isIgnored]) @@ -283,9 +302,9 @@ bool GetState(WebAccessibility accessibility, int state) { // accessibility API via |accessibilitySetValue:forAttribute:|. - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute { if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) - return GetState(webAccessibility_, WebAccessibility::STATE_FOCUSABLE); + return GetState(browserAccessibility_, WebAccessibility::STATE_FOCUSABLE); if ([attribute isEqualToString:NSAccessibilityValueAttribute]) - return !GetState(webAccessibility_, WebAccessibility::STATE_READONLY); + return !GetState(browserAccessibility_, WebAccessibility::STATE_READONLY); return NO; } @@ -299,7 +318,7 @@ bool GetState(WebAccessibility accessibility, int state) { // that backs this object. - (void)accessibilityPerformAction:(NSString*)action { // TODO(feldstein): Support more actions. - [delegate_ doDefaultAction:webAccessibility_.id]; + [delegate_ doDefaultAction:browserAccessibility_->renderer_id()]; } // Returns the description of the given action. @@ -320,7 +339,7 @@ bool GetState(WebAccessibility accessibility, int state) { NSNumber* focusedNumber = value; BOOL focused = [focusedNumber intValue]; [delegate_ setAccessibilityFocus:focused - accessibilityId:webAccessibility_.id]; + accessibilityId:browserAccessibility_->renderer_id()]; } } @@ -348,13 +367,13 @@ bool GetState(WebAccessibility accessibility, int state) { } - (BOOL)isEqual:(id)object { - if (![object isKindOfClass:[BrowserAccessibility class]]) + if (![object isKindOfClass:[BrowserAccessibilityCocoa class]]) return NO; return ([self hash] == [object hash]); } - (NSUInteger)hash { - return webAccessibility_.id; + return browserAccessibility_->renderer_id(); } @end diff --git a/chrome/browser/cocoa/browser_accessibility_delegate.h b/chrome/browser/cocoa/browser_accessibility_delegate.h index 800174d91..3ee821c 100644 --- a/chrome/browser/cocoa/browser_accessibility_delegate.h +++ b/chrome/browser/cocoa/browser_accessibility_delegate.h @@ -2,22 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_DELEGATE_H -#define CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_DELEGATE_H +#ifndef CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_DELEGATE_H_ +#define CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_DELEGATE_H_ #pragma once -@class BrowserAccessibility; +@class BrowserAccessibilityCocoa; @class NSWindow; // This protocol is used by the BrowserAccessibility objects to pass messages // to, or otherwise communicate with, their underlying WebAccessibility // objects over the IPC boundary. -@protocol BrowserAccessibilityDelegate -- (NSPoint)accessibilityPointInScreen:(BrowserAccessibility*)accessibility; +@protocol BrowserAccessibilityDelegateCocoa +- (NSPoint)accessibilityPointInScreen:(BrowserAccessibilityCocoa*)accessibility; - (void)doDefaultAction:(int32)accessibilityObjectId; - (void)setAccessibilityFocus:(BOOL)focus accessibilityId:(int32)accessibilityObjectId; - (NSWindow*)window; @end -#endif // CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_DELEGATE_H +#endif // CHROME_BROWSER_COCOA_BROWSER_ACCESSIBILITY_DELEGATE_H_ diff --git a/chrome/browser/cocoa/browser_accessibility_unittest.mm b/chrome/browser/cocoa/browser_accessibility_unittest.mm index 104c26e..27bee1a 100644 --- a/chrome/browser/cocoa/browser_accessibility_unittest.mm +++ b/chrome/browser/cocoa/browser_accessibility_unittest.mm @@ -6,14 +6,16 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/accessibility/browser_accessibility_mac.h" #include "chrome/browser/cocoa/browser_accessibility.h" #include "chrome/browser/cocoa/cocoa_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" -@interface MockAccessibilityDelegate : NSObject<BrowserAccessibilityDelegate> +@interface MockAccessibilityDelegate : + NSObject<BrowserAccessibilityDelegateCocoa> -- (NSPoint)accessibilityPointInScreen:(BrowserAccessibility*)accessibility; +- (NSPoint)accessibilityPointInScreen:(BrowserAccessibilityCocoa*)accessibility; - (void)doDefaultAction:(int32)accessibilityObjectId; - (void)setAccessibilityFocus:(BOOL)focus accessibilityId:(int32)accessibilityObjectId; @@ -23,7 +25,8 @@ @implementation MockAccessibilityDelegate -- (NSPoint)accessibilityPointInScreen:(BrowserAccessibility*)accessibility { +- (NSPoint)accessibilityPointInScreen: + (BrowserAccessibilityCocoa*)accessibility { return NSZeroPoint; } - (void)doDefaultAction:(int32)accessibilityObjectId { @@ -62,24 +65,50 @@ class BrowserAccessibilityTest : public CocoaTest { child2.location.width = 250; child2.location.height = 100; - root.children.push_back(child1); - root.children.push_back(child2); + // TODO(dtseng): use BrowserAccessibilityManagerMac once it manages + // these objects. + BrowserAccessibility* rootBrowserAccessibility = + BrowserAccessibility::Create(); + BrowserAccessibility* child1BrowserAccessibility = + BrowserAccessibility::Create(); + BrowserAccessibility* child2BrowserAccessibility = + BrowserAccessibility::Create(); + + rootBrowserAccessibility->Initialize(NULL, + NULL, + 0, + 0, + root); + child1BrowserAccessibility->Initialize(NULL, + NULL, + 0, + 0, + child1); + child2BrowserAccessibility->Initialize(NULL, + NULL, + 0, + 0, + child2); + + rootBrowserAccessibility->AddChild(child1BrowserAccessibility); + rootBrowserAccessibility->AddChild(child2BrowserAccessibility); delegate_.reset([[MockAccessibilityDelegate alloc] init]); accessibility_.reset( - [[BrowserAccessibility alloc] initWithObject:root - delegate:delegate_ - parent:delegate_]); + [[BrowserAccessibilityCocoa alloc] + initWithObject:rootBrowserAccessibility + delegate:delegate_ + parent:delegate_]); } protected: scoped_nsobject<MockAccessibilityDelegate> delegate_; - scoped_nsobject<BrowserAccessibility> accessibility_; + scoped_nsobject<BrowserAccessibilityCocoa> accessibility_; }; // Standard hit test. TEST_F(BrowserAccessibilityTest, HitTestTest) { - BrowserAccessibility* firstChild = + BrowserAccessibilityCocoa* firstChild = [accessibility_ accessibilityHitTest:NSMakePoint(50, 50)]; EXPECT_NSEQ(@"Child1", [firstChild accessibilityAttributeValue:NSAccessibilityTitleAttribute]); @@ -87,7 +116,7 @@ TEST_F(BrowserAccessibilityTest, HitTestTest) { // Test doing a hit test on the edge of a child. TEST_F(BrowserAccessibilityTest, EdgeHitTest) { - BrowserAccessibility* firstChild = + BrowserAccessibilityCocoa* firstChild = [accessibility_ accessibilityHitTest:NSMakePoint(0, 0)]; EXPECT_NSEQ(@"Child1", [firstChild accessibilityAttributeValue:NSAccessibilityTitleAttribute]); @@ -97,7 +126,7 @@ TEST_F(BrowserAccessibilityTest, EdgeHitTest) { // the hit test has been narrowed down to this object or one of its children // so it should return itself since it has no better hit result. TEST_F(BrowserAccessibilityTest, InvalidHitTestCoordsTest) { - BrowserAccessibility* hitTestResult = + BrowserAccessibilityCocoa* hitTestResult = [accessibility_ accessibilityHitTest:NSMakePoint(-50, 50)]; EXPECT_NSEQ(accessibility_, hitTestResult); } diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index 16a78fc..f41ae8d 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -13,6 +13,7 @@ #include "base/scoped_ptr.h" #include "base/task.h" #include "base/time.h" +#include "chrome/browser/accessibility/browser_accessibility_manager.h" #include "chrome/browser/cocoa/base_view.h" #include "chrome/browser/cocoa/browser_accessibility.h" #include "chrome/browser/cocoa/browser_accessibility_delegate.h" @@ -41,16 +42,15 @@ class RWHVMEditCommandHelper; : BaseView <RenderWidgetHostViewMacOwner, NSTextInput, NSChangeSpelling, - BrowserAccessibilityDelegate> { + BrowserAccessibilityDelegateCocoa> { @private scoped_ptr<RenderWidgetHostViewMac> renderWidgetHostView_; BOOL canBeKeyView_; BOOL takesFocusOnlyOnMouseDown_; BOOL closeOnDeactivate_; - BOOL rendererAccessible_; - BOOL accessibilityRequested_; - BOOL accessibilityReceived_; scoped_ptr<RWHVMEditCommandHelper> editCommand_helper_; + + // TODO(dtseng): refactor to BrowserAccessibilityManagerMac. scoped_nsobject<NSArray> accessibilityChildren_; // These are part of the magic tooltip code from WebKit's WebHTMLView: @@ -142,7 +142,7 @@ class RWHVMEditCommandHelper; // Cancel ongoing composition (abandon the marked text). - (void)cancelComposition; // Set the new accessibility tree. -- (void)setAccessibilityTree:(const webkit_glue::WebAccessibility&) tree; +- (void)setAccessibilityTreeRoot:(BrowserAccessibility*) treeRoot; // Confirm ongoing composition. - (void)confirmComposition; @@ -220,8 +220,10 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { virtual void WindowFrameChanged(); virtual void SetBackground(const SkBitmap& background); virtual bool ContainsNativeView(gfx::NativeView native_view) const; - virtual void UpdateAccessibilityTree( - const webkit_glue::WebAccessibility& tree); + + virtual void OnAccessibilityNotifications( + const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params); + // Methods associated with GPU-accelerated plug-in instances and the // accelerated compositor. virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(bool opaque, @@ -274,6 +276,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { // paint requests by expanding the invalid rect rather than actually painting. bool about_to_validate_and_paint_; + scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_; + // This is true when we have already scheduled a call to // |-callSetNeedsDisplayInRect:| but it has not been fulfilled yet. Used to // prevent us from scheduling multiple calls. @@ -344,9 +348,6 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { // Used for positioning a popup menu. NSView* parent_view_; - // Whether or not web accessibility is enabled. - bool renderer_accessible_; - // selected text on the renderer. std::string selected_text_; diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index 768de34..e6a6ba6 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -444,10 +444,9 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) initWithRenderWidgetHostViewMac:this] autorelease]; render_widget_host_->set_view(this); - // Turn on accessibility only if one or both of these flags is true. - renderer_accessible_ = IsVoiceOverRunning() || - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kForceRendererAccessibility); + // Turn on accessibility only if VoiceOver is running. + if (IsVoiceOverRunning()) + render_widget_host_->EnableRendererAccessibility(); } RenderWidgetHostViewMac::~RenderWidgetHostViewMac() { @@ -1151,11 +1150,20 @@ bool RenderWidgetHostViewMac::ContainsNativeView( return false; } -void RenderWidgetHostViewMac::UpdateAccessibilityTree( - const webkit_glue::WebAccessibility& tree) { - if (renderer_accessible_) { - [cocoa_view_ setAccessibilityTree:tree]; +void RenderWidgetHostViewMac::OnAccessibilityNotifications( + const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) { + if (!browser_accessibility_manager_.get()) { + // Use empty document to process notifications + webkit_glue::WebAccessibility empty_document; + empty_document.role = WebAccessibility::ROLE_WEB_AREA; + empty_document.state = 0; + browser_accessibility_manager_.reset( + BrowserAccessibilityManager::Create(cocoa_view_, empty_document, NULL)); + // TODO(dtseng): refactor to BrowserAccessibilityManagerMac. + [cocoa_view_ + setAccessibilityTreeRoot:browser_accessibility_manager_->GetRoot()]; } + browser_accessibility_manager_->OnAccessibilityNotifications(params); } void RenderWidgetHostViewMac::SetTextInputActive(bool active) { @@ -1186,12 +1194,6 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { canBeKeyView_ = YES; takesFocusOnlyOnMouseDown_ = NO; closeOnDeactivate_ = NO; - - rendererAccessible_ = - !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableRendererAccessibility); - accessibilityRequested_ = NO; - accessibilityReceived_ = NO; } return self; } @@ -1771,14 +1773,15 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { // Create the BrowserAccessibility tree from the WebAccessibility tree passed // from the renderer. -- (void)setAccessibilityTree:(const webkit_glue::WebAccessibility&) tree { - BrowserAccessibility* root = - [[BrowserAccessibility alloc] initWithObject:tree - delegate:self - parent:self]; +// TODO(dtseng): refactor to BrowserAccessibilityManagerMac. +- (void)setAccessibilityTreeRoot:(BrowserAccessibility*) treeRoot { + BrowserAccessibilityCocoa* root = + [[BrowserAccessibilityCocoa alloc] initWithObject:treeRoot + delegate:self + parent:self]; [root autorelease]; accessibilityChildren_.reset([[NSArray alloc] initWithObjects:root, nil]); - accessibilityReceived_ = YES; + [root updateDescendants]; } - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute @@ -1798,36 +1801,23 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { } - (id)accessibilityAttributeValue:(NSString *)attribute { - if (!accessibilityRequested_) { - renderWidgetHostView_->render_widget_host_->EnableRendererAccessibility(); - accessibilityRequested_ = YES; - } - if (accessibilityReceived_) { - if (rendererAccessible_ && - [attribute isEqualToString:NSAccessibilityChildrenAttribute]) { + if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { + // TODO(dtseng): refactor to BrowserAccessibilityManagerMac. return accessibilityChildren_.get(); } else if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) { return NSAccessibilityScrollAreaRole; } - } id ret = [super accessibilityAttributeValue:attribute]; return ret; } - (id)accessibilityHitTest:(NSPoint)point { - if (!accessibilityRequested_) { - renderWidgetHostView_->render_widget_host_->EnableRendererAccessibility(); - accessibilityRequested_ = YES; - } - if (!accessibilityReceived_) { - return self; - } NSPoint pointInWindow = [[self window] convertScreenToBase:point]; NSPoint localPoint = [self convertPoint:pointInWindow fromView:nil]; localPoint.y = NSHeight([self bounds]) - localPoint.y; if ([accessibilityChildren_ count] == 0) return self; - BrowserAccessibility* root = [accessibilityChildren_ objectAtIndex:0]; + BrowserAccessibilityCocoa* root = [accessibilityChildren_ objectAtIndex:0]; id obj = [root accessibilityHitTest:localPoint]; return obj; } @@ -1840,6 +1830,23 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { return [accessibilityChildren_ indexOfObject:child]; } +- (id)accessibilityFocusedUIElement { + BrowserAccessibilityManager* manager = + renderWidgetHostView_->browser_accessibility_manager_.get(); + if (manager) { + BrowserAccessibility* focused_item = manager->GetFocus(NULL); + DCHECK(focused_item); + if (focused_item) { + BrowserAccessibilityCocoa* focused_item_cocoa = + focused_item->toBrowserAccessibilityMac()->native_view(); + DCHECK(focused_item_cocoa); + if (focused_item_cocoa) + return focused_item_cocoa; + } + } + return [super accessibilityFocusedUIElement]; +} + - (void)doDefaultAction:(int32)accessibilityObjectId { renderWidgetHostView_->render_widget_host_-> AccessibilityDoDefaultAction(accessibilityObjectId); @@ -1847,7 +1854,8 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { // Convert a web accessibility's location in web coordinates into a cocoa // screen coordinate. -- (NSPoint)accessibilityPointInScreen:(BrowserAccessibility*)accessibility { +- (NSPoint)accessibilityPointInScreen: + (BrowserAccessibilityCocoa*)accessibility { NSPoint origin = [accessibility origin]; NSSize size = [accessibility size]; origin.y = NSHeight([self bounds]) - origin.y; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index db6aa60..8b898be 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -65,6 +65,10 @@ 'browser/accessibility/browser_accessibility_state.h', 'browser/accessibility/browser_accessibility_manager.cc', 'browser/accessibility/browser_accessibility_manager.h', + 'browser/accessibility/browser_accessibility_manager_mac.h', + 'browser/accessibility/browser_accessibility_manager_mac.mm', + 'browser/accessibility/browser_accessibility_mac.h', + 'browser/accessibility/browser_accessibility_mac.mm', 'browser/accessibility/browser_accessibility_manager_win.cc', 'browser/accessibility/browser_accessibility_manager_win.h', 'browser/accessibility/browser_accessibility_win.cc', |