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