OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "content/browser/accessibility/browser_accessibility_manager_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
6 | 6 |
7 #include <atlbase.h> | |
8 #include <atlapp.h> | |
9 #include <atlcom.h> | |
10 #include <atlcrack.h> | |
11 #include <oleacc.h> | |
12 | |
13 #include "base/command_line.h" | 7 #include "base/command_line.h" |
14 #include "base/win/scoped_comptr.h" | 8 #include "base/win/scoped_comptr.h" |
15 #include "base/win/windows_version.h" | 9 #include "base/win/windows_version.h" |
16 #include "content/browser/accessibility/browser_accessibility_state_impl.h" | 10 #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
17 #include "content/browser/accessibility/browser_accessibility_win.h" | 11 #include "content/browser/accessibility/browser_accessibility_win.h" |
| 12 #include "content/browser/renderer_host/legacy_render_widget_host_win.h" |
18 #include "content/common/accessibility_messages.h" | 13 #include "content/common/accessibility_messages.h" |
19 | 14 |
20 namespace content { | 15 namespace content { |
21 | 16 |
22 // Some screen readers expect every tab / every unique web content container | |
23 // to be in its own HWND, like it was before Aura, but with Aura there's just | |
24 // one main HWND for a frame, or even for the whole desktop. So, we need a | |
25 // fake HWND as the root of the accessibility tree for each tab. | |
26 // We should get rid of this code when the latest two versions of all | |
27 // supported screen readers no longer make this assumption. | |
28 // | |
29 // This class implements a child HWND with zero size, that delegates its | |
30 // accessibility implementation to the root of the BrowserAccessibilityManager | |
31 // tree. This HWND is hooked up as the parent of the root object in the | |
32 // BrowserAccessibilityManager tree, so when any accessibility client | |
33 // calls ::WindowFromAccessibleObject, they get this HWND instead of the | |
34 // DesktopWindowTreeHostWin. | |
35 class AccessibleHWND | |
36 : public ATL::CWindowImpl<AccessibleHWND, | |
37 ATL::CWindow, | |
38 ATL::CWinTraits<WS_CHILD> > { | |
39 public: | |
40 // Unfortunately, some screen readers look for this exact window class | |
41 // to enable certain features. It'd be great to remove this. | |
42 DECLARE_WND_CLASS_EX(L"Chrome_RenderWidgetHostHWND", CS_DBLCLKS, 0); | |
43 | |
44 BEGIN_MSG_MAP_EX(AccessibleHWND) | |
45 MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject) | |
46 END_MSG_MAP() | |
47 | |
48 AccessibleHWND(HWND parent, BrowserAccessibilityManagerWin* manager) | |
49 : manager_(manager) { | |
50 Create(parent); | |
51 ShowWindow(true); | |
52 MoveWindow(0, 0, 0, 0); | |
53 | |
54 HRESULT hr = ::CreateStdAccessibleObject( | |
55 hwnd(), OBJID_WINDOW, IID_IAccessible, | |
56 reinterpret_cast<void **>(window_accessible_.Receive())); | |
57 DCHECK(SUCCEEDED(hr)); | |
58 } | |
59 | |
60 HWND hwnd() { | |
61 DCHECK(::IsWindow(m_hWnd)); | |
62 return m_hWnd; | |
63 } | |
64 | |
65 IAccessible* window_accessible() { return window_accessible_; } | |
66 | |
67 void OnManagerDeleted() { | |
68 manager_ = NULL; | |
69 } | |
70 | |
71 protected: | |
72 virtual void OnFinalMessage(HWND hwnd) OVERRIDE { | |
73 if (manager_) | |
74 manager_->OnAccessibleHwndDeleted(); | |
75 delete this; | |
76 } | |
77 | |
78 private: | |
79 LRESULT OnGetObject(UINT message, | |
80 WPARAM w_param, | |
81 LPARAM l_param) { | |
82 if (OBJID_CLIENT != l_param || !manager_) | |
83 return static_cast<LRESULT>(0L); | |
84 | |
85 base::win::ScopedComPtr<IAccessible> root( | |
86 manager_->GetRoot()->ToBrowserAccessibilityWin()); | |
87 return LresultFromObject(IID_IAccessible, w_param, | |
88 static_cast<IAccessible*>(root.Detach())); | |
89 } | |
90 | |
91 BrowserAccessibilityManagerWin* manager_; | |
92 base::win::ScopedComPtr<IAccessible> window_accessible_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(AccessibleHWND); | |
95 }; | |
96 | |
97 | |
98 // static | 17 // static |
99 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( | 18 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( |
100 const ui::AXNodeData& src, | 19 const ui::AXNodeData& src, |
101 BrowserAccessibilityDelegate* delegate, | 20 BrowserAccessibilityDelegate* delegate, |
102 BrowserAccessibilityFactory* factory) { | 21 BrowserAccessibilityFactory* factory) { |
103 return new BrowserAccessibilityManagerWin( | 22 return new BrowserAccessibilityManagerWin( |
104 GetDesktopWindow(), NULL, src, delegate, factory); | 23 content::LegacyRenderWidgetHostHWND::Create(GetDesktopWindow()).get(), |
| 24 NULL, src, delegate, factory); |
105 } | 25 } |
106 | 26 |
107 BrowserAccessibilityManagerWin* | 27 BrowserAccessibilityManagerWin* |
108 BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() { | 28 BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() { |
109 return static_cast<BrowserAccessibilityManagerWin*>(this); | 29 return static_cast<BrowserAccessibilityManagerWin*>(this); |
110 } | 30 } |
111 | 31 |
112 BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin( | 32 BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin( |
113 HWND parent_hwnd, | 33 LegacyRenderWidgetHostHWND* accessible_hwnd, |
114 IAccessible* parent_iaccessible, | 34 IAccessible* parent_iaccessible, |
115 const ui::AXNodeData& src, | 35 const ui::AXNodeData& src, |
116 BrowserAccessibilityDelegate* delegate, | 36 BrowserAccessibilityDelegate* delegate, |
117 BrowserAccessibilityFactory* factory) | 37 BrowserAccessibilityFactory* factory) |
118 : BrowserAccessibilityManager(src, delegate, factory), | 38 : BrowserAccessibilityManager(src, delegate, factory), |
119 parent_hwnd_(parent_hwnd), | 39 parent_hwnd_(accessible_hwnd->GetParent()), |
120 parent_iaccessible_(parent_iaccessible), | 40 parent_iaccessible_(parent_iaccessible), |
121 tracked_scroll_object_(NULL), | 41 tracked_scroll_object_(NULL), |
122 accessible_hwnd_(NULL) { | 42 accessible_hwnd_(accessible_hwnd) { |
123 } | 43 } |
124 | 44 |
125 BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() { | 45 BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() { |
126 if (tracked_scroll_object_) { | 46 if (tracked_scroll_object_) { |
127 tracked_scroll_object_->Release(); | 47 tracked_scroll_object_->Release(); |
128 tracked_scroll_object_ = NULL; | 48 tracked_scroll_object_ = NULL; |
129 } | 49 } |
130 if (accessible_hwnd_) | 50 if (accessible_hwnd_) |
131 accessible_hwnd_->OnManagerDeleted(); | 51 accessible_hwnd_->OnManagerDeleted(); |
132 } | 52 } |
133 | 53 |
134 // static | 54 // static |
135 ui::AXNodeData BrowserAccessibilityManagerWin::GetEmptyDocument() { | 55 ui::AXNodeData BrowserAccessibilityManagerWin::GetEmptyDocument() { |
136 ui::AXNodeData empty_document; | 56 ui::AXNodeData empty_document; |
137 empty_document.id = 0; | 57 empty_document.id = 0; |
138 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; | 58 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; |
139 empty_document.state = | 59 empty_document.state = |
140 (1 << blink::WebAXStateEnabled) | | 60 (1 << blink::WebAXStateEnabled) | |
141 (1 << ui::AX_STATE_READONLY) | | 61 (1 << ui::AX_STATE_READONLY) | |
142 (1 << ui::AX_STATE_BUSY); | 62 (1 << ui::AX_STATE_BUSY); |
143 return empty_document; | 63 return empty_document; |
144 } | 64 } |
145 | 65 |
146 void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event, | 66 void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event, |
147 LONG child_id) { | 67 LONG child_id) { |
148 // Don't fire events if this view isn't hooked up to its parent. | 68 // Don't fire events if this view isn't hooked up to its parent. |
149 if (!parent_iaccessible()) | 69 if (!parent_iaccessible()) |
150 return; | 70 return; |
151 | 71 |
152 // If on Win 7 and complete accessibility is enabled, create a fake child HWND | 72 // If on Win 7 and complete accessibility is enabled, use the fake child HWND |
153 // to use as the root of the accessibility tree. See comments above | 73 // to use as the root of the accessibility tree. See comments above |
154 // AccessibleHWND for details. | 74 // LegacyRenderWidgetHostHWND for details. |
155 if (BrowserAccessibilityStateImpl::GetInstance()->IsAccessibleBrowser() && | 75 if (BrowserAccessibilityStateImpl::GetInstance()->IsAccessibleBrowser()) { |
156 !accessible_hwnd_) { | 76 DCHECK(accessible_hwnd_); |
157 accessible_hwnd_ = new AccessibleHWND(parent_hwnd_, this); | 77 accessible_hwnd_->set_browser_accessibility_manager(this); |
158 parent_hwnd_ = accessible_hwnd_->hwnd(); | 78 parent_hwnd_ = accessible_hwnd_->hwnd(); |
159 parent_iaccessible_ = accessible_hwnd_->window_accessible(); | 79 parent_iaccessible_ = accessible_hwnd_->window_accessible(); |
160 } | 80 } |
161 | |
162 ::NotifyWinEvent(event, parent_hwnd(), OBJID_CLIENT, child_id); | 81 ::NotifyWinEvent(event, parent_hwnd(), OBJID_CLIENT, child_id); |
163 } | 82 } |
164 | 83 |
165 void BrowserAccessibilityManagerWin::AddNodeToMap(BrowserAccessibility* node) { | 84 void BrowserAccessibilityManagerWin::AddNodeToMap(BrowserAccessibility* node) { |
166 BrowserAccessibilityManager::AddNodeToMap(node); | 85 BrowserAccessibilityManager::AddNodeToMap(node); |
167 LONG unique_id_win = node->ToBrowserAccessibilityWin()->unique_id_win(); | 86 LONG unique_id_win = node->ToBrowserAccessibilityWin()->unique_id_win(); |
168 unique_id_to_renderer_id_map_[unique_id_win] = node->renderer_id(); | 87 unique_id_to_renderer_id_map_[unique_id_win] = node->renderer_id(); |
169 } | 88 } |
170 | 89 |
171 void BrowserAccessibilityManagerWin::RemoveNode(BrowserAccessibility* node) { | 90 void BrowserAccessibilityManagerWin::RemoveNode(BrowserAccessibility* node) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 // |parent_iaccessible_| are no longer valid either, since they were | 230 // |parent_iaccessible_| are no longer valid either, since they were |
312 // derived from AccessibleHWND. We don't have to restore them to | 231 // derived from AccessibleHWND. We don't have to restore them to |
313 // previous values, though, because this should only happen | 232 // previous values, though, because this should only happen |
314 // during the destruct sequence for this window. | 233 // during the destruct sequence for this window. |
315 accessible_hwnd_ = NULL; | 234 accessible_hwnd_ = NULL; |
316 parent_hwnd_ = NULL; | 235 parent_hwnd_ = NULL; |
317 parent_iaccessible_ = NULL; | 236 parent_iaccessible_ = NULL; |
318 } | 237 } |
319 | 238 |
320 } // namespace content | 239 } // namespace content |
OLD | NEW |