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_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_win.h" |
6 | 6 |
7 #include <UIAutomationClient.h> | 7 #include <UIAutomationClient.h> |
8 #include <UIAutomationCoreApi.h> | 8 #include <UIAutomationCoreApi.h> |
9 | 9 |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 // These nonstandard GUIDs are taken directly from the Mozilla sources | 28 // These nonstandard GUIDs are taken directly from the Mozilla sources |
29 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here: | 29 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here: |
30 // http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/
MSAA | 30 // http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/
MSAA |
31 const GUID GUID_ISimpleDOM = { | 31 const GUID GUID_ISimpleDOM = { |
32 0x0c539790, 0x12e4, 0x11cf, | 32 0x0c539790, 0x12e4, 0x11cf, |
33 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}; | 33 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}; |
34 const GUID GUID_IAccessibleContentDocument = { | 34 const GUID GUID_IAccessibleContentDocument = { |
35 0xa5d8e1f3, 0x3571, 0x4d8f, | 35 0xa5d8e1f3, 0x3571, 0x4d8f, |
36 0x95, 0x21, 0x07, 0xed, 0x28, 0xfb, 0x07, 0x2e}; | 36 0x95, 0x21, 0x07, 0xed, 0x28, 0xfb, 0x07, 0x2e}; |
37 | 37 |
38 const base::char16 BrowserAccessibilityWin::kEmbeddedCharacter[] = L"\xfffc"; | 38 const base::char16 BrowserAccessibilityWin::kEmbeddedCharacter = L'\xfffc'; |
39 | 39 |
40 // static | 40 // static |
41 LONG BrowserAccessibilityWin::next_unique_id_win_ = | 41 LONG BrowserAccessibilityWin::next_unique_id_win_ = |
42 base::win::kFirstBrowserAccessibilityManagerAccessibilityId; | 42 base::win::kFirstBrowserAccessibilityManagerAccessibilityId; |
43 | 43 |
44 // | 44 // |
45 // BrowserAccessibilityRelation | 45 // BrowserAccessibilityRelation |
46 // | 46 // |
47 // A simple implementation of IAccessibleRelation, used to represent | 47 // A simple implementation of IAccessibleRelation, used to represent |
48 // a relationship between two accessible nodes in the tree. | 48 // a relationship between two accessible nodes in the tree. |
(...skipping 2118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2167 return get_text(*start_offset, *end_offset, text); | 2167 return get_text(*start_offset, *end_offset, text); |
2168 } | 2168 } |
2169 | 2169 |
2170 STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { | 2170 STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { |
2171 if (!instance_active()) | 2171 if (!instance_active()) |
2172 return E_FAIL; | 2172 return E_FAIL; |
2173 | 2173 |
2174 if (!new_text) | 2174 if (!new_text) |
2175 return E_INVALIDARG; | 2175 return E_INVALIDARG; |
2176 | 2176 |
| 2177 if (!old_win_attributes_) |
| 2178 return E_FAIL; |
| 2179 |
2177 int start, old_len, new_len; | 2180 int start, old_len, new_len; |
2178 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | 2181 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); |
2179 if (new_len == 0) | 2182 if (new_len == 0) |
2180 return E_FAIL; | 2183 return E_FAIL; |
2181 | 2184 |
2182 base::string16 substr = hypertext_.substr(start, new_len); | 2185 base::string16 substr = hypertext().substr(start, new_len); |
2183 new_text->text = SysAllocString(substr.c_str()); | 2186 new_text->text = SysAllocString(substr.c_str()); |
2184 new_text->start = static_cast<long>(start); | 2187 new_text->start = static_cast<long>(start); |
2185 new_text->end = static_cast<long>(start + new_len); | 2188 new_text->end = static_cast<long>(start + new_len); |
2186 return S_OK; | 2189 return S_OK; |
2187 } | 2190 } |
2188 | 2191 |
2189 STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) { | 2192 STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) { |
2190 if (!instance_active()) | 2193 if (!instance_active()) |
2191 return E_FAIL; | 2194 return E_FAIL; |
2192 | 2195 |
2193 if (!old_text) | 2196 if (!old_text) |
2194 return E_INVALIDARG; | 2197 return E_INVALIDARG; |
2195 | 2198 |
| 2199 if (!old_win_attributes_) |
| 2200 return E_FAIL; |
| 2201 |
2196 int start, old_len, new_len; | 2202 int start, old_len, new_len; |
2197 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | 2203 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); |
2198 if (old_len == 0) | 2204 if (old_len == 0) |
2199 return E_FAIL; | 2205 return E_FAIL; |
2200 | 2206 |
2201 base::string16 substr = old_hypertext_.substr(start, old_len); | 2207 base::string16 old_hypertext = old_win_attributes_->hypertext; |
| 2208 base::string16 substr = old_hypertext.substr(start, old_len); |
2202 old_text->text = SysAllocString(substr.c_str()); | 2209 old_text->text = SysAllocString(substr.c_str()); |
2203 old_text->start = static_cast<long>(start); | 2210 old_text->start = static_cast<long>(start); |
2204 old_text->end = static_cast<long>(start + old_len); | 2211 old_text->end = static_cast<long>(start + old_len); |
2205 return S_OK; | 2212 return S_OK; |
2206 } | 2213 } |
2207 | 2214 |
2208 STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint( | 2215 STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint( |
2209 LONG x, | 2216 LONG x, |
2210 LONG y, | 2217 LONG y, |
2211 enum IA2CoordinateType coord_type, | 2218 enum IA2CoordinateType coord_type, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2295 // IAccessibleHypertext methods. | 2302 // IAccessibleHypertext methods. |
2296 // | 2303 // |
2297 | 2304 |
2298 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { | 2305 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { |
2299 if (!instance_active()) | 2306 if (!instance_active()) |
2300 return E_FAIL; | 2307 return E_FAIL; |
2301 | 2308 |
2302 if (!hyperlink_count) | 2309 if (!hyperlink_count) |
2303 return E_INVALIDARG; | 2310 return E_INVALIDARG; |
2304 | 2311 |
2305 *hyperlink_count = hyperlink_offset_to_index_.size(); | 2312 *hyperlink_count = hyperlink_offset_to_index().size(); |
2306 return S_OK; | 2313 return S_OK; |
2307 } | 2314 } |
2308 | 2315 |
2309 STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( | 2316 STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( |
2310 long index, | 2317 long index, |
2311 IAccessibleHyperlink** hyperlink) { | 2318 IAccessibleHyperlink** hyperlink) { |
2312 if (!instance_active()) | 2319 if (!instance_active()) |
2313 return E_FAIL; | 2320 return E_FAIL; |
2314 | 2321 |
2315 if (!hyperlink || | 2322 if (!hyperlink || |
2316 index < 0 || | 2323 index < 0 || |
2317 index >= static_cast<long>(hyperlinks_.size())) { | 2324 index >= static_cast<long>(hyperlinks().size())) { |
2318 return E_INVALIDARG; | 2325 return E_INVALIDARG; |
2319 } | 2326 } |
2320 | 2327 |
| 2328 int32 id = hyperlinks()[index]; |
2321 BrowserAccessibilityWin* child = | 2329 BrowserAccessibilityWin* child = |
2322 InternalGetChild(hyperlinks_[index])->ToBrowserAccessibilityWin(); | 2330 manager()->GetFromID(id)->ToBrowserAccessibilityWin(); |
2323 *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference()); | 2331 if (child) { |
2324 return S_OK; | 2332 *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference()); |
| 2333 return S_OK; |
| 2334 } |
| 2335 |
| 2336 return E_FAIL; |
2325 } | 2337 } |
2326 | 2338 |
2327 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( | 2339 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( |
2328 long char_index, | 2340 long char_index, |
2329 long* hyperlink_index) { | 2341 long* hyperlink_index) { |
2330 if (!instance_active()) | 2342 if (!instance_active()) |
2331 return E_FAIL; | 2343 return E_FAIL; |
2332 | 2344 |
2333 if (!hyperlink_index) | 2345 if (!hyperlink_index) |
2334 return E_INVALIDARG; | 2346 return E_INVALIDARG; |
2335 | 2347 |
2336 *hyperlink_index = -1; | 2348 *hyperlink_index = -1; |
2337 | 2349 |
2338 if (char_index < 0 || | 2350 if (char_index < 0 || |
2339 char_index >= static_cast<long>(hypertext_.size())) { | 2351 char_index >= static_cast<long>(hypertext().size())) { |
2340 return E_INVALIDARG; | 2352 return E_INVALIDARG; |
2341 } | 2353 } |
2342 | 2354 |
2343 std::map<int32, int32>::iterator it = | 2355 std::map<int32, int32>::iterator it = |
2344 hyperlink_offset_to_index_.find(char_index); | 2356 hyperlink_offset_to_index().find(char_index); |
2345 if (it == hyperlink_offset_to_index_.end()) | 2357 if (it == hyperlink_offset_to_index().end()) |
2346 return E_FAIL; | 2358 return E_FAIL; |
2347 | 2359 |
2348 *hyperlink_index = it->second; | 2360 *hyperlink_index = it->second; |
2349 return S_OK; | 2361 return S_OK; |
2350 } | 2362 } |
2351 | 2363 |
2352 // | 2364 // |
2353 // IAccessibleValue methods. | 2365 // IAccessibleValue methods. |
2354 // | 2366 // |
2355 | 2367 |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2936 } | 2948 } |
2937 | 2949 |
2938 return CComObjectRootBase::InternalQueryInterface( | 2950 return CComObjectRootBase::InternalQueryInterface( |
2939 this_ptr, entries, iid, object); | 2951 this_ptr, entries, iid, object); |
2940 } | 2952 } |
2941 | 2953 |
2942 // | 2954 // |
2943 // Private methods. | 2955 // Private methods. |
2944 // | 2956 // |
2945 | 2957 |
2946 // Called every time this node's data changes, while the tree update is | 2958 void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() { |
2947 // still in progress. | 2959 // Swap win_attributes_ to old_win_attributes_, allowing us to see |
2948 void BrowserAccessibilityWin::OnDataChanged() { | 2960 // exactly what changed and fire appropriate events. Note that |
2949 BrowserAccessibility::OnDataChanged(); | 2961 // old_win_attributes_ is cleared at the end of UpdateStep3FireEvents. |
2950 } | |
2951 | |
2952 // Called every time this node's data changes, after an atomic tree update. | |
2953 void BrowserAccessibilityWin::OnUpdateFinished() { | |
2954 BrowserAccessibility::OnUpdateFinished(); | |
2955 | |
2956 if (PlatformIsChildOfLeaf()) | |
2957 return; | |
2958 | |
2959 bool is_new_object = ia_role() == 0 && role_name().empty(); | |
2960 | |
2961 old_win_attributes_.swap(win_attributes_); | 2962 old_win_attributes_.swap(win_attributes_); |
2962 win_attributes_.reset(new WinAttributes()); | 2963 win_attributes_.reset(new WinAttributes()); |
2963 | 2964 |
2964 InitRoleAndState(); | 2965 InitRoleAndState(); |
2965 | 2966 |
2966 win_attributes_->ia2_attributes.clear(); | 2967 win_attributes_->ia2_attributes.clear(); |
2967 | 2968 |
2968 // Expose autocomplete attribute for combobox and textbox. | 2969 // Expose autocomplete attribute for combobox and textbox. |
2969 StringAttributeToIA2(ui::AX_ATTR_AUTO_COMPLETE, "autocomplete"); | 2970 StringAttributeToIA2(ui::AX_ATTR_AUTO_COMPLETE, "autocomplete"); |
2970 | 2971 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3188 win_attributes_->ia2_attributes.push_back(L"valuetext:" + GetValueText()); | 3189 win_attributes_->ia2_attributes.push_back(L"valuetext:" + GetValueText()); |
3189 } | 3190 } |
3190 | 3191 |
3191 // If this is a web area for a presentational iframe, give it a role of | 3192 // If this is a web area for a presentational iframe, give it a role of |
3192 // something other than DOCUMENT so that the fact that it's a separate doc | 3193 // something other than DOCUMENT so that the fact that it's a separate doc |
3193 // is not exposed to AT. | 3194 // is not exposed to AT. |
3194 if (IsWebAreaForPresentationalIframe()) { | 3195 if (IsWebAreaForPresentationalIframe()) { |
3195 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; | 3196 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; |
3196 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; | 3197 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; |
3197 } | 3198 } |
| 3199 } |
3198 | 3200 |
| 3201 void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() { |
| 3202 // Construct the hypertext for this node, which contains the concatenation |
| 3203 // of all of the static text of this node's children and an embedded object |
| 3204 // character for all non-static-text children. Build up a map from the |
| 3205 // character index of each embedded object character to the id of the |
| 3206 // child object it points to. |
| 3207 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { |
| 3208 BrowserAccessibilityWin* child = |
| 3209 PlatformGetChild(i)->ToBrowserAccessibilityWin(); |
| 3210 if (child->GetRole() == ui::AX_ROLE_STATIC_TEXT) { |
| 3211 win_attributes_->hypertext += child->name(); |
| 3212 } else { |
| 3213 int32 char_offset = hypertext().size(); |
| 3214 int32 child_id = child->GetId(); |
| 3215 int32 index = hyperlinks().size(); |
| 3216 win_attributes_->hyperlink_offset_to_index[char_offset] = index; |
| 3217 win_attributes_->hyperlinks.push_back(child_id); |
| 3218 win_attributes_->hypertext += kEmbeddedCharacter; |
| 3219 } |
| 3220 } |
| 3221 } |
| 3222 |
| 3223 void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) { |
3199 BrowserAccessibilityManagerWin* manager = | 3224 BrowserAccessibilityManagerWin* manager = |
3200 this->manager()->ToBrowserAccessibilityManagerWin(); | 3225 this->manager()->ToBrowserAccessibilityManagerWin(); |
3201 | 3226 |
3202 // Fire an event when an alert first appears. | 3227 // Fire an event when an alert first appears. |
3203 if (ia_role() == ROLE_SYSTEM_ALERT && | 3228 if (ia_role() == ROLE_SYSTEM_ALERT && |
3204 old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { | 3229 old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { |
3205 manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); | 3230 manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); |
3206 } | 3231 } |
3207 | 3232 |
3208 // Fire an event if the name, description, help, or value changes. | 3233 // Fire an event when a new subtree is created. |
3209 if (!is_new_object) { | 3234 if (is_subtree_creation) |
3210 if (name != old_win_attributes_->name) | 3235 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SHOW, this); |
| 3236 |
| 3237 // The rest of the events only fire on changes, not on new objects. |
| 3238 if (old_win_attributes_->ia_role != 0 || |
| 3239 !old_win_attributes_->role_name.empty()) { |
| 3240 // Fire an event if the name, description, help, or value changes. |
| 3241 if (name() != old_win_attributes_->name) |
3211 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); | 3242 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); |
3212 if (description != old_win_attributes_->description) | 3243 if (description() != old_win_attributes_->description) |
3213 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); | 3244 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); |
3214 if (help != old_win_attributes_->help) | 3245 if (help() != old_win_attributes_->help) |
3215 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this); | 3246 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this); |
3216 if (value != old_win_attributes_->value) | 3247 if (value() != old_win_attributes_->value) |
3217 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); | 3248 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); |
3218 if (ia_state() != old_win_attributes_->ia_state) { | 3249 if (ia_state() != old_win_attributes_->ia_state) |
3219 LOG(INFO) << "State change:" | |
3220 << " from " << old_win_attributes_->ia_state | |
3221 << " to " << ia_state(); | |
3222 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); | 3250 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); |
3223 } | |
3224 | 3251 |
3225 // Normally focus events are handled elsewhere, however | 3252 // Normally focus events are handled elsewhere, however |
3226 // focus for managed descendants is platform-specific. | 3253 // focus for managed descendants is platform-specific. |
3227 // Fire a focus event if the focused descendant in a multi-select | 3254 // Fire a focus event if the focused descendant in a multi-select |
3228 // list box changes. | 3255 // list box changes. |
3229 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && | 3256 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && |
3230 (ia_state() & STATE_SYSTEM_FOCUSABLE) && | 3257 (ia_state() & STATE_SYSTEM_FOCUSABLE) && |
3231 (ia_state() & STATE_SYSTEM_SELECTABLE) && | 3258 (ia_state() & STATE_SYSTEM_SELECTABLE) && |
3232 (ia_state() & STATE_SYSTEM_FOCUSED) && | 3259 (ia_state() & STATE_SYSTEM_FOCUSED) && |
3233 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { | 3260 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { |
(...skipping 15 matching lines...) Expand all Loading... |
3249 int sy = 0; | 3276 int sy = 0; |
3250 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && | 3277 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && |
3251 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { | 3278 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { |
3252 if (sx != previous_scroll_x_ || sy != previous_scroll_y_) | 3279 if (sx != previous_scroll_x_ || sy != previous_scroll_y_) |
3253 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); | 3280 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); |
3254 previous_scroll_x_ = sx; | 3281 previous_scroll_x_ = sx; |
3255 previous_scroll_y_ = sy; | 3282 previous_scroll_y_ = sy; |
3256 } | 3283 } |
3257 | 3284 |
3258 // Changing a static text node can affect the IAccessibleText hypertext | 3285 // Changing a static text node can affect the IAccessibleText hypertext |
3259 // of the parent node, so force it to be recomputed here. | 3286 // of the parent node, so force an update on the parent. |
3260 if (GetParent() && | 3287 BrowserAccessibilityWin* parent = GetParent()->ToBrowserAccessibilityWin(); |
| 3288 if (parent && |
3261 GetRole() == ui::AX_ROLE_STATIC_TEXT && | 3289 GetRole() == ui::AX_ROLE_STATIC_TEXT && |
3262 name != old_win_attributes_->name) { | 3290 name() != old_win_attributes_->name) { |
3263 GetParent()->ToBrowserAccessibilityWin()->UpdateIAccessibleText(); | 3291 parent->UpdateStep1ComputeWinAttributes(); |
| 3292 parent->UpdateStep2ComputeHypertext(); |
| 3293 parent->UpdateStep3FireEvents(false); |
| 3294 } |
| 3295 |
| 3296 // Fire hypertext-related events. |
| 3297 int start, old_len, new_len; |
| 3298 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); |
| 3299 if (old_len > 0) { |
| 3300 // In-process screen readers may call IAccessibleText::get_oldText |
| 3301 // in reaction to this event to retrieve the text that was removed. |
| 3302 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); |
| 3303 } |
| 3304 if (new_len > 0) { |
| 3305 // In-process screen readers may call IAccessibleText::get_newText |
| 3306 // in reaction to this event to retrieve the text that was inserted. |
| 3307 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); |
3264 } | 3308 } |
3265 } | 3309 } |
3266 | 3310 |
3267 old_win_attributes_.reset(nullptr); | 3311 old_win_attributes_.reset(nullptr); |
3268 } | 3312 } |
3269 | 3313 |
3270 void BrowserAccessibilityWin::UpdateIAccessibleText() { | |
3271 old_hypertext_ = hypertext_; | |
3272 hypertext_.clear(); | |
3273 | |
3274 // Construct the hypertext for this node. | |
3275 hyperlink_offset_to_index_.clear(); | |
3276 hyperlinks_.clear(); | |
3277 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { | |
3278 BrowserAccessibilityWin* child = | |
3279 PlatformGetChild(i)->ToBrowserAccessibilityWin(); | |
3280 if (child->GetRole() == ui::AX_ROLE_STATIC_TEXT) { | |
3281 hypertext_ += child->name(); | |
3282 } else { | |
3283 hyperlink_offset_to_index_[hypertext_.size()] = | |
3284 hyperlinks_.size(); | |
3285 hypertext_ += kEmbeddedCharacter; | |
3286 hyperlinks_.push_back(i); | |
3287 } | |
3288 } | |
3289 DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size()); | |
3290 | |
3291 if (hypertext_ != old_hypertext_) { | |
3292 BrowserAccessibilityManagerWin* manager = | |
3293 this->manager()->ToBrowserAccessibilityManagerWin(); | |
3294 | |
3295 int start, old_len, new_len; | |
3296 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | |
3297 if (old_len) { | |
3298 // In-process screen readers may call IAccessibleText::get_oldText | |
3299 // to retrieve the text that was removed. | |
3300 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); | |
3301 } | |
3302 if (new_len) { | |
3303 // In-process screen readers may call IAccessibleText::get_newText | |
3304 // to retrieve the text that was inserted. | |
3305 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); | |
3306 } | |
3307 } | |
3308 | |
3309 old_hypertext_.clear(); | |
3310 } | |
3311 | |
3312 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { | 3314 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { |
3313 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( | 3315 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( |
3314 EVENT_OBJECT_HIDE, this); | 3316 EVENT_OBJECT_HIDE, this); |
3315 } | 3317 } |
3316 | 3318 |
3317 void BrowserAccessibilityWin::OnSubtreeCreationFinished() { | |
3318 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( | |
3319 EVENT_OBJECT_SHOW, this); | |
3320 } | |
3321 | |
3322 void BrowserAccessibilityWin::NativeAddReference() { | 3319 void BrowserAccessibilityWin::NativeAddReference() { |
3323 AddRef(); | 3320 AddRef(); |
3324 } | 3321 } |
3325 | 3322 |
3326 void BrowserAccessibilityWin::NativeReleaseReference() { | 3323 void BrowserAccessibilityWin::NativeReleaseReference() { |
3327 Release(); | 3324 Release(); |
3328 } | 3325 } |
3329 | 3326 |
3330 bool BrowserAccessibilityWin::IsNative() const { | 3327 bool BrowserAccessibilityWin::IsNative() const { |
3331 return true; | 3328 return true; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3426 if (value.empty() && | 3423 if (value.empty() && |
3427 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { | 3424 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { |
3428 value = base::UTF8ToUTF16(base::DoubleToString(fval)); | 3425 value = base::UTF8ToUTF16(base::DoubleToString(fval)); |
3429 } | 3426 } |
3430 return value; | 3427 return value; |
3431 } | 3428 } |
3432 | 3429 |
3433 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { | 3430 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { |
3434 if (IsEditableText()) | 3431 if (IsEditableText()) |
3435 return value(); | 3432 return value(); |
3436 return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext_; | 3433 return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext(); |
| 3434 } |
| 3435 |
| 3436 bool BrowserAccessibilityWin::IsSameHypertextCharacter(size_t old_char_index, |
| 3437 size_t new_char_index) { |
| 3438 CHECK(old_win_attributes_); |
| 3439 |
| 3440 // For anything other than the "embedded character", we just compare the |
| 3441 // characters directly. |
| 3442 base::char16 old_ch = old_win_attributes_->hypertext[old_char_index]; |
| 3443 base::char16 new_ch = win_attributes_->hypertext[new_char_index]; |
| 3444 if (old_ch != new_ch) |
| 3445 return false; |
| 3446 if (old_ch == new_ch && new_ch != kEmbeddedCharacter) |
| 3447 return true; |
| 3448 |
| 3449 // If it's an embedded character, they're only identical if the child id |
| 3450 // the hyperlink points to is the same. |
| 3451 std::map<int32, int32>& old_offset_to_index = |
| 3452 old_win_attributes_->hyperlink_offset_to_index; |
| 3453 std::vector<int32>& old_hyperlinks = old_win_attributes_->hyperlinks; |
| 3454 int32 old_hyperlinks_count = static_cast<int32>(old_hyperlinks.size()); |
| 3455 std::map<int32, int32>::iterator iter; |
| 3456 iter = old_offset_to_index.find(old_char_index); |
| 3457 int old_index = (iter != old_offset_to_index.end()) ? iter->second : -1; |
| 3458 int old_child_id = (old_index >= 0 && old_index < old_hyperlinks_count) ? |
| 3459 old_hyperlinks[old_index] : -1; |
| 3460 |
| 3461 std::map<int32, int32>& new_offset_to_index = |
| 3462 win_attributes_->hyperlink_offset_to_index; |
| 3463 std::vector<int32>& new_hyperlinks = win_attributes_->hyperlinks; |
| 3464 int32 new_hyperlinks_count = static_cast<int32>(new_hyperlinks.size()); |
| 3465 iter = new_offset_to_index.find(new_char_index); |
| 3466 int new_index = (iter != new_offset_to_index.end()) ? iter->second : -1; |
| 3467 int new_child_id = (new_index >= 0 && new_index < new_hyperlinks_count) ? |
| 3468 new_hyperlinks[new_index] : -1; |
| 3469 |
| 3470 return old_child_id == new_child_id; |
3437 } | 3471 } |
3438 | 3472 |
3439 void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted( | 3473 void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted( |
3440 int* start, int* old_len, int* new_len) { | 3474 int* start, int* old_len, int* new_len) { |
| 3475 CHECK(old_win_attributes_); |
| 3476 |
3441 *start = 0; | 3477 *start = 0; |
3442 *old_len = 0; | 3478 *old_len = 0; |
3443 *new_len = 0; | 3479 *new_len = 0; |
3444 | 3480 |
3445 const base::string16& old_text = old_hypertext_; | 3481 const base::string16& old_text = old_win_attributes_->hypertext; |
3446 const base::string16& new_text = hypertext_; | 3482 const base::string16& new_text = hypertext(); |
3447 | 3483 |
3448 size_t common_prefix = 0; | 3484 size_t common_prefix = 0; |
3449 while (common_prefix < old_text.size() && | 3485 while (common_prefix < old_text.size() && |
3450 common_prefix < new_text.size() && | 3486 common_prefix < new_text.size() && |
3451 old_text[common_prefix] == new_text[common_prefix]) { | 3487 IsSameHypertextCharacter(common_prefix, common_prefix)) { |
3452 ++common_prefix; | 3488 ++common_prefix; |
3453 } | 3489 } |
3454 | 3490 |
3455 size_t common_suffix = 0; | 3491 size_t common_suffix = 0; |
3456 while (common_prefix + common_suffix < old_text.size() && | 3492 while (common_prefix + common_suffix < old_text.size() && |
3457 common_prefix + common_suffix < new_text.size() && | 3493 common_prefix + common_suffix < new_text.size() && |
3458 old_text[old_text.size() - common_suffix - 1] == | 3494 IsSameHypertextCharacter( |
3459 new_text[new_text.size() - common_suffix - 1]) { | 3495 old_text.size() - common_suffix - 1, |
| 3496 new_text.size() - common_suffix - 1)) { |
3460 ++common_suffix; | 3497 ++common_suffix; |
3461 } | 3498 } |
3462 | 3499 |
3463 *start = common_prefix; | 3500 *start = common_prefix; |
3464 *old_len = old_text.size() - common_prefix - common_suffix; | 3501 *old_len = old_text.size() - common_prefix - common_suffix; |
3465 *new_len = new_text.size() - common_prefix - common_suffix; | 3502 *new_len = new_text.size() - common_prefix - common_suffix; |
3466 } | 3503 } |
3467 | 3504 |
3468 void BrowserAccessibilityWin::HandleSpecialTextOffset( | 3505 void BrowserAccessibilityWin::HandleSpecialTextOffset( |
3469 const base::string16& text, | 3506 const base::string16& text, |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4044 ia2_role = ia_role; | 4081 ia2_role = ia_role; |
4045 | 4082 |
4046 win_attributes_->ia_role = ia_role; | 4083 win_attributes_->ia_role = ia_role; |
4047 win_attributes_->ia_state = ia_state; | 4084 win_attributes_->ia_state = ia_state; |
4048 win_attributes_->role_name = role_name; | 4085 win_attributes_->role_name = role_name; |
4049 win_attributes_->ia2_role = ia2_role; | 4086 win_attributes_->ia2_role = ia2_role; |
4050 win_attributes_->ia2_state = ia2_state; | 4087 win_attributes_->ia2_state = ia2_state; |
4051 } | 4088 } |
4052 | 4089 |
4053 } // namespace content | 4090 } // namespace content |
OLD | NEW |