"Fossies" - the Fresh Open Source Software Archive 
Member "selenium-selenium-4.8.1/cpp/iedriver/Alert.cpp" (17 Feb 2023, 23937 Bytes) of package /linux/www/selenium-selenium-4.8.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "Alert.cpp" see the
Fossies "Dox" file reference documentation.
1 // Licensed to the Software Freedom Conservancy (SFC) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The SFC licenses this file
5 // to you under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 #include "Alert.h"
18
19 #include <UIAutomation.h>
20
21 #include "errorcodes.h"
22 #include "logging.h"
23 #include "DocumentHost.h"
24 #include "StringUtilities.h"
25 #include "WebDriverConstants.h"
26
27 #define INVALID_CONTROL_ID -1
28
29 namespace webdriver {
30
31 Alert::Alert(std::shared_ptr<DocumentHost> browser, HWND handle) {
32 LOG(TRACE) << "Entering Alert::Alert";
33 this->browser_ = browser;
34 this->alert_handle_ = handle;
35
36 this->is_standard_alert_ = true;
37 this->is_standard_control_alert_ = true;
38 HWND direct_ui_child = this->GetDirectUIChild();
39 if (direct_ui_child) {
40 this->is_standard_control_alert_ = false;
41 DialogButtonInfo cancel_button_info = this->GetDialogButton(CANCEL);
42 if (cancel_button_info.button_exists) {
43 this->is_standard_alert_ = !IsLinkButton(cancel_button_info.button_handle);
44 } else {
45 DialogButtonInfo ok_button_info = this->GetDialogButton(OK);
46 if (ok_button_info.button_exists) {
47 this->is_standard_alert_ = !IsLinkButton(ok_button_info.button_handle);
48 } else {
49 this->is_standard_alert_ = false;
50 }
51 }
52 }
53
54 std::vector<char> window_class(30);
55 ::GetClassNameA(handle, &window_class[0], 30);
56
57 if (strcmp(&window_class[0], SECURITY_DIALOG_WINDOW_CLASS) == 0) {
58 this->is_standard_alert_ = false;
59 this->is_standard_control_alert_ = false;
60 this->is_security_alert_ = true;
61 } else {
62 std::vector<HWND> text_boxes;
63 ::EnumChildWindows(this->alert_handle_,
64 &Alert::FindTextBoxes,
65 reinterpret_cast<LPARAM>(&text_boxes));
66 this->is_security_alert_ = text_boxes.size() > 1;
67 }
68 }
69
70
71 Alert::~Alert(void) {
72 }
73
74 int Alert::Accept() {
75 LOG(TRACE) << "Entering Alert::Accept";
76 DialogButtonInfo button_info = this->GetDialogButton(OK);
77 if (!button_info.button_exists) {
78 // No OK button on dialog. Look for a cancel button
79 // (JavaScript alert() dialogs have a single button, but its ID
80 // can be that of a "cancel" button.)
81 LOG(INFO) << "OK button does not exist on dialog; looking for Cancel button";
82 button_info = this->GetDialogButton(CANCEL);
83 }
84
85 if (!button_info.button_exists) {
86 LOG(WARN) << "OK and Cancel button do not exist on alert";
87 return EUNHANDLEDERROR;
88 }
89
90 LOG(DEBUG) << "Closing alert using SendMessage";
91 int status_code = this->ClickAlertButton(button_info);
92 return WD_SUCCESS;
93 }
94
95 int Alert::Dismiss() {
96 LOG(TRACE) << "Entering Alert::Dismiss";
97 DialogButtonInfo button_info = this->GetDialogButton(CANCEL);
98 if (!button_info.button_exists) {
99 if (!this->is_standard_control_alert_) {
100 // If this is not a standard control alert (i.e., has the
101 // "do not create any more dialogs check box"), the use of
102 // dialog control IDs won't work, so we have to look explicitly
103 // for the OK button.
104 button_info = this->GetDialogButton(OK);
105 }
106 }
107
108 if (!button_info.button_exists) {
109 LOG(WARN) << "Cancel button does not exist on alert";
110 return EUNHANDLEDERROR;
111 }
112
113 // TODO(JimEvans): Check return code and return an appropriate
114 // error if the alert didn't get closed properly.
115 LOG(DEBUG) << "Closing alert using SendMessage";
116 int status_code = this->ClickAlertButton(button_info);
117 return WD_SUCCESS;
118 }
119
120 int Alert::SendKeys(const std::string& keys) {
121 LOG(TRACE) << "Entering Alert::SendKeys";
122 TextBoxFindInfo text_box_find_info;
123 text_box_find_info.textbox_handle = NULL;
124 text_box_find_info.match_proc = &Alert::IsSimpleEdit;
125 return this->SendKeysInternal(keys, &text_box_find_info);
126 }
127
128 int Alert::SetUserName(const std::string& username) {
129 LOG(TRACE) << "Entering Alert::SetUserName";
130 // If this isn't a security alert, return an error.
131 if (!this->is_security_alert_) {
132 return EUNEXPECTEDALERTOPEN;
133 }
134 return this->SendKeys(username);
135 }
136
137 int Alert::SetPassword(const std::string& password) {
138 LOG(TRACE) << "Entering Alert::SetPassword";
139 // If this isn't a security alert, return an error.
140 if (!this->is_security_alert_) {
141 return EUNEXPECTEDALERTOPEN;
142 }
143 TextBoxFindInfo text_box_find_info;
144 text_box_find_info.textbox_handle = NULL;
145 text_box_find_info.match_proc = &Alert::IsPasswordEdit;
146 return this->SendKeysInternal(password, &text_box_find_info);
147 }
148
149 int Alert::SendKeysInternal(const std::string& keys,
150 TextBoxFindInfo* text_box_find_info) {
151 LOG(TRACE) << "Entering Alert::SendKeysInternal";
152 if (!this->is_standard_alert_) {
153 return EUNSUPPORTEDOPERATION;
154 }
155 // Alert present, find the text box.
156 // Retry up to 10 times to find the dialog.
157 int max_wait = 10;
158 while ((text_box_find_info->textbox_handle == NULL) && --max_wait) {
159 ::EnumChildWindows(this->alert_handle_,
160 &Alert::FindTextBox,
161 reinterpret_cast<LPARAM>(text_box_find_info));
162 if (text_box_find_info->textbox_handle == NULL) {
163 ::Sleep(50);
164 }
165 }
166
167 if (text_box_find_info->textbox_handle == NULL) {
168 LOG(WARN) << "Text box not found on alert";
169 return EELEMENTNOTDISPLAYED;
170 } else {
171 LOG(DEBUG) << "Sending keystrokes to alert using SendMessage";
172 std::wstring text = StringUtilities::ToWString(keys);
173 ::SendMessage(text_box_find_info->textbox_handle,
174 WM_SETTEXT,
175 NULL,
176 reinterpret_cast<LPARAM>(text.c_str()));
177 }
178 return WD_SUCCESS;
179 }
180
181 std::string Alert::GetText() {
182 LOG(TRACE) << "Entering Alert::GetText";
183 std::string alert_text_value = "";
184 if (this->is_standard_control_alert_) {
185 alert_text_value = this->GetStandardDialogText();
186 } else {
187 std::string alert_text = this->GetDirectUIDialogText();
188 if (!this->is_security_alert_) {
189 if (!this->is_standard_alert_) {
190 // This means the alert is from onbeforeunload, and we need to
191 // strip off everything up to and including the first CR-LF pair.
192 size_t first_crlf = alert_text.find("\r\n\r\n");
193 if (first_crlf != std::string::npos && first_crlf + 4 < alert_text.size()) {
194 alert_text_value = alert_text.substr(first_crlf + 4);
195 }
196 } else {
197 alert_text_value = alert_text;
198 }
199 }
200 }
201 return alert_text_value;
202 }
203
204 std::string Alert::GetStandardDialogText() {
205 LOG(TRACE) << "Entering Alert::GetStandardDialogText";
206 TextLabelFindInfo info;
207 info.label_handle = NULL;
208 info.control_id_found = 0;
209 info.excluded_control_id = 0;
210
211 // Alert present, find the OK button.
212 // Retry up to 10 times to find the dialog.
213 int max_wait = 10;
214 while ((info.label_handle == NULL) && --max_wait) {
215 ::EnumChildWindows(this->alert_handle_,
216 &Alert::FindTextLabel,
217 reinterpret_cast<LPARAM>(&info));
218 if (info.label_handle == NULL) {
219 ::Sleep(50);
220 }
221 }
222
223 // BIG ASSUMPTION HERE! If we found the text label, assume that
224 // all other controls on the alert are fully drawn too.
225 TextBoxFindInfo textbox_find_info;
226 textbox_find_info.textbox_handle = NULL;
227 textbox_find_info.match_proc = &Alert::IsSimpleEdit;
228 ::EnumChildWindows(this->alert_handle_,
229 &Alert::FindTextBox,
230 reinterpret_cast<LPARAM>(&textbox_find_info));
231 if (textbox_find_info.textbox_handle) {
232 // There's a text box on the alert. That means the first
233 // label found is the system-provided label. Ignore that
234 // one and return the next one.
235 info.label_handle = NULL;
236 info.excluded_control_id = info.control_id_found;
237 info.control_id_found = 0;
238 ::EnumChildWindows(this->alert_handle_,
239 &Alert::FindTextLabel,
240 reinterpret_cast<LPARAM>(&info));
241 }
242
243 std::string alert_text_value;
244 if (info.label_handle == NULL) {
245 alert_text_value = "";
246 } else {
247 int text_length = ::GetWindowTextLength(info.label_handle);
248 std::vector<wchar_t> text_buffer(text_length + 1);
249 ::GetWindowText(info.label_handle, &text_buffer[0], text_length + 1);
250 std::wstring alert_text = &text_buffer[0];
251 alert_text_value = StringUtilities::ToString(alert_text);
252 }
253 return alert_text_value;
254 }
255
256 std::string Alert::GetDirectUIDialogText() {
257 LOG(TRACE) << "Entering Alert::GetDirectUIDialogText";
258 std::string alert_text_value = "";
259 HWND direct_ui_child_handle = this->GetDirectUIChild();
260
261 CComPtr<IAccessible> window_object;
262 HRESULT hr = ::AccessibleObjectFromWindow(
263 direct_ui_child_handle,
264 OBJID_WINDOW,
265 IID_IAccessible,
266 reinterpret_cast<void**>(&window_object));
267 if (FAILED(hr)) {
268 LOGHR(WARN, hr) << "Failed to get Active Accessibility window object from dialog";
269 return alert_text_value;
270 }
271
272 // ASSUMPTION: There is an object with the role of "pane" as a child of
273 // the window object.
274 CComPtr<IAccessible> pane_object = this->GetChildWithRole(window_object,
275 ROLE_SYSTEM_PANE,
276 0);
277 if (!pane_object) {
278 LOG(WARN) << "Failed to get Active Accessibility pane child object from window";
279 return alert_text_value;
280 }
281
282 int child_index = 0;
283 if (!this->is_standard_alert_) {
284 // ASSUMPTION: This means the alert is from onbeforeunload, and
285 // the second "static text" accessibility object is the one
286 // that contains the message.
287 child_index = 1;
288 }
289
290 CComPtr<IAccessible> message_text_object = this->GetChildWithRole(
291 pane_object,
292 ROLE_SYSTEM_STATICTEXT,
293 child_index);
294 if (!message_text_object) {
295 LOG(WARN) << "Failed to get Active Accessibility text child object from pane";
296 return alert_text_value;
297 }
298
299 CComVariant child_id;
300 child_id.vt = VT_I4;
301 child_id.lVal = CHILDID_SELF;
302
303 CComBSTR text_bstr;
304 hr = message_text_object->get_accName(child_id, &text_bstr);
305 if (FAILED(hr)) {
306 LOGHR(WARN, hr) << "Failed to get accName property from text object";
307 return alert_text_value;
308 } else if (hr != S_OK) {
309 // N.B., get_accName can return an error value without it being a
310 // standard COM error.
311 LOG(WARN) << "Getting accName property from text object returned an error "
312 << "(value: " << hr << "). The text object may not have a name.";
313 return alert_text_value;
314 } else if (text_bstr == NULL) {
315 LOG(WARN) << "Getting accName property from text object returned a null "
316 << "value";
317 return alert_text_value;
318 }
319
320 std::wstring text = text_bstr;
321 alert_text_value = StringUtilities::ToString(text);
322 return alert_text_value;
323 }
324
325 IAccessible* Alert::GetChildWithRole(IAccessible* parent, long expected_role, int index) {
326 LOG(TRACE) << "Entering Alert::GetChildWithRole";
327 IAccessible* child = NULL;
328 long child_count;
329 HRESULT hr = parent->get_accChildCount(&child_count);
330 if (FAILED(hr)) {
331 LOGHR(WARN, hr) << "Failed to get accChildCount property from Active Accessibility object";
332 return child;
333 }
334
335 long returned_children = 0;
336 std::vector<CComVariant> child_array(child_count);
337 hr = ::AccessibleChildren(parent, 0, child_count, &child_array[0], &returned_children);
338
339 int found_index = 0;
340 for (long i = 0; i < child_count; ++i) {
341 if (child_array[i].vt == VT_DISPATCH) {
342 CComPtr<IAccessible> child_object;
343 hr = child_array[i].pdispVal->QueryInterface<IAccessible>(&child_object);
344 if (FAILED(hr)) {
345 LOGHR(WARN, hr) << "QueryInterface for IAccessible failed for child object with index " << i;
346 }
347
348 CComVariant child_id;
349 child_id.vt = VT_I4;
350 child_id.lVal = CHILDID_SELF;
351
352 CComVariant actual_role;
353 hr = child_object->get_accRole(child_id, &actual_role);
354 if (FAILED(hr)) {
355 LOGHR(WARN, hr) << "Failed to get accRole property from Active Accessibility object";
356 }
357
358 if (expected_role == actual_role.lVal) {
359 if (found_index == index) {
360 child = child_object.Detach();
361 } else {
362 ++found_index;
363 }
364 }
365 LOG(DEBUG) << "accRole for child with index " << i << ": " << actual_role.lVal;
366 }
367 }
368 return child;
369 }
370
371 HWND Alert::GetDirectUIChild() {
372 LOG(TRACE) << "Entering Alert::GetDirectUIChild";
373 HWND direct_ui_child = NULL;
374 ::EnumChildWindows(this->alert_handle_,
375 &Alert::FindDirectUIChild,
376 reinterpret_cast<LPARAM>(&direct_ui_child));
377 return direct_ui_child;
378 }
379
380 int Alert::ClickAlertButton(DialogButtonInfo button_info) {
381 LOG(TRACE) << "Entering Alert::ClickAlertButton";
382 // Click on the appropriate button of the Alert
383 if (this->is_standard_control_alert_) {
384 ::SendMessage(this->alert_handle_,
385 WM_COMMAND,
386 button_info.button_control_id,
387 NULL);
388 } else {
389 if (button_info.use_accessibility) {
390 int status_code = ClickAlertButtonUsingAccessibility(button_info.accessibility_id);
391 if (status_code != WD_SUCCESS) {
392 return status_code;
393 }
394 } else {
395 // For non-standard alerts (that is, alerts that are not
396 // created by alert(), confirm() or prompt() JavaScript
397 // functions), we cheat. Sending the BN_CLICKED notification
398 // via WM_COMMAND makes the dialog think that the proper
399 // button was clicked, but it's not the same as sending the
400 // click message to the button. N.B., sending the BM_CLICK
401 // message to the button may fail if the dialog doesn't have
402 // focus, so we do it this way. Also, we send the notification
403 // to the immediate parent of the button, which, in turn,
404 // notifies the top-level dialog.
405 ::SendMessage(::GetParent(button_info.button_handle),
406 WM_COMMAND,
407 MAKEWPARAM(0, BN_CLICKED),
408 reinterpret_cast<LPARAM>(button_info.button_handle));
409 }
410 }
411 // Hack to make sure alert is really closed, and browser
412 // is ready for the next operation. This may be a flawed
413 // algorithim, since the busy property of the browser may
414 // not be the right thing to check here.
415 int retry_count = 20;
416 bool is_alert_handle_valid = (::IsWindow(this->alert_handle_) == TRUE);
417 while ((is_alert_handle_valid || this->browser_->IsBusy()) && retry_count > 0) {
418 ::Sleep(50);
419 is_alert_handle_valid = (::IsWindow(this->alert_handle_) == TRUE);
420 retry_count--;
421 }
422
423 // TODO(JimEvans): Check for the following error conditions:
424 // 1. Alert window still present (::IsWindow(this->alert_handle_) == TRUE)
425 // 2. Browser still busy (this->browser_->IsBusy() == true)
426 // and return an appropriate non-WD_SUCCESS error code.
427 LOG(DEBUG) << "IsWindow() for alert handle 0x" << this->alert_handle_ << ": "
428 << is_alert_handle_valid ? "true" : "false";
429 return WD_SUCCESS;
430 }
431
432 Alert::DialogButtonInfo Alert::GetDialogButton(BUTTON_TYPE button_type) {
433 LOG(TRACE) << "Entering Alert::GetDialogButton";
434 // Return the simple version of the struct so that subclasses do not
435 // have to know anything about the function pointer definition.
436 DialogButtonInfo button_info;
437 if (this->is_standard_alert_ || !this->is_security_alert_) {
438 DialogButtonFindInfo button_find_info;
439 button_find_info.button_handle = NULL;
440 button_find_info.button_control_id = this->is_standard_alert_ ? IDOK : INVALID_CONTROL_ID;
441 if (button_type == OK) {
442 button_find_info.match_proc = &Alert::IsOKButton;
443 } else {
444 button_find_info.match_proc = &Alert::IsCancelButton;
445 }
446
447 int max_wait = 10;
448 // Retry up to 10 times to find the dialog.
449 while ((button_find_info.button_handle == NULL) && --max_wait) {
450 ::EnumChildWindows(this->alert_handle_,
451 &Alert::FindDialogButton,
452 reinterpret_cast<LPARAM>(&button_find_info));
453 if (button_find_info.button_handle == NULL) {
454 ::Sleep(50);
455 } else {
456 break;
457 }
458 }
459 button_info.button_handle = button_find_info.button_handle;
460 button_info.button_control_id = button_find_info.button_control_id;
461 button_info.button_exists = button_find_info.button_handle != NULL;
462 button_info.accessibility_id = "";
463 button_info.use_accessibility = false;
464 } else {
465 button_info.button_handle = NULL;
466 button_info.button_control_id = 0;
467 button_info.button_exists = true;
468 button_info.accessibility_id = button_type == OK ? "OKButton" : "CancelButton";
469 button_info.use_accessibility = true;
470 }
471
472 return button_info;
473 }
474
475 int Alert::ClickAlertButtonUsingAccessibility(const std::string& automation_id) {
476 CComPtr<IUIAutomation> ui_automation;
477 HRESULT hr = ::CoCreateInstance(CLSID_CUIAutomation,
478 NULL,
479 CLSCTX_INPROC_SERVER,
480 IID_IUIAutomation,
481 reinterpret_cast<void**>(&ui_automation));
482
483 if (FAILED(hr)) {
484 LOGHR(WARN, hr) << "Unable to create global UI Automation object";
485 return EUNHANDLEDERROR;
486 }
487
488 CComPtr<IUIAutomationElement> parent_window;
489 hr = ui_automation->ElementFromHandle(this->alert_handle_,
490 &parent_window);
491 if (FAILED(hr)) {
492 LOGHR(WARN, hr) << "Unable to get automation object from window handle";
493 return EUNHANDLEDERROR;
494 }
495
496 CComVariant button_automation_id = automation_id.c_str();
497 CComPtr<IUIAutomationCondition> button_condition;
498 hr = ui_automation->CreatePropertyCondition(UIA_AutomationIdPropertyId,
499 button_automation_id,
500 &button_condition);
501 if (FAILED(hr)) {
502 LOGHR(WARN, hr) << "Unable to create button finding condition";
503 return EUNHANDLEDERROR;
504 }
505
506 CComPtr<IUIAutomationElement> button;
507 hr = parent_window->FindFirst(TreeScope::TreeScope_Children,
508 button_condition,
509 &button);
510 if (FAILED(hr)) {
511 LOGHR(WARN, hr) << "Unable to find button";
512 return EUNHANDLEDERROR;
513 }
514
515 CComPtr<IUIAutomationInvokePattern> button_invoke_pattern;
516 hr = button->GetCurrentPatternAs(UIA_InvokePatternId,
517 IID_PPV_ARGS(&button_invoke_pattern));
518 if (FAILED(hr)) {
519 LOGHR(WARN, hr) << "Unable to get invoke pattern on button";
520 return EUNHANDLEDERROR;
521 }
522
523 hr = button_invoke_pattern->Invoke();
524 if (FAILED(hr)) {
525 LOGHR(WARN, hr) << "Unable to invoke button";
526 return EUNHANDLEDERROR;
527 }
528
529 return WD_SUCCESS;
530 }
531
532 bool Alert::IsOKButton(HWND button_handle) {
533 int control_id = ::GetDlgCtrlID(button_handle);
534 if (control_id != 0) {
535 return control_id == IDOK || control_id == IDYES || control_id == IDRETRY;
536 }
537 std::vector<wchar_t> button_window_class(100);
538 ::GetClassName(button_handle, &button_window_class[0], static_cast<int>(button_window_class.size()));
539 if (wcscmp(&button_window_class[0], L"Button") == 0) {
540 long window_long = ::GetWindowLong(button_handle, GWL_STYLE);
541 long button_style = window_long & BS_TYPEMASK;
542 return button_style == BS_DEFCOMMANDLINK || button_style == BS_DEFPUSHBUTTON;
543 }
544 return false;
545 }
546
547 bool Alert::IsCancelButton(HWND button_handle) {
548 int control_id = ::GetDlgCtrlID(button_handle);
549 if (control_id != 0) {
550 return control_id == IDCANCEL || control_id == IDNO;
551 }
552 std::vector<wchar_t> button_window_class(100);
553 ::GetClassName(button_handle, &button_window_class[0], static_cast<int>(button_window_class.size()));
554 if (wcscmp(&button_window_class[0], L"Button") == 0) {
555 long window_long = ::GetWindowLong(button_handle, GWL_STYLE);
556 long button_style = window_long & BS_TYPEMASK;
557 // The BS_DEFCOMMANDLINK mask includes BS_COMMANDLINK, but we
558 // want only to match those without the default bits set.
559 return button_style == BS_COMMANDLINK || button_style == BS_PUSHBUTTON;
560 }
561 return false;
562 }
563
564 bool Alert::IsLinkButton(HWND button_handle) {
565 std::vector<wchar_t> button_window_class(100);
566 ::GetClassName(button_handle, &button_window_class[0], static_cast<int>(button_window_class.size()));
567 if (wcscmp(&button_window_class[0], L"Button") == 0) {
568 long window_long = ::GetWindowLong(button_handle, GWL_STYLE);
569 long button_style = window_long & BS_TYPEMASK;
570 return button_style == BS_COMMANDLINK;
571 }
572 return false;
573 }
574
575 bool Alert::IsSimpleEdit(HWND edit_handle) {
576 std::vector<wchar_t> child_window_class(100);
577 ::GetClassName(edit_handle, &child_window_class[0], 100);
578
579 if (wcscmp(&child_window_class[0], L"Edit") == 0) {
580 long window_long = ::GetWindowLong(edit_handle, GWL_STYLE);
581 bool is_read_only = (window_long & ES_READONLY) == ES_READONLY;
582 bool is_password = (window_long & ES_PASSWORD) == ES_PASSWORD;
583 return !is_read_only && !is_password;
584 }
585 return false;
586 }
587
588 bool Alert::IsPasswordEdit(HWND edit_handle) {
589 std::vector<wchar_t> child_window_class(100);
590 ::GetClassName(edit_handle, &child_window_class[0], 100);
591
592 if (wcscmp(&child_window_class[0], L"Edit") == 0) {
593 long window_long = ::GetWindowLong(edit_handle, GWL_STYLE);
594 bool is_password = (window_long & ES_PASSWORD) == ES_PASSWORD;
595 return is_password;
596 }
597 return false;
598 }
599
600 BOOL CALLBACK Alert::FindDialogButton(HWND hwnd, LPARAM arg) {
601 Alert::DialogButtonFindInfo* button_info = reinterpret_cast<Alert::DialogButtonFindInfo*>(arg);
602 int control_id = ::GetDlgCtrlID(hwnd);
603 if (button_info->match_proc(hwnd)) {
604 button_info->button_handle = hwnd;
605 button_info->button_control_id = control_id;
606 return FALSE;
607 }
608 return TRUE;
609 }
610
611 BOOL CALLBACK Alert::FindTextBox(HWND hwnd, LPARAM arg) {
612 TextBoxFindInfo* find_info = reinterpret_cast<TextBoxFindInfo*>(arg);
613 if (find_info->match_proc(hwnd)) {
614 find_info->textbox_handle = hwnd;
615 return FALSE;
616 }
617 return TRUE;
618 }
619
620 BOOL CALLBACK Alert::FindTextLabel(HWND hwnd, LPARAM arg) {
621 TextLabelFindInfo* find_info = reinterpret_cast<TextLabelFindInfo*>(arg);
622 std::vector<wchar_t> child_window_class(100);
623 ::GetClassName(hwnd, &child_window_class[0], 100);
624
625 if (wcscmp(&child_window_class[0], L"Static") != 0) {
626 return TRUE;
627 }
628
629 int control_id = ::GetDlgCtrlID(hwnd);
630 int text_length = ::GetWindowTextLength(hwnd);
631 if (text_length > 0) {
632 if (find_info->excluded_control_id == 0 ||
633 control_id != find_info->excluded_control_id) {
634 find_info->label_handle = hwnd;
635 find_info->control_id_found = control_id;
636 return FALSE;
637 }
638 }
639 return TRUE;
640 }
641
642 BOOL CALLBACK Alert::FindDirectUIChild(HWND hwnd, LPARAM arg){
643 HWND *dialog_handle = reinterpret_cast<HWND*>(arg);
644 std::vector<wchar_t> child_window_class(100);
645 ::GetClassName(hwnd, &child_window_class[0], 100);
646
647 if (wcscmp(&child_window_class[0], L"DirectUIHWND") != 0) {
648 return TRUE;
649 }
650 *dialog_handle = hwnd;
651 return FALSE;
652 }
653
654 BOOL CALLBACK Alert::FindTextBoxes(HWND hwnd, LPARAM arg) {
655 std::vector<HWND>* dialog_handles = reinterpret_cast<std::vector<HWND>*>(arg);
656 std::vector<wchar_t> child_window_class(100);
657 ::GetClassName(hwnd, &child_window_class[0], 100);
658
659 if (wcscmp(&child_window_class[0], L"Edit") == 0) {
660 dialog_handles->push_back(hwnd);
661 }
662 return TRUE;
663 }
664
665 } // namespace webdriver