2022-10-13 19:21:50 +02:00
/*
* Copyright ( c ) 2022 , Linus Groh < linusg @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <LibJS/Heap/Heap.h>
# include <LibJS/Runtime/VM.h>
2023-04-19 09:15:16 -04:00
# include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
2022-10-13 19:21:50 +02:00
# include <LibWeb/Fetch/Infrastructure/FetchController.h>
2023-04-19 09:15:16 -04:00
# include <LibWeb/Fetch/Infrastructure/FetchParams.h>
2024-03-22 15:28:41 -04:00
# include <LibWeb/HTML/EventLoop/EventLoop.h>
2022-10-13 19:21:50 +02:00
# include <LibWeb/WebIDL/DOMException.h>
namespace Web : : Fetch : : Infrastructure {
2023-11-19 19:47:52 +01:00
JS_DEFINE_ALLOCATOR ( FetchController ) ;
2022-10-13 19:21:50 +02:00
FetchController : : FetchController ( ) = default ;
JS : : NonnullGCPtr < FetchController > FetchController : : create ( JS : : VM & vm )
{
2022-12-14 17:40:33 +00:00
return vm . heap ( ) . allocate_without_realm < FetchController > ( ) ;
2022-10-13 19:21:50 +02:00
}
void FetchController : : visit_edges ( JS : : Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_full_timing_info ) ;
2023-09-25 18:04:10 +02:00
visitor . visit ( m_report_timing_steps ) ;
visitor . visit ( m_next_manual_redirect_steps ) ;
2023-04-19 09:15:16 -04:00
visitor . visit ( m_fetch_params ) ;
2022-10-13 19:21:50 +02:00
}
2023-09-25 18:04:10 +02:00
void FetchController : : set_report_timing_steps ( Function < void ( JS : : Object const & ) > report_timing_steps )
{
m_report_timing_steps = JS : : create_heap_function ( vm ( ) . heap ( ) , move ( report_timing_steps ) ) ;
}
void FetchController : : set_next_manual_redirect_steps ( Function < void ( ) > next_manual_redirect_steps )
{
m_next_manual_redirect_steps = JS : : create_heap_function ( vm ( ) . heap ( ) , move ( next_manual_redirect_steps ) ) ;
}
2022-10-13 19:21:50 +02:00
// https://fetch.spec.whatwg.org/#finalize-and-report-timing
void FetchController : : report_timing ( JS : : Object const & global ) const
{
// 1. Assert: this’ s report timing steps is not null.
2023-09-25 18:04:10 +02:00
VERIFY ( m_report_timing_steps ) ;
2022-10-13 19:21:50 +02:00
// 2. Call this’ s report timing steps with global.
2023-09-25 18:04:10 +02:00
m_report_timing_steps - > function ( ) ( global ) ;
2022-10-13 19:21:50 +02:00
}
// https://fetch.spec.whatwg.org/#fetch-controller-process-the-next-manual-redirect
void FetchController : : process_next_manual_redirect ( ) const
{
// 1. Assert: controller’ s next manual redirect steps are not null.
2023-09-25 18:04:10 +02:00
VERIFY ( m_next_manual_redirect_steps ) ;
2022-10-13 19:21:50 +02:00
// 2. Call controller’ s next manual redirect steps.
2023-09-25 18:04:10 +02:00
m_next_manual_redirect_steps - > function ( ) ( ) ;
2022-10-13 19:21:50 +02:00
}
// https://fetch.spec.whatwg.org/#extract-full-timing-info
JS : : NonnullGCPtr < FetchTimingInfo > FetchController : : extract_full_timing_info ( ) const
{
// 1. Assert: this’ s full timing info is not null.
VERIFY ( m_full_timing_info ) ;
// 2. Return this’ s full timing info.
return * m_full_timing_info ;
}
// https://fetch.spec.whatwg.org/#fetch-controller-abort
2023-02-28 17:45:49 +00:00
void FetchController : : abort ( JS : : Realm & realm , Optional < JS : : Value > error )
2022-10-13 19:21:50 +02:00
{
// 1. Set controller’ s state to "aborted".
m_state = State : : Aborted ;
// 2. Let fallbackError be an "AbortError" DOMException.
2024-10-12 20:56:21 +02:00
auto fallback_error = WebIDL : : AbortError : : create ( realm , " Fetch was aborted " _string ) ;
2022-10-13 19:21:50 +02:00
// 3. Set error to fallbackError if it is not given.
if ( ! error . has_value ( ) )
error = fallback_error ;
// FIXME: 4. Let serializedError be StructuredSerialize(error). If that threw an exception, catch it, and let serializedError be StructuredSerialize(fallbackError).
// FIXME: 5. Set controller’ s serialized abort reason to serializedError.
( void ) error ;
}
// FIXME: https://fetch.spec.whatwg.org/#deserialize-a-serialized-abort-reason
// https://fetch.spec.whatwg.org/#fetch-controller-terminate
void FetchController : : terminate ( )
{
// To terminate a fetch controller controller, set controller’ s state to "terminated".
m_state = State : : Terminated ;
}
2023-04-19 09:15:16 -04:00
void FetchController : : stop_fetch ( )
{
auto & vm = this - > vm ( ) ;
// 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
2024-03-22 15:28:41 -04:00
// 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 ) {
2024-08-04 17:10:49 +02:00
return ongoing_fetch_tasks . remove_all_matching ( [ & ] ( u64 , HTML : : TaskID task_id ) {
2024-03-22 15:28:41 -04:00
return task . id ( ) = = task_id ;
} ) ;
} ) ;
2023-04-19 09:15:16 -04:00
if ( m_fetch_params ) {
auto fetch_algorithms = FetchAlgorithms : : create ( vm , { } ) ;
m_fetch_params - > set_algorithms ( fetch_algorithms ) ;
}
}
2024-08-04 17:10:49 +02:00
void FetchController : : fetch_task_queued ( u64 fetch_task_id , HTML : : TaskID event_id )
2024-03-22 15:28:41 -04:00
{
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 ) ;
}
2022-10-13 19:21:50 +02:00
}