Skip to content

Commit

Permalink
Rewriting IE driver file upload dialog handling code.
Browse files Browse the repository at this point in the history
Previously, the IE driver would use simple window handling and Windows
APIs to find and manipulate the IE file selection dialog for the file
upload case. With this change, the driver now uses the Windows UI
Automation library that ships as part of the Windows operating system
to detect and manipulate the dialog. Unfortunately, since handling
native dialogs this way is highly OS-dependent, there may be changes
in behavior based on different versions of Windows, or different
versions of IE. At the moment, this change has been tested against
Windows 10, and IE 11. Other versions may not work exactly the same.
Temporarily, to retain backward compatibility, it's possible to use
the legacy handling with the file upload dialog box. This can be set
by setting a capability of "ie.useLegacyFileUploadDialogHandling" to
true. This capability is only intended to be provided temporarily, and
will be removed as soon as is practical. As such, the capability is
not documented, and its presence should not be relied on over the long
term. It should be pointed out that, as has been the case since July
2016, the driver now only supports IE versions 9, 10, and 11, and only
supports Windows Vista and above.
  • Loading branch information
jimevans committed Apr 9, 2017
1 parent 4497162 commit 5c8380b
Show file tree
Hide file tree
Showing 10 changed files with 953 additions and 556 deletions.
4 changes: 4 additions & 0 deletions cpp/iedriver/CommandHandlers/NewSessionCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ void NewSessionCommandHandler::SetInputSettings(const IECommandExecutor& executo
mutable_executor.set_file_upload_dialog_timeout(file_upload_dialog_timeout.asInt());
}

Json::Value use_legacy_file_upload_dialog_handling = this->GetCapability(capabilities, USE_LEGACY_FILE_UPLOAD_DIALOG_HANDLING_CAPABILITY, Json::booleanValue, false);
mutable_executor.set_use_legacy_file_upload_dialog_handling(use_legacy_file_upload_dialog_handling.asBool());

