Skip to content

Commit c427f9f

Browse files
authored
fix: added new line handling for cdp (#3100)
<!-- This is an auto-generated description by cubic. --> ## Summary by cubic Handled newline input in CDP typing by sending proper Enter key events, so multiline text and form submissions work reliably. This fixes cases where “\n” was ignored or typed as a literal character. - **Bug Fixes** - Map “\n” to Enter with keyDown/char('\r')/keyUp (code: Enter, VK: 13). - Applied in _type_to_page and _input_text_element_node_impl with existing typing delays. <!-- End of auto-generated description by cubic. -->
2 parents 59791b9 + af07b8f commit c427f9f

File tree

1 file changed

+131
-61
lines changed

1 file changed

+131
-61
lines changed

browser_use/browser/watchdogs/default_action_watchdog.py

Lines changed: 131 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -563,30 +563,62 @@ async def _type_to_page(self, text: str):
563563

564564
# Type the text character by character to the focused element
565565
for char in text:
566-
# Send keydown
567-
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
568-
params={
569-
'type': 'keyDown',
570-
'key': char,
571-
},
572-
session_id=cdp_session.session_id,
573-
)
574-
# Send char for actual text input
575-
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
576-
params={
577-
'type': 'char',
578-
'text': char,
579-
},
580-
session_id=cdp_session.session_id,
581-
)
582-
# Send keyup
583-
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
584-
params={
585-
'type': 'keyUp',
586-
'key': char,
587-
},
588-
session_id=cdp_session.session_id,
589-
)
566+
# Handle newline characters as Enter key
567+
if char == '\n':
568+
# Send proper Enter key sequence
569+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
570+
params={
571+
'type': 'keyDown',
572+
'key': 'Enter',
573+
'code': 'Enter',
574+
'windowsVirtualKeyCode': 13,
575+
},
576+
session_id=cdp_session.session_id,
577+
)
578+
# Send char event with carriage return
579+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
580+
params={
581+
'type': 'char',
582+
'text': '\r',
583+
},
584+
session_id=cdp_session.session_id,
585+
)
586+
# Send keyup
587+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
588+
params={
589+
'type': 'keyUp',
590+
'key': 'Enter',
591+
'code': 'Enter',
592+
'windowsVirtualKeyCode': 13,
593+
},
594+
session_id=cdp_session.session_id,
595+
)
596+
else:
597+
# Handle regular characters
598+
# Send keydown
599+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
600+
params={
601+
'type': 'keyDown',
602+
'key': char,
603+
},
604+
session_id=cdp_session.session_id,
605+
)
606+
# Send char for actual text input
607+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
608+
params={
609+
'type': 'char',
610+
'text': char,
611+
},
612+
session_id=cdp_session.session_id,
613+
)
614+
# Send keyup
615+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
616+
params={
617+
'type': 'keyUp',
618+
'key': char,
619+
},
620+
session_id=cdp_session.session_id,
621+
)
590622
# Add 18ms delay between keystrokes
591623
await asyncio.sleep(0.018)
592624

@@ -1007,48 +1039,86 @@ async def _input_text_element_node_impl(
10071039
self.logger.debug(f'🎯 Typing text character by character: "{text}"')
10081040

10091041
for i, char in enumerate(text):
1010-
# Get proper modifiers, VK code, and base key for the character
1011-
modifiers, vk_code, base_key = self._get_char_modifiers_and_vk(char)
1012-
key_code = self._get_key_code_for_char(base_key)
1042+
# Handle newline characters as Enter key
1043+
if char == '\n':
1044+
# Send proper Enter key sequence
1045+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1046+
params={
1047+
'type': 'keyDown',
1048+
'key': 'Enter',
1049+
'code': 'Enter',
1050+
'windowsVirtualKeyCode': 13,
1051+
},
1052+
session_id=cdp_session.session_id,
1053+
)
10131054

1014-
# self.logger.debug(f'🎯 Typing character {i + 1}/{len(text)}: "{char}" (base_key: {base_key}, code: {key_code}, modifiers: {modifiers}, vk: {vk_code})')
1055+
# Small delay to emulate human typing speed
1056+
await asyncio.sleep(0.001)
10151057

1016-
# Step 1: Send keyDown event (NO text parameter)
1017-
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1018-
params={
1019-
'type': 'keyDown',
1020-
'key': base_key,
1021-
'code': key_code,
1022-
'modifiers': modifiers,
1023-
'windowsVirtualKeyCode': vk_code,
1024-
},
1025-
session_id=cdp_session.session_id,
1026-
)
1058+
# Send char event with carriage return
1059+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1060+
params={
1061+
'type': 'char',
1062+
'text': '\r',
1063+
'key': 'Enter',
1064+
},
1065+
session_id=cdp_session.session_id,
1066+
)
10271067

1028-
# Small delay to emulate human typing speed
1029-
await asyncio.sleep(0.001)
1068+
# Send keyUp event
1069+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1070+
params={
1071+
'type': 'keyUp',
1072+
'key': 'Enter',
1073+
'code': 'Enter',
1074+
'windowsVirtualKeyCode': 13,
1075+
},
1076+
session_id=cdp_session.session_id,
1077+
)
1078+
else:
1079+
# Handle regular characters
1080+
# Get proper modifiers, VK code, and base key for the character
1081+
modifiers, vk_code, base_key = self._get_char_modifiers_and_vk(char)
1082+
key_code = self._get_key_code_for_char(base_key)
10301083

1031-
# Step 2: Send char event (WITH text parameter) - this is crucial for text input
1032-
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1033-
params={
1034-
'type': 'char',
1035-
'text': char,
1036-
'key': char,
1037-
},
1038-
session_id=cdp_session.session_id,
1039-
)
1084+
# self.logger.debug(f'🎯 Typing character {i + 1}/{len(text)}: "{char}" (base_key: {base_key}, code: {key_code}, modifiers: {modifiers}, vk: {vk_code})')
10401085

1041-
# Step 3: Send keyUp event (NO text parameter)
1042-
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1043-
params={
1044-
'type': 'keyUp',
1045-
'key': base_key,
1046-
'code': key_code,
1047-
'modifiers': modifiers,
1048-
'windowsVirtualKeyCode': vk_code,
1049-
},
1050-
session_id=cdp_session.session_id,
1051-
)
1086+
# Step 1: Send keyDown event (NO text parameter)
1087+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1088+
params={
1089+
'type': 'keyDown',
1090+
'key': base_key,
1091+
'code': key_code,
1092+
'modifiers': modifiers,
1093+
'windowsVirtualKeyCode': vk_code,
1094+
},
1095+
session_id=cdp_session.session_id,
1096+
)
1097+
1098+
# Small delay to emulate human typing speed
1099+
await asyncio.sleep(0.001)
1100+
1101+
# Step 2: Send char event (WITH text parameter) - this is crucial for text input
1102+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1103+
params={
1104+
'type': 'char',
1105+
'text': char,
1106+
'key': char,
1107+
},
1108+
session_id=cdp_session.session_id,
1109+
)
1110+
1111+
# Step 3: Send keyUp event (NO text parameter)
1112+
await cdp_session.cdp_client.send.Input.dispatchKeyEvent(
1113+
params={
1114+
'type': 'keyUp',
1115+
'key': base_key,
1116+
'code': key_code,
1117+
'modifiers': modifiers,
1118+
'windowsVirtualKeyCode': vk_code,
1119+
},
1120+
session_id=cdp_session.session_id,
1121+
)
10521122

10531123
# Small delay between characters to look human (realistic typing speed)
10541124
await asyncio.sleep(0.001)

0 commit comments

Comments
 (0)