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::collections::HashMap;
12use std::path::PathBuf;
13
14use base::id::{
15    BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, ImageBitmapId,
16    QuotaExceededErrorId,
17};
18use euclid::default::Transform3D;
19use malloc_size_of_derive::MallocSizeOf;
20use net_traits::filemanager_thread::RelativePos;
21use pixels::Snapshot;
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<HashMap<Self::Id, Self>>;
40    /// The field into which to place cloned values.
41    fn destination(data: &mut StructuredSerializedData) -> &mut Option<HashMap<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(
172        data: &StructuredSerializedData,
173    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
174        &data.blobs
175    }
176
177    fn destination(
178        data: &mut StructuredSerializedData,
179    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
180        &mut data.blobs
181    }
182
183    fn clone_for_broadcast(&self) -> Option<Self> {
184        let type_string = self.type_string();
185
186        if let BlobData::Memory(bytes) = self.blob_data() {
187            let blob_clone = BlobImpl::new_from_bytes(bytes.clone(), type_string);
188
189            // Note: we insert the blob at the original id,
190            // otherwise this will not match the storage key as serialized by SM in `serialized`.
191            // The clone has it's own new Id however.
192            return Some(blob_clone);
193        } else {
194            // Not panicking only because this is called from the constellation.
195            log::warn!("Serialized blob not in memory format(should never happen).");
196        }
197        None
198    }
199}
200
201/// The data backing a DOM Blob.
202#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
203pub struct BlobImpl {
204    /// UUID of the blob.
205    blob_id: BlobId,
206    /// Content-type string
207    type_string: String,
208    /// Blob data-type.
209    blob_data: BlobData,
210    /// Sliced blobs referring to this one.
211    slices: Vec<BlobId>,
212}
213
214/// Different backends of Blob
215#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
216pub enum BlobData {
217    /// File-based blob, whose content lives in the net process
218    File(FileBlob),
219    /// Memory-based blob, whose content lives in the script process
220    Memory(Vec<u8>),
221    /// Sliced blob, including parent blob-id and
222    /// relative positions of current slicing range,
223    /// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
224    /// either File-based or Memory-based
225    Sliced(BlobId, RelativePos),
226}
227
228impl BlobImpl {
229    /// Construct memory-backed BlobImpl
230    pub fn new_from_bytes(bytes: Vec<u8>, type_string: String) -> BlobImpl {
231        let blob_id = BlobId::new();
232        let blob_data = BlobData::Memory(bytes);
233        BlobImpl {
234            blob_id,
235            type_string,
236            blob_data,
237            slices: vec![],
238        }
239    }
240
241    /// Construct file-backed BlobImpl from File ID
242    pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64, type_string: String) -> BlobImpl {
243        let blob_id = BlobId::new();
244        let blob_data = BlobData::File(FileBlob {
245            id: file_id,
246            name: Some(name),
247            cache: RefCell::new(None),
248            size,
249        });
250        BlobImpl {
251            blob_id,
252            type_string,
253            blob_data,
254            slices: vec![],
255        }
256    }
257
258    /// Construct a BlobImpl from a slice of a parent.
259    pub fn new_sliced(range: RelativePos, parent: BlobId, type_string: String) -> BlobImpl {
260        let blob_id = BlobId::new();
261        let blob_data = BlobData::Sliced(parent, range);
262        BlobImpl {
263            blob_id,
264            type_string,
265            blob_data,
266            slices: vec![],
267        }
268    }
269
270    /// Get a clone of the blob-id
271    pub fn blob_id(&self) -> BlobId {
272        self.blob_id
273    }
274
275    /// Get a clone of the type-string
276    pub fn type_string(&self) -> String {
277        self.type_string.clone()
278    }
279
280    /// Get a mutable ref to the data
281    pub fn blob_data(&self) -> &BlobData {
282        &self.blob_data
283    }
284
285    /// Get a mutable ref to the data
286    pub fn blob_data_mut(&mut self) -> &mut BlobData {
287        &mut self.blob_data
288    }
289}
290
291#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
292/// A serializable version of the DOMPoint/DOMPointReadOnly interface.
293pub struct DomPoint {
294    /// The x coordinate.
295    pub x: f64,
296    /// The y coordinate.
297    pub y: f64,
298    /// The z coordinate.
299    pub z: f64,
300    /// The w coordinate.
301    pub w: f64,
302}
303
304impl BroadcastClone for DomPoint {
305    type Id = DomPointId;
306
307    fn source(
308        data: &StructuredSerializedData,
309    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
310        &data.points
311    }
312
313    fn destination(
314        data: &mut StructuredSerializedData,
315    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
316        &mut data.points
317    }
318
319    fn clone_for_broadcast(&self) -> Option<Self> {
320        Some(self.clone())
321    }
322}
323
324#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
325/// A serializable version of the DOMRect/DOMRectReadOnly interface.
326pub struct DomRect {
327    /// The x coordinate.
328    pub x: f64,
329    /// The y coordinate.
330    pub y: f64,
331    /// The width.
332    pub width: f64,
333    /// The height.
334    pub height: f64,
335}
336
337impl BroadcastClone for DomRect {
338    type Id = DomRectId;
339
340    fn source(
341        data: &StructuredSerializedData,
342    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
343        &data.rects
344    }
345
346    fn destination(
347        data: &mut StructuredSerializedData,
348    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
349        &mut data.rects
350    }
351
352    fn clone_for_broadcast(&self) -> Option<Self> {
353        Some(self.clone())
354    }
355}
356
357#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
358/// A serializable version of the DOMQuad interface.
359pub struct DomQuad {
360    /// The first point.
361    pub p1: DomPoint,
362    /// The second point.
363    pub p2: DomPoint,
364    /// The third point.
365    pub p3: DomPoint,
366    /// The fourth point.
367    pub p4: DomPoint,
368}
369
370impl BroadcastClone for DomQuad {
371    type Id = DomQuadId;
372
373    fn source(
374        data: &StructuredSerializedData,
375    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
376        &data.quads
377    }
378
379    fn destination(
380        data: &mut StructuredSerializedData,
381    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
382        &mut data.quads
383    }
384
385    fn clone_for_broadcast(&self) -> Option<Self> {
386        Some(self.clone())
387    }
388}
389
390#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
391/// A serializable version of the DOMMatrix/DOMMatrixReadOnly interface.
392pub struct DomMatrix {
393    /// The matrix.
394    pub matrix: Transform3D<f64>,
395    /// Whether this matrix represents a 2D transformation.
396    pub is_2d: bool,
397}
398
399impl BroadcastClone for DomMatrix {
400    type Id = DomMatrixId;
401
402    fn source(
403        data: &StructuredSerializedData,
404    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
405        &data.matrices
406    }
407
408    fn destination(
409        data: &mut StructuredSerializedData,
410    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
411        &mut data.matrices
412    }
413
414    fn clone_for_broadcast(&self) -> Option<Self> {
415        Some(self.clone())
416    }
417}
418
419#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
420/// A serializable version of the DOMException interface.
421pub struct DomException {
422    pub message: String,
423    pub name: String,
424}
425
426impl BroadcastClone for DomException {
427    type Id = DomExceptionId;
428
429    fn source(
430        data: &StructuredSerializedData,
431    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
432        &data.exceptions
433    }
434
435    fn destination(
436        data: &mut StructuredSerializedData,
437    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
438        &mut data.exceptions
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 QuotaExceededError interface.
448pub struct SerializableQuotaExceededError {
449    pub dom_exception: DomException,
450    pub quota: Option<f64>,
451    pub requested: Option<f64>,
452}
453
454impl BroadcastClone for SerializableQuotaExceededError {
455    type Id = QuotaExceededErrorId;
456
457    fn source(data: &StructuredSerializedData) -> &Option<HashMap<Self::Id, Self>> {
458        &data.quota_exceeded_errors
459    }
460
461    fn destination(data: &mut StructuredSerializedData) -> &mut Option<HashMap<Self::Id, Self>> {
462        &mut data.quota_exceeded_errors
463    }
464
465    fn clone_for_broadcast(&self) -> Option<Self> {
466        Some(self.clone())
467    }
468}
469
470#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
471/// A serializable version of the ImageBitmap interface.
472pub struct SerializableImageBitmap {
473    pub bitmap_data: Snapshot,
474}
475
476impl BroadcastClone for SerializableImageBitmap {
477    type Id = ImageBitmapId;
478
479    fn source(
480        data: &StructuredSerializedData,
481    ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
482        &data.image_bitmaps
483    }
484
485    fn destination(
486        data: &mut StructuredSerializedData,
487    ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
488        &mut data.image_bitmaps
489    }
490
491    fn clone_for_broadcast(&self) -> Option<Self> {
492        Some(self.clone())
493    }
494}