Chromium Code Reviews| Index: ui/views/accessibility/native_view_accessibility_win.cc |
| diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc |
| index 10c17ff3d6d636f153644cf34b0ece332e4d2a6a..6c9996b08ffdf04997372aabcd5c26082bf3e6c5 100644 |
| --- a/ui/views/accessibility/native_view_accessibility_win.cc |
| +++ b/ui/views/accessibility/native_view_accessibility_win.cc |
| @@ -189,6 +189,7 @@ void AccessibleWebViewRegistry::QueryIAccessible2Interface(View* web_view) { |
| long NativeViewAccessibilityWin::next_unique_id_ = 1; |
| int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0}; |
| int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0; |
| +std::vector<int> NativeViewAccessibilityWin::alert_target_view_storage_ids_; |
| // static |
| NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { |
| @@ -210,6 +211,7 @@ NativeViewAccessibilityWin::NativeViewAccessibilityWin() |
| } |
| NativeViewAccessibilityWin::~NativeViewAccessibilityWin() { |
| + RemoveAlertTarget(); |
| } |
| void NativeViewAccessibilityWin::NotifyAccessibilityEvent( |
| @@ -236,6 +238,10 @@ void NativeViewAccessibilityWin::NotifyAccessibilityEvent( |
| ::NotifyWinEvent(MSAAEvent(event_type), hwnd, OBJID_CLIENT, child_id); |
| next_view_storage_id_index_ = |
| (next_view_storage_id_index_ + 1) % kMaxViewStorageIds; |
| + |
| + // Keep track of views that are a target of an alert event. |
| + if (event_type == ui::AX_EVENT_ALERT) |
| + AddAlertTarget(); |
| } |
| gfx::NativeViewAccessible NativeViewAccessibilityWin::GetNativeObject() { |
| @@ -865,6 +871,61 @@ STDMETHODIMP NativeViewAccessibilityWin::get_windowHandle(HWND* window_handle) { |
| return *window_handle ? S_OK : S_FALSE; |
| } |
| +STDMETHODIMP NativeViewAccessibilityWin::get_relationTargetsOfType( |
| + BSTR type_bstr, |
| + long max_targets, |
| + IUnknown ***targets, |
| + long *n_targets) { |
| + if (!view_) |
| + return E_FAIL; |
| + |
| + if (!targets || !n_targets) |
| + return E_INVALIDARG; |
| + |
| + *n_targets = 0; |
| + *targets = NULL; |
| + |
| + // Only respond to requests for relations of type "alerts" on the |
| + // root view. |
| + base::string16 type(type_bstr); |
| + if (type != L"alerts" || view_->parent()) |
| + return S_FALSE; |
| + |
| + // Collect all of the alert views that are still valid. |
| + std::vector<View*> alert_views; |
| + ViewStorage* view_storage = ViewStorage::GetInstance(); |
| + for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) { |
| + int view_storage_id = alert_target_view_storage_ids_[i]; |
| + View* view = view_storage->RetrieveView(view_storage_id); |
| + if (!view || !view_->Contains(view)) |
| + continue; |
| + alert_views.push_back(view); |
| + } |
| + |
| + long count = alert_views.size(); |
| + if (count == 0) |
| + return S_FALSE; |
| + |
| + // Don't return more targets than max_targets - but note that the caller |
| + // is allowed to specify max_targets=0 to mean no limit. |
| + if (max_targets > 0 && count > max_targets) |
| + count = max_targets; |
| + |
| + // Return the number of targets. |
| + *n_targets = count; |
| + |
| + // Allocate COM memory for the result array and populate it. |
| + if (targets) { |
|
David Tseng
2014/05/13 01:34:54
Didn't you check this above?
dmazzoni
2014/05/13 07:38:46
Done.
|
| + *targets = static_cast<IUnknown**>( |
| + CoTaskMemAlloc(count * sizeof(IUnknown*))); |
| + for (long i = 0; i < count; ++i) { |
| + (*targets)[i] = alert_views[i]->GetNativeViewAccessible(); |
| + (*targets)[i]->AddRef(); |
| + } |
| + } |
| + return S_OK; |
| +} |
| + |
| // |
| // IAccessibleText |
| // |
| @@ -1071,11 +1132,12 @@ STDMETHODIMP NativeViewAccessibilityWin::QueryService( |
| if (!view_) |
| return E_FAIL; |
| - if (riid == IID_IAccessible2) |
| + if (riid == IID_IAccessible2 || riid == IID_IAccessible2_2) |
| AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); |
| if (guidService == IID_IAccessible || |
| guidService == IID_IAccessible2 || |
| + guidService == IID_IAccessible2_2 || |
| guidService == IID_IAccessibleText) { |
| return QueryInterface(riid, object); |
| } |
| @@ -1412,4 +1474,32 @@ void NativeViewAccessibilityWin::PopulateChildWidgetVector( |
| } |
| } |
| +void NativeViewAccessibilityWin::AddAlertTarget() { |
| + ViewStorage* view_storage = ViewStorage::GetInstance(); |
| + for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) { |
| + int view_storage_id = alert_target_view_storage_ids_[i]; |
| + View* view = view_storage->RetrieveView(view_storage_id); |
| + if (view == view_) |
| + return; |
| + } |
| + int view_storage_id = view_storage->CreateStorageID(); |
| + view_storage->StoreView(view_storage_id, view_); |
| + alert_target_view_storage_ids_.push_back(view_storage_id); |
| +} |
| + |
| +void NativeViewAccessibilityWin::RemoveAlertTarget() { |
| + ViewStorage* view_storage = ViewStorage::GetInstance(); |
| + size_t i = 0; |
| + while (i < alert_target_view_storage_ids_.size()) { |
| + int view_storage_id = alert_target_view_storage_ids_[i]; |
| + View* view = view_storage->RetrieveView(view_storage_id); |
| + if (view == NULL || view == view_) { |
| + alert_target_view_storage_ids_.erase( |
| + alert_target_view_storage_ids_.begin() + i); |
|
David Tseng
2014/05/13 01:34:54
break? (since you're never duplicating ids) on ins
David Tseng
2014/05/13 13:47:11
FYI (unresolved comment); not really a big deal si
dmazzoni
2014/05/13 15:52:44
Sorry, forgot to respond. I don't want to break be
|
| + } else { |
| + ++i; |
| + } |
| + } |
| +} |
| + |
| } // namespace views |