| 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 |