diff options
Diffstat (limited to 'components/shared/script/script_msg.rs')
-rw-r--r-- | components/shared/script/script_msg.rs | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/components/shared/script/script_msg.rs b/components/shared/script/script_msg.rs new file mode 100644 index 00000000000..42be2685ccf --- /dev/null +++ b/components/shared/script/script_msg.rs @@ -0,0 +1,493 @@ +/* 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/. */ + +use std::collections::{HashMap, VecDeque}; +use std::fmt; + +use canvas_traits::canvas::{CanvasId, CanvasMsg}; +use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; +use embedder_traits::{EmbedderMsg, MediaSessionEvent}; +use euclid::default::Size2D as UntypedSize2D; +use euclid::Size2D; +use gfx_traits::Epoch; +use ipc_channel::ipc::{IpcReceiver, IpcSender}; +use msg::constellation_msg::{ + BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId, + MessagePortRouterId, PipelineId, ServiceWorkerId, ServiceWorkerRegistrationId, + TopLevelBrowsingContextId, TraversalDirection, +}; +use net_traits::request::RequestBuilder; +use net_traits::storage_thread::StorageType; +use net_traits::CoreResourceMsg; +use serde::{Deserialize, Serialize}; +use servo_url::{ImmutableOrigin, ServoUrl}; +use smallvec::SmallVec; +use style_traits::CSSPixel; +use webgpu::{wgpu, WebGPU, WebGPUResponseResult}; +use webrender_api::units::{DeviceIntPoint, DeviceIntSize}; + +use crate::{ + AnimationState, AuxiliaryBrowsingContextLoadInfo, BroadcastMsg, DocumentState, + IFrameLoadInfoWithData, LayoutControlMsg, LoadData, MessagePortMsg, PortMessageTask, + StructuredSerializedData, WindowSizeType, WorkerGlobalScopeInit, WorkerScriptLoadOrigin, +}; + +/// An iframe sizing operation. +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub struct IFrameSizeMsg { + /// The child browsing context for this iframe. + pub browsing_context_id: BrowsingContextId, + /// The size of the iframe. + pub size: Size2D<f32, CSSPixel>, + /// The kind of sizing operation. + pub type_: WindowSizeType, +} + +/// Messages from the layout to the constellation. +#[derive(Deserialize, Serialize)] +pub enum LayoutMsg { + /// Inform the constellation of the size of the iframe's viewport. + IFrameSizes(Vec<IFrameSizeMsg>), + /// Requests that the constellation inform the compositor that it needs to record + /// the time when the frame with the given ID (epoch) is painted. + PendingPaintMetric(PipelineId, Epoch), +} + +impl fmt::Debug for LayoutMsg { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + use self::LayoutMsg::*; + let variant = match *self { + IFrameSizes(..) => "IFrameSizes", + PendingPaintMetric(..) => "PendingPaintMetric", + }; + write!(formatter, "LayoutMsg::{}", variant) + } +} + +/// Whether a DOM event was prevented by web content +#[derive(Debug, Deserialize, Serialize)] +pub enum EventResult { + /// Allowed by web content + DefaultAllowed, + /// Prevented by web content + DefaultPrevented, +} + +/// A log entry reported to the constellation +/// We don't report all log entries, just serious ones. +/// We need a separate type for this because `LogLevel` isn't serializable. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum LogEntry { + /// Panic, with a reason and backtrace + Panic(String, String), + /// Error, with a reason + Error(String), + /// warning, with a reason + Warn(String), +} + +/// https://html.spec.whatwg.org/multipage/#replacement-enabled +#[derive(Debug, Deserialize, Serialize)] +pub enum HistoryEntryReplacement { + /// Traverse the history with replacement enabled. + Enabled, + /// Traverse the history with replacement disabled. + Disabled, +} + +/// Messages from the script to the constellation. +#[derive(Deserialize, Serialize)] +pub enum ScriptMsg { + /// Request to complete the transfer of a set of ports to a router. + CompleteMessagePortTransfer(MessagePortRouterId, Vec<MessagePortId>), + /// The results of attempting to complete the transfer of a batch of ports. + MessagePortTransferResult( + /* The router whose transfer of ports succeeded, if any */ + Option<MessagePortRouterId>, + /* The ids of ports transferred successfully */ + Vec<MessagePortId>, + /* The ids, and buffers, of ports whose transfer failed */ + HashMap<MessagePortId, VecDeque<PortMessageTask>>, + ), + /// A new message-port was created or transferred, with corresponding control-sender. + NewMessagePort(MessagePortRouterId, MessagePortId), + /// A global has started managing message-ports + NewMessagePortRouter(MessagePortRouterId, IpcSender<MessagePortMsg>), + /// A global has stopped managing message-ports + RemoveMessagePortRouter(MessagePortRouterId), + /// A task requires re-routing to an already shipped message-port. + RerouteMessagePort(MessagePortId, PortMessageTask), + /// A message-port was shipped, let the entangled port know. + MessagePortShipped(MessagePortId), + /// A message-port has been discarded by script. + RemoveMessagePort(MessagePortId), + /// Entangle two message-ports. + EntanglePorts(MessagePortId, MessagePortId), + /// A global has started managing broadcast-channels. + NewBroadcastChannelRouter( + BroadcastChannelRouterId, + IpcSender<BroadcastMsg>, + ImmutableOrigin, + ), + /// A global has stopped managing broadcast-channels. + RemoveBroadcastChannelRouter(BroadcastChannelRouterId, ImmutableOrigin), + /// A global started managing broadcast channels for a given channel-name. + NewBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin), + /// A global stopped managing broadcast channels for a given channel-name. + RemoveBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin), + /// Broadcast a message to all same-origin broadcast channels, + /// excluding the source of the broadcast. + ScheduleBroadcast(BroadcastChannelRouterId, BroadcastMsg), + /// Forward a message to the embedder. + ForwardToEmbedder(EmbedderMsg), + /// Requests are sent to constellation and fetches are checked manually + /// for cross-origin loads + InitiateNavigateRequest(RequestBuilder, /* cancellation_chan */ IpcReceiver<()>), + /// Broadcast a storage event to every same-origin pipeline. + /// The strings are key, old value and new value. + BroadcastStorageEvent( + StorageType, + ServoUrl, + Option<String>, + Option<String>, + Option<String>, + ), + /// Indicates whether this pipeline is currently running animations. + ChangeRunningAnimationsState(AnimationState), + /// Requests that a new 2D canvas thread be created. (This is done in the constellation because + /// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.) + CreateCanvasPaintThread( + UntypedSize2D<u64>, + IpcSender<(IpcSender<CanvasMsg>, CanvasId)>, + ), + /// Notifies the constellation that this frame has received focus. + Focus, + /// Get the top-level browsing context info for a given browsing context. + GetTopForBrowsingContext( + BrowsingContextId, + IpcSender<Option<TopLevelBrowsingContextId>>, + ), + /// Get the browsing context id of the browsing context in which pipeline is + /// embedded and the parent pipeline id of that browsing context. + GetBrowsingContextInfo( + PipelineId, + IpcSender<Option<(BrowsingContextId, Option<PipelineId>)>>, + ), + /// Get the nth child browsing context ID for a given browsing context, sorted in tree order. + GetChildBrowsingContextId( + BrowsingContextId, + usize, + IpcSender<Option<BrowsingContextId>>, + ), + /// All pending loads are complete, and the `load` event for this pipeline + /// has been dispatched. + LoadComplete, + /// A new load has been requested, with an option to replace the current entry once loaded + /// instead of adding a new entry. + LoadUrl(LoadData, HistoryEntryReplacement), + /// Abort loading after sending a LoadUrl message. + AbortLoadUrl, + /// Post a message to the currently active window of a given browsing context. + PostMessage { + /// The target of the posted message. + target: BrowsingContextId, + /// The source of the posted message. + source: PipelineId, + /// The expected origin of the target. + target_origin: Option<ImmutableOrigin>, + /// The source origin of the message. + /// https://html.spec.whatwg.org/multipage/#dom-messageevent-origin + source_origin: ImmutableOrigin, + /// The data to be posted. + data: StructuredSerializedData, + }, + /// Inform the constellation that a fragment was navigated to and whether or not it was a replacement navigation. + NavigatedToFragment(ServoUrl, HistoryEntryReplacement), + /// HTMLIFrameElement Forward or Back traversal. + TraverseHistory(TraversalDirection), + /// Inform the constellation of a pushed history state. + PushHistoryState(HistoryStateId, ServoUrl), + /// Inform the constellation of a replaced history state. + ReplaceHistoryState(HistoryStateId, ServoUrl), + /// Gets the length of the joint session history from the constellation. + JointSessionHistoryLength(IpcSender<u32>), + /// Notification that this iframe should be removed. + /// Returns a list of pipelines which were closed. + RemoveIFrame(BrowsingContextId, IpcSender<Vec<PipelineId>>), + /// Notifies constellation that an iframe's visibility has been changed. + VisibilityChangeComplete(bool), + /// A load has been requested in an IFrame. + ScriptLoadedURLInIFrame(IFrameLoadInfoWithData), + /// A load of the initial `about:blank` has been completed in an IFrame. + ScriptNewIFrame(IFrameLoadInfoWithData, IpcSender<LayoutControlMsg>), + /// Script has opened a new auxiliary browsing context. + ScriptNewAuxiliary( + AuxiliaryBrowsingContextLoadInfo, + IpcSender<LayoutControlMsg>, + ), + /// Mark a new document as active + ActivateDocument, + /// Set the document state for a pipeline (used by screenshot / reftests) + SetDocumentState(DocumentState), + /// Update the pipeline Url, which can change after redirections. + SetFinalUrl(ServoUrl), + /// Script has handled a touch event, and either prevented or allowed default actions. + TouchEventProcessed(EventResult), + /// A log entry, with the top-level browsing context id and thread name + LogEntry(Option<String>, LogEntry), + /// Discard the document. + DiscardDocument, + /// Discard the browsing context. + DiscardTopLevelBrowsingContext, + /// Notifies the constellation that this pipeline has exited. + PipelineExited, + /// Send messages from postMessage calls from serviceworker + /// to constellation for storing in service worker manager + ForwardDOMMessage(DOMMessage, ServoUrl), + /// https://w3c.github.io/ServiceWorker/#schedule-job-algorithm. + ScheduleJob(Job), + /// Get Window Informations size and position + GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>), + /// Get the screen size (pixel) + GetScreenSize(IpcSender<DeviceIntSize>), + /// Get the available screen size (pixel) + GetScreenAvailSize(IpcSender<DeviceIntSize>), + /// Notifies the constellation about media session events + /// (i.e. when there is metadata for the active media session, playback state changes...). + MediaSessionEvent(PipelineId, MediaSessionEvent), + /// Create a WebGPU Adapter instance + RequestAdapter( + IpcSender<WebGPUResponseResult>, + wgpu::instance::RequestAdapterOptions, + SmallVec<[wgpu::id::AdapterId; 4]>, + ), + /// Get WebGPU channel + GetWebGPUChan(IpcSender<WebGPU>), + /// Notify the constellation of a pipeline's document's title. + TitleChanged(PipelineId, String), +} + +impl fmt::Debug for ScriptMsg { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + use self::ScriptMsg::*; + let variant = match *self { + CompleteMessagePortTransfer(..) => "CompleteMessagePortTransfer", + MessagePortTransferResult(..) => "MessagePortTransferResult", + NewMessagePortRouter(..) => "NewMessagePortRouter", + RemoveMessagePortRouter(..) => "RemoveMessagePortRouter", + NewMessagePort(..) => "NewMessagePort", + RerouteMessagePort(..) => "RerouteMessagePort", + RemoveMessagePort(..) => "RemoveMessagePort", + MessagePortShipped(..) => "MessagePortShipped", + EntanglePorts(..) => "EntanglePorts", + NewBroadcastChannelRouter(..) => "NewBroadcastChannelRouter", + RemoveBroadcastChannelRouter(..) => "RemoveBroadcastChannelRouter", + RemoveBroadcastChannelNameInRouter(..) => "RemoveBroadcastChannelNameInRouter", + NewBroadcastChannelNameInRouter(..) => "NewBroadcastChannelNameInRouter", + ScheduleBroadcast(..) => "ScheduleBroadcast", + ForwardToEmbedder(..) => "ForwardToEmbedder", + InitiateNavigateRequest(..) => "InitiateNavigateRequest", + BroadcastStorageEvent(..) => "BroadcastStorageEvent", + ChangeRunningAnimationsState(..) => "ChangeRunningAnimationsState", + CreateCanvasPaintThread(..) => "CreateCanvasPaintThread", + Focus => "Focus", + GetBrowsingContextInfo(..) => "GetBrowsingContextInfo", + GetTopForBrowsingContext(..) => "GetParentBrowsingContext", + GetChildBrowsingContextId(..) => "GetChildBrowsingContextId", + LoadComplete => "LoadComplete", + LoadUrl(..) => "LoadUrl", + AbortLoadUrl => "AbortLoadUrl", + PostMessage { .. } => "PostMessage", + NavigatedToFragment(..) => "NavigatedToFragment", + TraverseHistory(..) => "TraverseHistory", + PushHistoryState(..) => "PushHistoryState", + ReplaceHistoryState(..) => "ReplaceHistoryState", + JointSessionHistoryLength(..) => "JointSessionHistoryLength", + RemoveIFrame(..) => "RemoveIFrame", + VisibilityChangeComplete(..) => "VisibilityChangeComplete", + ScriptLoadedURLInIFrame(..) => "ScriptLoadedURLInIFrame", + ScriptNewIFrame(..) => "ScriptNewIFrame", + ScriptNewAuxiliary(..) => "ScriptNewAuxiliary", + ActivateDocument => "ActivateDocument", + SetDocumentState(..) => "SetDocumentState", + SetFinalUrl(..) => "SetFinalUrl", + TouchEventProcessed(..) => "TouchEventProcessed", + LogEntry(..) => "LogEntry", + DiscardDocument => "DiscardDocument", + DiscardTopLevelBrowsingContext => "DiscardTopLevelBrowsingContext", + PipelineExited => "PipelineExited", + ForwardDOMMessage(..) => "ForwardDOMMessage", + ScheduleJob(..) => "ScheduleJob", + GetClientWindow(..) => "GetClientWindow", + GetScreenSize(..) => "GetScreenSize", + GetScreenAvailSize(..) => "GetScreenAvailSize", + MediaSessionEvent(..) => "MediaSessionEvent", + RequestAdapter(..) => "RequestAdapter", + GetWebGPUChan(..) => "GetWebGPUChan", + TitleChanged(..) => "TitleChanged", + }; + write!(formatter, "ScriptMsg::{}", variant) + } +} + +/// 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)] +/// 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, +} |