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