Commit 745e1b45 authored by Joshua Bell's avatar Joshua Bell Committed by Commit Bot

<input type=file webkitdirectory>: Launch picker on Enter keyup

Avoid key repeat triggering an unintentional commit of the subsequent
dialog by launching the picker on the Enter keyup event rather than on
keydown.

Bug: 637098
Change-Id: Ia327a7a9f92c34fd3fcdf971d8c21a5ce744254b
Reviewed-on: https://chromium-review.googlesource.com/814916
Commit-Queue: Joshua Bell <jsbell@chromium.org>
Reviewed-by: default avatarChris Palmer <palmer@chromium.org>
Reviewed-by: default avatarEmily Stark <estark@chromium.org>
Reviewed-by: default avatarKeishi Hattori <keishi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523507}
parent a6098813
...@@ -39,7 +39,7 @@ function logEvent(event) ...@@ -39,7 +39,7 @@ function logEvent(event)
debug(event.type + ': ' + targetDescription(event.target)); debug(event.type + ': ' + targetDescription(event.target));
} }
var keys = ['\r', ' ']; var keys = ['Enter', ' '];
var keyNames = ['Enter', 'U+0020']; var keyNames = ['Enter', 'U+0020'];
var tagNames = ['button', 'input']; var tagNames = ['button', 'input'];
......
Mock: Opening a file chooser.
Ensure pressing Enter key with focus on an INPUT element with TYPE=FILE and WEBKITDIRECTORY still launches a file chooser if preventDefault() is called on the 'keypress' event. Automated test passes if 'Opening a file chooser' was logged.
keypress prevented
<!DOCTYPE html>
<title>INPUT TYPE=FILE WEBKITDIRECTORY and key events - Enter keypress prevented</title>
<p>
Ensure pressing Enter key with focus on an INPUT element with
TYPE=FILE and WEBKITDIRECTORY still launches a file chooser if
preventDefault() is called on the 'keypress' event. Automated test
passes if 'Opening a file chooser' was logged.
</p>
<pre id=console></pre>
<input type="file" webkitdirectory>
<script>
document.querySelector('input').onkeypress = e => {
document.querySelector('#console').innerText = `${e.type} prevented`;
e.preventDefault();
};
if (testRunner && eventSender) {
testRunner.dumpAsText();
document.querySelector('input').focus();
// Despite the name, 'keyDown' simulates a full down/press/up sequence.
eventSender.keyDown('Enter', []);
}
</script>
Ensure pressing Enter key with focus on an INPUT element with TYPE=FILE and WEBKITDIRECTORY does not launch a file chooser if preventDefault() is called on the 'keyup' event. Automated test passes if 'Opening a file chooser' was not logged.
keyup prevented
<!DOCTYPE html>
<title>INPUT TYPE=FILE WEBKITDIRECTORY and key events - Enter keyup prevented</title>
<p>
Ensure pressing Enter key with focus on an INPUT element with
TYPE=FILE and WEBKITDIRECTORY does <b>not</b> launch a file chooser
if preventDefault() is called on the 'keyup' event. Automated test
passes if 'Opening a file chooser' was <b>not</b> logged.
</p>
<pre id=console></pre>
<input type="file" webkitdirectory>
<script>
document.querySelector('input').onkeyup = e => {
document.querySelector('#console').innerText = `${e.type} prevented`;
e.preventDefault();
};
if (testRunner && eventSender) {
testRunner.dumpAsText();
document.querySelector('input').focus();
// Despite the name, 'keyDown' simulates a full down/press/up sequence.
eventSender.keyDown('Enter', []);
}
</script>
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "core/css/StyleChangeReason.h" #include "core/css/StyleChangeReason.h"
#include "core/dom/ShadowRoot.h" #include "core/dom/ShadowRoot.h"
#include "core/dom/events/Event.h" #include "core/dom/events/Event.h"
#include "core/events/KeyboardEvent.h"
#include "core/fileapi/File.h" #include "core/fileapi/File.h"
#include "core/fileapi/FileList.h" #include "core/fileapi/FileList.h"
#include "core/frame/UseCounter.h" #include "core/frame/UseCounter.h"
...@@ -420,4 +421,30 @@ void FileInputType::CopyNonAttributeProperties(const HTMLInputElement& source) { ...@@ -420,4 +421,30 @@ void FileInputType::CopyNonAttributeProperties(const HTMLInputElement& source) {
file_list_->Append(source_list->item(i)->Clone()); file_list_->Append(source_list->item(i)->Clone());
} }
void FileInputType::HandleKeypressEvent(KeyboardEvent* event) {
if (GetElement().FastHasAttribute(webkitdirectoryAttr)) {
// Override to invoke the action on Enter key up (not press) to avoid
// repeats committing the file chooser.
const String& key = event->key();
if (key == "Enter") {
event->SetDefaultHandled();
return;
}
}
KeyboardClickableInputTypeView::HandleKeypressEvent(event);
}
void FileInputType::HandleKeyupEvent(KeyboardEvent* event) {
if (GetElement().FastHasAttribute(webkitdirectoryAttr)) {
// Override to invoke the action on Enter key up (not press) to avoid
// repeats committing the file chooser.
if (event->key() == "Enter") {
GetElement().DispatchSimulatedClick(event);
event->SetDefaultHandled();
return;
}
}
KeyboardClickableInputTypeView::HandleKeyupEvent(event);
}
} // namespace blink } // namespace blink
...@@ -91,6 +91,10 @@ class CORE_EXPORT FileInputType final : public InputType, ...@@ -91,6 +91,10 @@ class CORE_EXPORT FileInputType final : public InputType,
String DefaultToolTip(const InputTypeView&) const override; String DefaultToolTip(const InputTypeView&) const override;
void CopyNonAttributeProperties(const HTMLInputElement&) override; void CopyNonAttributeProperties(const HTMLInputElement&) override;
// KeyboardClickableInputTypeView overrides.
void HandleKeypressEvent(KeyboardEvent*) override;
void HandleKeyupEvent(KeyboardEvent*) override;
// FileChooserClient implementation. // FileChooserClient implementation.
void FilesChosen(const Vector<FileChooserFileInfo>&) override; void FilesChosen(const Vector<FileChooserFileInfo>&) override;
......
...@@ -49,13 +49,13 @@ void KeyboardClickableInputTypeView::HandleKeydownEvent(KeyboardEvent* event) { ...@@ -49,13 +49,13 @@ void KeyboardClickableInputTypeView::HandleKeydownEvent(KeyboardEvent* event) {
} }
void KeyboardClickableInputTypeView::HandleKeypressEvent(KeyboardEvent* event) { void KeyboardClickableInputTypeView::HandleKeypressEvent(KeyboardEvent* event) {
int char_code = event->charCode(); const String& key = event->key();
if (char_code == '\r') { if (key == "Enter") {
GetElement().DispatchSimulatedClick(event); GetElement().DispatchSimulatedClick(event);
event->SetDefaultHandled(); event->SetDefaultHandled();
return; return;
} }
if (char_code == ' ') { if (key == " ") {
// Prevent scrolling down the page. // Prevent scrolling down the page.
event->SetDefaultHandled(); event->SetDefaultHandled();
} }
......
...@@ -42,7 +42,7 @@ class CORE_EXPORT KeyboardClickableInputTypeView : public InputTypeView { ...@@ -42,7 +42,7 @@ class CORE_EXPORT KeyboardClickableInputTypeView : public InputTypeView {
KeyboardClickableInputTypeView(HTMLInputElement& element) KeyboardClickableInputTypeView(HTMLInputElement& element)
: InputTypeView(element) {} : InputTypeView(element) {}
private: protected:
void HandleKeydownEvent(KeyboardEvent*) override; void HandleKeydownEvent(KeyboardEvent*) override;
void HandleKeypressEvent(KeyboardEvent*) override; void HandleKeypressEvent(KeyboardEvent*) override;
void HandleKeyupEvent(KeyboardEvent*) override; void HandleKeyupEvent(KeyboardEvent*) override;
......
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