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