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 base::id::{
14    BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, ImageBitmapId,
15    QuotaExceededErrorId,
16};
17use euclid::default::Transform3D;
18use malloc_size_of_derive::MallocSizeOf;
19use net_traits::filemanager_thread::RelativePos;
20use pixels::Snapshot;
21use rustc_hash::FxHashMap;
22use serde::{Deserialize, Serialize};
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 `Blob` interface.
51    Blob,
52    /// The `DOMPoint` interface.
53    DomPoint,
54    /// The `DOMPointReadOnly` interface.
55    DomPointReadOnly,
56    /// The `DOMRect` interface.
57    DomRect,
58    /// The `DOMRectReadOnly` interface.
59    DomRectReadOnly,
60    /// The `DOMQuad` interface.
61    DomQuad,
62    /// The `DOMMatrix` interface.
63    DomMatrix,
64    /// The `DOMMatrixReadOnly` interface.
65    DomMatrixReadOnly,
66    /// The `QuotaExceededError` interface.
67    QuotaExceededError,
68    /// The `DOMException` interface.
69    DomException,
70    /// The `ImageBitmap` interface.
71    ImageBitmap,
72}
73
74impl Serializable {
75    pub(super) fn clone_values(
76        &self,
77    ) -> fn(&StructuredSerializedData, &mut StructuredSerializedData) {
78        match self {
79            Serializable::Blob => StructuredSerializedData::clone_all_of_type::<BlobImpl>,
80            Serializable::DomPoint => StructuredSerializedData::clone_all_of_type::<DomPoint>,
81            Serializable::DomPointReadOnly => {
82                StructuredSerializedData::clone_all_of_type::<DomPoint>
83            },
84            Serializable::DomRect => StructuredSerializedData::clone_all_of_type::<DomRect>,
85            Serializable::DomRectReadOnly => StructuredSerializedData::clone_all_of_type::<DomRect>,
86            Serializable::DomQuad => StructuredSerializedData::clone_all_of_type::<DomQuad>,
87            Serializable::DomMatrix => StructuredSerializedData::clone_all_of_type::<DomMatrix>,
88            Serializable::DomMatrixReadOnly => {
89                StructuredSerializedData::clone_all_of_type::<DomMatrix>
90            },
91            Serializable::DomException => {
92                StructuredSerializedData::clone_all_of_type::<DomException>
93            },
94            Serializable::ImageBitmap => {
95                StructuredSerializedData::clone_all_of_type::<SerializableImageBitmap>
96            },
97            Serializable::QuotaExceededError => {
98                StructuredSerializedData::clone_all_of_type::<SerializableQuotaExceededError>
99            },
100        }
101    }
102}
103
104/// Message for communication between the constellation and a global managing broadcast channels.
105#[derive(Debug, Deserialize, Serialize)]
106pub struct BroadcastChannelMsg {
107    /// The origin of this message.
108    pub origin: ImmutableOrigin,
109    /// The name of the channel.
110    pub channel_name: String,
111    /// A data-holder for serialized data.
112    pub data: StructuredSerializedData,
113}
114
115impl Clone for BroadcastChannelMsg {
116    fn clone(&self) -> BroadcastChannelMsg {
117        BroadcastChannelMsg {
118            data: self.data.clone_for_broadcast(),
119            origin: self.origin.clone(),
120            channel_name: self.channel_name.clone(),
121        }
122    }
123}
124
125/// File-based blob
126#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
127pub struct FileBlob {
128    #[ignore_malloc_size_of = "Uuid are hard(not really)"]
129    id: Uuid,
130    #[ignore_malloc_size_of = "PathBuf are hard"]
131    name: Option<PathBuf>,
132    cache: RefCell<Option<Vec<u8>>>,
133    size: u64,
134}
135
136impl FileBlob {
137    /// Create a new file blob.
138    pub fn new(id: Uuid, name: Option<PathBuf>, cache: Option<Vec<u8>>, size: u64) -> FileBlob {
139        FileBlob {
140            id,
141            name,
142            cache: RefCell::new(cache),
143            size,
144        }
145    }
146
147    /// Get the size of the file.
148    pub fn get_size(&self) -> u64 {
149        self.size
150    }
151
152    /// Get the cached file data, if any.
153    pub fn get_cache(&self) -> Option<Vec<u8>> {
154        self.cache.borrow().clone()
155    }
156
157    /// Cache data.
158    pub fn cache_bytes(&self, bytes: Vec<u8>) {
159        *self.cache.borrow_mut() = Some(bytes);
160    }
161
162    /// Get the file id.
163    pub fn get_id(&self) -> Uuid {
164        self.id
165    }
166}
167
168impl BroadcastClone for BlobImpl {
169    type Id = BlobId;
170
171    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
172        &data.blobs
173    }
174
175    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
176        &mut data.blobs
177    }
178
179    fn clone_for_broadcast(&self) -> Option<Self> {
180        let type_string = self.type_string();
181
182        if let BlobData::Memory(bytes) = self.blob_data() {
183            let blob_clone = BlobImpl::new_from_bytes(bytes.clone(), type_string);
184
185            // Note: we insert the blob at the original id,
186            // otherwise this will not match the storage key as serialized by SM in `serialized`.
187            // The clone has it's own new Id however.
188            return Some(blob_clone);
189        } else {
190            // Not panicking only because this is called from the constellation.
191            log::warn!("Serialized blob not in memory format(should never happen).");
192        }
193        None
194    }
195}
196
197/// The data backing a DOM Blob.
198#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
199pub struct BlobImpl {
200    /// UUID of the blob.
201    blob_id: BlobId,
202    /// Content-type string
203    type_string: String,
204    /// Blob data-type.
205    blob_data: BlobData,
206    /// Sliced blobs referring to this one.
207    slices: Vec<BlobId>,
208}
209
210/// Different backends of Blob
211#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
212pub enum BlobData {
213    /// File-based blob, whose content lives in the net process
214    File(FileBlob),
215    /// Memory-based blob, whose content lives in the script process
216    Memory(Vec<u8>),
217    /// Sliced blob, including parent blob-id and
218    /// relative positions of current slicing range,
219    /// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
220    /// either File-based or Memory-based
221    Sliced(BlobId, RelativePos),
222}
223
224impl BlobImpl {
225    /// Construct memory-backed BlobImpl
226    pub fn new_from_bytes(bytes: Vec<u8>, type_string: String) -> BlobImpl {
227        let blob_id = BlobId::new();
228        let blob_data = BlobData::Memory(bytes);
229        BlobImpl {
230            blob_id,
231            type_string,
232            blob_data,
233            slices: vec![],
234        }
235    }
236
237    /// Construct file-backed BlobImpl from File ID
238    pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64, type_string: String) -> BlobImpl {
239        let blob_id = BlobId::new();
240        let blob_data = BlobData::File(FileBlob {
241            id: file_id,
242            name: Some(name),
243            cache: RefCell::new(None),
244            size,
245        });
246        BlobImpl {
247            blob_id,
248            type_string,
249            blob_data,
250            slices: vec![],
251        }
252    }
253
254    /// Construct a BlobImpl from a slice of a parent.
255    pub fn new_sliced(range: RelativePos, parent: BlobId, type_string: String) -> BlobImpl {
256        let blob_id = BlobId::new();
257        let blob_data = BlobData::Sliced(parent, range);
258        BlobImpl {
259            blob_id,
260            type_string,
261            blob_data,
262            slices: vec![],
263        }
264    }
265
266    /// Get a clone of the blob-id
267    pub fn blob_id(&self) -> BlobId {
268        self.blob_id
269    }
270
271    /// Get a clone of the type-string
272    pub fn type_string(&self) -> String {
273        self.type_string.clone()
274    }
275
276    /// Get a mutable ref to the data
277    pub fn blob_data(&self) -> &BlobData {
278        &self.blob_data
279    }
280
281    /// Get a mutable ref to the data
282    pub fn blob_data_mut(&mut self) -> &mut BlobData {
283        &mut self.blob_data
284    }
285}
286
287#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
288/// A serializable version of the DOMPoint/DOMPointReadOnly interface.
289pub struct DomPoint {
290    /// The x coordinate.
291    pub x: f64,
292    /// The y coordinate.
293    pub y: f64,
294    /// The z coordinate.
295    pub z: f64,
296    /// The w coordinate.
297    pub w: f64,
298}
299
300impl BroadcastClone for DomPoint {
301    type Id = DomPointId;
302
303    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
304        &data.points
305    }
306
307    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
308        &mut data.points
309    }
310
311    fn clone_for_broadcast(&self) -> Option<Self> {
312        Some(self.clone())
313    }
314}
315
316#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
317/// A serializable version of the DOMRect/DOMRectReadOnly interface.
318pub struct DomRect {
319    /// The x coordinate.
320    pub x: f64,
321    /// The y coordinate.
322    pub y: f64,
323    /// The width.
324    pub width: f64,
325    /// The height.
326    pub height: f64,
327}
328
329impl BroadcastClone for DomRect {
330    type Id = DomRectId;
331
332    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
333        &data.rects
334    }
335
336    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
337        &mut data.rects
338    }
339
340    fn clone_for_broadcast(&self) -> Option<Self> {
341        Some(self.clone())
342    }
343}
344
345#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
346/// A serializable version of the DOMQuad interface.
347pub struct DomQuad {
348    /// The first point.
349    pub p1: DomPoint,
350    /// The second point.
351    pub p2: DomPoint,
352    /// The third point.
353    pub p3: DomPoint,
354    /// The fourth point.
355    pub p4: DomPoint,
356}
357
358impl BroadcastClone for DomQuad {
359    type Id = DomQuadId;
360
361    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
362        &data.quads
363    }
364
365    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
366        &mut data.quads
367    }
368
369    fn clone_for_broadcast(&self) -> Option<Self> {
370        Some(self.clone())
371    }
372}
373
374#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
375/// A serializable version of the DOMMatrix/DOMMatrixReadOnly interface.
376pub struct DomMatrix {
377    /// The matrix.
378    pub matrix: Transform3D<f64>,
379    /// Whether this matrix represents a 2D transformation.
380    pub is_2d: bool,
381}
382
383impl BroadcastClone for DomMatrix {
384    type Id = DomMatrixId;
385
386    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
387        &data.matrices
388    }
389
390    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
391        &mut data.matrices
392    }
393
394    fn clone_for_broadcast(&self) -> Option<Self> {
395        Some(self.clone())
396    }
397}
398
399#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
400/// A serializable version of the DOMException interface.
401pub struct DomException {
402    pub message: String,
403    pub name: String,
404}
405
406impl BroadcastClone for DomException {
407    type Id = DomExceptionId;
408
409    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
410        &data.exceptions
411    }
412
413    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
414        &mut data.exceptions
415    }
416
417    fn clone_for_broadcast(&self) -> Option<Self> {
418        Some(self.clone())
419    }
420}
421
422#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
423/// A serializable version of the QuotaExceededError interface.
424pub struct SerializableQuotaExceededError {
425    pub dom_exception: DomException,
426    pub quota: Option<f64>,
427    pub requested: Option<f64>,
428}
429
430impl BroadcastClone for SerializableQuotaExceededError {
431    type Id = QuotaExceededErrorId;
432
433    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
434        &data.quota_exceeded_errors
435    }
436
437    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
438        &mut data.quota_exceeded_errors
439    }
440
441    fn clone_for_broadcast(&self) -> Option<Self> {
442        Some(self.clone())
443    }
444}
445
446#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
447/// A serializable version of the ImageBitmap interface.
448pub struct SerializableImageBitmap {
449    pub bitmap_data: Snapshot,
450}
451
452impl BroadcastClone for SerializableImageBitmap {
453    type Id = ImageBitmapId;
454
455    fn source(data: &StructuredSerializedData) -> &Option<FxHashMap<Self::Id, Self>> {
456        &data.image_bitmaps
457    }
458
459    fn destination(data: &mut StructuredSerializedData) -> &mut Option<FxHashMap<Self::Id, Self>> {
460        &mut data.image_bitmaps
461    }
462
463    fn clone_for_broadcast(&self) -> Option<Self> {
464        Some(self.clone())
465    }
466}