Commit c8b74680 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

dialog: Set 'autofocus process flag' to true at the end of dialog focusing steps

- Unify multiple |focus(); return;| in SetFocusForDialog() into one.
- Add origin check and FinalizeAutofocus() call to SetFocusForDialog().

Bug: 985637
Change-Id: Ibb9a7161f384c9d15452dd2559c69cb0d458b9da

Experimental implementation for https://github.com/whatwg/html/pull/4918

Bug: 985637
Change-Id: I321736d512d6d8c76095f0f6de8751cd0a5e44e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1911061Reviewed-by: default avatarRakina Zata Amni <rakina@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714672}
parent 54f6513a
...@@ -7904,9 +7904,8 @@ void Document::FlushAutofocusCandidates() { ...@@ -7904,9 +7904,8 @@ void Document::FlushAutofocusCandidates() {
// https://github.com/whatwg/html/issues/5027 // https://github.com/whatwg/html/issues/5027
element.DelegatesFocus()) { element.DelegatesFocus()) {
// 9.1. Empty candidates. // 9.1. Empty candidates.
autofocus_candidates_.clear();
// 9.2. Set topDocument's autofocus processed flag to true. // 9.2. Set topDocument's autofocus processed flag to true.
autofocus_processed_flag_ = true; FinalizeAutofocus();
// 9.3. Run the focusing steps for element. // 9.3. Run the focusing steps for element.
element.focus(); element.focus();
} else { } else {
...@@ -7916,6 +7915,11 @@ void Document::FlushAutofocusCandidates() { ...@@ -7916,6 +7915,11 @@ void Document::FlushAutofocusCandidates() {
} }
} }
void Document::FinalizeAutofocus() {
autofocus_candidates_.clear();
autofocus_processed_flag_ = true;
}
bool Document::HasNonEmptyFragment() const { bool Document::HasNonEmptyFragment() const {
return !Url().FragmentIdentifier().IsEmpty(); return !Url().FragmentIdentifier().IsEmpty();
} }
......
...@@ -840,6 +840,7 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -840,6 +840,7 @@ class CORE_EXPORT Document : public ContainerNode,
void EnqueueAutofocusCandidate(Element&); void EnqueueAutofocusCandidate(Element&);
bool HasAutofocusCandidates() const; bool HasAutofocusCandidates() const;
void FlushAutofocusCandidates(); void FlushAutofocusCandidates();
void FinalizeAutofocus();
void SetSequentialFocusNavigationStartingPoint(Node*); void SetSequentialFocusNavigationStartingPoint(Node*);
Element* SequentialFocusNavigationStartingPoint(WebFocusType) const; Element* SequentialFocusNavigationStartingPoint(WebFocusType) const;
......
...@@ -39,10 +39,11 @@ ...@@ -39,10 +39,11 @@
namespace blink { namespace blink {
// https://html.spec.whatwg.org/C/#the-dialog-element
// This function chooses the focused element when show() or showModal() is // This function chooses the focused element when show() or showModal() is
// invoked, as described in their spec. // invoked, as described in their spec.
static void SetFocusForDialog(HTMLDialogElement* dialog) { static void SetFocusForDialog(HTMLDialogElement* dialog) {
Element* focusable_descendant = nullptr; Element* control = nullptr;
Node* next = nullptr; Node* next = nullptr;
// TODO(kochi): How to find focusable element inside Shadow DOM is not // TODO(kochi): How to find focusable element inside Shadow DOM is not
...@@ -57,24 +58,35 @@ static void SetFocusForDialog(HTMLDialogElement* dialog) { ...@@ -57,24 +58,35 @@ static void SetFocusForDialog(HTMLDialogElement* dialog) {
if (!element) if (!element)
continue; continue;
if (element->IsAutofocusable() && element->IsFocusable()) { if (element->IsAutofocusable() && element->IsFocusable()) {
element->focus(); control = element;
return; break;
} }
if (!focusable_descendant && element->IsFocusable()) if (!control && element->IsFocusable())
focusable_descendant = element; control = element;
} }
if (!control)
control = dialog;
if (focusable_descendant) { // 3. Run the focusing steps for control.
focusable_descendant->focus(); if (control->IsFocusable())
return; control->focus();
} else
dialog->GetDocument().ClearFocusedElement();
if (dialog->IsFocusable()) { // 4. Let topDocument be the active document of control's node document's
dialog->focus(); // browsing context's top-level browsing context.
// 5. If control's node document's origin is not the same as the origin of
// topDocument, then return.
Document& doc = control->GetDocument();
if (!doc.IsActive())
return;
if (!doc.IsInMainFrame() &&
!doc.TopFrameOrigin()->CanAccess(doc.GetSecurityOrigin()))
return; return;
}
dialog->GetDocument().ClearFocusedElement(); // 6. Empty topDocument's autofocus candidates.
// 7. Set topDocument's autofocus processed flag to true.
doc.TopDocument().FinalizeAutofocus();
} }
static void InertSubtreesChanged(Document& document) { static void InertSubtreesChanged(Document& document) {
......
This is a testharness.js-based test.
FAIL An autofocus element in a dialog element should not try to get focus twice. assert_equals: Non-dialog autofocus processing should be skipped. expected Element node <body>
<dialog open="">
<input>
<input autofocus="">
</di... but got Element node <input autofocus=""></input>
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL After showing a dialog, non-dialog autofocus processing won't work. assert_equals: Non-dialog autofocus processing should be skipped. expected Element node <body>
<input autofocus=""><dialog></dialog>
<script>
// ... but got Element node <input autofocus=""></input>
Harness: the test ran to completion.
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