Commit f226daab authored by Stanley Hon's avatar Stanley Hon Committed by Commit Bot

[ChromeDriver] Update sendKeysToElement focus behavior when targeting contenteditable element.

This change updates chromedriver to call focus.js if the element is a non-text element.
This is specifically to fix some cases where browser based text editors use <body contenteditable=true>
to create a text area of sorts.

Before this change, but after https://crrev.com/674640, we were not resetting focus to the body
element as it was considered already focused. This results in sendkeys being lost.

We now call focus on any non-text elements, which still abides by the W3C SendKeys spec change
incoming https://github.com/w3c/webdriver/issues/1430 as carat preservation behavior is only
specified for text-type inputs.

Additionally, this change also updates focus.js javascript to not move carat after a focus.
Which was erroneously not updated in https://crrev.com/674640

Bug: chromedriver:3006
Change-Id: Ie4d4bab3eb45aec64a586cbfa786968601a06189
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1700475
Commit-Queue: Stanley Hon <stahon@microsoft.com>
Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678908}
parent b4339047
...@@ -91,9 +91,12 @@ Status SendKeysToElement(Session* session, ...@@ -91,9 +91,12 @@ Status SendKeysToElement(Session* session,
const base::ListValue* key_list) { const base::ListValue* key_list) {
// If we were previously focused, we don't need to focus again. // If we were previously focused, we don't need to focus again.
// But also, later we don't move the carat if we were already in focus. // But also, later we don't move the carat if we were already in focus.
// However, non-text elements such as contenteditable elements needs to be
// focused to ensure the keys will end up being sent to the correct place.
// So in the case of non-text elements, we still focusToElement.
bool wasPreviouslyFocused = false; bool wasPreviouslyFocused = false;
IsElementFocused(session, web_view, element_id, &wasPreviouslyFocused); IsElementFocused(session, web_view, element_id, &wasPreviouslyFocused);
if (!wasPreviouslyFocused) { if (!wasPreviouslyFocused || !is_text) {
Status status = FocusToElement(session, web_view, element_id); Status status = FocusToElement(session, web_view, element_id);
if (status.IsError()) if (status.IsError())
return Status(kElementNotInteractable); return Status(kElementNotInteractable);
...@@ -481,8 +484,16 @@ Status ExecuteSendKeysToElement(Session* session, ...@@ -481,8 +484,16 @@ Status ExecuteSendKeysToElement(Session* session,
key_list); key_list);
} }
// If element_type is in textControlTypes, sendKeys should append // If element_type is in textControlTypes, sendKeys should append
bool is_text = is_input && textControlTypes.find(element_type) != bool is_textControlType = is_input && textControlTypes.find(element_type) !=
textControlTypes.end(); textControlTypes.end();
// If the element is a textarea, sendKeys should also append
bool is_textarea = false;
status = IsElementAttributeEqualToIgnoreCase(
session, web_view, element_id, "tagName", "textarea", &is_textarea);
if (status.IsError())
return status;
bool is_text = is_textControlType || is_textarea;
return SendKeysToElement(session, web_view, element_id, is_text, key_list); return SendKeysToElement(session, web_view, element_id, is_text, key_list);
} }
} }
......
...@@ -9,9 +9,7 @@ function focus(element) { ...@@ -9,9 +9,7 @@ function focus(element) {
// because this may cause us to lose the current cursor position in the // because this may cause us to lose the current cursor position in the
// element. // element.
// Secondly, we focus the target element. // Secondly, we focus the target element.
// Thirdly, if the target element is newly focused and is a text input, we // Thirdly, we check if the new active element is the target element. If not,
// set the cursor position at the end.
// Fourthly, we check if the new active element is the target element. If not,
// we throw an error. // we throw an error.
// Additional notes: // Additional notes:
// - |document.activeElement| is the currently focused element, or body if // - |document.activeElement| is the currently focused element, or body if
...@@ -28,16 +26,6 @@ function focus(element) { ...@@ -28,16 +26,6 @@ function focus(element) {
if (element != prevActiveElement && prevActiveElement) if (element != prevActiveElement && prevActiveElement)
prevActiveElement.blur(); prevActiveElement.blur();
element.focus(); element.focus();
if (element != prevActiveElement && element.value &&
element.value.length && element.setSelectionRange) {
try {
element.setSelectionRange(element.value.length, element.value.length);
} catch (error) {
if (!(error instanceof TypeError) && !(error instanceof DOMException &&
error.code == DOMException.INVALID_STATE_ERR))
throw error;
}
}
var activeElement = doc.activeElement; var activeElement = doc.activeElement;
// If the element is in a shadow DOM, then as far as the document is // If the element is in a shadow DOM, then as far as the document is
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment