Skip to main content

net_traits/fetch/
fetch_controller.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use malloc_size_of_derive::MallocSizeOf;
6
7use crate::request::RequestId;
8use crate::{CoreResourceThread, cancel_and_forget_async_fetch, cancel_async_fetch};
9
10/// <https://fetch.spec.whatwg.org/#fetch-controller-state>
11#[derive(Default, MallocSizeOf, PartialEq)]
12pub enum FetchControllerState {
13    #[default]
14    Ongoing,
15    Terminated,
16    Aborted,
17}
18
19/// Fetch controller object. By default initialized to having a
20/// request associated with it, which can be aborted or terminated.
21/// Calling `ignore` will sever the relationship with the request,
22/// meaning it cannot be cancelled through this controller from that point on.
23/// <https://fetch.spec.whatwg.org/#fetch-controller>
24#[derive(Default, MallocSizeOf)]
25pub struct FetchController {
26    request_id: Option<RequestId>,
27    core_resource_thread: Option<CoreResourceThread>,
28    keep_alive: bool,
29    /// <https://fetch.spec.whatwg.org/#fetch-controller-state>
30    pub state: FetchControllerState,
31}
32
33impl FetchController {
34    /// Create a FetchController associated with a request,
35    /// and a particular(public vs private) resource thread.
36    pub fn new(
37        request_id: RequestId,
38        keep_alive: bool,
39        core_resource_thread: CoreResourceThread,
40    ) -> Self {
41        Self {
42            request_id: Some(request_id),
43            core_resource_thread: Some(core_resource_thread),
44            keep_alive,
45            state: Default::default(),
46        }
47    }
48
49    pub fn keep_alive(&self) -> bool {
50        self.keep_alive
51    }
52
53    fn cancel(&mut self) {
54        // stop trying to make fetch happen
55        // it's not going to happen
56        let Some(request_id) = self.request_id.take() else {
57            return;
58        };
59        let Some(core_resource_thread) = &self.core_resource_thread else {
60            return;
61        };
62
63        if self.state == FetchControllerState::Terminated {
64            cancel_and_forget_async_fetch(vec![request_id], core_resource_thread);
65        } else {
66            cancel_async_fetch(vec![request_id], core_resource_thread);
67        }
68    }
69
70    /// Use this if you don't want it to send a cancellation request
71    /// on drop (e.g. if the fetch completes)
72    pub fn ignore(&mut self) {
73        let _ = self.request_id.take();
74    }
75
76    /// <https://fetch.spec.whatwg.org/#fetch-controller-abort>
77    pub fn abort(&mut self) {
78        // Step 1. Set controller’s state to "aborted".
79        self.state = FetchControllerState::Aborted;
80
81        self.cancel();
82    }
83
84    /// <https://fetch.spec.whatwg.org/#fetch-controller-terminate>
85    pub fn terminate(&mut self) {
86        // > To terminate a fetch controller controller,
87        // > set controller’s state to "terminated".
88        self.state = FetchControllerState::Terminated;
89
90        self.cancel();
91    }
92}