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