1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:04:57 +00:00

LibWeb: Allow bypassing transient activation checks for tests

We have a 5 second timeout between a user-activated event occurring and
an activation-gated API being invoked in order for that API to succeed.
This is quite fine in normal circumstances, but the machines used in CI
often exceed that limit (we see upwards of 10 seconds passing between
generating the user-activated event and the API call running).

So instead of generating a user-activated event, add a hook to allow
tests to bypass the very next activation check.
This commit is contained in:
Timothy Flynn 2024-02-20 16:30:26 -05:00 committed by Tim Flynn
parent 4bdcf9a4b7
commit e52c30cbd5
6 changed files with 22 additions and 14 deletions

View file

@ -16,10 +16,7 @@
asyncTest((done) => { asyncTest((done) => {
writeText(() => { writeText(() => {
const button = document.getElementById("button"); internals.bypassNextTransientActivationTest = true;
internals.dispatchUserActivatedEvent(button, new Event("mousedown"));
button.dispatchEvent(new Event("click"));
writeText(done); writeText(done);
}); });
}); });

View file

@ -134,6 +134,7 @@ void Window::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(mime_type_object); visitor.visit(mime_type_object);
visitor.visit(m_count_queuing_strategy_size_function); visitor.visit(m_count_queuing_strategy_size_function);
visitor.visit(m_byte_length_queuing_strategy_size_function); visitor.visit(m_byte_length_queuing_strategy_size_function);
visitor.visit(m_internals);
} }
void Window::finalize() void Window::finalize()
@ -605,6 +606,14 @@ bool Window::has_transient_activation() const
// perceive the link between an interaction with the page and the page calling the activation-gated API. // perceive the link between an interaction with the page and the page calling the activation-gated API.
auto transient_activation_duration = 5; auto transient_activation_duration = 5;
// AD-HOC: Due to resource limitations on CI, we cannot rely on the time between the activation timestamp and the
// transient activation timeout being predictable. So we allow tests to indicate when they want the next
// check for a user gesture to succeed.
if (m_internals && m_internals->bypass_next_transient_activation_test()) {
m_internals->set_bypass_next_transient_activation_test(false);
return true;
}
// When the current high resolution time given W // When the current high resolution time given W
auto unsafe_shared_time = HighResolutionTime::unsafe_shared_current_time(); auto unsafe_shared_time = HighResolutionTime::unsafe_shared_current_time();
auto current_time = HighResolutionTime::relative_high_resolution_time(unsafe_shared_time, realm().global_object()); auto current_time = HighResolutionTime::relative_high_resolution_time(unsafe_shared_time, realm().global_object());
@ -813,8 +822,11 @@ WebIDL::ExceptionOr<void> Window::initialize_web_interfaces(Badge<WindowEnvironm
if (s_inspector_object_exposed) if (s_inspector_object_exposed)
define_direct_property("inspector", heap().allocate<Internals::Inspector>(realm, realm), JS::default_attributes); define_direct_property("inspector", heap().allocate<Internals::Inspector>(realm, realm), JS::default_attributes);
if (s_internals_object_exposed)
define_direct_property("internals", heap().allocate<Internals::Internals>(realm, realm), JS::default_attributes); if (s_internals_object_exposed) {
m_internals = heap().allocate<Internals::Internals>(realm, realm);
define_direct_property("internals", m_internals, JS::default_attributes);
}
return {}; return {};
} }

View file

@ -282,6 +282,8 @@ private:
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-status // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-status
// When the Window object is created, the attribute must be set to the empty string. It does not do anything else. // When the Window object is created, the attribute must be set to the empty string. It does not do anything else.
String m_status; String m_status;
JS::GCPtr<Internals::Internals> m_internals;
}; };
void run_animation_frame_callbacks(DOM::Document&, double now); void run_animation_frame_callbacks(DOM::Document&, double now);

View file

@ -89,10 +89,4 @@ void Internals::wheel(double x, double y, double delta_x, double delta_y)
page.handle_mousewheel({ x, y }, { x, y }, 0, 0, 0, delta_x, delta_y); page.handle_mousewheel({ x, y }, { x, y }, 0, 0, 0, delta_x, delta_y);
} }
WebIDL::ExceptionOr<bool> Internals::dispatch_user_activated_event(DOM::EventTarget& target, DOM::Event& event)
{
event.set_is_trusted(true);
return target.dispatch_event(event);
}
} }

View file

@ -28,11 +28,14 @@ public:
void click(double x, double y); void click(double x, double y);
void wheel(double x, double y, double delta_x, double delta_y); void wheel(double x, double y, double delta_x, double delta_y);
WebIDL::ExceptionOr<bool> dispatch_user_activated_event(DOM::EventTarget&, DOM::Event& event); bool bypass_next_transient_activation_test() const { return m_bypass_next_transient_activation_test; }
void set_bypass_next_transient_activation_test(bool bypass_next_transient_activation_test) { m_bypass_next_transient_activation_test = bypass_next_transient_activation_test; }
private: private:
explicit Internals(JS::Realm&); explicit Internals(JS::Realm&);
virtual void initialize(JS::Realm&) override; virtual void initialize(JS::Realm&) override;
bool m_bypass_next_transient_activation_test { false };
}; };
} }

View file

@ -13,6 +13,6 @@
undefined click(double x, double y); undefined click(double x, double y);
undefined wheel(double x, double y, double deltaX, double deltaY); undefined wheel(double x, double y, double deltaX, double deltaY);
boolean dispatchUserActivatedEvent(EventTarget target, Event event); attribute boolean bypassNextTransientActivationTest;
}; };