Skip to content

Commit b57575a

Browse files
committed
Modifying to silently dismiss onbeforeupdate dialogs in IE
The W3C WebDriver Specification dictates that all onbeforeupdate dialogs are automatically dismissed without notification. This commit brings the IE driver into compliance with that part of the spec.
1 parent db52375 commit b57575a

File tree

7 files changed

+86
-22
lines changed

7 files changed

+86
-22
lines changed

cpp/iedriver/IECommandExecutor.cpp

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace webdriver {
4545

4646
struct WaitThreadContext {
4747
HWND window_handle;
48+
bool is_deferred_command;
4849
LPSTR deferred_response;
4950
};
5051

@@ -183,12 +184,15 @@ LRESULT IECommandExecutor::OnWait(UINT uMsg,
183184
std::string deferred_response(str);
184185
delete[] str;
185186

187+
bool is_single_wait = (wParam == 0);
188+
186189
BrowserHandle browser;
187190
int status_code = this->GetCurrentBrowser(&browser);
188191
if (status_code == WD_SUCCESS && !browser->is_closing()) {
189192
if (this->page_load_timeout_ >= 0 && this->wait_timeout_ < clock()) {
190193
Response timeout_response;
191-
timeout_response.SetErrorResponse(ERROR_WEBDRIVER_TIMEOUT, "Timed out waiting for page to load.");
194+
timeout_response.SetErrorResponse(ERROR_WEBDRIVER_TIMEOUT,
195+
"Timed out waiting for page to load.");
192196
this->serialized_response_ = timeout_response.Serialize();
193197
this->is_waiting_ = false;
194198
browser->set_wait_required(false);
@@ -198,14 +202,20 @@ LRESULT IECommandExecutor::OnWait(UINT uMsg,
198202
if (this->IsAlertActive(browser, &alert_handle)) {
199203
LOG(WARN) << "Found alert";
200204
}
201-
if (this->is_waiting_) {
202-
this->CreateWaitThread(deferred_response);
205+
if (is_single_wait) {
206+
this->is_waiting_ = false;
203207
} else {
204-
this->serialized_response_ = deferred_response;
208+
if (this->is_waiting_) {
209+
this->CreateWaitThread(deferred_response);
210+
} else {
211+
LOG(DEBUG) << "Setting serialized response to " << deferred_response;
212+
this->serialized_response_ = deferred_response;
213+
}
205214
}
206215
}
207216
} else {
208217
this->is_waiting_ = false;
218+
LOG(DEBUG) << "Setting serialized response to " << deferred_response;
209219
this->serialized_response_ = deferred_response;
210220
}
211221
return 0;
@@ -548,6 +558,7 @@ unsigned int WINAPI IECommandExecutor::WaitThreadProc(LPVOID lpParameter) {
548558
LOG(TRACE) << "Entering IECommandExecutor::WaitThreadProc";
549559
WaitThreadContext* thread_context = reinterpret_cast<WaitThreadContext*>(lpParameter);
550560
HWND window_handle = thread_context->window_handle;
561+
bool is_deferred_command = thread_context->is_deferred_command;
551562
std::string deferred_response(thread_context->deferred_response);
552563
delete thread_context->deferred_response;
553564
delete thread_context;
@@ -560,8 +571,14 @@ unsigned int WINAPI IECommandExecutor::WaitThreadProc(LPVOID lpParameter) {
560571
::Sleep(WAIT_TIME_IN_MILLISECONDS);
561572
::PostMessage(window_handle,
562573
WD_WAIT,
563-
NULL,
574+
static_cast<WPARAM>(deferred_response.size()),
564575
reinterpret_cast<LPARAM>(message_payload));
576+
if (is_deferred_command) {
577+
// This wait is requested by the automatic handling of a user prompt
578+
// before a command was executed, so re-queue the command execution
579+
// for after the wait.
580+
::PostMessage(window_handle, WD_EXEC_COMMAND, NULL, NULL);
581+
}
565582
return 0;
566583
}
567584

@@ -675,22 +692,37 @@ void IECommandExecutor::DispatchCommand() {
675692
command_type == webdriver::CommandType::SwitchToWindow) {
676693
LOG(DEBUG) << "Alert is detected, and the sent command is valid";
677694
} else {
678-
LOG(DEBUG) << "Unexpected alert is detected, and the sent command is invalid when an alert is present";
695+
LOG(DEBUG) << "Unexpected alert is detected, and the sent command "
696+
<< "is invalid when an alert is present";
679697
std::string alert_text;
680698
bool is_quit_command = command_type == webdriver::CommandType::Quit;
681699
bool is_notify_unexpected_alert = this->HandleUnexpectedAlert(browser,
682700
alert_handle,
683701
is_quit_command,
684702
&alert_text);
685-
if (!is_quit_command && is_notify_unexpected_alert) {
686-
// To keep pace with what Firefox does, we'll return the text of the
687-
// alert in the error response.
688-
response.SetErrorResponse(EUNEXPECTEDALERTOPEN, "Modal dialog present with text: " + alert_text);
689-
response.AddAdditionalData("text", alert_text);
690-
this->serialized_response_ = response.Serialize();
691-
return;
703+
if (!is_quit_command) {
704+
if (is_notify_unexpected_alert) {
705+
// To keep pace with what the specification suggests, we'll
706+
// return the text of the alert in the error response.
707+
response.SetErrorResponse(EUNEXPECTEDALERTOPEN,
708+
"Modal dialog present with text: " + alert_text);
709+
response.AddAdditionalData("text", alert_text);
710+
this->serialized_response_ = response.Serialize();
711+
return;
712+
} else {
713+
LOG(DEBUG) << "Command other than quit was issued, and option "
714+
<< "to not notify was specified. Continuing with "
715+
<< "command after automatically closing alert.";
716+
// Push a wait cycle, then re-execute the current command (which
717+
// hasn't actually been executed yet). Note that an empty string
718+
// for the deferred response parameter of CreateWaitThread will
719+
// re-queue the execution of the command.
720+
this->CreateWaitThread("", true);
721+
return;
722+
}
692723
} else {
693-
LOG(DEBUG) << "Quit command was issued. Continuing with command after automatically closing alert.";
724+
LOG(DEBUG) << "Quit command was issued. Continuing with "
725+
<< "command after automatically closing alert.";
694726
}
695727
}
696728
}
@@ -751,16 +783,28 @@ void IECommandExecutor::DispatchCommand() {
751783
}
752784

753785
this->serialized_response_ = response.Serialize();
786+
LOG(DEBUG) << "Setting serialized response to " << this->serialized_response_;
787+
LOG(DEBUG) << "Is waiting flag: " << this->is_waiting_ ? "true" : "false";
754788
}
755789

756790
void IECommandExecutor::CreateWaitThread(const std::string& deferred_response) {
791+
this->CreateWaitThread(deferred_response, false);
792+
}
793+
794+
void IECommandExecutor::CreateWaitThread(const std::string& deferred_response,
795+
const bool is_deferred_command_execution) {
757796
// If we are still waiting, we need to wait a bit then post a message to
758797
// ourselves to run the wait again. However, we can't wait using Sleep()
759798
// on this thread. This call happens in a message loop, and we would be
760799
// unable to process the COM events in the browser if we put this thread
761800
// to sleep.
801+
LOG(DEBUG) << "Creating wait thread with deferred response of `" << deferred_response << "`";
802+
if (is_deferred_command_execution) {
803+
LOG(DEBUG) << "Command execution will be rescheduled.";
804+
}
762805
WaitThreadContext* thread_context = new WaitThreadContext;
763806
thread_context->window_handle = this->m_hWnd;
807+
thread_context->is_deferred_command = is_deferred_command_execution;
764808
thread_context->deferred_response = new CHAR[deferred_response.size() + 1];
765809
strcpy_s(thread_context->deferred_response,
766810
deferred_response.size() + 1,
@@ -808,6 +852,12 @@ bool IECommandExecutor::HandleUnexpectedAlert(BrowserHandle browser,
808852
LOG(TRACE) << "Entering IECommandExecutor::HandleUnexpectedAlert";
809853
Alert dialog(browser, alert_handle);
810854
*alert_text = dialog.GetText();
855+
if (!dialog.is_standard_alert()) {
856+
// The dialog was non-standard. The most common case of this is
857+
// an onBeforeUnload dialog, which must be accepted to continue.
858+
dialog.Accept();
859+
return false;
860+
}
811861
if (this->unexpected_alert_behavior_ == ACCEPT_UNEXPECTED_ALERTS ||
812862
this->unexpected_alert_behavior_ == ACCEPT_AND_NOTIFY_UNEXPECTED_ALERTS) {
813863
LOG(DEBUG) << "Automatically accepting the alert";
@@ -832,6 +882,7 @@ bool IECommandExecutor::HandleUnexpectedAlert(BrowserHandle browser,
832882
this->unexpected_alert_behavior_ == IGNORE_UNEXPECTED_ALERTS ||
833883
this->unexpected_alert_behavior_ == DISMISS_AND_NOTIFY_UNEXPECTED_ALERTS ||
834884
this->unexpected_alert_behavior_ == ACCEPT_AND_NOTIFY_UNEXPECTED_ALERTS;
885+
is_notify_unexpected_alert = is_notify_unexpected_alert && dialog.is_standard_alert();
835886
return is_notify_unexpected_alert;
836887
}
837888

cpp/iedriver/IECommandExecutor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ class IECommandExecutor : public CWindowImpl<IECommandExecutor>, public IElement
213213
void PopulateElementFinderMethods(void);
214214

215215
void CreateWaitThread(const std::string& deferred_response);
216+
void CreateWaitThread(const std::string& deferred_response,
217+
const bool is_deferred_command_execution);
216218
bool IsAlertActive(BrowserHandle browser, HWND* alert_handle);
217219
bool HandleUnexpectedAlert(BrowserHandle browser,
218220
HWND alert_handle,

cpp/iedriver/IEDriver.rc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ END
5050
//
5151

5252
VS_VERSION_INFO VERSIONINFO
53-
FILEVERSION 3,13,0,4
54-
PRODUCTVERSION 3,13,0,4
53+
FILEVERSION 3,13,0,5
54+
PRODUCTVERSION 3,13,0,5
5555
FILEFLAGSMASK 0x3fL
5656
#ifdef _DEBUG
5757
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
6868
BEGIN
6969
VALUE "CompanyName", "Software Freedom Conservancy"
7070
VALUE "FileDescription", "Driver library for the IE driver"
71-
VALUE "FileVersion", "3.13.0.4"
71+
VALUE "FileVersion", "3.13.0.5"
7272
VALUE "InternalName", "IEDriver.dll"
7373
VALUE "LegalCopyright", "Copyright (C) 2018"
7474
VALUE "OriginalFilename", "IEDriver.dll"
7575
VALUE "ProductName", "Selenium WebDriver"
76-
VALUE "ProductVersion", "3.13.0.4"
76+
VALUE "ProductVersion", "3.13.0.5"
7777
END
7878
END
7979
BLOCK "VarFileInfo"

cpp/iedriverserver/CHANGELOG

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ available via the project downloads page. Changes in "revision" field indicate
99
private releases checked into the prebuilts directory of the source tree, but
1010
not made generally available on the downloads page.
1111

12+
v3.13.0.5
13+
=========
14+
* Modified to silently dismiss onbeforeupdate dialogs. The W3C WebDriver
15+
Specification dictates that all onbeforeupdate dialogs are automatically
16+
dismissed without notification. This commit brings the IE driver into
17+
compliance with that part of the spec.
18+
* Resetting frame focus to top-level frame on refresh. The W3C WebDriver
19+
Specification dictates that issuing the Refresh command will reset the
20+
focus to the top-level frame. This commit brings the IE driver into
21+
compliance with that part of the spec.
22+
1223
v3.13.0.4
1324
=========
1425
* Made set window rect command spec-compliant for x and y coordinates

cpp/iedriverserver/IEDriverServer.rc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ END
5050
//
5151

5252
VS_VERSION_INFO VERSIONINFO
53-
FILEVERSION 3,13,0,4
54-
PRODUCTVERSION 3,13,0,4
53+
FILEVERSION 3,13,0,5
54+
PRODUCTVERSION 3,13,0,5
5555
FILEFLAGSMASK 0x3fL
5656
#ifdef _DEBUG
5757
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
6868
BEGIN
6969
VALUE "CompanyName", "Software Freedom Conservancy"
7070
VALUE "FileDescription", "Command line server for the IE driver"
71-
VALUE "FileVersion", "3.13.0.4"
71+
VALUE "FileVersion", "3.13.0.5"
7272
VALUE "InternalName", "IEDriverServer.exe"
7373
VALUE "LegalCopyright", "Copyright (C) 2018"
7474
VALUE "OriginalFilename", "IEDriverServer.exe"
7575
VALUE "ProductName", "Selenium WebDriver"
76-
VALUE "ProductVersion", "3.13.0.4"
76+
VALUE "ProductVersion", "3.13.0.5"
7777
END
7878
END
7979
BLOCK "VarFileInfo"
Binary file not shown.
2 KB
Binary file not shown.

0 commit comments

Comments
 (0)