Skip to content

Commit 0283f1f

Browse files
committed
Throw an error for key actions taking multiple characters in IE
The key actions as defined by the W3C WebDriver Specification take a JSON payload that requires the resulting key for the key down or key up action to resolve to a single Unicode code point or a single grapheme cluster (what appears to be a single logical "character" from a user's perspective). The IE driver will now evaluate the item passed into the key down or key up action, and, taking combining characters into account, attempts to make sure there is only a single grapheme present, if more than one Unicode code point is sent. If the entered string would results in multiple grapheme clusters, the driver now returns an invalid argument error, as per the spec.
1 parent f1ceebf commit 0283f1f

4 files changed

Lines changed: 55 additions & 0 deletions

File tree

cpp/iedriver/InputManager.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,10 @@ int InputManager::KeyDown(BrowserHandle browser_wrapper,
540540
std::string key_value = down_action["value"].asString();
541541
std::wstring key = StringUtilities::ToWString(key_value);
542542

543+
if (!this->IsSingleKey(key)) {
544+
return EINVALIDARGUMENT;
545+
}
546+
543547
if (this->action_simulator_->UseExtraInfo()) {
544548
LOG(DEBUG) << "Using synthetic events for sending keys";
545549
KeyboardExtraInfo* extra_info = new KeyboardExtraInfo();
@@ -567,13 +571,50 @@ int InputManager::KeyUp(BrowserHandle browser_wrapper,
567571
std::string key_value = up_action["value"].asString();
568572
std::wstring key = StringUtilities::ToWString(key_value);
569573

574+
if (!this->IsSingleKey(key)) {
575+
return EINVALIDARGUMENT;
576+
}
577+
570578
if (!this->action_simulator_->UseExtraInfo()) {
571579
HWND window_handle = browser_wrapper->GetContentWindowHandle();
572580
this->AddKeyboardInput(window_handle, key, true, input_state);
573581
}
574582
return status_code;
575583
}
576584

585+
bool InputManager::IsSingleKey(const std::wstring& input) {
586+
bool is_single_key = true;
587+
if (input.size() > 1) {
588+
WORD combining_bitmask = C3_NONSPACING | C3_DIACRITIC | C3_VOWELMARK;
589+
std::vector<WORD> char_types(input.size());
590+
BOOL get_type_success = ::GetStringTypeW(CT_CTYPE3,
591+
input.c_str(),
592+
input.size(),
593+
&char_types[0]);
594+
if (get_type_success) {
595+
bool found_alpha = false;
596+
for (int i = 0; i < char_types.size(); ++i) {
597+
if (char_types[i] & combining_bitmask) {
598+
continue;
599+
}
600+
601+
if (char_types[i] & C3_ALPHA) {
602+
if (!found_alpha) {
603+
found_alpha = true;
604+
} else {
605+
is_single_key = false;
606+
break;
607+
}
608+
}
609+
}
610+
}
611+
}
612+
if (!is_single_key) {
613+
LOG(WARN) << "key value did not pass validation";
614+
}
615+
return is_single_key;
616+
}
617+
577618
int InputManager::Pause(BrowserHandle browser_wrapper,
578619
const Json::Value& pause_action) {
579620
int status_code = 0;

cpp/iedriver/InputManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class InputManager {
117117
InputState CloneCurrentInputState(void);
118118
void UpdatePressedKeys(wchar_t character, bool press_key);
119119
bool IsKeyPressed(wchar_t character);
120+
bool IsSingleKey(const std::wstring& input);
120121

121122
void SetupKeyDescriptions(void);
122123
std::wstring GetKeyDescription(const wchar_t character);

cpp/iedriver/StringUtilities.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ std::wstring StringUtilities::ToWString(const std::string& input) {
6666
} else {
6767
output = &output_buffer[0];
6868
}
69+
70+
if (output.size() > 0) {
71+
if (FALSE == ::IsNormalizedString(NormalizationC, output.c_str(), -1)) {
72+
int required = ::NormalizeString(NormalizationC, output.c_str(), -1, NULL, 0);
73+
output_buffer.clear();
74+
output_buffer.resize(required);
75+
::NormalizeString(NormalizationC, output.c_str(), -1, &output_buffer[0], output_buffer.size());
76+
output = &output_buffer[0];
77+
}
78+
}
79+
6980
return output;
7081
}
7182

cpp/webdriver-server/response.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ std::string Response::ConvertErrorCode(const int error_code) {
186186
return ERROR_SCRIPT_TIMEOUT;
187187
} else if (error_code == EMOVETARGETOUTOFBOUNDS) {
188188
return ERROR_MOVE_TARGET_OUT_OF_BOUNDS;
189+
} else if (error_code == EINVALIDARGUMENT) {
190+
return ERROR_INVALID_ARGUMENT;
189191
}
190192

191193
return "";

0 commit comments

Comments
 (0)