Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: content/browser/accessibility/browser_accessibility_win.cc

Issue 859133003: Fire AX text inserted event when embedded obj char changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor cleanup Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 FireIAccessibleTextEvents.
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
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
3233 // Fire an event when a new subtree is created.
3234 if (is_subtree_creation)
3235 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SHOW, this);
3236
3237 // No other events fire on new objects, only on objects that changed,
3238 // so exit now if this is a new object.
3239 bool is_new_object = old_win_attributes_->ia_role == 0 &&
3240 old_win_attributes_->role_name.empty();
3241 if (is_new_object)
David Tseng 2015/01/30 23:57:25 nit: no need for this local var.
dmazzoni 2015/01/31 07:45:21 Done.
3242 return;
3243
3208 // Fire an event if the name, description, help, or value changes. 3244 // Fire an event if the name, description, help, or value changes.
3209 if (!is_new_object) { 3245 if (name() != old_win_attributes_->name)
3210 if (name != old_win_attributes_->name) 3246 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this);
3211 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); 3247 if (description() != old_win_attributes_->description)
3212 if (description != old_win_attributes_->description) 3248 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this);
3213 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); 3249 if (help() != old_win_attributes_->help)
3214 if (help != old_win_attributes_->help) 3250 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this);
3215 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this); 3251 if (value() != old_win_attributes_->value)
3216 if (value != old_win_attributes_->value) 3252 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this);
3217 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); 3253 if (ia_state() != old_win_attributes_->ia_state)
3218 if (ia_state() != old_win_attributes_->ia_state) 3254 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this);
3219 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this);
3220 3255
3221 // Normally focus events are handled elsewhere, however 3256 // Normally focus events are handled elsewhere, however
3222 // focus for managed descendants is platform-specific. 3257 // focus for managed descendants is platform-specific.
3223 // Fire a focus event if the focused descendant in a multi-select 3258 // Fire a focus event if the focused descendant in a multi-select
3224 // list box changes. 3259 // list box changes.
3225 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && 3260 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION &&
3226 (ia_state() & STATE_SYSTEM_FOCUSABLE) && 3261 (ia_state() & STATE_SYSTEM_FOCUSABLE) &&
3227 (ia_state() & STATE_SYSTEM_SELECTABLE) && 3262 (ia_state() & STATE_SYSTEM_SELECTABLE) &&
3228 (ia_state() & STATE_SYSTEM_FOCUSED) && 3263 (ia_state() & STATE_SYSTEM_FOCUSED) &&
3229 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { 3264 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) {
3230 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this); 3265 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this);
3231 }
3232
3233 // Handle selection being added or removed.
3234 bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0;
3235 bool was_selected_before =
3236 (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0;
3237 if (is_selected_now && !was_selected_before) {
3238 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this);
3239 } else if (!is_selected_now && was_selected_before) {
3240 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this);
3241 }
3242
3243 // Fire an event if this container object has scrolled.
3244 int sx = 0;
3245 int sy = 0;
3246 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) &&
3247 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) {
3248 if (sx != previous_scroll_x_ || sy != previous_scroll_y_)
3249 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this);
3250 previous_scroll_x_ = sx;
3251 previous_scroll_y_ = sy;
3252 }
3253
3254 // Changing a static text node can affect the IAccessibleText hypertext
3255 // of the parent node, so force it to be recomputed here.
3256 if (GetParent() &&
3257 GetRole() == ui::AX_ROLE_STATIC_TEXT &&
3258 name != old_win_attributes_->name) {
3259 GetParent()->ToBrowserAccessibilityWin()->UpdateIAccessibleText();
3260 }
3261 } 3266 }
3262 3267
3268 // Handle selection being added or removed.
3269 bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0;
3270 bool was_selected_before =
3271 (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0;
3272 if (is_selected_now && !was_selected_before) {
3273 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this);
3274 } else if (!is_selected_now && was_selected_before) {
3275 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this);
3276 }
3277
3278 // Fire an event if this container object has scrolled.
3279 int sx = 0;
3280 int sy = 0;
3281 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) &&
3282 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) {
3283 if (sx != previous_scroll_x_ || sy != previous_scroll_y_)
3284 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this);
3285 previous_scroll_x_ = sx;
3286 previous_scroll_y_ = sy;
3287 }
3288
3289 // Changing a static text node can affect the IAccessibleText hypertext
3290 // of the parent node, so force an update on the parent.
3291 if (GetParent() &&
David Tseng 2015/01/30 23:57:25 nit: store parent in a local variable.
dmazzoni 2015/01/31 07:45:21 Done.
3292 GetRole() == ui::AX_ROLE_STATIC_TEXT &&
3293 name() != old_win_attributes_->name) {
3294 GetParent()->ToBrowserAccessibilityWin()->UpdateStep1ComputeWinAttributes();
3295 GetParent()->ToBrowserAccessibilityWin()->UpdateStep2ComputeHypertext();
3296 GetParent()->ToBrowserAccessibilityWin()->UpdateStep3FireEvents(false);
3297 GetParent()->ToBrowserAccessibilityWin()->
3298 UpdateStep4DeleteOldWinAttributes();
3299 }
3300
3301 // Fire hypertext-related events.
David Tseng 2015/01/30 23:57:25 This would mean this object's parent fires hyperte
dmazzoni 2015/01/31 07:45:21 No, I checked with NV Access. The order in which w
3302 int start, old_len, new_len;
3303 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
3304 if (old_len) {
David Tseng 2015/01/30 23:57:25 nit: old_len > 0?
dmazzoni 2015/01/31 07:45:21 Done.
3305 // In-process screen readers may call IAccessibleText::get_oldText
3306 // to retrieve the text that was removed.
3307 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this);
3308 }
3309 if (new_len) {
David Tseng 2015/01/30 23:57:25 ditto
dmazzoni 2015/01/31 07:45:21 Done.
3310 // In-process screen readers may call IAccessibleText::get_newText
David Tseng 2015/01/30 23:57:25 in reaction to this event?
dmazzoni 2015/01/31 07:45:21 Done.
3311 // to retrieve the text that was inserted.
3312 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this);
3313 }
3314 }
3315
3316 void BrowserAccessibilityWin::UpdateStep4DeleteOldWinAttributes() {
3263 old_win_attributes_.reset(nullptr); 3317 old_win_attributes_.reset(nullptr);
3264 } 3318 }
3265 3319
3266 void BrowserAccessibilityWin::UpdateIAccessibleText() {
3267 old_hypertext_ = hypertext_;
3268 hypertext_.clear();
3269
3270 // Construct the hypertext for this node.
3271 hyperlink_offset_to_index_.clear();
3272 hyperlinks_.clear();
3273 for (unsigned int i = 0; i < PlatformChildCount(); ++i) {
3274 BrowserAccessibilityWin* child =
3275 PlatformGetChild(i)->ToBrowserAccessibilityWin();
3276 if (child->GetRole() == ui::AX_ROLE_STATIC_TEXT) {
3277 hypertext_ += child->name();
3278 } else {
3279 hyperlink_offset_to_index_[hypertext_.size()] =
3280 hyperlinks_.size();
3281 hypertext_ += kEmbeddedCharacter;
3282 hyperlinks_.push_back(i);
3283 }
3284 }
3285 DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size());
3286
3287 if (hypertext_ != old_hypertext_) {
3288 BrowserAccessibilityManagerWin* manager =
3289 this->manager()->ToBrowserAccessibilityManagerWin();
3290
3291 int start, old_len, new_len;
3292 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
3293 if (old_len) {
3294 // In-process screen readers may call IAccessibleText::get_oldText
3295 // to retrieve the text that was removed.
3296 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this);
3297 }
3298 if (new_len) {
3299 // In-process screen readers may call IAccessibleText::get_newText
3300 // to retrieve the text that was inserted.
3301 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this);
3302 }
3303 }
3304
3305 old_hypertext_.clear();
3306 }
3307
3308 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { 3320 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() {
3309 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( 3321 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
3310 EVENT_OBJECT_HIDE, this); 3322 EVENT_OBJECT_HIDE, this);
3311 } 3323 }
3312 3324
3313 void BrowserAccessibilityWin::OnSubtreeCreationFinished() {
3314 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
3315 EVENT_OBJECT_SHOW, this);
3316 }
3317
3318 void BrowserAccessibilityWin::NativeAddReference() { 3325 void BrowserAccessibilityWin::NativeAddReference() {
3319 AddRef(); 3326 AddRef();
3320 } 3327 }
3321 3328
3322 void BrowserAccessibilityWin::NativeReleaseReference() { 3329 void BrowserAccessibilityWin::NativeReleaseReference() {
3323 Release(); 3330 Release();
3324 } 3331 }
3325 3332
3326 bool BrowserAccessibilityWin::IsNative() const { 3333 bool BrowserAccessibilityWin::IsNative() const {
3327 return true; 3334 return true;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
3422 if (value.empty() && 3429 if (value.empty() &&
3423 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { 3430 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) {
3424 value = base::UTF8ToUTF16(base::DoubleToString(fval)); 3431 value = base::UTF8ToUTF16(base::DoubleToString(fval));
3425 } 3432 }
3426 return value; 3433 return value;
3427 } 3434 }
3428 3435
3429 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { 3436 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() {
3430 if (IsEditableText()) 3437 if (IsEditableText())
3431 return value(); 3438 return value();
3432 return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext_; 3439 return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext();
3440 }
3441
3442 bool BrowserAccessibilityWin::IsSameHypertextCharacter(size_t old_char_index,
3443 size_t new_char_index) {
3444 CHECK(old_win_attributes_);
3445
3446 // For anything other than the "embedded character", we just compare the
3447 // characters directly.
3448 base::char16 old_ch = old_win_attributes_->hypertext[old_char_index];
3449 base::char16 new_ch = win_attributes_->hypertext[new_char_index];
3450 if (old_ch != new_ch)
3451 return false;
3452 if (old_ch == new_ch && new_ch != kEmbeddedCharacter)
3453 return true;
3454
3455 // If it's an embedded character, they're only identical if the child id
3456 // the hyperlink points to is the same.
3457 std::map<int32, int32>& old_offset_to_index =
3458 old_win_attributes_->hyperlink_offset_to_index;
3459 std::vector<int32>& old_hyperlinks = old_win_attributes_->hyperlinks;
3460 int32 old_hyperlinks_count = static_cast<int32>(old_hyperlinks.size());
3461 std::map<int32, int32>::iterator iter;
3462 iter = old_offset_to_index.find(old_char_index);
3463 int old_index = (iter != old_offset_to_index.end()) ? iter->second : -1;
3464 int old_child_id = (old_index >= 0 && old_index < old_hyperlinks_count) ?
3465 old_hyperlinks[old_index] : -1;
3466
3467 std::map<int32, int32>& new_offset_to_index =
3468 win_attributes_->hyperlink_offset_to_index;
3469 std::vector<int32>& new_hyperlinks = win_attributes_->hyperlinks;
3470 int32 new_hyperlinks_count = static_cast<int32>(new_hyperlinks.size());
3471 iter = new_offset_to_index.find(new_char_index);
3472 int new_index = (iter != new_offset_to_index.end()) ? iter->second : -1;
3473 int new_child_id = (new_index >= 0 && new_index < new_hyperlinks_count) ?
3474 new_hyperlinks[new_index] : -1;
3475
3476 return old_child_id == new_child_id;
3433 } 3477 }
3434 3478
3435 void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted( 3479 void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted(
3436 int* start, int* old_len, int* new_len) { 3480 int* start, int* old_len, int* new_len) {
3481 CHECK(old_win_attributes_);
3482
3437 *start = 0; 3483 *start = 0;
3438 *old_len = 0; 3484 *old_len = 0;
3439 *new_len = 0; 3485 *new_len = 0;
3440 3486
3441 const base::string16& old_text = old_hypertext_; 3487 const base::string16& old_text = old_win_attributes_->hypertext;
3442 const base::string16& new_text = hypertext_; 3488 const base::string16& new_text = hypertext();
3443 3489
3444 size_t common_prefix = 0; 3490 size_t common_prefix = 0;
3445 while (common_prefix < old_text.size() && 3491 while (common_prefix < old_text.size() &&
3446 common_prefix < new_text.size() && 3492 common_prefix < new_text.size() &&
3447 old_text[common_prefix] == new_text[common_prefix]) { 3493 IsSameHypertextCharacter(common_prefix, common_prefix)) {
3448 ++common_prefix; 3494 ++common_prefix;
3449 } 3495 }
3450 3496
3451 size_t common_suffix = 0; 3497 size_t common_suffix = 0;
3452 while (common_prefix + common_suffix < old_text.size() && 3498 while (common_prefix + common_suffix < old_text.size() &&
3453 common_prefix + common_suffix < new_text.size() && 3499 common_prefix + common_suffix < new_text.size() &&
3454 old_text[old_text.size() - common_suffix - 1] == 3500 IsSameHypertextCharacter(
3455 new_text[new_text.size() - common_suffix - 1]) { 3501 old_text.size() - common_suffix - 1,
3502 new_text.size() - common_suffix - 1)) {
3456 ++common_suffix; 3503 ++common_suffix;
3457 } 3504 }
3458 3505
3459 *start = common_prefix; 3506 *start = common_prefix;
3460 *old_len = old_text.size() - common_prefix - common_suffix; 3507 *old_len = old_text.size() - common_prefix - common_suffix;
3461 *new_len = new_text.size() - common_prefix - common_suffix; 3508 *new_len = new_text.size() - common_prefix - common_suffix;
3462 } 3509 }
3463 3510
3464 void BrowserAccessibilityWin::HandleSpecialTextOffset( 3511 void BrowserAccessibilityWin::HandleSpecialTextOffset(
3465 const base::string16& text, 3512 const base::string16& text,
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
4040 ia2_role = ia_role; 4087 ia2_role = ia_role;
4041 4088
4042 win_attributes_->ia_role = ia_role; 4089 win_attributes_->ia_role = ia_role;
4043 win_attributes_->ia_state = ia_state; 4090 win_attributes_->ia_state = ia_state;
4044 win_attributes_->role_name = role_name; 4091 win_attributes_->role_name = role_name;
4045 win_attributes_->ia2_role = ia2_role; 4092 win_attributes_->ia2_role = ia2_role;
4046 win_attributes_->ia2_state = ia2_state; 4093 win_attributes_->ia2_state = ia2_state;
4047 } 4094 }
4048 4095
4049 } // namespace content 4096 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698