aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2025-04-06 00:13:29 +0200
committerGitHub <noreply@github.com>2025-04-05 22:13:29 +0000
commit6031a12fd1fa4aee8368e0b3dc0cb792caac56bc (patch)
treecc91327012041a24bd1b71c7768660a2efbe862f /components/shared
parenta67409fb253b3cb6dd1adbaf9d3cad47941f4993 (diff)
downloadservo-6031a12fd1fa4aee8368e0b3dc0cb792caac56bc.tar.gz
servo-6031a12fd1fa4aee8368e0b3dc0cb792caac56bc.zip
Move `ScriptToConstellationMsg` to `constellation_traits` (#36364)
This is the last big change necessary to create the `constellation_traits` crate. This moves the data structure for messages that originate from the `ScriptThread` and are sent to the `Contellation` to `constellation_traits`, effectively splitting `script_traits` in half. Before, `script_traits` was responsible for exposing the API of both the `ScriptThread` and the `Constellation` to the rest of Servo. - Data structures that are used by `ScriptToConstellationMsg` are moved to `constellation_traits`. The dependency graph looks a bit like this: `script_layout_interface` depends on `script_traits` depends on `constellation_traits` depends on `embedder_traits`. - Data structures that are used in the embedding layer (`UntrustedNodeAddress`, `CompositorHitTestResult`, `TouchEventResult` and `AnimationState`) are moved to embedder_traits, to avoid a dependency cycle between `webrender_traits` and `constellation_traits`. - Types dealing with MessagePorts and serialization are moved to `constellation_traits::message_port`. Testing: This is covered by existing tests as it just moves types around. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/shared')
-rw-r--r--components/shared/compositing/lib.rs5
-rw-r--r--components/shared/constellation/Cargo.toml16
-rw-r--r--components/shared/constellation/from_script_message.rs (renamed from components/shared/script/script_msg.rs)605
-rw-r--r--components/shared/constellation/lib.rs73
-rw-r--r--components/shared/constellation/message_port.rs525
-rw-r--r--components/shared/embedder/lib.rs88
-rw-r--r--components/shared/script/Cargo.toml12
-rw-r--r--components/shared/script/lib.rs449
-rw-r--r--components/shared/script/serializable.rs217
-rw-r--r--components/shared/script/transferable.rs161
-rw-r--r--components/shared/script_layout/lib.rs6
-rw-r--r--components/shared/webrender/Cargo.toml1
-rw-r--r--components/shared/webrender/lib.rs3
13 files changed, 1078 insertions, 1083 deletions
diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs
index 738619ffc31..9c13afb8dc3 100644
--- a/components/shared/compositing/lib.rs
+++ b/components/shared/compositing/lib.rs
@@ -8,12 +8,13 @@ use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, WebViewId};
use crossbeam_channel::{Receiver, Sender};
-use embedder_traits::{EventLoopWaker, MouseButton, MouseButtonAction};
+use embedder_traits::{
+ AnimationState, EventLoopWaker, MouseButton, MouseButtonAction, TouchEventResult,
+};
use euclid::Rect;
use ipc_channel::ipc::IpcSender;
use log::warn;
use pixels::Image;
-use script_traits::{AnimationState, TouchEventResult};
use strum_macros::IntoStaticStr;
use style_traits::CSSPixel;
use webrender_api::DocumentId;
diff --git a/components/shared/constellation/Cargo.toml b/components/shared/constellation/Cargo.toml
index 10ee64d0b42..53a4307df60 100644
--- a/components/shared/constellation/Cargo.toml
+++ b/components/shared/constellation/Cargo.toml
@@ -11,16 +11,30 @@ rust-version.workspace = true
name = "constellation_traits"
path = "lib.rs"
+[features]
+bluetooth = []
+webgpu = ["wgpu-core"]
+
[dependencies]
base = { workspace = true }
bitflags = { workspace = true }
+canvas_traits = { workspace = true }
+devtools_traits = { workspace = true }
embedder_traits = { workspace = true }
euclid = { workspace = true }
+http = { workspace = true }
+hyper_serde = { workspace = true }
ipc-channel = { workspace = true }
+log = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
+net_traits = { workspace = true }
+profile_traits = { workspace = true }
serde = { workspace = true }
servo_url = { path = "../../url" }
+strum = { workspace = true }
strum_macros = { workspace = true }
-stylo_traits = { workspace = true }
+uuid = { workspace = true }
+webgpu_traits = { workspace = true }
webrender_api = { workspace = true }
+wgpu-core = { workspace = true, optional = true }
diff --git a/components/shared/script/script_msg.rs b/components/shared/constellation/from_script_message.rs
index 30244c9b46a..bccb3059e24 100644
--- a/components/shared/script/script_msg.rs
+++ b/components/shared/constellation/from_script_message.rs
@@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+//! Messages send from the ScriptThread to the Constellation.
+
use std::collections::{HashMap, VecDeque};
use std::fmt;
@@ -11,15 +13,19 @@ use base::id::{
MessagePortRouterId, PipelineId, ServiceWorkerId, ServiceWorkerRegistrationId, WebViewId,
};
use canvas_traits::canvas::{CanvasId, CanvasMsg};
-use constellation_traits::{LogEntry, TraversalDirection};
-use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
+use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
use embedder_traits::{
- EmbedderMsg, MediaSessionEvent, TouchEventType, TouchSequenceId, ViewportDetails,
+ AnimationState, EmbedderMsg, MediaSessionEvent, TouchEventResult, ViewportDetails,
};
use euclid::default::Size2D as UntypedSize2D;
+use http::{HeaderMap, Method};
+use ipc_channel::Error as IpcError;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
-use net_traits::CoreResourceMsg;
+use net_traits::request::{InsecureRequestsPolicy, Referrer, RequestBody};
use net_traits::storage_thread::StorageType;
+use net_traits::{CoreResourceMsg, ReferrerPolicy, ResourceThreads};
+use profile_traits::mem::MemoryReportResult;
+use profile_traits::{mem, time as profile_time};
use serde::{Deserialize, Serialize};
use servo_url::{ImmutableOrigin, ServoUrl};
use strum_macros::IntoStaticStr;
@@ -27,12 +33,420 @@ use strum_macros::IntoStaticStr;
use webgpu_traits::{WebGPU, WebGPUAdapterResponse};
use webrender_api::ImageKey;
-use crate::mem::MemoryReportResult;
-use crate::{
- AnimationState, AuxiliaryWebViewCreationRequest, BroadcastMsg, DocumentState,
- IFrameLoadInfoWithData, LoadData, MessagePortMsg, NavigationHistoryBehavior, PortMessageTask,
- StructuredSerializedData, WindowSizeType, WorkerGlobalScopeInit, WorkerScriptLoadOrigin,
+use crate::message_port::{
+ BroadcastMsg, MessagePortMsg, PortMessageTask, StructuredSerializedData,
};
+use crate::{LogEntry, TraversalDirection, WindowSizeType};
+
+/// A Script to Constellation channel.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct ScriptToConstellationChan {
+ /// Sender for communicating with constellation thread.
+ pub sender: IpcSender<(PipelineId, ScriptToConstellationMessage)>,
+ /// Used to identify the origin of the message.
+ pub pipeline_id: PipelineId,
+}
+
+impl ScriptToConstellationChan {
+ /// Send ScriptMsg and attach the pipeline_id to the message.
+ pub fn send(&self, msg: ScriptToConstellationMessage) -> Result<(), IpcError> {
+ self.sender.send((self.pipeline_id, msg))
+ }
+}
+
+/// The origin where a given load was initiated.
+/// Useful for origin checks, for example before evaluation a JS URL.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub enum LoadOrigin {
+ /// A load originating in the constellation.
+ Constellation,
+ /// A load originating in webdriver.
+ WebDriver,
+ /// A load originating in script.
+ Script(ImmutableOrigin),
+}
+
+/// can be passed to `LoadUrl` to load a page with GET/POST
+/// parameters or headers
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct LoadData {
+ /// The origin where the load started.
+ pub load_origin: LoadOrigin,
+ /// The URL.
+ pub url: ServoUrl,
+ /// The creator pipeline id if this is an about:blank load.
+ pub creator_pipeline_id: Option<PipelineId>,
+ /// The method.
+ #[serde(
+ deserialize_with = "::hyper_serde::deserialize",
+ serialize_with = "::hyper_serde::serialize"
+ )]
+ pub method: Method,
+ /// The headers.
+ #[serde(
+ deserialize_with = "::hyper_serde::deserialize",
+ serialize_with = "::hyper_serde::serialize"
+ )]
+ pub headers: HeaderMap,
+ /// The data that will be used as the body of the request.
+ pub data: Option<RequestBody>,
+ /// The result of evaluating a javascript scheme url.
+ pub js_eval_result: Option<JsEvalResult>,
+ /// The referrer.
+ pub referrer: Referrer,
+ /// The referrer policy.
+ pub referrer_policy: ReferrerPolicy,
+
+ /// The source to use instead of a network response for a srcdoc document.
+ pub srcdoc: String,
+ /// The inherited context is Secure, None if not inherited
+ pub inherited_secure_context: Option<bool>,
+ /// The inherited policy for upgrading insecure requests; None if not inherited.
+ pub inherited_insecure_requests_policy: Option<InsecureRequestsPolicy>,
+ /// Whether the page's ancestors have potentially trustworthy origin
+ pub has_trustworthy_ancestor_origin: bool,
+ /// Servo internal: if crash details are present, trigger a crash error page with these details.
+ pub crash: Option<String>,
+}
+
+/// The result of evaluating a javascript scheme url.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub enum JsEvalResult {
+ /// The js evaluation had a non-string result, 204 status code.
+ /// <https://html.spec.whatwg.org/multipage/#navigate> 12.11
+ NoContent,
+ /// The js evaluation had a string result.
+ Ok(Vec<u8>),
+}
+
+impl LoadData {
+ /// Create a new `LoadData` object.
+ #[allow(clippy::too_many_arguments)]
+ pub fn new(
+ load_origin: LoadOrigin,
+ url: ServoUrl,
+ creator_pipeline_id: Option<PipelineId>,
+ referrer: Referrer,
+ referrer_policy: ReferrerPolicy,
+ inherited_secure_context: Option<bool>,
+ inherited_insecure_requests_policy: Option<InsecureRequestsPolicy>,
+ has_trustworthy_ancestor_origin: bool,
+ ) -> LoadData {
+ LoadData {
+ load_origin,
+ url,
+ creator_pipeline_id,
+ method: Method::GET,
+ headers: HeaderMap::new(),
+ data: None,
+ js_eval_result: None,
+ referrer,
+ referrer_policy,
+ srcdoc: "".to_string(),
+ inherited_secure_context,
+ crash: None,
+ inherited_insecure_requests_policy,
+ has_trustworthy_ancestor_origin,
+ }
+ }
+}
+
+/// <https://html.spec.whatwg.org/multipage/#navigation-supporting-concepts:navigationhistorybehavior>
+#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
+pub enum NavigationHistoryBehavior {
+ /// The default value, which will be converted very early in the navigate algorithm into "push"
+ /// or "replace". Usually it becomes "push", but under certain circumstances it becomes
+ /// "replace" instead.
+ #[default]
+ Auto,
+ /// A regular navigation which adds a new session history entry, and will clear the forward
+ /// session history.
+ Push,
+ /// A navigation that will replace the active session history entry.
+ Replace,
+}
+
+/// Entities required to spawn service workers
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct ScopeThings {
+ /// script resource url
+ pub script_url: ServoUrl,
+ /// network load origin of the resource
+ pub worker_load_origin: WorkerScriptLoadOrigin,
+ /// base resources required to create worker global scopes
+ pub init: WorkerGlobalScopeInit,
+ /// the port to receive devtools message from
+ pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+ /// service worker id
+ pub worker_id: WorkerId,
+}
+
+/// Message that gets passed to service worker scope on postMessage
+#[derive(Debug, Deserialize, Serialize)]
+pub struct DOMMessage {
+ /// The origin of the message
+ pub origin: ImmutableOrigin,
+ /// The payload of the message
+ pub data: StructuredSerializedData,
+}
+
+/// Channels to allow service worker manager to communicate with constellation and resource thread
+#[derive(Deserialize, Serialize)]
+pub struct SWManagerSenders {
+ /// Sender of messages to the constellation.
+ pub swmanager_sender: IpcSender<SWManagerMsg>,
+ /// Sender for communicating with resource thread.
+ pub resource_sender: IpcSender<CoreResourceMsg>,
+ /// Sender of messages to the manager.
+ pub own_sender: IpcSender<ServiceWorkerMsg>,
+ /// Receiver of messages from the constellation.
+ pub receiver: IpcReceiver<ServiceWorkerMsg>,
+}
+
+/// Messages sent to Service Worker Manager thread
+#[derive(Debug, Deserialize, Serialize)]
+pub enum ServiceWorkerMsg {
+ /// Timeout message sent by active service workers
+ Timeout(ServoUrl),
+ /// Message sent by constellation to forward to a running service worker
+ ForwardDOMMessage(DOMMessage, ServoUrl),
+ /// <https://w3c.github.io/ServiceWorker/#schedule-job-algorithm>
+ ScheduleJob(Job),
+ /// Exit the service worker manager
+ Exit,
+}
+
+#[derive(Debug, Deserialize, PartialEq, Serialize)]
+/// <https://w3c.github.io/ServiceWorker/#dfn-job-type>
+pub enum JobType {
+ /// <https://w3c.github.io/ServiceWorker/#register>
+ Register,
+ /// <https://w3c.github.io/ServiceWorker/#unregister-algorithm>
+ Unregister,
+ /// <https://w3c.github.io/ServiceWorker/#update-algorithm>
+ Update,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+/// The kind of error the job promise should be rejected with.
+pub enum JobError {
+ /// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
+ TypeError,
+ /// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
+ SecurityError,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+#[allow(clippy::large_enum_variant)]
+/// Messages sent from Job algorithms steps running in the SW manager,
+/// in order to resolve or reject the job promise.
+pub enum JobResult {
+ /// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
+ RejectPromise(JobError),
+ /// <https://w3c.github.io/ServiceWorker/#resolve-job-promise>
+ ResolvePromise(Job, JobResultValue),
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+/// Jobs are resolved with the help of various values.
+pub enum JobResultValue {
+ /// Data representing a serviceworker registration.
+ Registration {
+ /// The Id of the registration.
+ id: ServiceWorkerRegistrationId,
+ /// The installing worker, if any.
+ installing_worker: Option<ServiceWorkerId>,
+ /// The waiting worker, if any.
+ waiting_worker: Option<ServiceWorkerId>,
+ /// The active worker, if any.
+ active_worker: Option<ServiceWorkerId>,
+ },
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+/// <https://w3c.github.io/ServiceWorker/#dfn-job>
+pub struct Job {
+ /// <https://w3c.github.io/ServiceWorker/#dfn-job-type>
+ pub job_type: JobType,
+ /// <https://w3c.github.io/ServiceWorker/#dfn-job-scope-url>
+ pub scope_url: ServoUrl,
+ /// <https://w3c.github.io/ServiceWorker/#dfn-job-script-url>
+ pub script_url: ServoUrl,
+ /// <https://w3c.github.io/ServiceWorker/#dfn-job-client>
+ pub client: IpcSender<JobResult>,
+ /// <https://w3c.github.io/ServiceWorker/#job-referrer>
+ pub referrer: ServoUrl,
+ /// Various data needed to process job.
+ pub scope_things: Option<ScopeThings>,
+}
+
+impl Job {
+ /// <https://w3c.github.io/ServiceWorker/#create-job-algorithm>
+ pub fn create_job(
+ job_type: JobType,
+ scope_url: ServoUrl,
+ script_url: ServoUrl,
+ client: IpcSender<JobResult>,
+ referrer: ServoUrl,
+ scope_things: Option<ScopeThings>,
+ ) -> Job {
+ Job {
+ job_type,
+ scope_url,
+ script_url,
+ client,
+ referrer,
+ scope_things,
+ }
+ }
+}
+
+impl PartialEq for Job {
+ /// Equality criteria as described in <https://w3c.github.io/ServiceWorker/#dfn-job-equivalent>
+ fn eq(&self, other: &Self) -> bool {
+ // TODO: match on job type, take worker type and `update_via_cache_mode` into account.
+ let same_job = self.job_type == other.job_type;
+ if same_job {
+ match self.job_type {
+ JobType::Register | JobType::Update => {
+ self.scope_url == other.scope_url && self.script_url == other.script_url
+ },
+ JobType::Unregister => self.scope_url == other.scope_url,
+ }
+ } else {
+ false
+ }
+ }
+}
+
+/// Messages outgoing from the Service Worker Manager thread to constellation
+#[derive(Debug, Deserialize, Serialize)]
+pub enum SWManagerMsg {
+ /// Placeholder to keep the enum,
+ /// as it will be needed when implementing
+ /// <https://github.com/servo/servo/issues/24660>
+ PostMessageToClient,
+}
+
+/// Used to determine if a script has any pending asynchronous activity.
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
+pub enum DocumentState {
+ /// The document has been loaded and is idle.
+ Idle,
+ /// The document is either loading or waiting on an event.
+ Pending,
+}
+
+/// This trait allows creating a `ServiceWorkerManager` without depending on the `script`
+/// crate.
+pub trait ServiceWorkerManagerFactory {
+ /// Create a `ServiceWorkerManager`.
+ fn create(sw_senders: SWManagerSenders, origin: ImmutableOrigin);
+}
+
+/// Whether the sandbox attribute is present for an iframe element
+#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
+pub enum IFrameSandboxState {
+ /// Sandbox attribute is present
+ IFrameSandboxed,
+ /// Sandbox attribute is not present
+ IFrameUnsandboxed,
+}
+
+/// Specifies the information required to load an auxiliary browsing context.
+#[derive(Debug, Deserialize, Serialize)]
+pub struct AuxiliaryWebViewCreationRequest {
+ /// Load data containing the url to load
+ pub load_data: LoadData,
+ /// The webview that caused this request.
+ pub opener_webview_id: WebViewId,
+ /// The pipeline opener browsing context.
+ pub opener_pipeline_id: PipelineId,
+ /// Sender for the constellation’s response to our request.
+ pub response_sender: IpcSender<Option<AuxiliaryWebViewCreationResponse>>,
+}
+
+/// Constellation’s response to auxiliary browsing context creation requests.
+#[derive(Debug, Deserialize, Serialize)]
+pub struct AuxiliaryWebViewCreationResponse {
+ /// The new webview ID.
+ pub new_webview_id: WebViewId,
+ /// The new pipeline ID.
+ pub new_pipeline_id: PipelineId,
+}
+
+/// Specifies the information required to load an iframe.
+#[derive(Debug, Deserialize, Serialize)]
+pub struct IFrameLoadInfo {
+ /// Pipeline ID of the parent of this iframe
+ pub parent_pipeline_id: PipelineId,
+ /// The ID for this iframe's nested browsing context.
+ pub browsing_context_id: BrowsingContextId,
+ /// The ID for the top-level ancestor browsing context of this iframe's nested browsing context.
+ pub webview_id: WebViewId,
+ /// The new pipeline ID that the iframe has generated.
+ pub new_pipeline_id: PipelineId,
+ /// Whether this iframe should be considered private
+ pub is_private: bool,
+ /// Whether this iframe should be considered secure
+ pub inherited_secure_context: Option<bool>,
+ /// Whether this load should replace the current entry (reload). If true, the current
+ /// entry will be replaced instead of a new entry being added.
+ pub history_handling: NavigationHistoryBehavior,
+}
+
+/// Specifies the information required to load a URL in an iframe.
+#[derive(Debug, Deserialize, Serialize)]
+pub struct IFrameLoadInfoWithData {
+ /// The information required to load an iframe.
+ pub info: IFrameLoadInfo,
+ /// Load data containing the url to load
+ pub load_data: LoadData,
+ /// The old pipeline ID for this iframe, if a page was previously loaded.
+ pub old_pipeline_id: Option<PipelineId>,
+ /// Sandbox type of this iframe
+ pub sandbox: IFrameSandboxState,
+ /// The initial viewport size for this iframe.
+ pub viewport_details: ViewportDetails,
+}
+
+/// Resources required by workerglobalscopes
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct WorkerGlobalScopeInit {
+ /// Chan to a resource thread
+ pub resource_threads: ResourceThreads,
+ /// Chan to the memory profiler
+ pub mem_profiler_chan: mem::ProfilerChan,
+ /// Chan to the time profiler
+ pub time_profiler_chan: profile_time::ProfilerChan,
+ /// To devtools sender
+ pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+ /// From devtools sender
+ pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
+ /// Messages to send to constellation
+ pub script_to_constellation_chan: ScriptToConstellationChan,
+ /// The worker id
+ pub worker_id: WorkerId,
+ /// The pipeline id
+ pub pipeline_id: PipelineId,
+ /// The origin
+ pub origin: ImmutableOrigin,
+ /// The creation URL
+ pub creation_url: Option<ServoUrl>,
+ /// True if secure context
+ pub inherited_secure_context: Option<bool>,
+}
+
+/// Common entities representing a network load origin
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct WorkerScriptLoadOrigin {
+ /// referrer url
+ pub referrer_url: Option<ServoUrl>,
+ /// the referrer policy which is used
+ pub referrer_policy: ReferrerPolicy,
+ /// the pipeline id of the entity requesting the load
+ pub pipeline_id: PipelineId,
+}
/// An iframe sizing operation.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
@@ -45,16 +459,7 @@ pub struct IFrameSizeMsg {
pub type_: WindowSizeType,
}
-/// Whether the default action for a touch event was prevented by web content
-#[derive(Debug, Deserialize, Serialize)]
-pub enum TouchEventResult {
- /// Allowed by web content
- DefaultAllowed(TouchSequenceId, TouchEventType),
- /// Prevented by web content
- DefaultPrevented(TouchSequenceId, TouchEventType),
-}
-
-/// Messages sent from the `ScriptThread` to the `Constellation`.
+/// Messages from the script to the constellation.
#[derive(Deserialize, IntoStaticStr, Serialize)]
pub enum ScriptToConstellationMessage {
/// Request to complete the transfer of a set of ports to a router.
@@ -225,165 +630,3 @@ impl fmt::Debug for ScriptToConstellationMessage {
write!(formatter, "ScriptMsg::{variant_string}")
}
}
-
-/// Entities required to spawn service workers
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct ScopeThings {
- /// script resource url
- pub script_url: ServoUrl,
- /// network load origin of the resource
- pub worker_load_origin: WorkerScriptLoadOrigin,
- /// base resources required to create worker global scopes
- pub init: WorkerGlobalScopeInit,
- /// the port to receive devtools message from
- pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
- /// service worker id
- pub worker_id: WorkerId,
-}
-
-/// Message that gets passed to service worker scope on postMessage
-#[derive(Debug, Deserialize, Serialize)]
-pub struct DOMMessage {
- /// The origin of the message
- pub origin: ImmutableOrigin,
- /// The payload of the message
- pub data: StructuredSerializedData,
-}
-
-/// Channels to allow service worker manager to communicate with constellation and resource thread
-#[derive(Deserialize, Serialize)]
-pub struct SWManagerSenders {
- /// Sender of messages to the constellation.
- pub swmanager_sender: IpcSender<SWManagerMsg>,
- /// Sender for communicating with resource thread.
- pub resource_sender: IpcSender<CoreResourceMsg>,
- /// Sender of messages to the manager.
- pub own_sender: IpcSender<ServiceWorkerMsg>,
- /// Receiver of messages from the constellation.
- pub receiver: IpcReceiver<ServiceWorkerMsg>,
-}
-
-/// Messages sent to Service Worker Manager thread
-#[derive(Debug, Deserialize, Serialize)]
-pub enum ServiceWorkerMsg {
- /// Timeout message sent by active service workers
- Timeout(ServoUrl),
- /// Message sent by constellation to forward to a running service worker
- ForwardDOMMessage(DOMMessage, ServoUrl),
- /// <https://w3c.github.io/ServiceWorker/#schedule-job-algorithm>
- ScheduleJob(Job),
- /// Exit the service worker manager
- Exit,
-}
-
-#[derive(Debug, Deserialize, PartialEq, Serialize)]
-/// <https://w3c.github.io/ServiceWorker/#dfn-job-type>
-pub enum JobType {
- /// <https://w3c.github.io/ServiceWorker/#register>
- Register,
- /// <https://w3c.github.io/ServiceWorker/#unregister-algorithm>
- Unregister,
- /// <https://w3c.github.io/ServiceWorker/#update-algorithm>
- Update,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-/// The kind of error the job promise should be rejected with.
-pub enum JobError {
- /// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
- TypeError,
- /// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
- SecurityError,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-#[allow(clippy::large_enum_variant)]
-/// Messages sent from Job algorithms steps running in the SW manager,
-/// in order to resolve or reject the job promise.
-pub enum JobResult {
- /// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
- RejectPromise(JobError),
- /// <https://w3c.github.io/ServiceWorker/#resolve-job-promise>
- ResolvePromise(Job, JobResultValue),
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-/// Jobs are resolved with the help of various values.
-pub enum JobResultValue {
- /// Data representing a serviceworker registration.
- Registration {
- /// The Id of the registration.
- id: ServiceWorkerRegistrationId,
- /// The installing worker, if any.
- installing_worker: Option<ServiceWorkerId>,
- /// The waiting worker, if any.
- waiting_worker: Option<ServiceWorkerId>,
- /// The active worker, if any.
- active_worker: Option<ServiceWorkerId>,
- },
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-/// <https://w3c.github.io/ServiceWorker/#dfn-job>
-pub struct Job {
- /// <https://w3c.github.io/ServiceWorker/#dfn-job-type>
- pub job_type: JobType,
- /// <https://w3c.github.io/ServiceWorker/#dfn-job-scope-url>
- pub scope_url: ServoUrl,
- /// <https://w3c.github.io/ServiceWorker/#dfn-job-script-url>
- pub script_url: ServoUrl,
- /// <https://w3c.github.io/ServiceWorker/#dfn-job-client>
- pub client: IpcSender<JobResult>,
- /// <https://w3c.github.io/ServiceWorker/#job-referrer>
- pub referrer: ServoUrl,
- /// Various data needed to process job.
- pub scope_things: Option<ScopeThings>,
-}
-
-impl Job {
- /// <https://w3c.github.io/ServiceWorker/#create-job-algorithm>
- pub fn create_job(
- job_type: JobType,
- scope_url: ServoUrl,
- script_url: ServoUrl,
- client: IpcSender<JobResult>,
- referrer: ServoUrl,
- scope_things: Option<ScopeThings>,
- ) -> Job {
- Job {
- job_type,
- scope_url,
- script_url,
- client,
- referrer,
- scope_things,
- }
- }
-}
-
-impl PartialEq for Job {
- /// Equality criteria as described in <https://w3c.github.io/ServiceWorker/#dfn-job-equivalent>
- fn eq(&self, other: &Self) -> bool {
- // TODO: match on job type, take worker type and `update_via_cache_mode` into account.
- let same_job = self.job_type == other.job_type;
- if same_job {
- match self.job_type {
- JobType::Register | JobType::Update => {
- self.scope_url == other.scope_url && self.script_url == other.script_url
- },
- JobType::Unregister => self.scope_url == other.scope_url,
- }
- } else {
- false
- }
- }
-}
-
-/// Messages outgoing from the Service Worker Manager thread to constellation
-#[derive(Debug, Deserialize, Serialize)]
-pub enum SWManagerMsg {
- /// Placeholder to keep the enum,
- /// as it will be needed when implementing
- /// <https://github.com/servo/servo/issues/24660>
- PostMessageToClient,
-}
diff --git a/components/shared/constellation/lib.rs b/components/shared/constellation/lib.rs
index 22de84c4711..627741a40fb 100644
--- a/components/shared/constellation/lib.rs
+++ b/components/shared/constellation/lib.rs
@@ -8,23 +8,27 @@
//! embedding/rendering layer all the way to script, thus it should have very minimal dependencies
//! on other parts of Servo.
+mod from_script_message;
+mod message_port;
+
use std::collections::HashMap;
-use std::ffi::c_void;
use std::fmt;
use std::time::Duration;
use base::Epoch;
use base::cross_process_instant::CrossProcessInstant;
-use base::id::{PipelineId, ScrollTreeNodeId, WebViewId};
+use base::id::{PipelineId, WebViewId};
use bitflags::bitflags;
use embedder_traits::{
- Cursor, InputEvent, MediaSessionActionType, Theme, ViewportDetails, WebDriverCommandMsg,
+ CompositorHitTestResult, Cursor, InputEvent, MediaSessionActionType, Theme, ViewportDetails,
+ WebDriverCommandMsg,
};
use euclid::Vector2D;
+pub use from_script_message::*;
use ipc_channel::ipc::IpcSender;
-use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
+pub use message_port::*;
+use serde::{Deserialize, Serialize};
use servo_url::ServoUrl;
use strum_macros::IntoStaticStr;
use webrender_api::ExternalScrollId;
@@ -137,28 +141,6 @@ bitflags! {
}
}
-/// The result of a hit test in the compositor.
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct CompositorHitTestResult {
- /// The pipeline id of the resulting item.
- pub pipeline_id: PipelineId,
-
- /// The hit test point in the item's viewport.
- pub point_in_viewport: euclid::default::Point2D<f32>,
-
- /// The hit test point relative to the item itself.
- pub point_relative_to_item: euclid::default::Point2D<f32>,
-
- /// The node address of the hit test result.
- pub node: UntrustedNodeAddress,
-
- /// The cursor that should be used when hovering the item hit by the hit test.
- pub cursor: Option<Cursor>,
-
- /// The scroll tree node associated with this hit test item.
- pub scroll_tree_node: ScrollTreeNodeId,
-}
-
/// The scroll state of a stacking context.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ScrollState {
@@ -168,43 +150,6 @@ pub struct ScrollState {
pub scroll_offset: Vector2D<f32, LayoutPixel>,
}
-/// The address of a node. Layout sends these back. They must be validated via
-/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct UntrustedNodeAddress(pub *const c_void);
-
-malloc_size_of_is_0!(UntrustedNodeAddress);
-
-#[allow(unsafe_code)]
-unsafe impl Send for UntrustedNodeAddress {}
-
-impl From<style_traits::dom::OpaqueNode> for UntrustedNodeAddress {
- fn from(o: style_traits::dom::OpaqueNode) -> Self {
- UntrustedNodeAddress(o.0 as *const c_void)
- }
-}
-
-impl Serialize for UntrustedNodeAddress {
- fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
- (self.0 as usize).serialize(s)
- }
-}
-
-impl<'de> Deserialize<'de> for UntrustedNodeAddress {
- fn deserialize<D: Deserializer<'de>>(d: D) -> Result<UntrustedNodeAddress, D::Error> {
- let value: usize = Deserialize::deserialize(d)?;
- Ok(UntrustedNodeAddress::from_id(value))
- }
-}
-
-impl UntrustedNodeAddress {
- /// Creates an `UntrustedNodeAddress` from the given pointer address value.
- #[inline]
- pub fn from_id(id: usize) -> UntrustedNodeAddress {
- UntrustedNodeAddress(id as *const c_void)
- }
-}
-
/// The direction of a history traversal
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TraversalDirection {
diff --git a/components/shared/constellation/message_port.rs b/components/shared/constellation/message_port.rs
new file mode 100644
index 00000000000..36c6213bf80
--- /dev/null
+++ b/components/shared/constellation/message_port.rs
@@ -0,0 +1,525 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+//! This module contains data structures used for message ports and serializing
+//! DOM objects to send across them as per
+//! <https://html.spec.whatwg.org/multipage/#serializable-objects>.
+//! The implementations are here instead of in `script``, because these
+//! types can be sent through the Constellation to other ScriptThreads,
+//! and Constellation cannot depend directly on `script`.
+
+use std::cell::RefCell;
+use std::collections::{HashMap, VecDeque};
+use std::path::PathBuf;
+
+use base::id::{BlobId, DomPointId, MessagePortId};
+use log::warn;
+use malloc_size_of_derive::MallocSizeOf;
+use net_traits::filemanager_thread::RelativePos;
+use serde::{Deserialize, Serialize};
+use servo_url::ImmutableOrigin;
+use strum::{EnumIter, IntoEnumIterator};
+use uuid::Uuid;
+
+#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+enum MessagePortState {
+ /// <https://html.spec.whatwg.org/multipage/#detached>
+ Detached,
+ /// <https://html.spec.whatwg.org/multipage/#port-message-queue>
+ /// The message-queue of this port is enabled,
+ /// the boolean represents awaiting completion of a transfer.
+ Enabled(bool),
+ /// <https://html.spec.whatwg.org/multipage/#port-message-queue>
+ /// The message-queue of this port is disabled,
+ /// the boolean represents awaiting completion of a transfer.
+ Disabled(bool),
+}
+
+#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+/// The data and logic backing the DOM managed MessagePort.
+pub struct MessagePortImpl {
+ /// The current state of the port.
+ state: MessagePortState,
+
+ /// <https://html.spec.whatwg.org/multipage/#entangle>
+ entangled_port: Option<MessagePortId>,
+
+ /// <https://html.spec.whatwg.org/multipage/#port-message-queue>
+ message_buffer: Option<VecDeque<PortMessageTask>>,
+
+ /// The UUID of this port.
+ message_port_id: MessagePortId,
+}
+
+impl MessagePortImpl {
+ /// Create a new messageport impl.
+ pub fn new(port_id: MessagePortId) -> MessagePortImpl {
+ MessagePortImpl {
+ state: MessagePortState::Disabled(false),
+ entangled_port: None,
+ message_buffer: None,
+ message_port_id: port_id,
+ }
+ }
+
+ /// Get the Id.
+ pub fn message_port_id(&self) -> &MessagePortId {
+ &self.message_port_id
+ }
+
+ /// Maybe get the Id of the entangled port.
+ pub fn entangled_port_id(&self) -> Option<MessagePortId> {
+ self.entangled_port
+ }
+
+ /// Entanged this port with another.
+ pub fn entangle(&mut self, other_id: MessagePortId) {
+ self.entangled_port = Some(other_id);
+ }
+
+ /// Is this port enabled?
+ pub fn enabled(&self) -> bool {
+ matches!(self.state, MessagePortState::Enabled(_))
+ }
+
+ /// Mark this port as having been shipped.
+ /// <https://html.spec.whatwg.org/multipage/#has-been-shipped>
+ pub fn set_has_been_shipped(&mut self) {
+ match self.state {
+ MessagePortState::Detached => {
+ panic!("Messageport set_has_been_shipped called in detached state")
+ },
+ MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(true),
+ MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(true),
+ }
+ }
+
+ /// Handle the completion of the transfer,
+ /// this is data received from the constellation.
+ pub fn complete_transfer(&mut self, mut tasks: VecDeque<PortMessageTask>) {
+ match self.state {
+ MessagePortState::Detached => return,
+ MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(false),
+ MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(false),
+ }
+
+ // Note: these are the tasks that were buffered while the transfer was ongoing,
+ // hence they need to execute first.
+ // The global will call `start` if we are enabled,
+ // which will add tasks on the event-loop to dispatch incoming messages.
+ match self.message_buffer {
+ Some(ref mut incoming_buffer) => {
+ while let Some(task) = tasks.pop_back() {
+ incoming_buffer.push_front(task);
+ }
+ },
+ None => self.message_buffer = Some(tasks),
+ }
+ }
+
+ /// A message was received from our entangled port,
+ /// returns an optional task to be dispatched.
+ pub fn handle_incoming(&mut self, task: PortMessageTask) -> Option<PortMessageTask> {
+ let should_dispatch = match self.state {
+ MessagePortState::Detached => return None,
+ MessagePortState::Enabled(in_transfer) => !in_transfer,
+ MessagePortState::Disabled(_) => false,
+ };
+
+ if should_dispatch {
+ Some(task)
+ } else {
+ match self.message_buffer {
+ Some(ref mut buffer) => {
+ buffer.push_back(task);
+ },
+ None => {
+ let mut queue = VecDeque::new();
+ queue.push_back(task);
+ self.message_buffer = Some(queue);
+ },
+ }
+ None
+ }
+ }
+
+ /// <https://html.spec.whatwg.org/multipage/#dom-messageport-start>
+ /// returns an optional queue of tasks that were buffered while the port was disabled.
+ pub fn start(&mut self) -> Option<VecDeque<PortMessageTask>> {
+ match self.state {
+ MessagePortState::Detached => return None,
+ MessagePortState::Enabled(_) => {},
+ MessagePortState::Disabled(in_transfer) => {
+ self.state = MessagePortState::Enabled(in_transfer);
+ },
+ }
+ if let MessagePortState::Enabled(true) = self.state {
+ return None;
+ }
+ self.message_buffer.take()
+ }
+
+ /// <https://html.spec.whatwg.org/multipage/#dom-messageport-close>
+ pub fn close(&mut self) {
+ // Step 1
+ self.state = MessagePortState::Detached;
+ }
+}
+
+/// A data-holder for serialized data and transferred objects.
+/// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
+#[derive(Debug, Default, Deserialize, MallocSizeOf, Serialize)]
+pub struct StructuredSerializedData {
+ /// Data serialized by SpiderMonkey.
+ pub serialized: Vec<u8>,
+ /// Serialized in a structured callback,
+ pub blobs: Option<HashMap<BlobId, BlobImpl>>,
+ /// Serialized point objects.
+ pub points: Option<HashMap<DomPointId, DomPoint>>,
+ /// Transferred objects.
+ pub ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
+}
+
+pub(crate) trait BroadcastClone
+where
+ Self: Sized,
+{
+ /// The ID type that uniquely identify each value.
+ type Id: Eq + std::hash::Hash + Copy;
+ /// Clone this value so that it can be reused with a broadcast channel.
+ /// Only return None if cloning is impossible.
+ fn clone_for_broadcast(&self) -> Option<Self>;
+ /// The field from which to clone values.
+ fn source(data: &StructuredSerializedData) -> &Option<HashMap<Self::Id, Self>>;
+ /// The field into which to place cloned values.
+ fn destination(data: &mut StructuredSerializedData) -> &mut Option<HashMap<Self::Id, Self>>;
+}
+
+/// All the DOM interfaces that can be serialized.
+#[derive(Clone, Copy, Debug, EnumIter)]
+pub enum Serializable {
+ /// The `Blob` interface.
+ Blob,
+ /// The `DOMPoint` interface.
+ DomPoint,
+ /// The `DOMPointReadOnly` interface.
+ DomPointReadOnly,
+}
+
+impl Serializable {
+ fn clone_values(&self) -> fn(&StructuredSerializedData, &mut StructuredSerializedData) {
+ match self {
+ Serializable::Blob => StructuredSerializedData::clone_all_of_type::<BlobImpl>,
+ Serializable::DomPointReadOnly => {
+ StructuredSerializedData::clone_all_of_type::<DomPoint>
+ },
+ Serializable::DomPoint => StructuredSerializedData::clone_all_of_type::<DomPoint>,
+ }
+ }
+}
+
+/// All the DOM interfaces that can be transferred.
+#[derive(Clone, Copy, Debug, EnumIter)]
+pub enum Transferrable {
+ /// The `MessagePort` interface.
+ MessagePort,
+}
+
+impl StructuredSerializedData {
+ fn is_empty(&self, val: Transferrable) -> bool {
+ fn is_field_empty<K, V>(field: &Option<HashMap<K, V>>) -> bool {
+ field.as_ref().is_some_and(|h| h.is_empty())
+ }
+ match val {
+ Transferrable::MessagePort => is_field_empty(&self.ports),
+ }
+ }
+
+ /// Clone all values of the same type stored in this StructuredSerializedData
+ /// into another instance.
+ fn clone_all_of_type<T: BroadcastClone>(&self, cloned: &mut StructuredSerializedData) {
+ let existing = T::source(self);
+ let Some(existing) = existing else { return };
+ let mut clones = HashMap::with_capacity(existing.len());
+
+ for (original_id, obj) in existing.iter() {
+ if let Some(clone) = obj.clone_for_broadcast() {
+ clones.insert(*original_id, clone);
+ }
+ }
+
+ *T::destination(cloned) = Some(clones);
+ }
+
+ /// Clone the serialized data for use with broadcast-channels.
+ pub fn clone_for_broadcast(&self) -> StructuredSerializedData {
+ for transferrable in Transferrable::iter() {
+ if !self.is_empty(transferrable) {
+ // Not panicking only because this is called from the constellation.
+ warn!(
+ "Attempt to broadcast structured serialized data including {:?} (should never happen).",
+ transferrable,
+ );
+ }
+ }
+
+ let serialized = self.serialized.clone();
+
+ let mut cloned = StructuredSerializedData {
+ serialized,
+ ..Default::default()
+ };
+
+ for serializable in Serializable::iter() {
+ let clone_impl = serializable.clone_values();
+ clone_impl(self, &mut cloned);
+ }
+
+ cloned
+ }
+}
+
+/// A task on the <https://html.spec.whatwg.org/multipage/#port-message-queue>
+#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct PortMessageTask {
+ /// The origin of this task.
+ pub origin: ImmutableOrigin,
+ /// A data-holder for serialized data and transferred objects.
+ pub data: StructuredSerializedData,
+}
+
+/// Messages for communication between the constellation and a global managing ports.
+#[derive(Debug, Deserialize, Serialize)]
+pub enum MessagePortMsg {
+ /// Complete the transfer for a batch of ports.
+ CompleteTransfer(HashMap<MessagePortId, VecDeque<PortMessageTask>>),
+ /// Complete the transfer of a single port,
+ /// whose transfer was pending because it had been requested
+ /// while a previous failed transfer was being rolled-back.
+ CompletePendingTransfer(MessagePortId, VecDeque<PortMessageTask>),
+ /// Remove a port, the entangled one doesn't exists anymore.
+ RemoveMessagePort(MessagePortId),
+ /// Handle a new port-message-task.
+ NewTask(MessagePortId, PortMessageTask),
+}
+
+/// Message for communication between the constellation and a global managing broadcast channels.
+#[derive(Debug, Deserialize, Serialize)]
+pub struct BroadcastMsg {
+ /// The origin of this message.
+ pub origin: ImmutableOrigin,
+ /// The name of the channel.
+ pub channel_name: String,
+ /// A data-holder for serialized data.
+ pub data: StructuredSerializedData,
+}
+
+impl Clone for BroadcastMsg {
+ fn clone(&self) -> BroadcastMsg {
+ BroadcastMsg {
+ data: self.data.clone_for_broadcast(),
+ origin: self.origin.clone(),
+ channel_name: self.channel_name.clone(),
+ }
+ }
+}
+
+/// File-based blob
+#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct FileBlob {
+ #[ignore_malloc_size_of = "Uuid are hard(not really)"]
+ id: Uuid,
+ #[ignore_malloc_size_of = "PathBuf are hard"]
+ name: Option<PathBuf>,
+ cache: RefCell<Option<Vec<u8>>>,
+ size: u64,
+}
+
+impl FileBlob {
+ /// Create a new file blob.
+ pub fn new(id: Uuid, name: Option<PathBuf>, cache: Option<Vec<u8>>, size: u64) -> FileBlob {
+ FileBlob {
+ id,
+ name,
+ cache: RefCell::new(cache),
+ size,
+ }
+ }
+
+ /// Get the size of the file.
+ pub fn get_size(&self) -> u64 {
+ self.size
+ }
+
+ /// Get the cached file data, if any.
+ pub fn get_cache(&self) -> Option<Vec<u8>> {
+ self.cache.borrow().clone()
+ }
+
+ /// Cache data.
+ pub fn cache_bytes(&self, bytes: Vec<u8>) {
+ *self.cache.borrow_mut() = Some(bytes);
+ }
+
+ /// Get the file id.
+ pub fn get_id(&self) -> Uuid {
+ self.id
+ }
+}
+
+impl BroadcastClone for BlobImpl {
+ type Id = BlobId;
+
+ fn source(
+ data: &StructuredSerializedData,
+ ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
+ &data.blobs
+ }
+
+ fn destination(
+ data: &mut StructuredSerializedData,
+ ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
+ &mut data.blobs
+ }
+
+ fn clone_for_broadcast(&self) -> Option<Self> {
+ let type_string = self.type_string();
+
+ if let BlobData::Memory(bytes) = self.blob_data() {
+ let blob_clone = BlobImpl::new_from_bytes(bytes.clone(), type_string);
+
+ // Note: we insert the blob at the original id,
+ // otherwise this will not match the storage key as serialized by SM in `serialized`.
+ // The clone has it's own new Id however.
+ return Some(blob_clone);
+ } else {
+ // Not panicking only because this is called from the constellation.
+ log::warn!("Serialized blob not in memory format(should never happen).");
+ }
+ None
+ }
+}
+
+/// The data backing a DOM Blob.
+#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct BlobImpl {
+ /// UUID of the blob.
+ blob_id: BlobId,
+ /// Content-type string
+ type_string: String,
+ /// Blob data-type.
+ blob_data: BlobData,
+ /// Sliced blobs referring to this one.
+ slices: Vec<BlobId>,
+}
+
+/// Different backends of Blob
+#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+pub enum BlobData {
+ /// File-based blob, whose content lives in the net process
+ File(FileBlob),
+ /// Memory-based blob, whose content lives in the script process
+ Memory(Vec<u8>),
+ /// Sliced blob, including parent blob-id and
+ /// relative positions of current slicing range,
+ /// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
+ /// either File-based or Memory-based
+ Sliced(BlobId, RelativePos),
+}
+
+impl BlobImpl {
+ /// Construct memory-backed BlobImpl
+ pub fn new_from_bytes(bytes: Vec<u8>, type_string: String) -> BlobImpl {
+ let blob_id = BlobId::new();
+ let blob_data = BlobData::Memory(bytes);
+ BlobImpl {
+ blob_id,
+ type_string,
+ blob_data,
+ slices: vec![],
+ }
+ }
+
+ /// Construct file-backed BlobImpl from File ID
+ pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64, type_string: String) -> BlobImpl {
+ let blob_id = BlobId::new();
+ let blob_data = BlobData::File(FileBlob {
+ id: file_id,
+ name: Some(name),
+ cache: RefCell::new(None),
+ size,
+ });
+ BlobImpl {
+ blob_id,
+ type_string,
+ blob_data,
+ slices: vec![],
+ }
+ }
+
+ /// Construct a BlobImpl from a slice of a parent.
+ pub fn new_sliced(rel_pos: RelativePos, parent: BlobId, type_string: String) -> BlobImpl {
+ let blob_id = BlobId::new();
+ let blob_data = BlobData::Sliced(parent, rel_pos);
+ BlobImpl {
+ blob_id,
+ type_string,
+ blob_data,
+ slices: vec![],
+ }
+ }
+
+ /// Get a clone of the blob-id
+ pub fn blob_id(&self) -> BlobId {
+ self.blob_id
+ }
+
+ /// Get a clone of the type-string
+ pub fn type_string(&self) -> String {
+ self.type_string.clone()
+ }
+
+ /// Get a mutable ref to the data
+ pub fn blob_data(&self) -> &BlobData {
+ &self.blob_data
+ }
+
+ /// Get a mutable ref to the data
+ pub fn blob_data_mut(&mut self) -> &mut BlobData {
+ &mut self.blob_data
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+/// A serializable version of the DOMPoint/DOMPointReadOnly interface.
+pub struct DomPoint {
+ /// The x coordinate.
+ pub x: f64,
+ /// The y coordinate.
+ pub y: f64,
+ /// The z coordinate.
+ pub z: f64,
+ /// The w coordinate.
+ pub w: f64,
+}
+
+impl BroadcastClone for DomPoint {
+ type Id = DomPointId;
+
+ fn source(
+ data: &StructuredSerializedData,
+ ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
+ &data.points
+ }
+
+ fn destination(
+ data: &mut StructuredSerializedData,
+ ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
+ &mut data.points
+ }
+
+ fn clone_for_broadcast(&self) -> Option<Self> {
+ Some(self.clone())
+ }
+}
diff --git a/components/shared/embedder/lib.rs b/components/shared/embedder/lib.rs
index 67ccd9887ae..85dd4bf3af9 100644
--- a/components/shared/embedder/lib.rs
+++ b/components/shared/embedder/lib.rs
@@ -13,21 +13,23 @@ pub mod resources;
pub mod user_content_manager;
mod webdriver;
+use std::ffi::c_void;
use std::fmt::{Debug, Error, Formatter};
use std::path::PathBuf;
use std::sync::Arc;
-use base::id::{PipelineId, WebViewId};
+use base::id::{PipelineId, ScrollTreeNodeId, WebViewId};
use crossbeam_channel::Sender;
use euclid::{Scale, Size2D};
use http::{HeaderMap, Method, StatusCode};
use ipc_channel::ipc::IpcSender;
pub use keyboard_types::{KeyboardEvent, Modifiers};
use log::warn;
+use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use num_derive::FromPrimitive;
use pixels::Image;
-use serde::{Deserialize, Serialize};
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
use servo_url::ServoUrl;
use strum_macros::IntoStaticStr;
use style_traits::CSSPixel;
@@ -705,3 +707,85 @@ impl From<SelectElementOption> for SelectElementOptionOrOptgroup {
Self::Option(value)
}
}
+
+/// The address of a node. Layout sends these back. They must be validated via
+/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct UntrustedNodeAddress(pub *const c_void);
+
+malloc_size_of_is_0!(UntrustedNodeAddress);
+
+#[allow(unsafe_code)]
+unsafe impl Send for UntrustedNodeAddress {}
+
+impl From<style_traits::dom::OpaqueNode> for UntrustedNodeAddress {
+ fn from(o: style_traits::dom::OpaqueNode) -> Self {
+ UntrustedNodeAddress(o.0 as *const c_void)
+ }
+}
+
+impl Serialize for UntrustedNodeAddress {
+ fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+ (self.0 as usize).serialize(s)
+ }
+}
+
+impl<'de> Deserialize<'de> for UntrustedNodeAddress {
+ fn deserialize<D: Deserializer<'de>>(d: D) -> Result<UntrustedNodeAddress, D::Error> {
+ let value: usize = Deserialize::deserialize(d)?;
+ Ok(UntrustedNodeAddress::from_id(value))
+ }
+}
+
+impl UntrustedNodeAddress {
+ /// Creates an `UntrustedNodeAddress` from the given pointer address value.
+ #[inline]
+ pub fn from_id(id: usize) -> UntrustedNodeAddress {
+ UntrustedNodeAddress(id as *const c_void)
+ }
+}
+
+/// The result of a hit test in the compositor.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct CompositorHitTestResult {
+ /// The pipeline id of the resulting item.
+ pub pipeline_id: PipelineId,
+
+ /// The hit test point in the item's viewport.
+ pub point_in_viewport: euclid::default::Point2D<f32>,
+
+ /// The hit test point relative to the item itself.
+ pub point_relative_to_item: euclid::default::Point2D<f32>,
+
+ /// The node address of the hit test result.
+ pub node: UntrustedNodeAddress,
+
+ /// The cursor that should be used when hovering the item hit by the hit test.
+ pub cursor: Option<Cursor>,
+
+ /// The scroll tree node associated with this hit test item.
+ pub scroll_tree_node: ScrollTreeNodeId,
+}
+
+/// Whether the default action for a touch event was prevented by web content
+#[derive(Debug, Deserialize, Serialize)]
+pub enum TouchEventResult {
+ /// Allowed by web content
+ DefaultAllowed(TouchSequenceId, TouchEventType),
+ /// Prevented by web content
+ DefaultPrevented(TouchSequenceId, TouchEventType),
+}
+
+/// For a given pipeline, whether any animations are currently running
+/// and any animation callbacks are queued
+#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
+pub enum AnimationState {
+ /// Animations are active but no callbacks are queued
+ AnimationsPresent,
+ /// Animations are active and callbacks are queued
+ AnimationCallbacksPresent,
+ /// No animations are active and no callbacks are queued
+ NoAnimationsPresent,
+ /// No animations are active but callbacks are queued
+ NoAnimationCallbacksPresent,
+}
diff --git a/components/shared/script/Cargo.toml b/components/shared/script/Cargo.toml
index dda1371817f..49efbadc165 100644
--- a/components/shared/script/Cargo.toml
+++ b/components/shared/script/Cargo.toml
@@ -13,26 +13,21 @@ path = "lib.rs"
[features]
bluetooth = ["bluetooth_traits"]
-webgpu = ["wgpu-core"]
+webgpu = ["webgpu_traits"]
[dependencies]
background_hang_monitor_api = { workspace = true }
base = { workspace = true }
-bitflags = { workspace = true }
bluetooth_traits = { workspace = true, optional = true }
canvas_traits = { workspace = true }
constellation_traits = { workspace = true }
-cookie = { workspace = true }
crossbeam-channel = { workspace = true }
devtools_traits = { workspace = true }
embedder_traits = { workspace = true }
euclid = { workspace = true }
http = { workspace = true }
-hyper_serde = { workspace = true }
ipc-channel = { workspace = true }
keyboard-types = { workspace = true }
-libc = { workspace = true }
-log = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
media = { path = "../../media" }
@@ -45,10 +40,7 @@ strum = { workspace = true, features = ["derive"] }
strum_macros = { workspace = true }
stylo_atoms = { workspace = true }
stylo_traits = { workspace = true }
-uuid = { workspace = true }
-webdriver = { workspace = true }
-webgpu_traits = { workspace = true }
+webgpu_traits = { workspace = true, optional = true }
webrender_api = { workspace = true }
webrender_traits = { workspace = true }
webxr-api = { workspace = true, features = ["ipc"] }
-wgpu-core = { workspace = true, optional = true }
diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs
index 91e4ca33dc4..1a35f4f7486 100644
--- a/components/shared/script/lib.rs
+++ b/components/shared/script/lib.rs
@@ -9,48 +9,38 @@
#![deny(missing_docs)]
#![deny(unsafe_code)]
-mod script_msg;
-pub mod serializable;
-pub mod transferable;
-
-use std::collections::{HashMap, VecDeque};
use std::fmt;
use std::sync::Arc;
use background_hang_monitor_api::BackgroundHangMonitorRegister;
use base::cross_process_instant::CrossProcessInstant;
-use base::id::{
- BlobId, BrowsingContextId, DomPointId, HistoryStateId, MessagePortId, PipelineId,
- PipelineNamespaceId, WebViewId,
-};
+use base::id::{BrowsingContextId, HistoryStateId, PipelineId, PipelineNamespaceId, WebViewId};
#[cfg(feature = "bluetooth")]
use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLPipeline;
use constellation_traits::{
- AnimationTickType, CompositorHitTestResult, ScrollState, WindowSizeType,
+ AnimationTickType, LoadData, NavigationHistoryBehavior, ScriptToConstellationChan, ScrollState,
+ StructuredSerializedData, WindowSizeType,
};
use crossbeam_channel::{RecvTimeoutError, Sender};
-use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
-use embedder_traits::input_events::InputEvent;
+use devtools_traits::ScriptToDevtoolsControlMsg;
use embedder_traits::user_content_manager::UserContentManager;
-use embedder_traits::{MediaSessionActionType, Theme, ViewportDetails, WebDriverScriptCommand};
+use embedder_traits::{
+ CompositorHitTestResult, InputEvent, MediaSessionActionType, Theme, ViewportDetails,
+ WebDriverScriptCommand,
+};
use euclid::{Rect, Scale, Size2D, UnknownUnit};
-use http::{HeaderMap, Method};
-use ipc_channel::Error as IpcError;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use keyboard_types::Modifiers;
-use log::warn;
use malloc_size_of_derive::MallocSizeOf;
use media::WindowGLContext;
+use net_traits::ResourceThreads;
use net_traits::image_cache::ImageCache;
-use net_traits::request::{InsecureRequestsPolicy, Referrer, RequestBody};
use net_traits::storage_thread::StorageType;
-use net_traits::{ReferrerPolicy, ResourceThreads};
use pixels::PixelFormat;
-use profile_traits::{mem, time as profile_time};
+use profile_traits::mem;
use serde::{Deserialize, Serialize};
use servo_url::{ImmutableOrigin, ServoUrl};
-use strum::{EnumIter, IntoEnumIterator};
use strum_macros::IntoStaticStr;
use style_traits::{CSSPixel, SpeculativePainter};
use stylo_atoms::Atom;
@@ -60,111 +50,6 @@ use webrender_api::units::DevicePixel;
use webrender_api::{DocumentId, ImageKey};
use webrender_traits::CrossProcessCompositorApi;
-pub use crate::script_msg::{
- DOMMessage, IFrameSizeMsg, Job, JobError, JobResult, JobResultValue, JobType, SWManagerMsg,
- SWManagerSenders, ScopeThings, ScriptToConstellationMessage, ServiceWorkerMsg,
- TouchEventResult,
-};
-use crate::serializable::{BlobImpl, DomPoint};
-use crate::transferable::MessagePortImpl;
-
-/// The origin where a given load was initiated.
-/// Useful for origin checks, for example before evaluation a JS URL.
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum LoadOrigin {
- /// A load originating in the constellation.
- Constellation,
- /// A load originating in webdriver.
- WebDriver,
- /// A load originating in script.
- Script(ImmutableOrigin),
-}
-
-/// can be passed to `LoadUrl` to load a page with GET/POST
-/// parameters or headers
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct LoadData {
- /// The origin where the load started.
- pub load_origin: LoadOrigin,
- /// The URL.
- pub url: ServoUrl,
- /// The creator pipeline id if this is an about:blank load.
- pub creator_pipeline_id: Option<PipelineId>,
- /// The method.
- #[serde(
- deserialize_with = "::hyper_serde::deserialize",
- serialize_with = "::hyper_serde::serialize"
- )]
- pub method: Method,
- /// The headers.
- #[serde(
- deserialize_with = "::hyper_serde::deserialize",
- serialize_with = "::hyper_serde::serialize"
- )]
- pub headers: HeaderMap,
- /// The data that will be used as the body of the request.
- pub data: Option<RequestBody>,
- /// The result of evaluating a javascript scheme url.
- pub js_eval_result: Option<JsEvalResult>,
- /// The referrer.
- pub referrer: Referrer,
- /// The referrer policy.
- pub referrer_policy: ReferrerPolicy,
-
- /// The source to use instead of a network response for a srcdoc document.
- pub srcdoc: String,
- /// The inherited context is Secure, None if not inherited
- pub inherited_secure_context: Option<bool>,
- /// The inherited policy for upgrading insecure requests; None if not inherited.
- pub inherited_insecure_requests_policy: Option<InsecureRequestsPolicy>,
- /// Whether the page's ancestors have potentially trustworthy origin
- pub has_trustworthy_ancestor_origin: bool,
- /// Servo internal: if crash details are present, trigger a crash error page with these details.
- pub crash: Option<String>,
-}
-
-/// The result of evaluating a javascript scheme url.
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum JsEvalResult {
- /// The js evaluation had a non-string result, 204 status code.
- /// <https://html.spec.whatwg.org/multipage/#navigate> 12.11
- NoContent,
- /// The js evaluation had a string result.
- Ok(Vec<u8>),
-}
-
-impl LoadData {
- /// Create a new `LoadData` object.
- #[allow(clippy::too_many_arguments)]
- pub fn new(
- load_origin: LoadOrigin,
- url: ServoUrl,
- creator_pipeline_id: Option<PipelineId>,
- referrer: Referrer,
- referrer_policy: ReferrerPolicy,
- inherited_secure_context: Option<bool>,
- inherited_insecure_requests_policy: Option<InsecureRequestsPolicy>,
- has_trustworthy_ancestor_origin: bool,
- ) -> LoadData {
- LoadData {
- load_origin,
- url,
- creator_pipeline_id,
- method: Method::GET,
- headers: HeaderMap::new(),
- data: None,
- js_eval_result: None,
- referrer,
- referrer_policy,
- srcdoc: "".to_string(),
- inherited_secure_context,
- crash: None,
- inherited_insecure_requests_policy,
- has_trustworthy_ancestor_origin,
- }
- }
-}
-
/// The initial data required to create a new layout attached to an existing script thread.
#[derive(Debug, Deserialize, Serialize)]
pub struct NewLayoutInfo {
@@ -194,21 +79,6 @@ pub enum DiscardBrowsingContext {
No,
}
-/// <https://html.spec.whatwg.org/multipage/#navigation-supporting-concepts:navigationhistorybehavior>
-#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
-pub enum NavigationHistoryBehavior {
- /// The default value, which will be converted very early in the navigate algorithm into "push"
- /// or "replace". Usually it becomes "push", but under certain circumstances it becomes
- /// "replace" instead.
- #[default]
- Auto,
- /// A regular navigation which adds a new session history entry, and will clear the forward
- /// session history.
- Push,
- /// A navigation that will replace the active session history entry.
- Replace,
-}
-
/// Is a document fully active, active or inactive?
/// A document is active if it is the current active document in its session history,
/// it is fuly active if it is active and all of its ancestors are active,
@@ -385,20 +255,6 @@ pub enum DocumentState {
Pending,
}
-/// For a given pipeline, whether any animations are currently running
-/// and any animation callbacks are queued
-#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
-pub enum AnimationState {
- /// Animations are active but no callbacks are queued
- AnimationsPresent,
- /// Animations are active and callbacks are queued
- AnimationCallbacksPresent,
- /// No animations are active and no callbacks are queued
- NoAnimationsPresent,
- /// No animations are active but callbacks are queued
- NoAnimationCallbacksPresent,
-}
-
/// Input events from the embedder that are sent via the `Constellation`` to the `ScriptThread`.
#[derive(Debug, Deserialize, Serialize)]
pub struct ConstellationInputEvent {
@@ -472,117 +328,6 @@ pub struct InitialScriptState {
pub user_content_manager: UserContentManager,
}
-/// This trait allows creating a `ServiceWorkerManager` without depending on the `script`
-/// crate.
-pub trait ServiceWorkerManagerFactory {
- /// Create a `ServiceWorkerManager`.
- fn create(sw_senders: SWManagerSenders, origin: ImmutableOrigin);
-}
-
-/// Whether the sandbox attribute is present for an iframe element
-#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
-pub enum IFrameSandboxState {
- /// Sandbox attribute is present
- IFrameSandboxed,
- /// Sandbox attribute is not present
- IFrameUnsandboxed,
-}
-
-/// Specifies the information required to load an auxiliary browsing context.
-#[derive(Debug, Deserialize, Serialize)]
-pub struct AuxiliaryWebViewCreationRequest {
- /// Load data containing the url to load
- pub load_data: LoadData,
- /// The webview that caused this request.
- pub opener_webview_id: WebViewId,
- /// The pipeline opener browsing context.
- pub opener_pipeline_id: PipelineId,
- /// Sender for the constellation’s response to our request.
- pub response_sender: IpcSender<Option<AuxiliaryWebViewCreationResponse>>,
-}
-
-/// Constellation’s response to auxiliary browsing context creation requests.
-#[derive(Debug, Deserialize, Serialize)]
-pub struct AuxiliaryWebViewCreationResponse {
- /// The new webview ID.
- pub new_webview_id: WebViewId,
- /// The new pipeline ID.
- pub new_pipeline_id: PipelineId,
-}
-
-/// Specifies the information required to load an iframe.
-#[derive(Debug, Deserialize, Serialize)]
-pub struct IFrameLoadInfo {
- /// Pipeline ID of the parent of this iframe
- pub parent_pipeline_id: PipelineId,
- /// The ID for this iframe's nested browsing context.
- pub browsing_context_id: BrowsingContextId,
- /// The ID for the top-level ancestor browsing context of this iframe's nested browsing context.
- pub webview_id: WebViewId,
- /// The new pipeline ID that the iframe has generated.
- pub new_pipeline_id: PipelineId,
- /// Whether this iframe should be considered private
- pub is_private: bool,
- /// Whether this iframe should be considered secure
- pub inherited_secure_context: Option<bool>,
- /// Whether this load should replace the current entry (reload). If true, the current
- /// entry will be replaced instead of a new entry being added.
- pub history_handling: NavigationHistoryBehavior,
-}
-
-/// Specifies the information required to load a URL in an iframe.
-#[derive(Debug, Deserialize, Serialize)]
-pub struct IFrameLoadInfoWithData {
- /// The information required to load an iframe.
- pub info: IFrameLoadInfo,
- /// Load data containing the url to load
- pub load_data: LoadData,
- /// The old pipeline ID for this iframe, if a page was previously loaded.
- pub old_pipeline_id: Option<PipelineId>,
- /// Sandbox type of this iframe
- pub sandbox: IFrameSandboxState,
- /// The initial viewport size for this iframe.
- pub viewport_details: ViewportDetails,
-}
-
-/// Resources required by workerglobalscopes
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct WorkerGlobalScopeInit {
- /// Chan to a resource thread
- pub resource_threads: ResourceThreads,
- /// Chan to the memory profiler
- pub mem_profiler_chan: mem::ProfilerChan,
- /// Chan to the time profiler
- pub time_profiler_chan: profile_time::ProfilerChan,
- /// To devtools sender
- pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
- /// From devtools sender
- pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
- /// Messages to send to constellation
- pub script_to_constellation_chan: ScriptToConstellationChan,
- /// The worker id
- pub worker_id: WorkerId,
- /// The pipeline id
- pub pipeline_id: PipelineId,
- /// The origin
- pub origin: ImmutableOrigin,
- /// The creation URL
- pub creation_url: Option<ServoUrl>,
- /// True if secure context
- pub inherited_secure_context: Option<bool>,
-}
-
-/// Common entities representing a network load origin
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct WorkerScriptLoadOrigin {
- /// referrer url
- pub referrer_url: Option<ServoUrl>,
- /// the referrer policy which is used
- pub referrer_policy: ReferrerPolicy,
- /// the pipeline id of the entity requesting the load
- pub pipeline_id: PipelineId,
-}
-
/// Errors from executing a paint worklet
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum PaintWorkletError {
@@ -634,177 +379,3 @@ pub struct DrawAPaintImageResult {
/// Drawing the image might have requested loading some image URLs.
pub missing_image_urls: Vec<ServoUrl>,
}
-
-/// A Script to Constellation channel.
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct ScriptToConstellationChan {
- /// Sender for communicating with constellation thread.
- pub sender: IpcSender<(PipelineId, ScriptToConstellationMessage)>,
- /// Used to identify the origin of the message.
- pub pipeline_id: PipelineId,
-}
-
-impl ScriptToConstellationChan {
- /// Send ScriptMsg and attach the pipeline_id to the message.
- pub fn send(&self, msg: ScriptToConstellationMessage) -> Result<(), IpcError> {
- self.sender.send((self.pipeline_id, msg))
- }
-}
-
-/// A data-holder for serialized data and transferred objects.
-/// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
-#[derive(Debug, Default, Deserialize, MallocSizeOf, Serialize)]
-pub struct StructuredSerializedData {
- /// Data serialized by SpiderMonkey.
- pub serialized: Vec<u8>,
- /// Serialized in a structured callback,
- pub blobs: Option<HashMap<BlobId, BlobImpl>>,
- /// Serialized point objects.
- pub points: Option<HashMap<DomPointId, DomPoint>>,
- /// Transferred objects.
- pub ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
-}
-
-pub(crate) trait BroadcastClone
-where
- Self: Sized,
-{
- /// The ID type that uniquely identify each value.
- type Id: Eq + std::hash::Hash + Copy;
- /// Clone this value so that it can be reused with a broadcast channel.
- /// Only return None if cloning is impossible.
- fn clone_for_broadcast(&self) -> Option<Self>;
- /// The field from which to clone values.
- fn source(data: &StructuredSerializedData) -> &Option<HashMap<Self::Id, Self>>;
- /// The field into which to place cloned values.
- fn destination(data: &mut StructuredSerializedData) -> &mut Option<HashMap<Self::Id, Self>>;
-}
-
-/// All the DOM interfaces that can be serialized.
-#[derive(Clone, Copy, Debug, EnumIter)]
-pub enum Serializable {
- /// The `Blob` interface.
- Blob,
- /// The `DOMPoint` interface.
- DomPoint,
- /// The `DOMPointReadOnly` interface.
- DomPointReadOnly,
-}
-
-impl Serializable {
- fn clone_values(&self) -> fn(&StructuredSerializedData, &mut StructuredSerializedData) {
- match self {
- Serializable::Blob => StructuredSerializedData::clone_all_of_type::<BlobImpl>,
- Serializable::DomPointReadOnly => {
- StructuredSerializedData::clone_all_of_type::<DomPoint>
- },
- Serializable::DomPoint => StructuredSerializedData::clone_all_of_type::<DomPoint>,
- }
- }
-}
-
-/// All the DOM interfaces that can be transferred.
-#[derive(Clone, Copy, Debug, EnumIter)]
-pub enum Transferrable {
- /// The `MessagePort` interface.
- MessagePort,
-}
-
-impl StructuredSerializedData {
- fn is_empty(&self, val: Transferrable) -> bool {
- fn is_field_empty<K, V>(field: &Option<HashMap<K, V>>) -> bool {
- field.as_ref().is_some_and(|h| h.is_empty())
- }
- match val {
- Transferrable::MessagePort => is_field_empty(&self.ports),
- }
- }
-
- /// Clone all values of the same type stored in this StructuredSerializedData
- /// into another instance.
- fn clone_all_of_type<T: BroadcastClone>(&self, cloned: &mut StructuredSerializedData) {
- let existing = T::source(self);
- let Some(existing) = existing else { return };
- let mut clones = HashMap::with_capacity(existing.len());
-
- for (original_id, obj) in existing.iter() {
- if let Some(clone) = obj.clone_for_broadcast() {
- clones.insert(*original_id, clone);
- }
- }
-
- *T::destination(cloned) = Some(clones);
- }
-
- /// Clone the serialized data for use with broadcast-channels.
- pub fn clone_for_broadcast(&self) -> StructuredSerializedData {
- for transferrable in Transferrable::iter() {
- if !self.is_empty(transferrable) {
- // Not panicking only because this is called from the constellation.
- warn!(
- "Attempt to broadcast structured serialized data including {:?} (should never happen).",
- transferrable,
- );
- }
- }
-
- let serialized = self.serialized.clone();
-
- let mut cloned = StructuredSerializedData {
- serialized,
- ..Default::default()
- };
-
- for serializable in Serializable::iter() {
- let clone_impl = serializable.clone_values();
- clone_impl(self, &mut cloned);
- }
-
- cloned
- }
-}
-
-/// A task on the <https://html.spec.whatwg.org/multipage/#port-message-queue>
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct PortMessageTask {
- /// The origin of this task.
- pub origin: ImmutableOrigin,
- /// A data-holder for serialized data and transferred objects.
- pub data: StructuredSerializedData,
-}
-
-/// Messages for communication between the constellation and a global managing ports.
-#[derive(Debug, Deserialize, Serialize)]
-pub enum MessagePortMsg {
- /// Complete the transfer for a batch of ports.
- CompleteTransfer(HashMap<MessagePortId, VecDeque<PortMessageTask>>),
- /// Complete the transfer of a single port,
- /// whose transfer was pending because it had been requested
- /// while a previous failed transfer was being rolled-back.
- CompletePendingTransfer(MessagePortId, VecDeque<PortMessageTask>),
- /// Remove a port, the entangled one doesn't exists anymore.
- RemoveMessagePort(MessagePortId),
- /// Handle a new port-message-task.
- NewTask(MessagePortId, PortMessageTask),
-}
-
-/// Message for communication between the constellation and a global managing broadcast channels.
-#[derive(Debug, Deserialize, Serialize)]
-pub struct BroadcastMsg {
- /// The origin of this message.
- pub origin: ImmutableOrigin,
- /// The name of the channel.
- pub channel_name: String,
- /// A data-holder for serialized data.
- pub data: StructuredSerializedData,
-}
-
-impl Clone for BroadcastMsg {
- fn clone(&self) -> BroadcastMsg {
- BroadcastMsg {
- data: self.data.clone_for_broadcast(),
- origin: self.origin.clone(),
- channel_name: self.channel_name.clone(),
- }
- }
-}
diff --git a/components/shared/script/serializable.rs b/components/shared/script/serializable.rs
deleted file mode 100644
index 5d89c622bee..00000000000
--- a/components/shared/script/serializable.rs
+++ /dev/null
@@ -1,217 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! This module contains implementations in script that are serializable,
-//! as per <https://html.spec.whatwg.org/multipage/#serializable-objects>.
-//! The implementations are here instead of in script
-//! so that the other modules involved in the serialization don't have
-//! to depend on script.
-
-use std::cell::RefCell;
-use std::path::PathBuf;
-
-use base::id::{BlobId, DomPointId};
-use malloc_size_of_derive::MallocSizeOf;
-use net_traits::filemanager_thread::RelativePos;
-use serde::{Deserialize, Serialize};
-use uuid::Uuid;
-
-/// File-based blob
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct FileBlob {
- #[ignore_malloc_size_of = "Uuid are hard(not really)"]
- id: Uuid,
- #[ignore_malloc_size_of = "PathBuf are hard"]
- name: Option<PathBuf>,
- cache: RefCell<Option<Vec<u8>>>,
- size: u64,
-}
-
-impl FileBlob {
- /// Create a new file blob.
- pub fn new(id: Uuid, name: Option<PathBuf>, cache: Option<Vec<u8>>, size: u64) -> FileBlob {
- FileBlob {
- id,
- name,
- cache: RefCell::new(cache),
- size,
- }
- }
-
- /// Get the size of the file.
- pub fn get_size(&self) -> u64 {
- self.size
- }
-
- /// Get the cached file data, if any.
- pub fn get_cache(&self) -> Option<Vec<u8>> {
- self.cache.borrow().clone()
- }
-
- /// Cache data.
- pub fn cache_bytes(&self, bytes: Vec<u8>) {
- *self.cache.borrow_mut() = Some(bytes);
- }
-
- /// Get the file id.
- pub fn get_id(&self) -> Uuid {
- self.id
- }
-}
-
-impl crate::BroadcastClone for BlobImpl {
- type Id = BlobId;
-
- fn source(
- data: &crate::StructuredSerializedData,
- ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
- &data.blobs
- }
-
- fn destination(
- data: &mut crate::StructuredSerializedData,
- ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
- &mut data.blobs
- }
-
- fn clone_for_broadcast(&self) -> Option<Self> {
- let type_string = self.type_string();
-
- if let BlobData::Memory(bytes) = self.blob_data() {
- let blob_clone = BlobImpl::new_from_bytes(bytes.clone(), type_string);
-
- // Note: we insert the blob at the original id,
- // otherwise this will not match the storage key as serialized by SM in `serialized`.
- // The clone has it's own new Id however.
- return Some(blob_clone);
- } else {
- // Not panicking only because this is called from the constellation.
- log::warn!("Serialized blob not in memory format(should never happen).");
- }
- None
- }
-}
-
-/// The data backing a DOM Blob.
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct BlobImpl {
- /// UUID of the blob.
- blob_id: BlobId,
- /// Content-type string
- type_string: String,
- /// Blob data-type.
- blob_data: BlobData,
- /// Sliced blobs referring to this one.
- slices: Vec<BlobId>,
-}
-
-/// Different backends of Blob
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum BlobData {
- /// File-based blob, whose content lives in the net process
- File(FileBlob),
- /// Memory-based blob, whose content lives in the script process
- Memory(Vec<u8>),
- /// Sliced blob, including parent blob-id and
- /// relative positions of current slicing range,
- /// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
- /// either File-based or Memory-based
- Sliced(BlobId, RelativePos),
-}
-
-impl BlobImpl {
- /// Construct memory-backed BlobImpl
- pub fn new_from_bytes(bytes: Vec<u8>, type_string: String) -> BlobImpl {
- let blob_id = BlobId::new();
- let blob_data = BlobData::Memory(bytes);
- BlobImpl {
- blob_id,
- type_string,
- blob_data,
- slices: vec![],
- }
- }
-
- /// Construct file-backed BlobImpl from File ID
- pub fn new_from_file(file_id: Uuid, name: PathBuf, size: u64, type_string: String) -> BlobImpl {
- let blob_id = BlobId::new();
- let blob_data = BlobData::File(FileBlob {
- id: file_id,
- name: Some(name),
- cache: RefCell::new(None),
- size,
- });
- BlobImpl {
- blob_id,
- type_string,
- blob_data,
- slices: vec![],
- }
- }
-
- /// Construct a BlobImpl from a slice of a parent.
- pub fn new_sliced(rel_pos: RelativePos, parent: BlobId, type_string: String) -> BlobImpl {
- let blob_id = BlobId::new();
- let blob_data = BlobData::Sliced(parent, rel_pos);
- BlobImpl {
- blob_id,
- type_string,
- blob_data,
- slices: vec![],
- }
- }
-
- /// Get a clone of the blob-id
- pub fn blob_id(&self) -> BlobId {
- self.blob_id
- }
-
- /// Get a clone of the type-string
- pub fn type_string(&self) -> String {
- self.type_string.clone()
- }
-
- /// Get a mutable ref to the data
- pub fn blob_data(&self) -> &BlobData {
- &self.blob_data
- }
-
- /// Get a mutable ref to the data
- pub fn blob_data_mut(&mut self) -> &mut BlobData {
- &mut self.blob_data
- }
-}
-
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-/// A serializable version of the DOMPoint/DOMPointReadOnly interface.
-pub struct DomPoint {
- /// The x coordinate.
- pub x: f64,
- /// The y coordinate.
- pub y: f64,
- /// The z coordinate.
- pub z: f64,
- /// The w coordinate.
- pub w: f64,
-}
-
-impl crate::BroadcastClone for DomPoint {
- type Id = DomPointId;
-
- fn source(
- data: &crate::StructuredSerializedData,
- ) -> &Option<std::collections::HashMap<Self::Id, Self>> {
- &data.points
- }
-
- fn destination(
- data: &mut crate::StructuredSerializedData,
- ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> {
- &mut data.points
- }
-
- fn clone_for_broadcast(&self) -> Option<Self> {
- Some(self.clone())
- }
-}
diff --git a/components/shared/script/transferable.rs b/components/shared/script/transferable.rs
deleted file mode 100644
index 8344dd493b0..00000000000
--- a/components/shared/script/transferable.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! This module contains implementations in script that are transferable.
-//! The implementations are here instead of in script
-//! so that the other modules involved in the transfer don't have
-//! to depend on script.
-
-use std::collections::VecDeque;
-
-use base::id::MessagePortId;
-use malloc_size_of_derive::MallocSizeOf;
-use serde::{Deserialize, Serialize};
-
-use crate::PortMessageTask;
-
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-enum MessagePortState {
- /// <https://html.spec.whatwg.org/multipage/#detached>
- Detached,
- /// <https://html.spec.whatwg.org/multipage/#port-message-queue>
- /// The message-queue of this port is enabled,
- /// the boolean represents awaiting completion of a transfer.
- Enabled(bool),
- /// <https://html.spec.whatwg.org/multipage/#port-message-queue>
- /// The message-queue of this port is disabled,
- /// the boolean represents awaiting completion of a transfer.
- Disabled(bool),
-}
-
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-/// The data and logic backing the DOM managed MessagePort.
-pub struct MessagePortImpl {
- /// The current state of the port.
- state: MessagePortState,
-
- /// <https://html.spec.whatwg.org/multipage/#entangle>
- entangled_port: Option<MessagePortId>,
-
- /// <https://html.spec.whatwg.org/multipage/#port-message-queue>
- message_buffer: Option<VecDeque<PortMessageTask>>,
-
- /// The UUID of this port.
- message_port_id: MessagePortId,
-}
-
-impl MessagePortImpl {
- /// Create a new messageport impl.
- pub fn new(port_id: MessagePortId) -> MessagePortImpl {
- MessagePortImpl {
- state: MessagePortState::Disabled(false),
- entangled_port: None,
- message_buffer: None,
- message_port_id: port_id,
- }
- }
-
- /// Get the Id.
- pub fn message_port_id(&self) -> &MessagePortId {
- &self.message_port_id
- }
-
- /// Maybe get the Id of the entangled port.
- pub fn entangled_port_id(&self) -> Option<MessagePortId> {
- self.entangled_port
- }
-
- /// Entanged this port with another.
- pub fn entangle(&mut self, other_id: MessagePortId) {
- self.entangled_port = Some(other_id);
- }
-
- /// Is this port enabled?
- pub fn enabled(&self) -> bool {
- matches!(self.state, MessagePortState::Enabled(_))
- }
-
- /// Mark this port as having been shipped.
- /// <https://html.spec.whatwg.org/multipage/#has-been-shipped>
- pub fn set_has_been_shipped(&mut self) {
- match self.state {
- MessagePortState::Detached => {
- panic!("Messageport set_has_been_shipped called in detached state")
- },
- MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(true),
- MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(true),
- }
- }
-
- /// Handle the completion of the transfer,
- /// this is data received from the constellation.
- pub fn complete_transfer(&mut self, mut tasks: VecDeque<PortMessageTask>) {
- match self.state {
- MessagePortState::Detached => return,
- MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(false),
- MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(false),
- }
-
- // Note: these are the tasks that were buffered while the transfer was ongoing,
- // hence they need to execute first.
- // The global will call `start` if we are enabled,
- // which will add tasks on the event-loop to dispatch incoming messages.
- match self.message_buffer {
- Some(ref mut incoming_buffer) => {
- while let Some(task) = tasks.pop_back() {
- incoming_buffer.push_front(task);
- }
- },
- None => self.message_buffer = Some(tasks),
- }
- }
-
- /// A message was received from our entangled port,
- /// returns an optional task to be dispatched.
- pub fn handle_incoming(&mut self, task: PortMessageTask) -> Option<PortMessageTask> {
- let should_dispatch = match self.state {
- MessagePortState::Detached => return None,
- MessagePortState::Enabled(in_transfer) => !in_transfer,
- MessagePortState::Disabled(_) => false,
- };
-
- if should_dispatch {
- Some(task)
- } else {
- match self.message_buffer {
- Some(ref mut buffer) => {
- buffer.push_back(task);
- },
- None => {
- let mut queue = VecDeque::new();
- queue.push_back(task);
- self.message_buffer = Some(queue);
- },
- }
- None
- }
- }
-
- /// <https://html.spec.whatwg.org/multipage/#dom-messageport-start>
- /// returns an optional queue of tasks that were buffered while the port was disabled.
- pub fn start(&mut self) -> Option<VecDeque<PortMessageTask>> {
- match self.state {
- MessagePortState::Detached => return None,
- MessagePortState::Enabled(_) => {},
- MessagePortState::Disabled(in_transfer) => {
- self.state = MessagePortState::Enabled(in_transfer);
- },
- }
- if let MessagePortState::Enabled(true) = self.state {
- return None;
- }
- self.message_buffer.take()
- }
-
- /// <https://html.spec.whatwg.org/multipage/#dom-messageport-close>
- pub fn close(&mut self) {
- // Step 1
- self.state = MessagePortState::Detached;
- }
-}
diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs
index 66ddb3a55fa..6d686d75f03 100644
--- a/components/shared/script_layout/lib.rs
+++ b/components/shared/script_layout/lib.rs
@@ -18,8 +18,8 @@ use app_units::Au;
use atomic_refcell::AtomicRefCell;
use base::Epoch;
use base::id::{BrowsingContextId, PipelineId, WebViewId};
-use constellation_traits::{ScrollState, UntrustedNodeAddress};
-use embedder_traits::ViewportDetails;
+use constellation_traits::{LoadData, ScrollState};
+use embedder_traits::{UntrustedNodeAddress, ViewportDetails};
use euclid::default::{Point2D, Rect};
use fnv::FnvHashMap;
use fonts::{FontContext, SystemFontServiceProxy};
@@ -31,7 +31,7 @@ use net_traits::image_cache::{ImageCache, PendingImageId};
use pixels::Image;
use profile_traits::mem::Report;
use profile_traits::time;
-use script_traits::{InitialScriptState, LoadData, Painter, ScriptThreadMessage};
+use script_traits::{InitialScriptState, Painter, ScriptThreadMessage};
use serde::{Deserialize, Serialize};
use servo_arc::Arc as ServoArc;
use servo_url::{ImmutableOrigin, ServoUrl};
diff --git a/components/shared/webrender/Cargo.toml b/components/shared/webrender/Cargo.toml
index 6ecaa7cdee3..b437174307d 100644
--- a/components/shared/webrender/Cargo.toml
+++ b/components/shared/webrender/Cargo.toml
@@ -17,7 +17,6 @@ no-wgl = ["surfman/sm-angle-default"]
[dependencies]
base = { workspace = true }
-constellation_traits = { workspace = true }
dpi = { version = "0.1" }
embedder_traits = { workspace = true }
euclid = { workspace = true }
diff --git a/components/shared/webrender/lib.rs b/components/shared/webrender/lib.rs
index c91931f0954..3438aeb28ef 100644
--- a/components/shared/webrender/lib.rs
+++ b/components/shared/webrender/lib.rs
@@ -12,9 +12,8 @@ use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use base::id::WebViewId;
-use constellation_traits::CompositorHitTestResult;
use display_list::CompositorDisplayListInfo;
-use embedder_traits::ScreenGeometry;
+use embedder_traits::{CompositorHitTestResult, ScreenGeometry};
use euclid::default::Size2D as UntypedSize2D;
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use log::warn;