1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/autocomplete/autocomplete_accessibility.h"
6
7#include "chrome/browser/autocomplete/autocomplete_edit.h"
8#include "chrome/browser/autocomplete/autocomplete_edit_view_win.h"
9#include "grit/generated_resources.h"
10#include "ui/base/l10n/l10n_util.h"
11#include "views/accessibility/native_view_accessibility_win.h"
12#include "views/view.h"
13
14HRESULT AutocompleteAccessibility::Initialize(
15    const AutocompleteEditViewWin* edit_box) {
16  if (edit_box == NULL) {
17    return E_INVALIDARG;
18  }
19
20  edit_box_ = edit_box;
21
22  // Create a default accessible object for this instance.
23  return CreateStdAccessibleObject(edit_box_->m_hWnd, OBJID_CLIENT,
24      IID_IAccessible,
25      reinterpret_cast<void **>(default_accessibility_server_.Receive()));
26}
27
28STDMETHODIMP AutocompleteAccessibility::get_accChildCount(LONG* child_count) {
29  if (!child_count) {
30    return E_INVALIDARG;
31  }
32
33  DCHECK(default_accessibility_server_);
34  return default_accessibility_server_->get_accChildCount(child_count);
35}
36
37STDMETHODIMP AutocompleteAccessibility::get_accChild(VARIANT var_child,
38                                                     IDispatch** disp_child) {
39  if (var_child.vt != VT_I4 || !disp_child) {
40    return E_INVALIDARG;
41  }
42
43  // If var_child is the parent, remain with the same IDispatch
44  if (var_child.lVal == CHILDID_SELF)
45    return S_OK;
46
47  *disp_child = NULL;
48  return S_FALSE;
49}
50
51STDMETHODIMP AutocompleteAccessibility::get_accParent(IDispatch** disp_parent) {
52  if (!disp_parent) {
53    return E_INVALIDARG;
54  }
55
56  if (edit_box_->parent_view() == NULL) {
57    *disp_parent = NULL;
58    return S_FALSE;
59  }
60
61  // Retrieve the IDispatch interface for the parent view.
62  *disp_parent = NativeViewAccessibilityWin::GetAccessibleForView(
63      edit_box_->parent_view());
64  // Increment the reference count for the retrieved interface.
65  (*disp_parent)->AddRef();
66  return S_OK;
67}
68
69STDMETHODIMP AutocompleteAccessibility::accNavigate(LONG nav_dir, VARIANT start,
70                                                    VARIANT* end) {
71  if (start.vt != VT_I4 || !end) {
72    return E_INVALIDARG;
73  }
74
75  DCHECK(default_accessibility_server_);
76  return default_accessibility_server_->accNavigate(nav_dir, start, end);
77}
78
79STDMETHODIMP AutocompleteAccessibility::get_accFocus(VARIANT* focus_child) {
80  if (!focus_child) {
81    return E_INVALIDARG;
82  }
83
84  DCHECK(default_accessibility_server_);
85  return default_accessibility_server_->get_accFocus(focus_child);
86}
87
88STDMETHODIMP AutocompleteAccessibility::get_accName(VARIANT var_id,
89                                                    BSTR* name) {
90  if (var_id.vt != VT_I4 || !name) {
91    return E_INVALIDARG;
92  }
93
94  string16 temp_name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
95
96  if (!temp_name.empty()) {
97    // Return name retrieved.
98    *name = SysAllocString(temp_name.c_str());
99  } else {
100    // If no name is found, return S_FALSE.
101    return S_FALSE;
102  }
103  DCHECK(*name);
104
105  return S_OK;
106}
107
108STDMETHODIMP AutocompleteAccessibility::get_accDescription(VARIANT var_id,
109                                                           BSTR* desc) {
110  if (var_id.vt != VT_I4 || !desc) {
111    return E_INVALIDARG;
112  }
113
114  return S_FALSE;
115}
116
117STDMETHODIMP AutocompleteAccessibility::get_accValue(VARIANT var_id,
118                                                     BSTR* value) {
119  if (var_id.vt != VT_I4 || !value) {
120    return E_INVALIDARG;
121  }
122
123  string16 temp_value;
124
125  if (var_id.lVal != CHILDID_SELF)
126    return E_INVALIDARG;
127
128  // Edit box has no children, only handle self.
129  temp_value = edit_box_->GetText();
130  if (temp_value.empty())
131    return S_FALSE;
132
133  // Return value retrieved.
134  *value = SysAllocString(temp_value.c_str());
135
136  DCHECK(*value);
137
138  return S_OK;
139}
140
141STDMETHODIMP AutocompleteAccessibility::get_accState(VARIANT var_id,
142                                                     VARIANT* state) {
143  if (var_id.vt != VT_I4 || !state) {
144    return E_INVALIDARG;
145  }
146
147  DCHECK(default_accessibility_server_);
148  HRESULT hr = default_accessibility_server_->get_accState(var_id, state);
149
150  if (hr != S_OK)
151    return hr;
152
153  // Adding on state to convey the fact that there is a dropdown.
154  state->lVal |= STATE_SYSTEM_HASPOPUP;
155  return S_OK;
156}
157
158STDMETHODIMP AutocompleteAccessibility::get_accRole(VARIANT var_id,
159                                                    VARIANT* role) {
160  if (var_id.vt != VT_I4 || !role) {
161    return E_INVALIDARG;
162  }
163
164  role->vt = VT_I4;
165
166  // Need to override the default role, which is ROLE_SYSTEM_CLIENT.
167  if (var_id.lVal == CHILDID_SELF) {
168    role->lVal = ROLE_SYSTEM_TEXT;
169  } else {
170    return S_FALSE;
171  }
172
173  return S_OK;
174}
175
176STDMETHODIMP AutocompleteAccessibility::get_accDefaultAction(VARIANT var_id,
177                                                             BSTR* def_action) {
178  if (var_id.vt != VT_I4 || !def_action) {
179    return E_INVALIDARG;
180  }
181
182  return S_FALSE;
183}
184
185STDMETHODIMP AutocompleteAccessibility::accLocation(LONG* x_left, LONG* y_top,
186                                                    LONG* width, LONG* height,
187                                                    VARIANT var_id) {
188  if (var_id.vt != VT_I4 || !x_left || !y_top || !width || !height) {
189    return E_INVALIDARG;
190  }
191
192  DCHECK(default_accessibility_server_);
193  return default_accessibility_server_->accLocation(x_left, y_top, width,
194                                                    height, var_id);
195}
196
197STDMETHODIMP AutocompleteAccessibility::accHitTest(LONG x_left, LONG y_top,
198                                                   VARIANT* child) {
199  if (!child) {
200    return E_INVALIDARG;
201  }
202
203  DCHECK(default_accessibility_server_);
204  return default_accessibility_server_->accHitTest(x_left, y_top, child);
205}
206
207STDMETHODIMP AutocompleteAccessibility::get_accKeyboardShortcut(VARIANT var_id,
208                                                                BSTR* acc_key) {
209  if (var_id.vt != VT_I4 || !acc_key) {
210    return E_INVALIDARG;
211  }
212
213  return S_FALSE;
214}
215
216// IAccessible functions not supported.
217
218HRESULT AutocompleteAccessibility::accDoDefaultAction(VARIANT var_id) {
219  return DISP_E_MEMBERNOTFOUND;
220}
221
222STDMETHODIMP AutocompleteAccessibility::get_accSelection(VARIANT* selected) {
223  if (selected)
224    selected->vt = VT_EMPTY;
225  return DISP_E_MEMBERNOTFOUND;
226}
227
228STDMETHODIMP AutocompleteAccessibility::accSelect(LONG flagsSelect,
229                                                  VARIANT var_id) {
230  return DISP_E_MEMBERNOTFOUND;
231}
232
233STDMETHODIMP AutocompleteAccessibility::get_accHelp(VARIANT var_id,
234                                                    BSTR* help) {
235  if (help)
236    *help = NULL;
237  return DISP_E_MEMBERNOTFOUND;
238}
239
240STDMETHODIMP AutocompleteAccessibility::get_accHelpTopic(BSTR* help_file,
241                                                         VARIANT var_id,
242                                                         LONG* topic_id) {
243  if (help_file) {
244    *help_file = NULL;
245  }
246  if (topic_id) {
247    *topic_id = static_cast<LONG>(-1);
248  }
249  return DISP_E_MEMBERNOTFOUND;
250}
251
252STDMETHODIMP AutocompleteAccessibility::put_accName(VARIANT var_id,
253                                                    BSTR put_name) {
254  // Deprecated.
255  return DISP_E_MEMBERNOTFOUND;
256}
257
258STDMETHODIMP AutocompleteAccessibility::put_accValue(VARIANT var_id,
259                                                     BSTR put_val) {
260  // Deprecated.
261  return DISP_E_MEMBERNOTFOUND;
262}
263