mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 20:29:18 +00:00
LibWeb: Stub out "focus-without-user-activation" feature policy
For now this always returns that focus is allowed, as that matches our
previous behavior.
Corresponds to d7053d86ad
This commit is contained in:
parent
7902d13c28
commit
70e3a48892
Notes:
github-actions[bot]
2025-03-14 20:34:25 +00:00
Author: https://github.com/AtkinsSJ
Commit: 70e3a48892
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3945
Reviewed-by: https://github.com/tcl3 ✅
5 changed files with 62 additions and 15 deletions
|
@ -3418,6 +3418,24 @@ bool Document::has_focus() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/interaction.html#allow-focus-steps
|
||||||
|
bool Document::allow_focus() const
|
||||||
|
{
|
||||||
|
// The allow focus steps, given a Document object target, are as follows:
|
||||||
|
|
||||||
|
// 1. If target is allowed to use the "focus-without-user-activation" feature, then return true.
|
||||||
|
if (is_allowed_to_use_feature(PolicyControlledFeature::FocusWithoutUserActivation))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// FIXME: 2. If any of the following are true:
|
||||||
|
// - target's relevant global object has transient user activation; or
|
||||||
|
// - target's node navigable's container, if any, is marked as locked for focus,
|
||||||
|
// then return true.
|
||||||
|
|
||||||
|
// 3. Return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Document::set_parser(Badge<HTML::HTMLParser>, HTML::HTMLParser& parser)
|
void Document::set_parser(Badge<HTML::HTMLParser>, HTML::HTMLParser& parser)
|
||||||
{
|
{
|
||||||
m_parser = parser;
|
m_parser = parser;
|
||||||
|
@ -4295,6 +4313,9 @@ bool Document::is_allowed_to_use_feature(PolicyControlledFeature feature) const
|
||||||
if (PermissionsPolicy::AutoplayAllowlist::the().is_allowed_for_origin(*this, origin()) == PermissionsPolicy::Decision::Enabled)
|
if (PermissionsPolicy::AutoplayAllowlist::the().is_allowed_for_origin(*this, origin()) == PermissionsPolicy::Decision::Enabled)
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
case PolicyControlledFeature::FocusWithoutUserActivation:
|
||||||
|
// FIXME: Implement allowlist for this.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Return false.
|
// 4. Return false.
|
||||||
|
|
|
@ -154,8 +154,9 @@ struct ElementCreationOptions {
|
||||||
Optional<String> is;
|
Optional<String> is;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PolicyControlledFeature {
|
enum class PolicyControlledFeature : u8 {
|
||||||
Autoplay,
|
Autoplay,
|
||||||
|
FocusWithoutUserActivation,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Document
|
class Document
|
||||||
|
@ -552,6 +553,8 @@ public:
|
||||||
|
|
||||||
bool has_focus() const;
|
bool has_focus() const;
|
||||||
|
|
||||||
|
bool allow_focus() const;
|
||||||
|
|
||||||
void set_parser(Badge<HTML::HTMLParser>, HTML::HTMLParser&);
|
void set_parser(Badge<HTML::HTMLParser>, HTML::HTMLParser&);
|
||||||
void detach_parser(Badge<HTML::HTMLParser>);
|
void detach_parser(Badge<HTML::HTMLParser>);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, the SerenityOS developers.
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
|
* Copyright (c) 2024-2025, Sam Atkins <sam@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
#include <LibWeb/HTML/Focus.h>
|
#include <LibWeb/HTML/Focus.h>
|
||||||
#include <LibWeb/HTML/HTMLDialogElement.h>
|
#include <LibWeb/HTML/HTMLDialogElement.h>
|
||||||
#include <LibWeb/HTML/ToggleEvent.h>
|
#include <LibWeb/HTML/ToggleEvent.h>
|
||||||
|
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
@ -406,18 +407,32 @@ void HTMLDialogElement::set_close_watcher()
|
||||||
// https://html.spec.whatwg.org/multipage/interactive-elements.html#dialog-focusing-steps
|
// https://html.spec.whatwg.org/multipage/interactive-elements.html#dialog-focusing-steps
|
||||||
void HTMLDialogElement::run_dialog_focusing_steps()
|
void HTMLDialogElement::run_dialog_focusing_steps()
|
||||||
{
|
{
|
||||||
// 1. Let control be null
|
// 1. If the allow focus steps given subject's node document return false, then return.
|
||||||
|
if (!document().allow_focus())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 2. Let control be null
|
||||||
GC::Ptr<Element> control = nullptr;
|
GC::Ptr<Element> control = nullptr;
|
||||||
|
|
||||||
// FIXME 2. If subject has the autofocus attribute, then set control to subject.
|
// FIXME 3. If subject has the autofocus attribute, then set control to subject.
|
||||||
// FIXME 3. If control is null, then set control to the focus delegate of subject.
|
// FIXME 4. If control is null, then set control to the focus delegate of subject.
|
||||||
|
|
||||||
// 4. If control is null, then set control to subject.
|
// 5. If control is null, then set control to subject.
|
||||||
if (!control)
|
if (!control)
|
||||||
control = this;
|
control = this;
|
||||||
|
|
||||||
// 5. Run the focusing steps for control.
|
// 6. Run the focusing steps for control.
|
||||||
run_focusing_steps(control);
|
run_focusing_steps(control);
|
||||||
|
|
||||||
|
// 7. Let topDocument be control's node navigable's top-level traversable's active document.
|
||||||
|
auto top_document = control->navigable()->top_level_traversable()->active_document();
|
||||||
|
|
||||||
|
// 8. If control's node document's origin is not the same as the origin of topDocument, then return.
|
||||||
|
if (!control->document().origin().is_same_origin(top_document->origin()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME: 9. Empty topDocument's autofocus candidates.
|
||||||
|
// FIXME: 10. Set topDocument's autofocus processed flag to true.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,24 +26,28 @@ GC::Ref<DOMStringMap> HTMLOrSVGElement<ElementBase>::dataset()
|
||||||
template<typename ElementBase>
|
template<typename ElementBase>
|
||||||
void HTMLOrSVGElement<ElementBase>::focus()
|
void HTMLOrSVGElement<ElementBase>::focus()
|
||||||
{
|
{
|
||||||
// FIXME: below are the focus(options) steps, also implement focus()
|
// 1. If the allow focus steps given the element's node document return false, then return.
|
||||||
|
if (!static_cast<ElementBase*>(this)->document().allow_focus())
|
||||||
|
return;
|
||||||
|
|
||||||
// 1. If the element is marked as locked for focus, then return.
|
// 2. If the element is marked as locked for focus, then return.
|
||||||
if (m_locked_for_focus)
|
if (m_locked_for_focus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 2. Mark the element as locked for focus.
|
// 3. Mark the element as locked for focus.
|
||||||
m_locked_for_focus = true;
|
m_locked_for_focus = true;
|
||||||
|
|
||||||
// 3. Run the focusing steps for the element.
|
// 4. Run the focusing steps for the element.
|
||||||
run_focusing_steps(static_cast<ElementBase*>(this));
|
run_focusing_steps(static_cast<ElementBase*>(this));
|
||||||
|
|
||||||
// FIXME: 4. If the value of the preventScroll dictionary member of options is false,
|
// FIXME: 5. If the value of the focusVisible dictionary member of options is true, or is not present but in an implementation-defined way the user agent determines it would be best to do so, then indicate focus.
|
||||||
|
|
||||||
|
// FIXME: 6. If the value of the preventScroll dictionary member of options is false,
|
||||||
// then scroll the element into view with scroll behavior "auto",
|
// then scroll the element into view with scroll behavior "auto",
|
||||||
// block flow direction position set to an implementation-defined value,
|
// block flow direction position set to an implementation-defined value,
|
||||||
// and inline base direction position set to an implementation-defined value.
|
// and inline base direction position set to an implementation-defined value.
|
||||||
|
|
||||||
// 5. Unmark the element as locked for focus.
|
// 7. Unmark the element as locked for focus.
|
||||||
m_locked_for_focus = false;
|
m_locked_for_focus = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -910,12 +910,16 @@ void Window::focus()
|
||||||
if (!current)
|
if (!current)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 3. Run the focusing steps with current.
|
// 3. If the allow focus steps given current's active document return false, then return.
|
||||||
|
if (!document()->allow_focus())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 4. Run the focusing steps with current.
|
||||||
// FIXME: We should pass in the browsing context itself instead of the active document, however the focusing steps don't currently accept browsing contexts.
|
// FIXME: We should pass in the browsing context itself instead of the active document, however the focusing steps don't currently accept browsing contexts.
|
||||||
// Passing in a browsing context always makes it resolve to its active document for focus, so this is fine for now.
|
// Passing in a browsing context always makes it resolve to its active document for focus, so this is fine for now.
|
||||||
run_focusing_steps(current->active_document());
|
run_focusing_steps(current->active_document());
|
||||||
|
|
||||||
// FIXME: 4. If current is a top-level traversable, user agents are encouraged to trigger some sort of notification to
|
// FIXME: 5. If current is a top-level traversable, user agents are encouraged to trigger some sort of notification to
|
||||||
// indicate to the user that the page is attempting to gain focus.
|
// indicate to the user that the page is attempting to gain focus.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue