LibWeb: Implement window.close and window.closed
This commit is contained in:
parent
ae130822a0
commit
aa1df95b31
Notes:
github-actions[bot]
2024-10-06 00:43:21 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/aa1df95b31d Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1644 Reviewed-by: https://github.com/shannonbooth ✅
7 changed files with 86 additions and 6 deletions
3
Tests/LibWeb/Text/expected/HTML/Window-close.txt
Normal file
3
Tests/LibWeb/Text/expected/HTML/Window-close.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
window.closed = false
|
||||
window.closed = true
|
||||
window.closed = true
|
15
Tests/LibWeb/Text/input/HTML/Window-close.html
Normal file
15
Tests/LibWeb/Text/input/HTML/Window-close.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<script src="../include.js"></script>
|
||||
<script>
|
||||
asyncTest(done => {
|
||||
const newWindow = window.open("about:blank", "_blank");
|
||||
|
||||
newWindow.addEventListener("beforeunload", () => {
|
||||
println(`window.closed = ${newWindow.closed}`);
|
||||
done();
|
||||
});
|
||||
|
||||
println(`window.closed = ${newWindow.closed}`);
|
||||
newWindow.close();
|
||||
println(`window.closed = ${newWindow.closed}`);
|
||||
});
|
||||
</script>
|
|
@ -96,6 +96,7 @@ public:
|
|||
}
|
||||
|
||||
bool is_top_level() const;
|
||||
bool is_auxiliary() const { return m_is_auxiliary; }
|
||||
|
||||
DOM::Document const* active_document() const;
|
||||
DOM::Document* active_document();
|
||||
|
|
|
@ -128,6 +128,21 @@ void Navigable::visit_edges(Cell::Visitor& visitor)
|
|||
m_event_handler.visit_edges(visitor);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#script-closable
|
||||
bool Navigable::is_script_closable()
|
||||
{
|
||||
// A navigable is script-closable if its active browsing context is an auxiliary browsing context that was created
|
||||
// by a script (as opposed to by an action of the user), or if it is a top-level traversable whose session history
|
||||
// entries's size is 1.
|
||||
if (auto browsing_context = active_browsing_context(); browsing_context && browsing_context->is_auxiliary())
|
||||
return true;
|
||||
|
||||
if (is_top_level_traversable())
|
||||
return get_session_history_entries().size() == 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Navigable::set_delaying_load_events(bool value)
|
||||
{
|
||||
if (value) {
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
|
||||
bool is_closing() const { return m_closing; }
|
||||
void set_closing(bool value) { m_closing = value; }
|
||||
bool is_script_closable();
|
||||
|
||||
void set_delaying_load_events(bool value);
|
||||
bool is_delaying_load_events() const { return m_delaying_the_load_event.has_value(); }
|
||||
|
|
|
@ -1178,8 +1178,9 @@ void TraversableNavigable::close_top_level_traversable()
|
|||
VERIFY(is_top_level_traversable());
|
||||
|
||||
// 1. If traversable's is closing is true, then return.
|
||||
if (is_closing())
|
||||
return;
|
||||
// FIXME: Spec-issue: The only place in the spec that sets the `is closing` flag to true is `window.close`, and it
|
||||
// does so immediately before invoking this method. So it does not make sense to return early here.
|
||||
// https://github.com/whatwg/html/issues/10678
|
||||
|
||||
// 2. Let toUnload be traversable's active document's inclusive descendant navigables.
|
||||
auto to_unload = active_document()->inclusive_descendant_navigables();
|
||||
|
|
|
@ -787,15 +787,59 @@ String Window::status() const
|
|||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-close
|
||||
void Window::close()
|
||||
{
|
||||
// FIXME: Implement this properly
|
||||
dbgln("(STUBBED) Window::close()");
|
||||
// 1. Let thisTraversable be this's navigable.
|
||||
auto traversable = navigable();
|
||||
|
||||
// 2. If thisTraversable is not a top-level traversable, then return.
|
||||
if (!traversable || !traversable->is_top_level_traversable())
|
||||
return;
|
||||
|
||||
// 3. If thisTraversable's is closing is true, then return.
|
||||
if (traversable->is_closing())
|
||||
return;
|
||||
|
||||
// 4. Let browsingContext be thisTraversable's active browsing context.
|
||||
auto browsing_context = traversable->active_browsing_context();
|
||||
|
||||
// 5. Let sourceSnapshotParams be the result of snapshotting source snapshot params given thisTraversable's active document.
|
||||
auto source_snapshot_params = traversable->active_document()->snapshot_source_snapshot_params();
|
||||
|
||||
auto& incumbent_global_object = verify_cast<HTML::Window>(HTML::incumbent_global_object());
|
||||
|
||||
// 6. If all the following are true:
|
||||
if (
|
||||
// thisTraversable is script-closable;
|
||||
traversable->is_script_closable()
|
||||
|
||||
// the incumbent global object's browsing context is familiar with browsingContext; and
|
||||
&& incumbent_global_object.browsing_context()->is_familiar_with(*browsing_context)
|
||||
|
||||
// the incumbent global object's navigable is allowed by sandboxing to navigate thisTraversable, given sourceSnapshotParams,
|
||||
&& incumbent_global_object.navigable()->allowed_by_sandboxing_to_navigate(*traversable, source_snapshot_params))
|
||||
// then:
|
||||
{
|
||||
// 1. Set thisTraversable's is closing to true.
|
||||
traversable->set_closing(true);
|
||||
|
||||
// 2. Queue a task on the DOM manipulation task source to close thisTraversable.
|
||||
HTML::queue_global_task(HTML::Task::Source::DOMManipulation, incumbent_global_object, JS::create_heap_function(heap(), [traversable] {
|
||||
verify_cast<TraversableNavigable>(*traversable).close_top_level_traversable();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-closed
|
||||
bool Window::closed() const
|
||||
{
|
||||
// FIXME: Implement this properly
|
||||
dbgln("(STUBBED) Window::closed");
|
||||
// The closed getter steps are to return true if this's browsing context is null or its is closing is true;
|
||||
// otherwise false.
|
||||
if (!browsing_context())
|
||||
return true;
|
||||
|
||||
// FIXME: The spec seems a bit out of date. The `is closing` flag is on the navigable, not the browsing context.
|
||||
if (auto navigable = this->navigable(); !navigable || navigable->is_closing())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue