constellation_traits/structured_data/
mod.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 of structured data as described in
6//! <https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data>
7
8mod serializable;
9mod transferable;
10
11use std::collections::HashMap;
12
13use base::id::{
14    BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, ImageBitmapId,
15    MessagePortId, OffscreenCanvasId, QuotaExceededErrorId,
16};
17use log::warn;
18use malloc_size_of_derive::MallocSizeOf;
19use serde::{Deserialize, Serialize};
20pub use serializable::*;
21use strum::IntoEnumIterator;
22pub use transferable::*;
23
24/// A data-holder for serialized data and transferred objects.
25/// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
26#[derive(Debug, Default, Deserialize, MallocSizeOf, Serialize)]
27pub struct StructuredSerializedData {
28    /// Data serialized by SpiderMonkey.
29    pub serialized: Vec<u8>,
30    /// Serialized in a structured callback,
31    pub blobs: Option<HashMap<BlobId, BlobImpl>>,
32    /// Serialized point objects.
33    pub points: Option<HashMap<DomPointId, DomPoint>>,
34    /// Serialized rect objects.
35    pub rects: Option<HashMap<DomRectId, DomRect>>,
36    /// Serialized quad objects.
37    pub quads: Option<HashMap<DomQuadId, DomQuad>>,
38    /// Serialized matrix objects.
39    pub matrices: Option<HashMap<DomMatrixId, DomMatrix>>,
40    /// Serialized exception objects.
41    pub exceptions: Option<HashMap<DomExceptionId, DomException>>,
42    /// Serialized quota exceeded errors.
43    pub quota_exceeded_errors:
44        Option<HashMap<QuotaExceededErrorId, SerializableQuotaExceededError>>,
45    /// Transferred objects.
46    pub ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
47    /// Transform streams transferred objects.
48    pub transform_streams: Option<HashMap<MessagePortId, TransformStreamData>>,
49    /// Serialized image bitmap objects.
50    pub image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>,
51    /// Transferred image bitmap objects.
52    pub transferred_image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>,
53    /// Transferred offscreen canvas objects.
54    pub offscreen_canvases: Option<HashMap<OffscreenCanvasId, TransferableOffscreenCanvas>>,
55}
56
57impl StructuredSerializedData {
58    fn is_empty(&self, val: Transferrable) -> bool {
59        fn is_field_empty<K, V>(field: &Option<HashMap<K, V>>) -> bool {
60            field.as_ref().is_none_or(|h| h.is_empty())
61        }
62        match val {
63            Transferrable::ImageBitmap => is_field_empty(&self.transferred_image_bitmaps),
64            Transferrable::MessagePort => is_field_empty(&self.ports),
65            Transferrable::OffscreenCanvas => is_field_empty(&self.offscreen_canvases),
66            Transferrable::ReadableStream => is_field_empty(&self.ports),
67            Transferrable::WritableStream => is_field_empty(&self.ports),
68            Transferrable::TransformStream => is_field_empty(&self.ports),
69        }
70    }
71
72    /// Clone all values of the same type stored in this StructuredSerializedData
73    /// into another instance.
74    fn clone_all_of_type<T: BroadcastClone>(&self, cloned: &mut StructuredSerializedData) {
75        let existing = T::source(self);
76        let Some(existing) = existing else { return };
77        let mut clones = HashMap::with_capacity(existing.len());
78
79        for (original_id, obj) in existing.iter() {
80            if let Some(clone) = obj.clone_for_broadcast() {
81                clones.insert(*original_id, clone);
82            }
83        }
84
85        *T::destination(cloned) = Some(clones);
86    }
87
88    /// Clone the serialized data for use with broadcast-channels.
89    pub fn clone_for_broadcast(&self) -> StructuredSerializedData {
90        for transferrable in Transferrable::iter() {
91            if !self.is_empty(transferrable) {
92                // Not panicking only because this is called from the constellation.
93                warn!(
94                    "Attempt to broadcast structured serialized data including {:?} (should never happen).",
95                    transferrable,
96                );
97            }
98        }
99
100        let serialized = self.serialized.clone();
101
102        let mut cloned = StructuredSerializedData {
103            serialized,
104            ..Default::default()
105        };
106
107        for serializable in Serializable::iter() {
108            let clone_impl = serializable.clone_values();
109            clone_impl(self, &mut cloned);
110        }
111
112        cloned
113    }
114}