Skip to content

Commit

Permalink
Fixed handling of IE auth dialogs for different Windows versions
Browse files Browse the repository at this point in the history
  • Loading branch information
jimevans committed Jul 15, 2015
1 parent e6e7536 commit 82debdc
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 30 deletions.
73 changes: 45 additions & 28 deletions cpp/iedriver/Alert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ int Alert::Dismiss() {

int Alert::SendKeys(const std::string& keys) {
LOG(TRACE) << "Entering Alert::SendKeys";
return this->SendKeysInternal(keys, 0);
TextBoxFindInfo text_box_find_info;
text_box_find_info.textbox_handle = NULL;
text_box_find_info.match_proc = &Alert::IsSimpleEdit;
return this->SendKeysInternal(keys, &text_box_find_info);
}

int Alert::SetUserName(const std::string& username) {
Expand All @@ -85,7 +88,7 @@ int Alert::SetUserName(const std::string& username) {
if (!this->is_security_alert_) {
return EUNEXPECTEDALERTOPEN;
}
return this->SendKeysInternal(username, 0);
return this->SendKeys(username);
}

int Alert::SetPassword(const std::string& password) {
Expand All @@ -94,33 +97,34 @@ int Alert::SetPassword(const std::string& password) {
if (!this->is_security_alert_) {
return EUNEXPECTEDALERTOPEN;
}
return this->SendKeysInternal(password, ES_PASSWORD);
TextBoxFindInfo text_box_find_info;
text_box_find_info.textbox_handle = NULL;
text_box_find_info.match_proc = &Alert::IsPasswordEdit;
return this->SendKeysInternal(password, &text_box_find_info);
}

int Alert::SendKeysInternal(const std::string& keys, const long text_box_style) {
int Alert::SendKeysInternal(const std::string& keys,
TextBoxFindInfo* text_box_find_info) {
LOG(TRACE) << "Entering Alert::SendKeysInternal";
TextBoxFindInfo text_box_find_info;
text_box_find_info.textbox_handle = NULL;
text_box_find_info.style_match = text_box_style;
// Alert present, find the text box.
// Retry up to 10 times to find the dialog.
int max_wait = 10;
while ((text_box_find_info.textbox_handle == NULL) && --max_wait) {
while ((text_box_find_info->textbox_handle == NULL) && --max_wait) {
::EnumChildWindows(this->alert_handle_,
&Alert::FindTextBox,
reinterpret_cast<LPARAM>(&text_box_find_info));
if (text_box_find_info.textbox_handle == NULL) {
reinterpret_cast<LPARAM>(text_box_find_info));
if (text_box_find_info->textbox_handle == NULL) {
::Sleep(50);
}
}

if (text_box_find_info.textbox_handle == NULL) {
if (text_box_find_info->textbox_handle == NULL) {
LOG(WARN) << "Text box not found on alert";
return EELEMENTNOTDISPLAYED;
} else {
LOG(DEBUG) << "Sending keystrokes to alert using SendMessage";
std::wstring text = StringUtilities::ToWString(keys);
::SendMessage(text_box_find_info.textbox_handle,
::SendMessage(text_box_find_info->textbox_handle,
WM_SETTEXT,
NULL,
reinterpret_cast<LPARAM>(text.c_str()));
Expand Down Expand Up @@ -168,7 +172,7 @@ std::string Alert::GetStandardDialogText() {
// all other controls on the alert are fully drawn too.
TextBoxFindInfo textbox_find_info;
textbox_find_info.textbox_handle = NULL;
textbox_find_info.style_match = 0;
textbox_find_info.match_proc = &Alert::IsSimpleEdit;
::EnumChildWindows(this->alert_handle_,
&Alert::FindTextBox,
reinterpret_cast<LPARAM>(&textbox_find_info));
Expand Down Expand Up @@ -425,6 +429,31 @@ bool Alert::IsCancelButton(HWND button_handle) {
return false;
}

bool Alert::IsSimpleEdit(HWND edit_handle) {
std::vector<wchar_t> child_window_class(100);
::GetClassName(edit_handle, &child_window_class[0], 100);

if (wcscmp(&child_window_class[0], L"Edit") == 0) {
long window_long = ::GetWindowLong(edit_handle, GWL_STYLE);
bool is_read_only = (window_long & ES_READONLY) == ES_READONLY;
bool is_password = (window_long & ES_PASSWORD) == ES_PASSWORD;
return !is_read_only && !is_password;
}
return false;
}

bool Alert::IsPasswordEdit(HWND edit_handle) {
std::vector<wchar_t> child_window_class(100);
::GetClassName(edit_handle, &child_window_class[0], 100);

if (wcscmp(&child_window_class[0], L"Edit") == 0) {
long window_long = ::GetWindowLong(edit_handle, GWL_STYLE);
bool is_password = (window_long & ES_PASSWORD) == ES_PASSWORD;
return is_password;
}
return false;
}

BOOL CALLBACK Alert::FindDialogButton(HWND hwnd, LPARAM arg) {
Alert::DialogButtonFindInfo* button_info = reinterpret_cast<Alert::DialogButtonFindInfo*>(arg);
int control_id = ::GetDlgCtrlID(hwnd);
Expand All @@ -438,21 +467,9 @@ BOOL CALLBACK Alert::FindDialogButton(HWND hwnd, LPARAM arg) {

BOOL CALLBACK Alert::FindTextBox(HWND hwnd, LPARAM arg) {
TextBoxFindInfo* find_info = reinterpret_cast<TextBoxFindInfo*>(arg);
std::vector<wchar_t> child_window_class(100);
::GetClassName(hwnd, &child_window_class[0], 100);

if (wcscmp(&child_window_class[0], L"Edit") == 0) {
if (find_info->style_match == 0) {
find_info->textbox_handle = hwnd;;;
return FALSE;
} else {
long window_long = ::GetWindowLong(hwnd, GWL_STYLE);
long edit_style = window_long & find_info->style_match;
if (edit_style == find_info->style_match) {
find_info->textbox_handle = hwnd;
return FALSE;
}
}
if (find_info->match_proc(hwnd)) {
find_info->textbox_handle = hwnd;
return FALSE;
}
return TRUE;
}
Expand Down
8 changes: 6 additions & 2 deletions cpp/iedriver/Alert.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Alert {

private:
typedef bool (__cdecl *ISBUTTONMATCHPROC)(HWND);
typedef bool (__cdecl *ISEDITMATCHPROC)(HWND);

struct DialogButtonInfo {
HWND button_handle;
Expand All @@ -64,15 +65,16 @@ class Alert {

struct TextBoxFindInfo {
HWND textbox_handle;
long style_match;
ISEDITMATCHPROC match_proc;
};

enum BUTTON_TYPE {
OK,
CANCEL
};

int SendKeysInternal(const std::string& keys, const long text_box_style);
int SendKeysInternal(const std::string& keys,
TextBoxFindInfo* text_box_find_info);

DialogButtonInfo GetDialogButton(BUTTON_TYPE button_type);
int ClickAlertButton(DialogButtonInfo button_info);
Expand All @@ -83,6 +85,8 @@ class Alert {

static bool IsOKButton(HWND button_handle);
static bool IsCancelButton(HWND button_handle);
static bool IsSimpleEdit(HWND edit_handle);
static bool IsPasswordEdit(HWND edit_handle);
static BOOL CALLBACK FindDialogButton(HWND hwnd, LPARAM arg);
static BOOL CALLBACK FindTextBox(HWND hwnd, LPARAM arg);
static BOOL CALLBACK FindTextLabel(HWND hwnd, LPARAM arg);
Expand Down
4 changes: 4 additions & 0 deletions cpp/iedriverserver/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ available via the project downloads page. Changes in "revision" field indicate
private releases checked into the prebuilts directory of the source tree, but
not made generally available on the downloads page.

v2.46.0.12
==========
* Fixed handling of authentication dialogs for different Windows versions.

v2.46.0.11
==========
* Enabling handling of authentication dialogs in IE driver.
Expand Down
Binary file modified cpp/iedriverserver/IEDriverServer.rc
Binary file not shown.
Binary file modified cpp/prebuilt/Win32/Release/IEDriverServer.exe
Binary file not shown.
Binary file modified cpp/prebuilt/x64/Release/IEDriverServer.exe
Binary file not shown.

0 comments on commit 82debdc

Please sign in to comment.