mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 13:49:16 +00:00
LibWeb: Track fetching-related tasks in FetchController for cancellation
The HTMLMediaElement, for example, contains spec text which states any ongoing fetch process must be "stopped". The spec does not indicate how to do this, so our implementation is rather ad-hoc. Our current implementation may cause a crash in places that assume one of the fetch algorithms that we set to null is *not* null. For example: if (fetch_params.process_response) { queue_fetch_task([]() { fetch_params.process_response(); }; } If the fetch process is stopped after queuing the fetch task, but not before the fetch task is run, we will crash when running this fetch algorithm. We now track queued fetch tasks on the fetch controller. When the fetch process is stopped, we cancel any such pending task. It is a little bit awkward maintaining a fetch task ID. Ideally, we could use the underlying task ID throughout. But we do not have access to the underlying task nor its ID when the task is running, at which point we need some ID to remove from the pending task list.
This commit is contained in:
parent
4806cf9527
commit
7b3ddd5e15
Notes:
sideshowbarker
2024-07-17 07:43:44 +09:00
Author: https://github.com/trflynn89
Commit: 7b3ddd5e15
Pull-request: https://github.com/SerenityOS/serenity/pull/23681
7 changed files with 66 additions and 7 deletions
|
@ -9,6 +9,7 @@
|
|||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/FetchParams.h>
|
||||
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
||||
#include <LibWeb/WebIDL/DOMException.h>
|
||||
|
||||
namespace Web::Fetch::Infrastructure {
|
||||
|
@ -105,11 +106,29 @@ void FetchController::stop_fetch()
|
|||
// AD-HOC: Some HTML elements need to stop an ongoing fetching process without causing any network error to be raised
|
||||
// (which abort() and terminate() will both do). This is tricky because the fetch process runs across several
|
||||
// nested Platform::EventLoopPlugin::deferred_invoke() invocations. For now, we "stop" the fetch process by
|
||||
// ignoring any callbacks.
|
||||
// cancelling any queued fetch tasks and then ignoring any callbacks.
|
||||
auto ongoing_fetch_tasks = move(m_ongoing_fetch_tasks);
|
||||
|
||||
HTML::main_thread_event_loop().task_queue().remove_tasks_matching([&](auto const& task) {
|
||||
return ongoing_fetch_tasks.remove_all_matching([&](u64, int task_id) {
|
||||
return task.id() == task_id;
|
||||
});
|
||||
});
|
||||
|
||||
if (m_fetch_params) {
|
||||
auto fetch_algorithms = FetchAlgorithms::create(vm, {});
|
||||
m_fetch_params->set_algorithms(fetch_algorithms);
|
||||
}
|
||||
}
|
||||
|
||||
void FetchController::fetch_task_queued(u64 fetch_task_id, int event_id)
|
||||
{
|
||||
m_ongoing_fetch_tasks.set(fetch_task_id, event_id);
|
||||
}
|
||||
|
||||
void FetchController::fetch_task_complete(u64 fetch_task_id)
|
||||
{
|
||||
m_ongoing_fetch_tasks.remove(fetch_task_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue