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

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

Issue 2054393002: Implemented IAccessible2 reverse relations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed content_browsertests. Created 4 years, 5 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 <algorithm> 10 #include <algorithm>
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 BEGIN_COM_MAP(BrowserAccessibilityRelation) 59 BEGIN_COM_MAP(BrowserAccessibilityRelation)
60 COM_INTERFACE_ENTRY(IAccessibleRelation) 60 COM_INTERFACE_ENTRY(IAccessibleRelation)
61 END_COM_MAP() 61 END_COM_MAP()
62 62
63 CONTENT_EXPORT BrowserAccessibilityRelation() {} 63 CONTENT_EXPORT BrowserAccessibilityRelation() {}
64 CONTENT_EXPORT virtual ~BrowserAccessibilityRelation() {} 64 CONTENT_EXPORT virtual ~BrowserAccessibilityRelation() {}
65 65
66 CONTENT_EXPORT void Initialize(BrowserAccessibilityWin* owner, 66 CONTENT_EXPORT void Initialize(BrowserAccessibilityWin* owner,
67 const base::string16& type); 67 const base::string16& type);
68 CONTENT_EXPORT void AddTarget(int target_id); 68 CONTENT_EXPORT void AddTarget(int target_id);
69 CONTENT_EXPORT void RemoveTarget(int target_id);
70
71 // Accessors.
72 const base::string16& get_type() const { return type_; }
73 const std::vector<int>& get_target_ids() const { return target_ids_; }
69 74
70 // IAccessibleRelation methods. 75 // IAccessibleRelation methods.
71 CONTENT_EXPORT STDMETHODIMP get_relationType(BSTR* relation_type) override; 76 CONTENT_EXPORT STDMETHODIMP get_relationType(BSTR* relation_type) override;
72 CONTENT_EXPORT STDMETHODIMP get_nTargets(long* n_targets) override; 77 CONTENT_EXPORT STDMETHODIMP get_nTargets(long* n_targets) override;
73 CONTENT_EXPORT STDMETHODIMP 78 CONTENT_EXPORT STDMETHODIMP
74 get_target(long target_index, IUnknown** target) override; 79 get_target(long target_index, IUnknown** target) override;
75 CONTENT_EXPORT STDMETHODIMP 80 CONTENT_EXPORT STDMETHODIMP
76 get_targets(long max_targets, IUnknown** targets, long* n_targets) override; 81 get_targets(long max_targets, IUnknown** targets, long* n_targets) override;
77 82
78 // IAccessibleRelation methods not implemented. 83 // IAccessibleRelation methods not implemented.
(...skipping 11 matching lines...) Expand all
90 void BrowserAccessibilityRelation::Initialize(BrowserAccessibilityWin* owner, 95 void BrowserAccessibilityRelation::Initialize(BrowserAccessibilityWin* owner,
91 const base::string16& type) { 96 const base::string16& type) {
92 owner_ = owner; 97 owner_ = owner;
93 type_ = type; 98 type_ = type;
94 } 99 }
95 100
96 void BrowserAccessibilityRelation::AddTarget(int target_id) { 101 void BrowserAccessibilityRelation::AddTarget(int target_id) {
97 target_ids_.push_back(target_id); 102 target_ids_.push_back(target_id);
98 } 103 }
99 104
105 void BrowserAccessibilityRelation::RemoveTarget(int target_id) {
106 target_ids_.erase(
107 std::remove(target_ids_.begin(), target_ids_.end(), target_id),
108 target_ids_.end());
109 }
110
100 STDMETHODIMP BrowserAccessibilityRelation::get_relationType( 111 STDMETHODIMP BrowserAccessibilityRelation::get_relationType(
101 BSTR* relation_type) { 112 BSTR* relation_type) {
102 if (!relation_type) 113 if (!relation_type)
103 return E_INVALIDARG; 114 return E_INVALIDARG;
104 115
105 if (!owner_->instance_active()) 116 if (!owner_->instance_active())
106 return E_FAIL; 117 return E_FAIL;
107 118
108 *relation_type = SysAllocString(type_.c_str()); 119 *relation_type = SysAllocString(type_.c_str());
109 DCHECK(*relation_type); 120 DCHECK(*relation_type);
(...skipping 3404 matching lines...) Expand 10 before | Expand all | Expand 10 after
3514 if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA || 3525 if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA ||
3515 GetRole() == ui::AX_ROLE_WEB_AREA) { 3526 GetRole() == ui::AX_ROLE_WEB_AREA) {
3516 value = base::UTF8ToUTF16(manager()->GetTreeData().url); 3527 value = base::UTF8ToUTF16(manager()->GetTreeData().url);
3517 } 3528 }
3518 // If this doesn't have a value and is linked then set its value to the url 3529 // If this doesn't have a value and is linked then set its value to the url
3519 // attribute. This allows screen readers to read an empty link's destination. 3530 // attribute. This allows screen readers to read an empty link's destination.
3520 if (value.empty() && (ia_state() & STATE_SYSTEM_LINKED)) 3531 if (value.empty() && (ia_state() & STATE_SYSTEM_LINKED))
3521 value = GetString16Attribute(ui::AX_ATTR_URL); 3532 value = GetString16Attribute(ui::AX_ATTR_URL);
3522 win_attributes_->value = value; 3533 win_attributes_->value = value;
3523 3534
3524 // Clear any old relationships between this node and other nodes. 3535 ClearOwnRelations();
3525 for (size_t i = 0; i < relations_.size(); ++i) 3536 AddBidirectionalRelations(IA2_RELATION_CONTROLLER_FOR,
3526 relations_[i]->Release(); 3537 IA2_RELATION_CONTROLLED_BY,
3527 relations_.clear(); 3538 ui::AX_ATTR_CONTROLS_IDS);
3539 AddBidirectionalRelations(IA2_RELATION_DESCRIBED_BY,
3540 IA2_RELATION_DESCRIPTION_FOR,
3541 ui::AX_ATTR_DESCRIBEDBY_IDS);
3542 AddBidirectionalRelations(IA2_RELATION_FLOWS_TO, IA2_RELATION_FLOWS_FROM,
3543 ui::AX_ATTR_FLOWTO_IDS);
3544 AddBidirectionalRelations(IA2_RELATION_LABELLED_BY, IA2_RELATION_LABEL_FOR,
3545 ui::AX_ATTR_LABELLEDBY_IDS);
3528 3546
3529 // Handle title UI element. 3547 int member_of_id;
3530 AddRelations(ui::AX_ATTR_CONTROLS_IDS, IA2_RELATION_CONTROLLER_FOR); 3548 if (GetIntAttribute(ui::AX_ATTR_MEMBER_OF_ID, &member_of_id))
3531 AddRelations(ui::AX_ATTR_DESCRIBEDBY_IDS, IA2_RELATION_DESCRIBED_BY); 3549 AddRelation(IA2_RELATION_MEMBER_OF, member_of_id);
3532 AddRelations(ui::AX_ATTR_FLOWTO_IDS, IA2_RELATION_FLOWS_TO);
3533 AddRelations(ui::AX_ATTR_LABELLEDBY_IDS, IA2_RELATION_LABELLED_BY);
3534 3550
3535 UpdateRequiredAttributes(); 3551 UpdateRequiredAttributes();
3536 // If this is a web area for a presentational iframe, give it a role of 3552 // If this is a web area for a presentational iframe, give it a role of
3537 // something other than DOCUMENT so that the fact that it's a separate doc 3553 // something other than DOCUMENT so that the fact that it's a separate doc
3538 // is not exposed to AT. 3554 // is not exposed to AT.
3539 if (IsWebAreaForPresentationalIframe()) { 3555 if (IsWebAreaForPresentationalIframe()) {
3540 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; 3556 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING;
3541 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; 3557 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING;
3542 } 3558 }
3543 } 3559 }
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after
4429 } 4445 }
4430 4446
4431 if (role == ui::AX_ROLE_MENU_LIST_OPTION && 4447 if (role == ui::AX_ROLE_MENU_LIST_OPTION &&
4432 parent_role == ui::AX_ROLE_MENU_LIST_POPUP) { 4448 parent_role == ui::AX_ROLE_MENU_LIST_POPUP) {
4433 return true; 4449 return true;
4434 } 4450 }
4435 4451
4436 return false; 4452 return false;
4437 } 4453 }
4438 4454
4439 void BrowserAccessibilityWin::AddRelations( 4455 void BrowserAccessibilityWin::AddRelation(const base::string16& relation_type,
4440 ui::AXIntListAttribute src_attr, 4456 int target_id) {
4441 const base::string16& iaccessiblerelation_type) { 4457 CComObject<BrowserAccessibilityRelation>* relation;
4442 if (!HasIntListAttribute(src_attr)) 4458 HRESULT hr =
4459 CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
4460 DCHECK(SUCCEEDED(hr));
4461 relation->AddRef();
4462 relation->Initialize(this, relation_type);
4463 relation->AddTarget(target_id);
4464 relations_.push_back(relation);
4465 }
4466
4467 void BrowserAccessibilityWin::AddBidirectionalRelations(
4468 const base::string16& relation_type,
4469 const base::string16& reverse_relation_type,
4470 ui::AXIntListAttribute attribute) {
4471 if (!HasIntListAttribute(attribute))
4443 return; 4472 return;
4444 4473
4445 const std::vector<int32_t>& ids = GetIntListAttribute(src_attr); 4474 CComObject<BrowserAccessibilityRelation>* relation;
4446 for (size_t i = 0; i < ids.size(); ++i) { 4475 HRESULT hr =
4447 CComObject<BrowserAccessibilityRelation>* relation; 4476 CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
4448 HRESULT hr = 4477 DCHECK(SUCCEEDED(hr));
4449 CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation); 4478 relation->AddRef();
4450 DCHECK(SUCCEEDED(hr)); 4479 relation->Initialize(this, relation_type);
4451 relation->AddRef(); 4480
4452 relation->Initialize(this, iaccessiblerelation_type); 4481 for (int target_id : GetIntListAttribute(attribute)) {
4453 relation->AddTarget(ids[i]); 4482 BrowserAccessibilityWin* target =
4454 relations_.push_back(relation); 4483 GetFromID(static_cast<int32_t>(target_id));
4484 if (!target || !target->instance_active())
4485 continue;
4486 relation->AddTarget(target_id);
4487 target->AddRelation(reverse_relation_type, GetId());
4488 }
4489
4490 relations_.push_back(relation);
4491 }
4492
4493 // Clears all the forward relations from this object to any other object and the
4494 // associated reverse relations on the other objects, but leaves any reverse
4495 // relations on this object alone.
4496 void BrowserAccessibilityWin::ClearOwnRelations() {
4497 RemoveBidirectionalRelationsOfType(IA2_RELATION_CONTROLLER_FOR,
4498 IA2_RELATION_CONTROLLED_BY);
4499 RemoveBidirectionalRelationsOfType(IA2_RELATION_DESCRIBED_BY,
4500 IA2_RELATION_DESCRIPTION_FOR);
4501 RemoveBidirectionalRelationsOfType(IA2_RELATION_FLOWS_TO,
4502 IA2_RELATION_FLOWS_FROM);
4503 RemoveBidirectionalRelationsOfType(IA2_RELATION_LABELLED_BY,
4504 IA2_RELATION_LABEL_FOR);
4505
4506 relations_.erase(
4507 std::remove_if(relations_.begin(), relations_.end(),
4508 [](BrowserAccessibilityRelation* relation) {
4509 if (relation->get_type() == IA2_RELATION_MEMBER_OF) {
4510 relation->Release();
4511 return true;
4512 }
4513 return false;
4514 }),
4515 relations_.end());
4516 }
4517
4518 void BrowserAccessibilityWin::RemoveBidirectionalRelationsOfType(
4519 const base::string16& relation_type,
4520 const base::string16& reverse_relation_type) {
4521 for (auto iter = relations_.begin(); iter != relations_.end();) {
4522 BrowserAccessibilityRelation* relation = *iter;
4523 DCHECK(relation);
4524 if (relation->get_type() == relation_type) {
4525 for (int target_id : relation->get_target_ids()) {
4526 BrowserAccessibilityWin* target =
4527 GetFromID(static_cast<int32_t>(target_id));
4528 if (!target || !target->instance_active())
4529 continue;
4530 target->RemoveTargetFromRelation(reverse_relation_type, GetId());
4531 }
4532 relation->Release();
4533 iter = relations_.erase(iter);
4534 } else {
4535 ++iter;
4536 }
4455 } 4537 }
4456 } 4538 }
4457 4539
4540 void BrowserAccessibilityWin::RemoveTargetFromRelation(
4541 const base::string16& relation_type,
4542 int target_id) {
4543 for (auto iter = relations_.begin(); iter != relations_.end();) {
4544 BrowserAccessibilityRelation* relation = *iter;
4545 DCHECK(relation);
4546 if (relation->get_type() == relation_type) {
4547 // If |target_id| is not present, |RemoveTarget| will do nothing.
4548 relation->RemoveTarget(target_id);
4549 }
4550 if (relation->get_target_ids().empty()) {
4551 relation->Release();
4552 iter = relations_.erase(iter);
4553 } else {
4554 ++iter;
4555 }
4556 }
4557 }
4558
4458 void BrowserAccessibilityWin::UpdateRequiredAttributes() { 4559 void BrowserAccessibilityWin::UpdateRequiredAttributes() {
4459 // Expose slider value. 4560 // Expose slider value.
4460 if (ia_role() == ROLE_SYSTEM_PROGRESSBAR || 4561 if (ia_role() == ROLE_SYSTEM_PROGRESSBAR ||
4461 ia_role() == ROLE_SYSTEM_SCROLLBAR || 4562 ia_role() == ROLE_SYSTEM_SCROLLBAR ||
4462 ia_role() == ROLE_SYSTEM_SLIDER) { 4563 ia_role() == ROLE_SYSTEM_SLIDER) {
4463 base::string16 value_text = GetValueText(); 4564 base::string16 value_text = GetValueText();
4464 SanitizeStringAttributeForIA2(value_text, &value_text); 4565 SanitizeStringAttributeForIA2(value_text, &value_text);
4465 win_attributes_->ia2_attributes.push_back(L"valuetext:" + value_text); 4566 win_attributes_->ia2_attributes.push_back(L"valuetext:" + value_text);
4466 } 4567 }
4467 4568
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after
5088 return static_cast<BrowserAccessibilityWin*>(obj); 5189 return static_cast<BrowserAccessibilityWin*>(obj);
5089 } 5190 }
5090 5191
5091 const BrowserAccessibilityWin* 5192 const BrowserAccessibilityWin*
5092 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { 5193 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) {
5093 DCHECK(!obj || obj->IsNative()); 5194 DCHECK(!obj || obj->IsNative());
5094 return static_cast<const BrowserAccessibilityWin*>(obj); 5195 return static_cast<const BrowserAccessibilityWin*>(obj);
5095 } 5196 }
5096 5197
5097 } // namespace content 5198 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698