net_traits/
filemanager_thread.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 std::cmp::{max, min};
6use std::ops::Range;
7
8use embedder_traits::{EmbedderControlId, EmbedderControlResponse, FilePickerRequest};
9use ipc_channel::ipc::IpcSender;
10use malloc_size_of_derive::MallocSizeOf;
11use num_traits::ToPrimitive;
12use profile_traits::generic_callback::GenericCallback;
13use serde::{Deserialize, Serialize};
14use servo_base::generic_channel::GenericSender;
15use servo_url::ImmutableOrigin;
16use uuid::Uuid;
17
18use crate::CoreResourceMsg;
19use crate::blob_url_store::{BlobBuf, BlobURLStoreError};
20
21/// A token modulating access to a file for a blob URL.
22#[derive(Clone, Debug)]
23pub enum FileTokenCheck {
24    /// Checking against a token not required,
25    /// used for accessing a file
26    /// that isn't linked to from a blob URL.
27    NotRequired,
28    /// Checking against token required.
29    Required(Uuid),
30    /// Request should always fail,
31    /// used for cases when a check is required,
32    /// but no token could be acquired.
33    ShouldFail,
34}
35
36/// Relative slice positions of a sequence,
37/// whose semantic should be consistent with (start, end) parameters in
38/// <https://w3c.github.io/FileAPI/#dfn-slice>
39#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize)]
40pub struct RelativePos {
41    /// Relative to first byte if non-negative,
42    /// relative to one past last byte if negative,
43    pub start: i64,
44    /// Relative offset from first byte if Some(non-negative),
45    /// relative to one past last byte if Some(negative),
46    /// None if one past last byte
47    pub end: Option<i64>,
48}
49
50impl RelativePos {
51    /// Full range from start to end
52    pub fn full_range() -> RelativePos {
53        RelativePos {
54            start: 0,
55            end: None,
56        }
57    }
58
59    /// Instantiate optional slice position parameters
60    pub fn from_opts(start: Option<i64>, end: Option<i64>) -> RelativePos {
61        RelativePos {
62            start: start.unwrap_or(0),
63            end,
64        }
65    }
66
67    /// Slice the inner sliced range by repositioning
68    pub fn slice_inner(&self, rel_pos: &RelativePos) -> RelativePos {
69        RelativePos {
70            start: self.start + rel_pos.start,
71            end: match (self.end, rel_pos.end) {
72                (Some(old_end), Some(rel_end)) => Some(old_end + rel_end),
73                (old, None) => old,
74                (None, rel) => rel,
75            },
76        }
77    }
78
79    /// Compute absolute range by giving the total size
80    /// <https://w3c.github.io/FileAPI/#slice-method-algo>
81    pub fn to_abs_range(&self, size: usize) -> Range<usize> {
82        let size = size as i64;
83
84        let start = {
85            if self.start < 0 {
86                max(size + self.start, 0)
87            } else {
88                min(self.start, size)
89            }
90        };
91
92        let end = match self.end {
93            Some(rel_end) => {
94                if rel_end < 0 {
95                    max(size + rel_end, 0)
96                } else {
97                    min(rel_end, size)
98                }
99            },
100            None => size,
101        };
102
103        let span: i64 = max(end - start, 0);
104
105        Range {
106            start: start.to_usize().unwrap(),
107            end: (start + span).to_usize().unwrap(),
108        }
109    }
110
111    // Per <https://fetch.spec.whatwg.org/#concept-scheme-fetch> step 3.blob.14.8:
112    // "A range header denotes an inclusive byte range, while the slice blob algorithm input range does not.
113    // To use the slice blob algorithm, we have to increment rangeEnd."
114    pub fn to_abs_blob_range(&self, size: usize) -> Range<usize> {
115        let orig_range = self.to_abs_range(size);
116        let start = orig_range.start;
117        let end = usize::min(orig_range.end + 1, size);
118        Range { start, end }
119    }
120}
121
122#[derive(Debug, Deserialize, Serialize)]
123pub enum FileManagerThreadMsg {
124    /// Select a file or files.
125    SelectFiles(
126        EmbedderControlId,
127        FilePickerRequest,
128        GenericCallback<EmbedderControlResponse>,
129    ),
130
131    /// Read FileID-indexed file in chunks, optionally check URL validity based on boolean flag
132    ReadFile(
133        IpcSender<FileManagerResult<ReadFileProgress>>,
134        Uuid,
135        ImmutableOrigin,
136    ),
137
138    /// Add an entry as promoted memory-based blob
139    PromoteMemory(Uuid, BlobBuf, bool, ImmutableOrigin),
140
141    /// Add a sliced entry pointing to the parent FileID, and send back the associated FileID
142    /// as part of a valid Blob URL
143    AddSlicedURLEntry(
144        Uuid,
145        RelativePos,
146        GenericSender<Result<Uuid, BlobURLStoreError>>,
147        ImmutableOrigin,
148    ),
149
150    /// Decrease reference count and send back the acknowledgement
151    DecRef(
152        Uuid,
153        ImmutableOrigin,
154        GenericSender<Result<(), BlobURLStoreError>>,
155    ),
156
157    /// Activate an internal FileID so it becomes valid as part of a Blob URL
158    ActivateBlobURL(
159        Uuid,
160        IpcSender<Result<(), BlobURLStoreError>>,
161        ImmutableOrigin,
162    ),
163
164    /// Revoke Blob URL and send back the acknowledgement
165    RevokeBlobURL(
166        Uuid,
167        ImmutableOrigin,
168        GenericSender<Result<(), BlobURLStoreError>>,
169    ),
170
171    GetTokenForFile(Uuid, ImmutableOrigin, GenericSender<GetTokenForFileReply>),
172    RevokeTokenForFile(Uuid, Uuid),
173}
174
175#[derive(Debug, Deserialize, Serialize)]
176pub struct GetTokenForFileReply {
177    pub token: Option<Uuid>,
178    pub revoke_sender: GenericSender<CoreResourceMsg>,
179    pub refresh_sender: GenericSender<CoreResourceMsg>,
180}
181
182#[derive(Debug, Deserialize, Serialize)]
183pub enum ReadFileProgress {
184    Meta(BlobBuf),
185    Partial(Vec<u8>),
186    EOF,
187}
188
189pub type FileManagerResult<T> = Result<T, FileManagerThreadError>;
190
191#[derive(Debug, Deserialize, Serialize)]
192pub enum FileManagerThreadError {
193    /// The selection action is invalid due to exceptional reason
194    InvalidSelection,
195    /// The selection action is cancelled by user
196    UserCancelled,
197    /// Errors returned from file system request
198    FileSystemError(String),
199    /// Blob URL Store error
200    BlobURLStoreError(BlobURLStoreError),
201}