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..241087d84f54fc19ac0b7e2891cd6715b90da306 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,59 @@ 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. |
+ *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 +1130,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 +1472,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); |
+ } else { |
+ ++i; |
+ } |
+ } |
+} |
+ |
} // namespace views |