Json::Value enable_persistent_hover = this->GetCapability(capabilities, ENABLE_PERSISTENT_HOVER_CAPABILITY, Json::booleanValue, true);
if (require_window_focus.asBool() || !enable_native_events.asBool()) {
// Setting "require_window_focus" implies SendInput() API, and does not therefore require
Expand Down Expand Up @@ -203,6 +206,7 @@ Json::Value NewSessionCommandHandler::CreateReturnedCapabilities(const IECommand
ie_options[ELEMENT_SCROLL_BEHAVIOR_CAPABILITY] = executor.input_manager()->scroll_behavior();
ie_options[REQUIRE_WINDOW_FOCUS_CAPABILITY] = executor.input_manager()->require_window_focus();
ie_options[FILE_UPLOAD_DIALOG_TIMEOUT_CAPABILITY] = executor.file_upload_dialog_timeout();
ie_options[USE_LEGACY_FILE_UPLOAD_DIALOG_HANDLING_CAPABILITY] = executor.use_legacy_file_upload_dialog_handling();
ie_options[ENABLE_ELEMENT_CACHE_CLEANUP_CAPABILITY] = executor.enable_element_cache_cleanup();
ie_options[ENABLE_FULL_PAGE_SCREENSHOT_CAPABILITY] = executor.enable_full_page_screenshot();

Expand Down
390 changes: 368 additions & 22 deletions cpp/iedriver/CommandHandlers/SendKeysCommandHandler.cpp

Large diffs are not rendered by default.

20 changes: 18 additions & 2 deletions cpp/iedriver/CommandHandlers/SendKeysCommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

#include "../IECommandHandler.h"

struct IUIAutomation;
struct IUIAutomationElement;
struct IUIAutomationElementArray;

namespace webdriver {

class SendKeysCommandHandler : public IECommandHandler {
Expand All @@ -28,6 +32,7 @@ class SendKeysCommandHandler : public IECommandHandler {
HWND hwnd;
DWORD ieProcId;
DWORD dialogTimeout;
bool useLegacyDialogHandling;
const wchar_t* text;
};

Expand All @@ -40,13 +45,24 @@ class SendKeysCommandHandler : public IECommandHandler {
Response* response);
private:
static unsigned int WINAPI SetFileValue(void *file_data);
static bool SendKeysToFileUploadAlert(HWND dialog_window_handle,
const wchar_t* value);
static bool SendFileNameKeys(FileNameData* file_data);
static bool GetFileSelectionDialogCandidates(HWND ie_window_handle, IUIAutomation* ui_automation, IUIAutomationElementArray** dialog_candidates);
static bool FillFileName(const wchar_t* file_name, IUIAutomation* ui_automation, IUIAutomationElement* file_selection_dialog);
static bool AcceptFileSelection(IUIAutomation* ui_automation, IUIAutomationElement* file_selection_dialog);
static bool WaitForFileSelectionDialogClose(const int timeout, IUIAutomationElement* file_selection_dialog);
static bool FindFileSelectionErrorDialog(IUIAutomation* ui_automation, IUIAutomationElement* file_selection_dialog, IUIAutomationElement** error_dialog);
static bool DismissFileSelectionErrorDialog(IUIAutomation* ui_automation, IUIAutomationElement* error_dialog);
static bool DismissFileSelectionDialog(IUIAutomation* ui_automation, IUIAutomationElement* file_selection_dialog);

static bool LegacySelectFile(FileNameData* file_data);
static bool LegacySendKeysToFileUploadAlert(HWND dialog_window_handle, const wchar_t* value);

bool VerifyPageHasFocus(HWND top_level_window_handle,
HWND browser_pane_window_handle);
bool WaitUntilElementFocused(IHTMLElement *element);
bool SetInsertionPoint(IHTMLElement* element);

static std::wstring error_text;
};

} // namespace webdriver
Expand Down
1,064 changes: 532 additions & 532 deletions cpp/iedriver/Generated/atoms.h

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions cpp/iedriver/IECommandExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ class IECommandExecutor : public CWindowImpl<IECommandExecutor> {
this->file_upload_dialog_timeout_ = file_upload_dialog_timeout;
}

bool use_legacy_file_upload_dialog_handling(void) const {
return this->use_legacy_file_upload_dialog_handling_;
}
void set_use_legacy_file_upload_dialog_handling(const bool use_legacy_file_upload_dialog_handling) {
this->use_legacy_file_upload_dialog_handling_ = use_legacy_file_upload_dialog_handling;
}

bool enable_full_page_screenshot(void) const {
return this->enable_full_page_screenshot_;
}
Expand Down Expand Up @@ -246,6 +253,7 @@ class IECommandExecutor : public CWindowImpl<IECommandExecutor> {
std::string unexpected_alert_behavior_;
std::string page_load_strategy_;
int file_upload_dialog_timeout_;
bool use_legacy_file_upload_dialog_handling_;
bool enable_full_page_screenshot_;

Command current_command_;
Expand Down
1 change: 1 addition & 0 deletions cpp/iedriver/IECommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#define ENSURE_CLEAN_SESSION_CAPABILITY "ie.ensureCleanSession"
#define FORCE_SHELL_WINDOWS_API_CAPABILITY "ie.forceShellWindowsApi"
#define FILE_UPLOAD_DIALOG_TIMEOUT_CAPABILITY "ie.fileUploadDialogTimeout"
#define USE_LEGACY_FILE_UPLOAD_DIALOG_HANDLING_CAPABILITY "ie.useLegacyFileUploadDialogHandling"
#define ENABLE_FULL_PAGE_SCREENSHOT_CAPABILITY "ie.enableFullPageScreenshot"
#define IE_DRIVER_EXTENSIONS_CAPABILITY "se:ieOptions"

Expand Down
22 changes: 22 additions & 0 deletions cpp/iedriverserver/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@ 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.

v3.3.0.2
========
* Updates to JavaScript automation atoms.
* Rewriting file upload dialog handling code. Previously, the IE driver
would use simple window handling and Windows APIs to find and manipulate
the IE file selection dialog for the file upload case. With this change,
the driver now uses the Windows UI Automation library that ships as part
of the Windows operating system to detect and manipulate the dialog.
Unfortunately, since handling native dialogs this way is highly OS-
dependent, there may be changes in behavior based on different versions
of Windows, or different versions of IE. At the moment, this change
has been tested against Windows 10, and IE 11. Other versions may not
work exactly the same. Temporarily, to retain backward compatibility,
it's possible to use the legacy handling with the file upload dialog
box. This can be set by setting a capability of
"ie.useLegacyFileUploadDialogHandling" to true. This capability is only
intended to be provided temporarily, and will be removed as soon as is
practical. As such, the capability is not documented, and its presence
should not be relied on over the long term. It should be pointed out
that, as has been the case since July 2016, the driver now only supports
IE versions 9, 10, and 11, and only supports Windows Vista and above.

v3.3.0.1
========
* Updates to JavaScript automation atoms.
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 5c8380b

Please sign in to comment.