Skip to main content

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    #[ignore_malloc_size_of = "Uuid are hard(not really)"]
196    id: Uuid,
197    #[ignore_malloc_size_of = "PathBuf are hard"]
198    name: Option<PathBuf>,
199    cache: RefCell<Option<Vec<u8>>>,
200    size: u64,
201}
202
203impl FileBlob {
204    /// Create a new file blob.
205    pub fn new(id: Uuid, name: Option<PathBuf>, cache: Option<Vec<u8>>, size: u64) -> FileBlob {
206        FileBlob {
207            id,
208            name,
209            cache: RefCell::new(cache),
210            size,
211        }
212    }
213
214    /// Get the size of the file.
215    pub fn get_size(&self) -> u64 {
216        self.size
217    }
218
219    /// Get the cached file data, if any.
220    pub fn get_cache(&self) -> Option<Vec<u8>> {
221        self.cache.borrow().clone()
222    }
223
224    /// Cache data.
225    pub fn cache_bytes(&self, bytes: Vec<u8>) {
226        *self.cache.borrow_mut() = Some(bytes);
227    }
228
229    /// Get the file id.
230    pub fn get_id(&self) -> Uuid {
231        self.id
232    }
233}
234
235impl BroadcastClone for BlobImpl {
236    type Id = BlobId;
237
238    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
239        &data.blobs
240    }
241
242    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
243        &mut data.blobs
244    }
245
246    fn clone_for_broadcast(&self) -> Option<Self> {
247        let type_string = self.type_string();
248
249        if let BlobData::Memory(bytes) = self.blob_data() {
250            let blob_clone = BlobImpl::new_from_bytes(bytes.clone(), type_string);
251
252            // Note: we insert the blob at the original id,
253            // otherwise this will not match the storage key as serialized by SM in `serialized`.
254            // The clone has it's own new Id however.
255            return Some(blob_clone);
256        } else {
257            // Not panicking only because this is called from the constellation.
258            log::warn!("Serialized blob not in memory format(should never happen).");
259        }
260        None
261    }
262}
263
264/// The data backing a DOM Blob.
265#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
266pub struct BlobImpl {
267    /// UUID of the blob.
268    blob_id: BlobId,
269    /// Content-type string
270    type_string: String,
271    /// Blob data-type.
272    blob_data: BlobData,
273    /// Sliced blobs referring to this one.
274    slices: Vec<BlobId>,
275}
276
277/// Different backends of Blob
278#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
279pub enum BlobData {
280    /// File-based blob, whose content lives in the net process
281    File(FileBlob),
282    /// Memory-based blob, whose content lives in the script process
283    Memory(Vec<u8>),
284    /// Sliced blob, including parent blob-id and
285    /// relative positions of current slicing range,
286    /// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
287    /// either File-based or Memory-based
288    Sliced(BlobId, RelativePos),
289}
290
291impl BlobImpl {
292    /// Construct memory-backed BlobImpl
293    pub fn new_from_bytes(bytes: Vec<u8>, type_string: String) -> BlobImpl {
294        let blob_id = BlobId::new();
295        let blob_data = BlobData::Memory(bytes);
296        BlobImpl {
297            blob_id,
298            type_string,
299            blob_data,
300            slices: vec![],
301        }
302    }
303
304    /// Construct file-backed BlobImpl from File ID
305    pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64, type_string: String) -> BlobImpl {
306        let blob_id = BlobId::new();
307        let blob_data = BlobData::File(FileBlob {
308            id: file_id,
309            name: Some(name),
310            cache: RefCell::new(None),
311            size,
312        });
313        BlobImpl {
314            blob_id,
315            type_string,
316            blob_data,
317            slices: vec![],
318        }
319    }
320
321    /// Construct a BlobImpl from a slice of a parent.
322    pub fn new_sliced(range: RelativePos, parent: BlobId, type_string: String) -> BlobImpl {
323        let blob_id = BlobId::new();
324        let blob_data = BlobData::Sliced(parent, range);
325        BlobImpl {
326            blob_id,
327            type_string,
328            blob_data,
329            slices: vec![],
330        }
331    }
332
333    /// Get a clone of the blob-id
334    pub fn blob_id(&self) -> BlobId {
335        self.blob_id
336    }
337
338    /// Get a clone of the type-string
339    pub fn type_string(&self) -> String {
340        self.type_string.clone()
341    }
342
343    /// Get a mutable ref to the data
344    pub fn blob_data(&self) -> &BlobData {
345        &self.blob_data
346    }
347
348    /// Get a mutable ref to the data
349    pub fn blob_data_mut(&mut self) -> &mut BlobData {
350        &mut self.blob_data
351    }
352}
353
354#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
355/// A serializable version of the DOMPoint/DOMPointReadOnly interface.
356pub struct DomPoint {
357    /// The x coordinate.
358    pub x: f64,
359    /// The y coordinate.
360    pub y: f64,
361    /// The z coordinate.
362    pub z: f64,
363    /// The w coordinate.
364    pub w: f64,
365}
366
367impl BroadcastClone for DomPoint {
368    type Id = DomPointId;
369
370    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
371        &data.points
372    }
373
374    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
375        &mut data.points
376    }
377
378    fn clone_for_broadcast(&self) -> Option<Self> {
379        Some(self.clone())
380    }
381}
382
383#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
384/// A serializable version of the DOMRect/DOMRectReadOnly interface.
385pub struct DomRect {
386    /// The x coordinate.
387    pub x: f64,
388    /// The y coordinate.
389    pub y: f64,
390    /// The width.
391    pub width: f64,
392    /// The height.
393    pub height: f64,
394}
395
396impl BroadcastClone for DomRect {
397    type Id = DomRectId;
398
399    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
400        &data.rects
401    }
402
403    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
404        &mut data.rects
405    }
406
407    fn clone_for_broadcast(&self) -> Option<Self> {
408        Some(self.clone())
409    }
410}
411
412#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
413/// A serializable version of the DOMQuad interface.
414pub struct DomQuad {
415    /// The first point.
416    pub p1: DomPoint,
417    /// The second point.
418    pub p2: DomPoint,
419    /// The third point.
420    pub p3: DomPoint,
421    /// The fourth point.
422    pub p4: DomPoint,
423}
424
425impl BroadcastClone for DomQuad {
426    type Id = DomQuadId;
427
428    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
429        &data.quads
430    }
431
432    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
433        &mut data.quads
434    }
435
436    fn clone_for_broadcast(&self) -> Option<Self> {
437        Some(self.clone())
438    }
439}
440
441#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
442/// A serializable version of the DOMMatrix/DOMMatrixReadOnly interface.
443pub struct DomMatrix {
444    /// The matrix.
445    pub matrix: Transform3D<f64>,
446    /// Whether this matrix represents a 2D transformation.
447    pub is_2d: bool,
448}
449
450impl BroadcastClone for DomMatrix {
451    type Id = DomMatrixId;
452
453    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
454        &data.matrices
455    }
456
457    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
458        &mut data.matrices
459    }
460
461    fn clone_for_broadcast(&self) -> Option<Self> {
462        Some(self.clone())
463    }
464}
465
466#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
467/// A serializable version of the DOMException interface.
468pub struct DomException {
469    pub message: String,
470    pub name: String,
471}
472
473impl BroadcastClone for DomException {
474    type Id = DomExceptionId;
475
476    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
477        &data.exceptions
478    }
479
480    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
481        &mut data.exceptions
482    }
483
484    fn clone_for_broadcast(&self) -> Option<Self> {
485        Some(self.clone())
486    }
487}
488
489#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
490/// A serializable version of the QuotaExceededError interface.
491pub struct SerializableQuotaExceededError {
492    pub dom_exception: DomException,
493    pub quota: Option<f64>,
494    pub requested: Option<f64>,
495}
496
497impl BroadcastClone for SerializableQuotaExceededError {
498    type Id = QuotaExceededErrorId;
499
500    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
501        &data.quota_exceeded_errors
502    }
503
504    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
505        &mut data.quota_exceeded_errors
506    }
507
508    fn clone_for_broadcast(&self) -> Option<Self> {
509        Some(self.clone())
510    }
511}
512
513#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
514/// A serializable version of the ImageBitmap interface.
515pub struct SerializableImageBitmap {
516    pub bitmap_data: SharedSnapshot,
517}
518
519impl BroadcastClone for SerializableImageBitmap {
520    type Id = ImageBitmapId;
521
522    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
523        &data.image_bitmaps
524    }
525
526    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
527        &mut data.image_bitmaps
528    }
529
530    fn clone_for_broadcast(&self) -> Option<Self> {
531        Some(self.clone())
532    }
533}
534
535#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
536pub struct SerializableImageData {
537    pub data: Vec<u8>,
538    pub width: u32,
539    pub height: u32,
540}
541
542impl BroadcastClone for SerializableImageData {
543    type Id = ImageDataId;
544
545    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
546        &data.image_data
547    }
548
549    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
550        &mut data.image_data
551    }
552
553    fn clone_for_broadcast(&self) -> Option<Self> {
554        Some(self.clone())
555    }
556}