servo_constellation_traits/structured_data/
serializable.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
5//! This module contains implementations in script that are serializable,
6//! as per <https://html.spec.whatwg.org/multipage/#serializable-objects>.
7//! The implementations are here instead of in script as they need to
8//! be passed through the Constellation.
9
10use std::cell::RefCell;
11use std::path::PathBuf;
12
13use euclid::default::Transform3D;
14use malloc_size_of_derive::MallocSizeOf;
15use net_traits::filemanager_thread::RelativePos;
16use pixels::SharedSnapshot;
17use rustc_hash::FxHashMap;
18use serde::{Deserialize, Serialize};
19use servo_base::id::{
20    BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, FileId, FileListId,
21    ImageBitmapId, ImageDataId, QuotaExceededErrorId,
22};
23use servo_url::ImmutableOrigin;
24use strum::EnumIter;
25use uuid::Uuid;
26
27use super::StructuredSerializedData;
28
29pub(crate) trait BroadcastClone
30where
31    Self: Sized,
32{
33    /// The ID type that uniquely identify each value.
34    type Id: Eq + std::hash::Hash + Copy;
35    /// Clone this value so that it can be reused with a broadcast channel.
36    /// Only return None if cloning is impossible.
37    fn clone_for_broadcast(&self) -> Option<Self>;
38    /// The field from which to clone values.
39    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>>;
40    /// The field into which to place cloned values.
41    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>>;
42}
43
44/// All the DOM interfaces that can be serialized.
45///
46/// NOTE: Variants which are derived from other serializable interfaces must come before their
47/// parents because serialization is attempted in order of the variants.
48#[derive(Clone, Copy, Debug, EnumIter)]
49pub enum Serializable {
50    /// The `File` interface.
51    File,
52    /// The `FileList` interface.
53    FileList,
54    /// The `Blob` interface.
55    Blob,
56    /// The `DOMPoint` interface.
57    DomPoint,
58    /// The `DOMPointReadOnly` interface.
59    DomPointReadOnly,
60    /// The `DOMRect` interface.
61    DomRect,
62    /// The `DOMRectReadOnly` interface.
63    DomRectReadOnly,
64    /// The `DOMQuad` interface.
65    DomQuad,
66    /// The `DOMMatrix` interface.
67    DomMatrix,
68    /// The `DOMMatrixReadOnly` interface.
69    DomMatrixReadOnly,
70    /// The `QuotaExceededError` interface.
71    QuotaExceededError,
72    /// The `DOMException` interface.
73    DomException,
74    /// The `ImageBitmap` interface.
75    ImageBitmap,
76    /// The `ImageData` interface.
77    ImageData,
78}
79
80impl Serializable {
81    pub(super) fn clone_values(
82        &self,
83    ) -> fn(&StructuredSerializedData, &mut StructuredSerializedData) {
84        match self {
85            Serializable::File => StructuredSerializedData::clone_all_of_type::<SerializableFile>,
86            Serializable::FileList => {
87                StructuredSerializedData::clone_all_of_type::<SerializableFileList>
88            },
89            Serializable::Blob => StructuredSerializedData::clone_all_of_type::<BlobImpl>,
90            Serializable::DomPoint => StructuredSerializedData::clone_all_of_type::<DomPoint>,
91            Serializable::DomPointReadOnly => {
92                StructuredSerializedData::clone_all_of_type::<DomPoint>
93            },
94            Serializable::DomRect => StructuredSerializedData::clone_all_of_type::<DomRect>,
95            Serializable::DomRectReadOnly => StructuredSerializedData::clone_all_of_type::<DomRect>,
96            Serializable::DomQuad => StructuredSerializedData::clone_all_of_type::<DomQuad>,
97            Serializable::DomMatrix => StructuredSerializedData::clone_all_of_type::<DomMatrix>,
98            Serializable::DomMatrixReadOnly => {
99                StructuredSerializedData::clone_all_of_type::<DomMatrix>
100            },
101            Serializable::DomException => {
102                StructuredSerializedData::clone_all_of_type::<DomException>
103            },
104            Serializable::ImageBitmap => {
105                StructuredSerializedData::clone_all_of_type::<SerializableImageBitmap>
106            },
107            Serializable::QuotaExceededError => {
108                StructuredSerializedData::clone_all_of_type::<SerializableQuotaExceededError>
109            },
110            Serializable::ImageData => {
111                StructuredSerializedData::clone_all_of_type::<SerializableImageData>
112            },
113        }
114    }
115}
116
117/// Message for communication between the constellation and a global managing broadcast channels.
118#[derive(Debug, Deserialize, Serialize)]
119pub struct BroadcastChannelMsg {
120    /// The origin of this message.
121    pub origin: ImmutableOrigin,
122    /// The name of the channel.
123    pub channel_name: String,
124    /// A data-holder for serialized data.
125    pub data: StructuredSerializedData,
126}
127
128impl Clone for BroadcastChannelMsg {
129    fn clone(&self) -> BroadcastChannelMsg {
130        BroadcastChannelMsg {
131            data: self.data.clone_for_broadcast(),
132            origin: self.origin.clone(),
133            channel_name: self.channel_name.clone(),
134        }
135    }
136}
137
138#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
139pub struct SerializableFile {
140    pub blob_impl: BlobImpl,
141    pub name: String,
142    pub modified: i64,
143}
144
145impl BroadcastClone for SerializableFile {
146    type Id = FileId;
147
148    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
149        &data.files
150    }
151
152    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
153        &mut data.files
154    }
155
156    fn clone_for_broadcast(&self) -> Option<Self> {
157        let blob_impl = self.blob_impl.clone_for_broadcast()?;
158        Some(SerializableFile {
159            blob_impl,
160            name: self.name.clone(),
161            modified: self.modified,
162        })
163    }
164}
165
166#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
167pub struct SerializableFileList {
168    pub files: Vec<SerializableFile>,
169}
170
171impl BroadcastClone for SerializableFileList {
172    type Id = FileListId;
173
174    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
175        &data.file_lists
176    }
177
178    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
179        &mut data.file_lists
180    }
181
182    fn clone_for_broadcast(&self) -> Option<Self> {
183        let files = self
184            .files
185            .iter()
186            .map(|file| file.clone_for_broadcast())
187            .collect::<Option<Vec<_>>>()?;
188        Some(SerializableFileList { files })
189    }
190}
191
192/// File-based blob
193#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
194pub struct FileBlob {
195    id: Uuid,
196    name: Option<PathBuf>,
197    cache: RefCell<Option<Vec<u8>>>,
198    size: u64,
199}
200
201impl FileBlob {
202    /// Create a new file blob.
203    pub fn new(id: Uuid, name: Option<PathBuf>, cache: Option<Vec<u8>>, size: u64) -> FileBlob {
204        FileBlob {
205            id,
206            name,
207            cache: RefCell::new(cache),
208            size,
209        }
210    }
211
212    /// Get the size of the file.
213    pub fn get_size(&self) -> u64 {
214        self.size
215    }
216
217    /// Get the cached file data, if any.
218    pub fn get_cache(&self) -> Option<Vec<u8>> {
219        self.cache.borrow().clone()
220    }
221
222    /// Cache data.
223    pub fn cache_bytes(&self, bytes: Vec<u8>) {
224        *self.cache.borrow_mut() = Some(bytes);
225    }
226
227    /// Get the file id.
228    pub fn get_id(&self) -> Uuid {
229        self.id
230    }
231}
232
233impl BroadcastClone for BlobImpl {
234    type Id = BlobId;
235
236    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
237        &data.blobs
238    }
239
240    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
241        &mut data.blobs
242    }
243
244    fn clone_for_broadcast(&self) -> Option<Self> {
245        let type_string = self.type_string();
246
247        if let BlobData::Memory(bytes) = self.blob_data() {
248            let blob_clone = BlobImpl::new_from_bytes(bytes.clone(), type_string);
249
250            // Note: we insert the blob at the original id,
251            // otherwise this will not match the storage key as serialized by SM in `serialized`.
252            // The clone has it's own new Id however.
253            return Some(blob_clone);
254        } else {
255            // Not panicking only because this is called from the constellation.
256            log::warn!("Serialized blob not in memory format(should never happen).");
257        }
258        None
259    }
260}
261
262/// The data backing a DOM Blob.
263#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
264pub struct BlobImpl {
265    /// UUID of the blob.
266    blob_id: BlobId,
267    /// Content-type string
268    type_string: String,
269    /// Blob data-type.
270    blob_data: BlobData,
271    /// Sliced blobs referring to this one.
272    slices: Vec<BlobId>,
273}
274
275/// Different backends of Blob
276#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
277pub enum BlobData {
278    /// File-based blob, whose content lives in the net process
279    File(FileBlob),
280    /// Memory-based blob, whose content lives in the script process
281    Memory(Vec<u8>),
282    /// Sliced blob, including parent blob-id and
283    /// relative positions of current slicing range,
284    /// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
285    /// either File-based or Memory-based
286    Sliced(BlobId, RelativePos),
287}
288
289impl BlobImpl {
290    /// Construct memory-backed BlobImpl
291    pub fn new_from_bytes(bytes: Vec<u8>, type_string: String) -> BlobImpl {
292        let blob_id = BlobId::new();
293        let blob_data = BlobData::Memory(bytes);
294        BlobImpl {
295            blob_id,
296            type_string,
297            blob_data,
298            slices: vec![],
299        }
300    }
301
302    /// Construct file-backed BlobImpl from File ID
303    pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64, type_string: String) -> BlobImpl {
304        let blob_id = BlobId::new();
305        let blob_data = BlobData::File(FileBlob {
306            id: file_id,
307            name: Some(name),
308            cache: RefCell::new(None),
309            size,
310        });
311        BlobImpl {
312            blob_id,
313            type_string,
314            blob_data,
315            slices: vec![],
316        }
317    }
318
319    /// Construct a BlobImpl from a slice of a parent.
320    pub fn new_sliced(range: RelativePos, parent: BlobId, type_string: String) -> BlobImpl {
321        let blob_id = BlobId::new();
322        let blob_data = BlobData::Sliced(parent, range);
323        BlobImpl {
324            blob_id,
325            type_string,
326            blob_data,
327            slices: vec![],
328        }
329    }
330
331    /// Get a clone of the blob-id
332    pub fn blob_id(&self) -> BlobId {
333        self.blob_id
334    }
335
336    /// Get a clone of the type-string
337    pub fn type_string(&self) -> String {
338        self.type_string.clone()
339    }
340
341    /// Get a mutable ref to the data
342    pub fn blob_data(&self) -> &BlobData {
343        &self.blob_data
344    }
345
346    /// Get a mutable ref to the data
347    pub fn blob_data_mut(&mut self) -> &mut BlobData {
348        &mut self.blob_data
349    }
350}
351
352#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
353/// A serializable version of the DOMPoint/DOMPointReadOnly interface.
354pub struct DomPoint {
355    /// The x coordinate.
356    pub x: f64,
357    /// The y coordinate.
358    pub y: f64,
359    /// The z coordinate.
360    pub z: f64,
361    /// The w coordinate.
362    pub w: f64,
363}
364
365impl BroadcastClone for DomPoint {
366    type Id = DomPointId;
367
368    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
369        &data.points
370    }
371
372    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
373        &mut data.points
374    }
375
376    fn clone_for_broadcast(&self) -> Option<Self> {
377        Some(self.clone())
378    }
379}
380
381#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
382/// A serializable version of the DOMRect/DOMRectReadOnly interface.
383pub struct DomRect {
384    /// The x coordinate.
385    pub x: f64,
386    /// The y coordinate.
387    pub y: f64,
388    /// The width.
389    pub width: f64,
390    /// The height.
391    pub height: f64,
392}
393
394impl BroadcastClone for DomRect {
395    type Id = DomRectId;
396
397    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
398        &data.rects
399    }
400
401    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
402        &mut data.rects
403    }
404
405    fn clone_for_broadcast(&self) -> Option<Self> {
406        Some(self.clone())
407    }
408}
409
410#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
411/// A serializable version of the DOMQuad interface.
412pub struct DomQuad {
413    /// The first point.
414    pub p1: DomPoint,
415    /// The second point.
416    pub p2: DomPoint,
417    /// The third point.
418    pub p3: DomPoint,
419    /// The fourth point.
420    pub p4: DomPoint,
421}
422
423impl BroadcastClone for DomQuad {
424    type Id = DomQuadId;
425
426    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
427        &data.quads
428    }
429
430    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
431        &mut data.quads
432    }
433
434    fn clone_for_broadcast(&self) -> Option<Self> {
435        Some(self.clone())
436    }
437}
438
439#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
440/// A serializable version of the DOMMatrix/DOMMatrixReadOnly interface.
441pub struct DomMatrix {
442    /// The matrix.
443    pub matrix: Transform3D<f64>,
444    /// Whether this matrix represents a 2D transformation.
445    pub is_2d: bool,
446}
447
448impl BroadcastClone for DomMatrix {
449    type Id = DomMatrixId;
450
451    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
452        &data.matrices
453    }
454
455    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
456        &mut data.matrices
457    }
458
459    fn clone_for_broadcast(&self) -> Option<Self> {
460        Some(self.clone())
461    }
462}
463
464#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
465/// A serializable version of the DOMException interface.
466pub struct DomException {
467    pub message: String,
468    pub name: String,
469}
470
471impl BroadcastClone for DomException {
472    type Id = DomExceptionId;
473
474    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
475        &data.exceptions
476    }
477
478    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
479        &mut data.exceptions
480    }
481
482    fn clone_for_broadcast(&self) -> Option<Self> {
483        Some(self.clone())
484    }
485}
486
487#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
488/// A serializable version of the QuotaExceededError interface.
489pub struct SerializableQuotaExceededError {
490    pub dom_exception: DomException,
491    pub quota: Option<f64>,
492    pub requested: Option<f64>,
493}
494
495impl BroadcastClone for SerializableQuotaExceededError {
496    type Id = QuotaExceededErrorId;
497
498    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
499        &data.quota_exceeded_errors
500    }
501
502    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
503        &mut data.quota_exceeded_errors
504    }
505
506    fn clone_for_broadcast(&self) -> Option<Self> {
507        Some(self.clone())
508    }
509}
510
511#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
512/// A serializable version of the ImageBitmap interface.
513pub struct SerializableImageBitmap {
514    pub bitmap_data: SharedSnapshot,
515}
516
517impl BroadcastClone for SerializableImageBitmap {
518    type Id = ImageBitmapId;
519
520    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
521        &data.image_bitmaps
522    }
523
524    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
525        &mut data.image_bitmaps
526    }
527
528    fn clone_for_broadcast(&self) -> Option<Self> {
529        Some(self.clone())
530    }
531}
532
533#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
534pub struct SerializableImageData {
535    pub data: Vec<u8>,
536    pub width: u32,
537    pub height: u32,
538}
539
540impl BroadcastClone for SerializableImageData {
541    type Id = ImageDataId;
542
543    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
544        &data.image_data
545    }
546
547    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
548        &mut data.image_data
549    }
550
551    fn clone_for_broadcast(&self) -> Option<Self> {
552        Some(self.clone())
553    }
554}