mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
continue messageport, transferable, postmessage options
This commit is contained in:
parent
c3b17c1201
commit
2f8932a6a1
100 changed files with 2456 additions and 1171 deletions
|
@ -17,8 +17,10 @@ extern crate malloc_size_of_derive;
|
|||
extern crate serde;
|
||||
|
||||
mod script_msg;
|
||||
pub mod transferable;
|
||||
pub mod webdriver_msg;
|
||||
|
||||
use crate::transferable::MessagePortImpl;
|
||||
use crate::webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas_traits::webgl::WebGLPipeline;
|
||||
|
@ -36,7 +38,7 @@ use keyboard_types::{CompositionEvent, KeyboardEvent};
|
|||
use libc::c_void;
|
||||
use media::WindowGLContext;
|
||||
use msg::constellation_msg::BackgroundHangMonitorRegister;
|
||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId};
|
||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, MessagePortId, PipelineId};
|
||||
use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache::ImageCache;
|
||||
|
@ -51,7 +53,7 @@ use servo_atoms::Atom;
|
|||
use servo_url::ImmutableOrigin;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
@ -324,8 +326,11 @@ pub enum ConstellationControlMsg {
|
|||
source_browsing_context: TopLevelBrowsingContextId,
|
||||
/// 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: Vec<u8>,
|
||||
data: StructuredSerializedData,
|
||||
},
|
||||
/// Updates the current pipeline ID of a given iframe.
|
||||
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
||||
|
@ -1013,3 +1018,33 @@ impl ScriptToConstellationChan {
|
|||
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, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct StructuredSerializedData {
|
||||
/// Data serialized by SpiderMonkey.
|
||||
pub serialized: Vec<u8>,
|
||||
/// Transferred objects.
|
||||
pub ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
/// Enables a port to catch-up on messages that were sent while the transfer was ongoing.
|
||||
CompleteTransfer(MessagePortId, VecDeque<PortMessageTask>),
|
||||
/// Remove a port, the entangled one doesn't exists anymore.
|
||||
RemoveMessagePort(MessagePortId),
|
||||
/// Handle a new port-message-task.
|
||||
NewTask(MessagePortId, PortMessageTask),
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ use crate::DocumentState;
|
|||
use crate::IFrameLoadInfoWithData;
|
||||
use crate::LayoutControlMsg;
|
||||
use crate::LoadData;
|
||||
use crate::MessagePortMsg;
|
||||
use crate::PortMessageTask;
|
||||
use crate::StructuredSerializedData;
|
||||
use crate::WindowSizeType;
|
||||
use crate::WorkerGlobalScopeInit;
|
||||
use crate::WorkerScriptLoadOrigin;
|
||||
|
@ -18,7 +21,9 @@ use euclid::default::Size2D as UntypedSize2D;
|
|||
use euclid::Size2D;
|
||||
use gfx_traits::Epoch;
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
|
||||
use msg::constellation_msg::{
|
||||
BrowsingContextId, MessagePortId, MessagePortRouterId, PipelineId, TopLevelBrowsingContextId,
|
||||
};
|
||||
use msg::constellation_msg::{HistoryStateId, TraversalDirection};
|
||||
use net_traits::request::RequestBuilder;
|
||||
use net_traits::storage_thread::StorageType;
|
||||
|
@ -109,6 +114,20 @@ pub enum HistoryEntryReplacement {
|
|||
/// Messages from the script to the constellation.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum ScriptMsg {
|
||||
/// 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),
|
||||
/// Forward a message to the embedder.
|
||||
ForwardToEmbedder(EmbedderMsg),
|
||||
/// Requests are sent to constellation and fetches are checked manually
|
||||
|
@ -166,8 +185,11 @@ pub enum ScriptMsg {
|
|||
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: Vec<u8>,
|
||||
data: StructuredSerializedData,
|
||||
},
|
||||
/// Inform the constellation that a fragment was navigated to and whether or not it was a replacement navigation.
|
||||
NavigatedToFragment(ServoUrl, HistoryEntryReplacement),
|
||||
|
@ -226,6 +248,13 @@ impl fmt::Debug for ScriptMsg {
|
|||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::ScriptMsg::*;
|
||||
let variant = match *self {
|
||||
NewMessagePortRouter(..) => "NewMessagePortRouter",
|
||||
RemoveMessagePortRouter(..) => "RemoveMessagePortRouter",
|
||||
NewMessagePort(..) => "NewMessagePort",
|
||||
RerouteMessagePort(..) => "RerouteMessagePort",
|
||||
RemoveMessagePort(..) => "RemoveMessagePort",
|
||||
MessagePortShipped(..) => "MessagePortShipped",
|
||||
EntanglePorts(..) => "EntanglePorts",
|
||||
ForwardToEmbedder(..) => "ForwardToEmbedder",
|
||||
InitiateNavigateRequest(..) => "InitiateNavigateRequest",
|
||||
BroadcastStorageEvent(..) => "BroadcastStorageEvent",
|
||||
|
@ -283,12 +312,12 @@ pub struct ScopeThings {
|
|||
}
|
||||
|
||||
/// Message that gets passed to service worker scope on postMessage
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DOMMessage {
|
||||
/// The origin of the message
|
||||
pub origin: String,
|
||||
pub origin: ImmutableOrigin,
|
||||
/// The payload of the message
|
||||
pub data: Vec<u8>,
|
||||
pub data: StructuredSerializedData,
|
||||
}
|
||||
|
||||
/// Channels to allow service worker manager to communicate with constellation and resource thread
|
||||
|
|
160
components/script_traits/transferable.rs
Normal file
160
components/script_traits/transferable.rs
Normal file
|
@ -0,0 +1,160 @@
|
|||
/* 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 crate::PortMessageTask;
|
||||
use msg::constellation_msg::MessagePortId;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[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.clone()
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
match self.state {
|
||||
MessagePortState::Enabled(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue