use std::fmt;
use content_security_policy::sandboxing_directive::SandboxingFlagSet;
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
use embedder_traits::user_contents::UserContentManagerId;
use embedder_traits::{
AnimationState, FocusSequenceNumber, JSValue, JavaScriptEvaluationError,
JavaScriptEvaluationId, MediaSessionEvent, ScriptToEmbedderChan, Theme, ViewportDetails,
WakeLockType,
};
use encoding_rs::Encoding;
use euclid::default::Size2D as UntypedSize2D;
use fonts_traits::SystemFontServiceProxySender;
use http::{HeaderMap, Method};
use ipc_channel::ipc::IpcSender;
use malloc_size_of_derive::MallocSizeOf;
use net_traits::policy_container::PolicyContainer;
use net_traits::request::{Destination, InsecureRequestsPolicy, Referrer, RequestBody};
use net_traits::{ReferrerPolicy, ResourceThreads};
use paint_api::CrossProcessPaintApi;
use profile_traits::mem::MemoryReportResult;
use profile_traits::{mem, time as profile_time};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use servo_base::Epoch;
use servo_base::generic_channel::{GenericCallback, GenericReceiver, GenericSender, SendResult};
use servo_base::id::{
BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId,
MessagePortRouterId, PipelineId, ScriptEventLoopId, ServiceWorkerId,
ServiceWorkerRegistrationId, WebViewId,
};
use servo_canvas_traits::canvas::{CanvasId, CanvasMsg};
use servo_canvas_traits::webgl::WebGLChan;
use servo_url::{ImmutableOrigin, OriginSnapshot, ServoUrl};
use storage_traits::StorageThreads;
use storage_traits::webstorage_thread::WebStorageType;
use strum::IntoStaticStr;
#[cfg(feature = "webgpu")]
use webgpu_traits::{WebGPU, WebGPUAdapterResponse};
use crate::structured_data::{BroadcastChannelMsg, StructuredSerializedData};
use crate::{
LogEntry, MessagePortMsg, PortMessageTask, PortTransferInfo, TraversalDirection, WindowSizeType,
};
pub type ScriptToConstellationSender =
GenericSender<(WebViewId, PipelineId, ScriptToConstellationMessage)>;
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct ScriptToConstellationChan {
pub sender: ScriptToConstellationSender,
pub webview_id: WebViewId,
pub pipeline_id: PipelineId,
}
impl ScriptToConstellationChan {
pub fn send(&self, msg: ScriptToConstellationMessage) -> SendResult {
self.sender.send((self.webview_id, self.pipeline_id, msg))
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum LoadOrigin {
Constellation,
WebDriver,
Script(OriginSnapshot),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LoadData {
pub load_origin: LoadOrigin,
pub url: ServoUrl,
pub about_base_url: Option<ServoUrl>,
pub creator_pipeline_id: Option<PipelineId>,
#[serde(
deserialize_with = "::hyper_serde::deserialize",
serialize_with = "::hyper_serde::serialize"
)]
pub method: Method,
#[serde(
deserialize_with = "::hyper_serde::deserialize",
serialize_with = "::hyper_serde::serialize"
)]
pub headers: HeaderMap,
pub data: Option<RequestBody>,
pub js_eval_result: Option<String>,
pub referrer: Referrer,
pub referrer_policy: ReferrerPolicy,
pub policy_container: Option<PolicyContainer>,
pub srcdoc: String,
pub inherited_secure_context: Option<bool>,
pub inherited_insecure_requests_policy: Option<InsecureRequestsPolicy>,
pub has_trustworthy_ancestor_origin: bool,
pub crash: Option<String>,
pub destination: Destination,
pub creation_sandboxing_flag_set: SandboxingFlagSet,
pub container_document_encoding: Option<&'static Encoding>,
}
impl LoadData {
#[expect(clippy::too_many_arguments)]
pub fn new(
load_origin: LoadOrigin,
url: ServoUrl,
about_base_url: Option<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,
creation_sandboxing_flag_set: SandboxingFlagSet,
) -> Self {
Self {
load_origin,
url,
about_base_url,
creator_pipeline_id,
method: Method::GET,
headers: HeaderMap::new(),
data: None,
js_eval_result: None,
referrer,
referrer_policy,
policy_container: None,
srcdoc: "".to_string(),
inherited_secure_context,
crash: None,
inherited_insecure_requests_policy,
has_trustworthy_ancestor_origin,
destination: Destination::Document,
creation_sandboxing_flag_set,
container_document_encoding: None,
}
}
pub fn new_for_new_unrelated_webview(url: ServoUrl) -> Self {
Self::new(
LoadOrigin::Constellation,
url,
None,
None,
Referrer::NoReferrer,
ReferrerPolicy::EmptyString,
None,
None,
false,
SandboxingFlagSet::empty(),
)
}
}
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
pub enum NavigationHistoryBehavior {
#[default]
Auto,
Push,
Replace,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ScopeThings {
pub script_url: ServoUrl,
pub worker_load_origin: WorkerScriptLoadOrigin,
pub init: WorkerGlobalScopeInit,
pub devtools_chan: Option<GenericCallback<ScriptToDevtoolsControlMsg>>,
pub worker_id: WorkerId,
pub browsing_context_id: BrowsingContextId,
pub webview_id: WebViewId,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct DOMMessage {
pub origin: ImmutableOrigin,
pub data: StructuredSerializedData,
}
#[derive(Deserialize, Serialize)]
pub struct SWManagerSenders {
pub swmanager_sender: GenericSender<SWManagerMsg>,
pub resource_threads: ResourceThreads,
pub paint_api: CrossProcessPaintApi,
pub system_font_service_sender: SystemFontServiceProxySender,
pub own_sender: GenericSender<ServiceWorkerMsg>,
pub receiver: GenericReceiver<ServiceWorkerMsg>,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum ServiceWorkerMsg {
Timeout(ServoUrl),
ForwardDOMMessage(DOMMessage, ServoUrl),
ScheduleJob(Job),
Exit,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub enum JobType {
Register,
Unregister,
Update,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum JobError {
TypeError,
SecurityError,
}
#[derive(Debug, Deserialize, Serialize)]
#[expect(clippy::large_enum_variant)]
pub enum JobResult {
RejectPromise(JobError),
ResolvePromise(Job, JobResultValue),
}
#[derive(Debug, Deserialize, Serialize)]
pub enum JobResultValue {
Registration {
id: ServiceWorkerRegistrationId,
installing_worker: Option<ServiceWorkerId>,
waiting_worker: Option<ServiceWorkerId>,
active_worker: Option<ServiceWorkerId>,
},
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Job {
pub job_type: JobType,
pub scope_url: ServoUrl,
pub script_url: ServoUrl,
pub client: GenericCallback<JobResult>,
pub referrer: ServoUrl,
pub scope_things: Option<ScopeThings>,
}
impl Job {
pub fn create_job(
job_type: JobType,
scope_url: ServoUrl,
script_url: ServoUrl,
client: GenericCallback<JobResult>,
referrer: ServoUrl,
scope_things: Option<ScopeThings>,
) -> Job {
Job {
job_type,
scope_url,
script_url,
client,
referrer,
scope_things,
}
}
}
impl PartialEq for Job {
fn eq(&self, other: &Self) -> bool {
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
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub enum SWManagerMsg {
PostMessageToClient,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum DocumentState {
Idle,
Pending,
}
pub trait ServiceWorkerManagerFactory {
fn create(sw_senders: SWManagerSenders, origin: ImmutableOrigin);
}
#[derive(Debug, Deserialize, Serialize)]
pub struct AuxiliaryWebViewCreationRequest {
pub load_data: LoadData,
pub opener_webview_id: WebViewId,
pub opener_pipeline_id: PipelineId,
pub response_sender: GenericSender<Option<AuxiliaryWebViewCreationResponse>>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct AuxiliaryWebViewCreationResponse {
pub new_webview_id: WebViewId,
pub new_pipeline_id: PipelineId,
pub user_content_manager_id: Option<UserContentManagerId>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct IFrameLoadInfo {
pub parent_pipeline_id: PipelineId,
pub browsing_context_id: BrowsingContextId,
pub webview_id: WebViewId,
pub new_pipeline_id: PipelineId,
pub is_private: bool,
pub inherited_secure_context: Option<bool>,
pub history_handling: NavigationHistoryBehavior,
pub target_snapshot_params: TargetSnapshotParams,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct IFrameLoadInfoWithData {
pub info: IFrameLoadInfo,
pub load_data: LoadData,
pub old_pipeline_id: Option<PipelineId>,
pub viewport_details: ViewportDetails,
pub theme: Theme,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct WorkerGlobalScopeInit {
pub resource_threads: ResourceThreads,
pub storage_threads: StorageThreads,
pub mem_profiler_chan: mem::ProfilerChan,
pub time_profiler_chan: profile_time::ProfilerChan,
pub to_devtools_sender: Option<GenericCallback<ScriptToDevtoolsControlMsg>>,
pub from_devtools_sender: Option<GenericSender<DevtoolScriptControlMsg>>,
pub script_to_constellation_chan: ScriptToConstellationChan,
pub script_to_embedder_chan: ScriptToEmbedderChan,
pub worker_id: WorkerId,
pub pipeline_id: PipelineId,
pub origin: ImmutableOrigin,
pub inherited_secure_context: Option<bool>,
pub unminify_js: bool,
pub webgl_chan: Option<WebGLChan>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct WorkerScriptLoadOrigin {
pub referrer_url: Option<ServoUrl>,
pub referrer_policy: ReferrerPolicy,
pub pipeline_id: PipelineId,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct IFrameSizeMsg {
pub browsing_context_id: BrowsingContextId,
pub size: ViewportDetails,
pub type_: WindowSizeType,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum KeyboardScroll {
Up,
Down,
Left,
Right,
PageUp,
PageDown,
Home,
End,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum ScreenshotReadinessResponse {
Ready(Epoch),
NoLongerActive,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum ConstellationInterest {
StorageEvent,
}
#[derive(Deserialize, IntoStaticStr, Serialize)]
pub enum ScriptToConstellationMessage {
CompleteMessagePortTransfer(MessagePortRouterId, Vec<MessagePortId>),
MessagePortTransferResult(
Option<MessagePortRouterId>,
Vec<MessagePortId>,
FxHashMap<MessagePortId, PortTransferInfo>,
),
NewMessagePort(MessagePortRouterId, MessagePortId),
NewMessagePortRouter(MessagePortRouterId, GenericCallback<MessagePortMsg>),
RemoveMessagePortRouter(MessagePortRouterId),
RerouteMessagePort(MessagePortId, PortMessageTask),
MessagePortShipped(MessagePortId),
EntanglePorts(MessagePortId, MessagePortId),
DisentanglePorts(MessagePortId, Option<MessagePortId>),
NewBroadcastChannelRouter(
BroadcastChannelRouterId,
IpcSender<BroadcastChannelMsg>,
ImmutableOrigin,
),
RemoveBroadcastChannelRouter(BroadcastChannelRouterId, ImmutableOrigin),
NewBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin),
RemoveBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin),
ScheduleBroadcast(BroadcastChannelRouterId, BroadcastChannelMsg),
RegisterInterest(ConstellationInterest),
UnregisterInterest(ConstellationInterest),
BroadcastStorageEvent(
WebStorageType,
ServoUrl,
Option<String>,
Option<String>,
Option<String>,
),
ChangeRunningAnimationsState(AnimationState),
CreateCanvasPaintThread(
UntypedSize2D<u64>,
GenericSender<Option<(GenericSender<CanvasMsg>, CanvasId)>>,
),
FocusAncestorBrowsingContextsForFocusingSteps(Option<BrowsingContextId>, FocusSequenceNumber),
FocusRemoteBrowsingContext(BrowsingContextId, RemoteFocusOperation),
GetTopForBrowsingContext(BrowsingContextId, GenericSender<Option<WebViewId>>),
GetBrowsingContextInfo(
PipelineId,
GenericSender<Option<(BrowsingContextId, Option<PipelineId>)>>,
),
GetChildBrowsingContextId(
BrowsingContextId,
usize,
GenericSender<Option<BrowsingContextId>>,
),
GetDocumentOrigin(PipelineId, GenericSender<Option<String>>),
LoadComplete,
LoadUrl(LoadData, NavigationHistoryBehavior, TargetSnapshotParams),
AbortLoadUrl,
PostMessage {
target: BrowsingContextId,
source: PipelineId,
target_origin: Option<ImmutableOrigin>,
source_origin: ImmutableOrigin,
data: StructuredSerializedData,
},
NavigatedToFragment(ServoUrl, NavigationHistoryBehavior),
TraverseHistory(TraversalDirection),
PushHistoryState(HistoryStateId, ServoUrl),
ReplaceHistoryState(HistoryStateId, ServoUrl),
JointSessionHistoryLength(GenericSender<u32>),
RemoveIFrame(BrowsingContextId, IpcSender<Vec<PipelineId>>),
SetThrottledComplete(bool),
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
ScriptNewIFrame(IFrameLoadInfoWithData),
CreateAuxiliaryWebView(AuxiliaryWebViewCreationRequest),
ActivateDocument,
SetDocumentState(DocumentState),
SetFinalUrl(ServoUrl),
LogEntry(Option<ScriptEventLoopId>, Option<String>, LogEntry),
DiscardDocument,
DiscardTopLevelBrowsingContext,
PipelineExited,
ForwardDOMMessage(DOMMessage, ServoUrl),
ScheduleJob(Job),
MediaSessionEvent(PipelineId, MediaSessionEvent),
#[cfg(feature = "webgpu")]
RequestAdapter(
GenericCallback<WebGPUAdapterResponse>,
wgpu_core::instance::RequestAdapterOptions,
wgpu_core::id::AdapterId,
),
#[cfg(feature = "webgpu")]
GetWebGPUChan(GenericSender<Option<WebGPU>>),
TitleChanged(PipelineId, String),
IFrameSizes(Vec<IFrameSizeMsg>),
ReportMemory(GenericCallback<MemoryReportResult>),
FinishJavaScriptEvaluation(
JavaScriptEvaluationId,
Result<JSValue, JavaScriptEvaluationError>,
),
ForwardKeyboardScroll(PipelineId, KeyboardScroll),
RespondToScreenshotReadinessRequest(ScreenshotReadinessResponse),
TriggerGarbageCollection,
AcquireWakeLock(WakeLockType),
ReleaseWakeLock(WakeLockType),
}
impl fmt::Debug for ScriptToConstellationMessage {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let variant_string: &'static str = self.into();
write!(formatter, "ScriptMsg::{variant_string}")
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct TargetSnapshotParams {
pub sandboxing_flags: SandboxingFlagSet,
pub iframe_element_referrer_policy: ReferrerPolicy,
}
impl Default for TargetSnapshotParams {
fn default() -> Self {
Self {
sandboxing_flags: SandboxingFlagSet::empty(),
iframe_element_referrer_policy: ReferrerPolicy::EmptyString,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum SequentialFocusDirection {
Forward,
Backward,
}
#[derive(Deserialize, Serialize)]
pub enum RemoteFocusOperation {
Viewport,
Sequential(SequentialFocusDirection, Option<BrowsingContextId>),
}