Skip to main content

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