Auto merge of #17425 - paulrouget:attach-pipeline-2, r=asajeffrey

cleanup embedder/compositor/constellation/script messages

Fix: #17226 #17200 #17201

This is work in progress. Some tests still fail.
I'd like to get early feedback as it's a pretty large PR.

There is nothing fundamentally new. Basically, I added TopLevelBrowsingContrextId to the relevant messages between the embedder, the compositor and the constellation, and enforced the PipelineId to be attached to each ScriptMsg (see #17201).

I unaliased all the ScriptMsg. It was getting difficult to understand the nature of the message as ScriptMsg was used aliased CompositorMsg sometimes (CompositorMsg is an actually type of message already). I renamed constellation_chan to script_to_constellation_chan, again, for clarification.

This cleanup code is necessary for #15934 and for tabs support.

/cc @asajeffrey can I ask you to look at this? No need for a formal review, I need feedback at this stage.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17425)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-08-15 02:20:10 -05:00 committed by GitHub
commit 74558990b2
33 changed files with 625 additions and 517 deletions

View file

@ -11,19 +11,17 @@ use gfx_traits::Epoch;
use gleam::gl; use gleam::gl;
use image::{DynamicImage, ImageFormat, RgbImage}; use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcSharedMemory}; use ipc_channel::ipc::{self, IpcSharedMemory};
use msg::constellation_msg::{Key, KeyModifiers, KeyState}; use msg::constellation_msg::{KeyState, PipelineId, PipelineIndex, PipelineNamespaceId};
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId, TraversalDirection};
use net_traits::image::base::{Image, PixelFormat}; use net_traits::image::base::{Image, PixelFormat};
use profile_traits::time::{self, ProfilerCategory, profile}; use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg}; use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
use script_traits::{ConstellationMsg, LayoutControlMsg, LoadData, MouseButton}; use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton};
use script_traits::{MouseEventType, ScrollState}; use script_traits::{MouseEventType, ScrollState};
use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId, WindowSizeData, WindowSizeType}; use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{self, MouseMoveEvent, MouseButtonEvent, TouchEvent, TouchpadPressureEvent}; use script_traits::CompositorEvent::{self, MouseMoveEvent, MouseButtonEvent, TouchEvent, TouchpadPressureEvent};
use servo_config::opts; use servo_config::opts;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_geometry::DeviceIndependentPixel; use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::rc::Rc; use std::rc::Rc;
@ -460,8 +458,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.change_running_animations_state(pipeline_id, animation_state); self.change_running_animations_state(pipeline_id, animation_state);
} }
(Msg::ChangePageTitle(pipeline_id, title), ShutdownState::NotShuttingDown) => { (Msg::ChangePageTitle(top_level_browsing_context, title), ShutdownState::NotShuttingDown) => {
self.change_page_title(pipeline_id, title); self.window.set_page_title(top_level_browsing_context, title);
} }
(Msg::SetFrameTree(frame_tree), (Msg::SetFrameTree(frame_tree),
@ -475,55 +473,56 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.scroll_fragment_to_point(scroll_root_id, point); self.scroll_fragment_to_point(scroll_root_id, point);
} }
(Msg::MoveTo(point), (Msg::MoveTo(top_level_browsing_context_id, point),
ShutdownState::NotShuttingDown) => { ShutdownState::NotShuttingDown) => {
self.window.set_position(point); self.window.set_position(top_level_browsing_context_id, point);
} }
(Msg::ResizeTo(size), (Msg::ResizeTo(top_level_browsing_context_id, size),
ShutdownState::NotShuttingDown) => { ShutdownState::NotShuttingDown) => {
self.window.set_inner_size(size); self.window.set_inner_size(top_level_browsing_context_id, size);
} }
(Msg::GetClientWindow(send), (Msg::GetClientWindow(top_level_browsing_context_id, send),
ShutdownState::NotShuttingDown) => { ShutdownState::NotShuttingDown) => {
let rect = self.window.client_window(); let rect = self.window.client_window(top_level_browsing_context_id);
if let Err(e) = send.send(rect) { if let Err(e) = send.send(rect) {
warn!("Sending response to get client window failed ({}).", e); warn!("Sending response to get client window failed ({}).", e);
} }
} }
(Msg::Status(message), ShutdownState::NotShuttingDown) => { (Msg::Status(top_level_browsing_context_id, message),
self.window.status(message); ShutdownState::NotShuttingDown) => {
self.window.status(top_level_browsing_context_id, message);
} }
(Msg::LoadStart, ShutdownState::NotShuttingDown) => { (Msg::LoadStart(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => {
self.window.load_start(); self.window.load_start(top_level_browsing_context_id);
} }
(Msg::LoadComplete, ShutdownState::NotShuttingDown) => { (Msg::LoadComplete(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => {
// If we're painting in headless mode, schedule a recomposite. // If we're painting in headless mode, schedule a recomposite.
if opts::get().output_file.is_some() || opts::get().exit_after_load { if opts::get().output_file.is_some() || opts::get().exit_after_load {
self.composite_if_necessary(CompositingReason::Headless); self.composite_if_necessary(CompositingReason::Headless);
} }
// Inform the embedder that the load has finished. // Inform the embedder that the load has finished.
// self.window.load_end(top_level_browsing_context_id);
// TODO(pcwalton): Specify which frame's load completed.
self.window.load_end();
} }
(Msg::AllowNavigation(url, response_chan), ShutdownState::NotShuttingDown) => { (Msg::AllowNavigation(top_level_browsing_context_id, url, response_chan),
self.window.allow_navigation(url, response_chan); ShutdownState::NotShuttingDown) => {
self.window.allow_navigation(top_level_browsing_context_id, url, response_chan);
} }
(Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => { (Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => {
self.composition_request = CompositionRequest::CompositeNow(reason) self.composition_request = CompositionRequest::CompositeNow(reason)
} }
(Msg::KeyEvent(ch, key, state, modified), ShutdownState::NotShuttingDown) => { (Msg::KeyEvent(top_level_browsing_context_id, ch, key, state, modified),
ShutdownState::NotShuttingDown) => {
if state == KeyState::Pressed { if state == KeyState::Pressed {
self.window.handle_key(ch, key, modified); self.window.handle_key(top_level_browsing_context_id, ch, key, modified);
} }
} }
@ -567,16 +566,16 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.composite_if_necessary(CompositingReason::Headless); self.composite_if_necessary(CompositingReason::Headless);
} }
(Msg::NewFavicon(url), ShutdownState::NotShuttingDown) => { (Msg::NewFavicon(top_level_browsing_context_id, url), ShutdownState::NotShuttingDown) => {
self.window.set_favicon(url); self.window.set_favicon(top_level_browsing_context_id, url);
} }
(Msg::HeadParsed, ShutdownState::NotShuttingDown) => { (Msg::HeadParsed(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => {
self.window.head_parsed(); self.window.head_parsed(top_level_browsing_context_id);
} }
(Msg::HistoryChanged(entries, current), ShutdownState::NotShuttingDown) => { (Msg::HistoryChanged(top_level_browsing_context_id, entries, current), ShutdownState::NotShuttingDown) => {
self.window.history_changed(entries, current); self.window.history_changed(top_level_browsing_context_id, entries, current);
} }
(Msg::PipelineVisibilityChanged(pipeline_id, visible), ShutdownState::NotShuttingDown) => { (Msg::PipelineVisibilityChanged(pipeline_id, visible), ShutdownState::NotShuttingDown) => {
@ -606,8 +605,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
func(); func();
} }
(Msg::SetFullscreenState(state), ShutdownState::NotShuttingDown) => { (Msg::SetFullscreenState(top_level_browsing_context_id, state), ShutdownState::NotShuttingDown) => {
self.window.set_fullscreen_state(state); self.window.set_fullscreen_state(top_level_browsing_context_id, state);
} }
// When we are shutting_down, we need to avoid performing operations // When we are shutting_down, we need to avoid performing operations
@ -665,15 +664,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
} }
} }
fn change_page_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
let set_title = self.root_pipeline.as_ref().map_or(false, |root_pipeline| {
root_pipeline.id == pipeline_id
});
if set_title {
self.window.set_page_title(title);
}
}
fn set_frame_tree(&mut self, frame_tree: &SendableFrameTree) { fn set_frame_tree(&mut self, frame_tree: &SendableFrameTree) {
debug!("Setting the frame tree for pipeline {}", frame_tree.pipeline.id); debug!("Setting the frame tree for pipeline {}", frame_tree.pipeline.id);
@ -743,8 +733,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.on_resize_window_event(size); self.on_resize_window_event(size);
} }
WindowEvent::LoadUrl(url_string) => { WindowEvent::LoadUrl(top_level_browsing_context_id, url) => {
self.on_load_url_window_event(url_string); let msg = ConstellationMsg::LoadUrl(top_level_browsing_context_id, url);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending load url to constellation failed ({}).", e);
}
} }
WindowEvent::MouseWindowEventClass(mouse_window_event) => { WindowEvent::MouseWindowEventClass(mouse_window_event) => {
@ -788,8 +781,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.on_pinch_zoom_window_event(magnification); self.on_pinch_zoom_window_event(magnification);
} }
WindowEvent::Navigation(direction) => { WindowEvent::Navigation(top_level_browsing_context_id, direction) => {
self.on_navigation_window_event(direction); let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending navigation to constellation failed ({}).", e);
}
} }
WindowEvent::TouchpadPressure(cursor, pressure, stage) => { WindowEvent::TouchpadPressure(cursor, pressure, stage) => {
@ -797,7 +793,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
} }
WindowEvent::KeyEvent(ch, key, state, modifiers) => { WindowEvent::KeyEvent(ch, key, state, modifiers) => {
self.on_key_event(ch, key, state, modifiers); let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending key event to constellation failed ({}).", e);
}
} }
WindowEvent::Quit => { WindowEvent::Quit => {
@ -807,11 +806,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
} }
} }
WindowEvent::Reload => { WindowEvent::Reload(top_level_browsing_context_id) => {
let top_level_browsing_context_id = match self.root_pipeline {
Some(ref pipeline) => pipeline.top_level_browsing_context_id,
None => return warn!("Window reload without root pipeline."),
};
let msg = ConstellationMsg::Reload(top_level_browsing_context_id); let msg = ConstellationMsg::Reload(top_level_browsing_context_id);
if let Err(e) = self.constellation_chan.send(msg) { if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending reload to constellation failed ({}).", e); warn!("Sending reload to constellation failed ({}).", e);
@ -824,6 +819,20 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.webrender.set_debug_flags(flags); self.webrender.set_debug_flags(flags);
self.webrender_api.generate_frame(self.webrender_document, None); self.webrender_api.generate_frame(self.webrender_document, None);
} }
WindowEvent::NewBrowser(url, response_chan) => {
let msg = ConstellationMsg::NewBrowser(url, response_chan);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending NewBrowser message to constellation failed ({}).", e);
}
}
WindowEvent::SelectBrowser(ctx) => {
let msg = ConstellationMsg::SelectBrowser(ctx);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending SelectBrowser message to constellation failed ({}).", e);
}
}
} }
} }
@ -851,23 +860,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.send_window_size(WindowSizeType::Resize); self.send_window_size(WindowSizeType::Resize);
} }
fn on_load_url_window_event(&mut self, url_string: String) {
debug!("osmain: loading URL `{}`", url_string);
match ServoUrl::parse(&url_string) {
Ok(url) => {
let msg = match self.root_pipeline {
Some(ref pipeline) =>
ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, Some(pipeline.id), None, None)),
None => ConstellationMsg::InitLoadUrl(url)
};
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending load url to constellation failed ({}).", e);
}
},
Err(e) => warn!("Parsing URL {} failed ({}).", url_string, e),
}
}
fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) { fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) {
if opts::get().convert_mouse_to_touch { if opts::get().convert_mouse_to_touch {
match mouse_window_event { match mouse_window_event {
@ -1292,28 +1284,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}); });
} }
fn on_navigation_window_event(&self, direction: TraversalDirection) {
let top_level_browsing_context_id = match self.root_pipeline {
Some(ref pipeline) => pipeline.top_level_browsing_context_id,
None => return warn!("Sending navigation to constellation with no root pipeline."),
};
let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending navigation to constellation failed ({}).", e);
}
}
fn on_key_event(&mut self,
ch: Option<char>,
key: Key,
state: KeyState,
modifiers: KeyModifiers) {
let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending key event to constellation failed ({}).", e);
}
}
fn send_viewport_rects(&self) { fn send_viewport_rects(&self) {
let mut scroll_states_per_pipeline = HashMap::new(); let mut scroll_states_per_pipeline = HashMap::new();
for scroll_layer_state in self.webrender_api.get_scroll_node_state(self.webrender_document) { for scroll_layer_state in self.webrender_api.get_scroll_node_state(self.webrender_document) {

View file

@ -8,7 +8,7 @@ use SendableFrameTree;
use compositor::CompositingReason; use compositor::CompositingReason;
use euclid::{Point2D, Size2D}; use euclid::{Point2D, Size2D};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId};
use net_traits::image::base::Image; use net_traits::image::base::Image;
use profile_traits::mem; use profile_traits::mem;
use profile_traits::time; use profile_traits::time;
@ -87,23 +87,23 @@ pub enum Msg {
/// Scroll a page in a window /// Scroll a page in a window
ScrollFragmentPoint(webrender_api::ClipId, Point2D<f32>, bool), ScrollFragmentPoint(webrender_api::ClipId, Point2D<f32>, bool),
/// Alerts the compositor that the current page has changed its title. /// Alerts the compositor that the current page has changed its title.
ChangePageTitle(PipelineId, Option<String>), ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
/// Alerts the compositor that the given pipeline has changed whether it is running animations. /// Alerts the compositor that the given pipeline has changed whether it is running animations.
ChangeRunningAnimationsState(PipelineId, AnimationState), ChangeRunningAnimationsState(PipelineId, AnimationState),
/// Replaces the current frame tree, typically called during main frame navigation. /// Replaces the current frame tree, typically called during main frame navigation.
SetFrameTree(SendableFrameTree), SetFrameTree(SendableFrameTree),
/// The load of a page has begun /// The load of a page has begun
LoadStart, LoadStart(TopLevelBrowsingContextId),
/// The load of a page has completed /// The load of a page has completed
LoadComplete, LoadComplete(TopLevelBrowsingContextId),
/// The history state has changed. /// The history state has changed.
HistoryChanged(Vec<LoadData>, usize), HistoryChanged(TopLevelBrowsingContextId, Vec<LoadData>, usize),
/// Wether or not to follow a link /// Wether or not to follow a link
AllowNavigation(ServoUrl, IpcSender<bool>), AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
/// Composite. /// Composite.
Recomposite(CompositingReason), Recomposite(CompositingReason),
/// Sends an unconsumed key event back to the compositor. /// Sends an unconsumed key event back to the compositor.
KeyEvent(Option<char>, Key, KeyState, KeyModifiers), KeyEvent(Option<TopLevelBrowsingContextId>, Option<char>, Key, KeyState, KeyModifiers),
/// Script has handled a touch event, and either prevented or allowed default actions. /// Script has handled a touch event, and either prevented or allowed default actions.
TouchEventProcessed(EventResult), TouchEventProcessed(EventResult),
/// Changes the cursor. /// Changes the cursor.
@ -115,17 +115,17 @@ pub enum Msg {
/// A reply to the compositor asking if the output image is stable. /// A reply to the compositor asking if the output image is stable.
IsReadyToSaveImageReply(bool), IsReadyToSaveImageReply(bool),
/// A favicon was detected /// A favicon was detected
NewFavicon(ServoUrl), NewFavicon(TopLevelBrowsingContextId, ServoUrl),
/// <head> tag finished parsing /// <head> tag finished parsing
HeadParsed, HeadParsed(TopLevelBrowsingContextId),
/// A status message to be displayed by the browser chrome. /// A status message to be displayed by the browser chrome.
Status(Option<String>), Status(TopLevelBrowsingContextId, Option<String>),
/// Get Window Informations size and position /// Get Window Informations size and position
GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>), GetClientWindow(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>, Point2D<i32>)>),
/// Move the window to a point /// Move the window to a point
MoveTo(Point2D<i32>), MoveTo(TopLevelBrowsingContextId, Point2D<i32>),
/// Resize the window to size /// Resize the window to size
ResizeTo(Size2D<u32>), ResizeTo(TopLevelBrowsingContextId, Size2D<u32>),
/// Pipeline visibility changed /// Pipeline visibility changed
PipelineVisibilityChanged(PipelineId, bool), PipelineVisibilityChanged(PipelineId, bool),
/// WebRender has successfully processed a scroll. The boolean specifies whether a composite is /// WebRender has successfully processed a scroll. The boolean specifies whether a composite is
@ -142,7 +142,7 @@ pub enum Msg {
/// Required to allow WGL GLContext sharing in Windows. /// Required to allow WGL GLContext sharing in Windows.
Dispatch(Box<Fn() + Send>), Dispatch(Box<Fn() + Send>),
/// Enter or exit fullscreen /// Enter or exit fullscreen
SetFullscreenState(bool), SetFullscreenState(TopLevelBrowsingContextId, bool),
} }
impl Debug for Msg { impl Debug for Msg {
@ -154,9 +154,9 @@ impl Debug for Msg {
Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"), Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"),
Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"), Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), Msg::SetFrameTree(..) => write!(f, "SetFrameTree"),
Msg::LoadComplete => write!(f, "LoadComplete"), Msg::LoadComplete(..) => write!(f, "LoadComplete"),
Msg::AllowNavigation(..) => write!(f, "AllowNavigation"), Msg::AllowNavigation(..) => write!(f, "AllowNavigation"),
Msg::LoadStart => write!(f, "LoadStart"), Msg::LoadStart(..) => write!(f, "LoadStart"),
Msg::HistoryChanged(..) => write!(f, "HistoryChanged"), Msg::HistoryChanged(..) => write!(f, "HistoryChanged"),
Msg::Recomposite(..) => write!(f, "Recomposite"), Msg::Recomposite(..) => write!(f, "Recomposite"),
Msg::KeyEvent(..) => write!(f, "KeyEvent"), Msg::KeyEvent(..) => write!(f, "KeyEvent"),
@ -166,7 +166,7 @@ impl Debug for Msg {
Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"), Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"),
Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"), Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"),
Msg::NewFavicon(..) => write!(f, "NewFavicon"), Msg::NewFavicon(..) => write!(f, "NewFavicon"),
Msg::HeadParsed => write!(f, "HeadParsed"), Msg::HeadParsed(..) => write!(f, "HeadParsed"),
Msg::Status(..) => write!(f, "Status"), Msg::Status(..) => write!(f, "Status"),
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"), Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
Msg::MoveTo(..) => write!(f, "MoveTo"), Msg::MoveTo(..) => write!(f, "MoveTo"),

View file

@ -9,7 +9,7 @@ use euclid::{Point2D, Size2D};
use euclid::{ScaleFactor, TypedPoint2D, TypedSize2D}; use euclid::{ScaleFactor, TypedPoint2D, TypedSize2D};
use gleam::gl; use gleam::gl;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, TraversalDirection}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection};
use net_traits::net_error_list::NetError; use net_traits::net_error_list::NetError;
use script_traits::{LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase}; use script_traits::{LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
use servo_geometry::DeviceIndependentPixel; use servo_geometry::DeviceIndependentPixel;
@ -45,7 +45,7 @@ pub enum WindowEvent {
/// Touchpad Pressure /// Touchpad Pressure
TouchpadPressure(TypedPoint2D<f32, DevicePixel>, f32, TouchpadPressurePhase), TouchpadPressure(TypedPoint2D<f32, DevicePixel>, f32, TouchpadPressurePhase),
/// Sent when a new URL is to be loaded. /// Sent when a new URL is to be loaded.
LoadUrl(String), LoadUrl(TopLevelBrowsingContextId, ServoUrl),
/// Sent when a mouse hit test is to be performed. /// Sent when a mouse hit test is to be performed.
MouseWindowEventClass(MouseWindowEvent), MouseWindowEventClass(MouseWindowEvent),
/// Sent when a mouse move. /// Sent when a mouse move.
@ -62,15 +62,20 @@ pub enum WindowEvent {
/// Sent when the user resets zoom to default. /// Sent when the user resets zoom to default.
ResetZoom, ResetZoom,
/// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace). /// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace).
Navigation(TraversalDirection), Navigation(TopLevelBrowsingContextId, TraversalDirection),
/// Sent when the user quits the application /// Sent when the user quits the application
Quit, Quit,
/// Sent when a key input state changes /// Sent when a key input state changes
KeyEvent(Option<char>, Key, KeyState, KeyModifiers), KeyEvent(Option<char>, Key, KeyState, KeyModifiers),
/// Sent when Ctr+R/Apple+R is called to reload the current page. /// Sent when Ctr+R/Apple+R is called to reload the current page.
Reload,
/// Toggles the Web renderer profiler on and off /// Toggles the Web renderer profiler on and off
ToggleWebRenderProfiler, ToggleWebRenderProfiler,
Reload(TopLevelBrowsingContextId),
/// Create a new top level browsing context
NewBrowser(ServoUrl, IpcSender<TopLevelBrowsingContextId>),
/// Make a top level browsing context visible, hiding the previous
/// visible one.
SelectBrowser(TopLevelBrowsingContextId),
} }
impl Debug for WindowEvent { impl Debug for WindowEvent {
@ -91,8 +96,10 @@ impl Debug for WindowEvent {
WindowEvent::ResetZoom => write!(f, "ResetZoom"), WindowEvent::ResetZoom => write!(f, "ResetZoom"),
WindowEvent::Navigation(..) => write!(f, "Navigation"), WindowEvent::Navigation(..) => write!(f, "Navigation"),
WindowEvent::Quit => write!(f, "Quit"), WindowEvent::Quit => write!(f, "Quit"),
WindowEvent::Reload => write!(f, "Reload"),
WindowEvent::ToggleWebRenderProfiler => write!(f, "ToggleWebRenderProfiler"), WindowEvent::ToggleWebRenderProfiler => write!(f, "ToggleWebRenderProfiler"),
WindowEvent::Reload(..) => write!(f, "Reload"),
WindowEvent::NewBrowser(..) => write!(f, "NewBrowser"),
WindowEvent::SelectBrowser(..) => write!(f, "SelectBrowser"),
} }
} }
} }
@ -114,30 +121,30 @@ pub trait WindowMethods {
fn present(&self); fn present(&self);
/// Return the size of the window with head and borders and position of the window values /// Return the size of the window with head and borders and position of the window values
fn client_window(&self) -> (Size2D<u32>, Point2D<i32>); fn client_window(&self, ctx: TopLevelBrowsingContextId) -> (Size2D<u32>, Point2D<i32>);
/// Set the size inside of borders and head /// Set the size inside of borders and head
fn set_inner_size(&self, size: Size2D<u32>); fn set_inner_size(&self, ctx: TopLevelBrowsingContextId, size: Size2D<u32>);
/// Set the window position /// Set the window position
fn set_position(&self, point: Point2D<i32>); fn set_position(&self, ctx: TopLevelBrowsingContextId, point: Point2D<i32>);
/// Set fullscreen state /// Set fullscreen state
fn set_fullscreen_state(&self, state: bool); fn set_fullscreen_state(&self, ctx: TopLevelBrowsingContextId, state: bool);
/// Sets the page title for the current page. /// Sets the page title for the current page.
fn set_page_title(&self, title: Option<String>); fn set_page_title(&self, ctx: TopLevelBrowsingContextId, title: Option<String>);
/// Called when the browser chrome should display a status message. /// Called when the browser chrome should display a status message.
fn status(&self, Option<String>); fn status(&self, ctx: TopLevelBrowsingContextId, Option<String>);
/// Called when the browser has started loading a frame. /// Called when the browser has started loading a frame.
fn load_start(&self); fn load_start(&self, ctx: TopLevelBrowsingContextId);
/// Called when the browser is done loading a frame. /// Called when the browser is done loading a frame.
fn load_end(&self); fn load_end(&self, ctx: TopLevelBrowsingContextId);
/// Called when the browser encounters an error while loading a URL /// Called when the browser encounters an error while loading a URL
fn load_error(&self, code: NetError, url: String); fn load_error(&self, ctx: TopLevelBrowsingContextId, code: NetError, url: String);
/// Wether or not to follow a link /// Wether or not to follow a link
fn allow_navigation(&self, url: ServoUrl, IpcSender<bool>); fn allow_navigation(&self, ctx: TopLevelBrowsingContextId, url: ServoUrl, IpcSender<bool>);
/// Called when the <head> tag has finished parsing /// Called when the <head> tag has finished parsing
fn head_parsed(&self); fn head_parsed(&self, ctx: TopLevelBrowsingContextId);
/// Called when the history state has changed. /// Called when the history state has changed.
fn history_changed(&self, Vec<LoadData>, usize); fn history_changed(&self, ctx: TopLevelBrowsingContextId, Vec<LoadData>, usize);
/// Returns the scale factor of the system (device pixels / device independent pixels). /// Returns the scale factor of the system (device pixels / device independent pixels).
fn hidpi_factor(&self) -> ScaleFactor<f32, DeviceIndependentPixel, DevicePixel>; fn hidpi_factor(&self) -> ScaleFactor<f32, DeviceIndependentPixel, DevicePixel>;
@ -154,13 +161,13 @@ pub trait WindowMethods {
fn set_cursor(&self, cursor: Cursor); fn set_cursor(&self, cursor: Cursor);
/// Process a key event. /// Process a key event.
fn handle_key(&self, ch: Option<char>, key: Key, mods: KeyModifiers); fn handle_key(&self, ctx: Option<TopLevelBrowsingContextId>, ch: Option<char>, key: Key, mods: KeyModifiers);
/// Does this window support a clipboard /// Does this window support a clipboard
fn supports_clipboard(&self) -> bool; fn supports_clipboard(&self) -> bool;
/// Add a favicon /// Add a favicon
fn set_favicon(&self, url: ServoUrl); fn set_favicon(&self, ctx: TopLevelBrowsingContextId, url: ServoUrl);
/// Return the GL function pointer trait. /// Return the GL function pointer trait.
fn gl(&self) -> Rc<gl::Gl>; fn gl(&self) -> Rc<gl::Gl>;

View file

@ -105,7 +105,7 @@ use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorM
use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData}; use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData};
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg}; use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg};
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory}; use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg}; use script_traits::{LogEntry, ScriptToConstellationChan, ServiceWorkerMsg, webdriver_msg};
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData}; use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WindowSizeType}; use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WindowSizeType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -147,11 +147,11 @@ use webvr_traits::{WebVREvent, WebVRMsg};
pub struct Constellation<Message, LTF, STF> { pub struct Constellation<Message, LTF, STF> {
/// An IPC channel for script threads to send messages to the constellation. /// An IPC channel for script threads to send messages to the constellation.
/// This is the script threads' view of `script_receiver`. /// This is the script threads' view of `script_receiver`.
script_sender: IpcSender<FromScriptMsg>, script_sender: IpcSender<(PipelineId, FromScriptMsg)>,
/// A channel for the constellation to receive messages from script threads. /// A channel for the constellation to receive messages from script threads.
/// This is the constellation's view of `script_sender`. /// This is the constellation's view of `script_sender`.
script_receiver: Receiver<Result<FromScriptMsg, IpcError>>, script_receiver: Receiver<Result<(PipelineId, FromScriptMsg), IpcError>>,
/// An IPC channel for layout threads to send messages to the constellation. /// An IPC channel for layout threads to send messages to the constellation.
/// This is the layout threads' view of `layout_receiver`. /// This is the layout threads' view of `layout_receiver`.
@ -174,6 +174,9 @@ pub struct Constellation<Message, LTF, STF> {
/// constellation to send messages to the compositor thread. /// constellation to send messages to the compositor thread.
compositor_proxy: CompositorProxy, compositor_proxy: CompositorProxy,
/// The last frame tree sent to WebRender.
active_browser_id: Option<TopLevelBrowsingContextId>,
/// Channels for the constellation to send messages to the public /// Channels for the constellation to send messages to the public
/// resource-related threads. There are two groups of resource /// resource-related threads. There are two groups of resource
/// threads: one for public browsing, and one for private /// threads: one for public browsing, and one for private
@ -385,14 +388,14 @@ enum ExitPipelineMode {
#[derive(Clone)] #[derive(Clone)]
pub struct FromScriptLogger { pub struct FromScriptLogger {
/// A channel to the constellation /// A channel to the constellation
pub constellation_chan: Arc<ReentrantMutex<IpcSender<FromScriptMsg>>>, pub script_to_constellation_chan: Arc<ReentrantMutex<ScriptToConstellationChan>>,
} }
impl FromScriptLogger { impl FromScriptLogger {
/// Create a new constellation logger. /// Create a new constellation logger.
pub fn new(constellation_chan: IpcSender<FromScriptMsg>) -> FromScriptLogger { pub fn new(script_to_constellation_chan: ScriptToConstellationChan) -> FromScriptLogger {
FromScriptLogger { FromScriptLogger {
constellation_chan: Arc::new(ReentrantMutex::new(constellation_chan)) script_to_constellation_chan: Arc::new(ReentrantMutex::new(script_to_constellation_chan))
} }
} }
@ -410,10 +413,9 @@ impl Log for FromScriptLogger {
fn log(&self, record: &LogRecord) { fn log(&self, record: &LogRecord) {
if let Some(entry) = log_entry(record) { if let Some(entry) = log_entry(record) {
debug!("Sending log entry {:?}.", entry); debug!("Sending log entry {:?}.", entry);
let top_level_id = TopLevelBrowsingContextId::installed();
let thread_name = thread::current().name().map(ToOwned::to_owned); let thread_name = thread::current().name().map(ToOwned::to_owned);
let msg = FromScriptMsg::LogEntry(top_level_id, thread_name, entry); let msg = FromScriptMsg::LogEntry(thread_name, entry);
let chan = self.constellation_chan.lock().unwrap_or_else(|err| err.into_inner()); let chan = self.script_to_constellation_chan.lock().unwrap_or_else(|err| err.into_inner());
let _ = chan.send(msg); let _ = chan.send(msg);
} }
} }
@ -528,6 +530,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
network_listener_sender: network_listener_sender, network_listener_sender: network_listener_sender,
network_listener_receiver: network_listener_receiver, network_listener_receiver: network_listener_receiver,
compositor_proxy: state.compositor_proxy, compositor_proxy: state.compositor_proxy,
active_browser_id: None,
debugger_chan: state.debugger_chan, debugger_chan: state.debugger_chan,
devtools_chan: state.devtools_chan, devtools_chan: state.devtools_chan,
bluetooth_thread: state.bluetooth_thread, bluetooth_thread: state.bluetooth_thread,
@ -674,7 +677,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
browsing_context_id, browsing_context_id,
top_level_browsing_context_id, top_level_browsing_context_id,
parent_info, parent_info,
constellation_chan: self.script_sender.clone(), script_to_constellation_chan: ScriptToConstellationChan {
sender: self.script_sender.clone(),
pipeline_id: pipeline_id,
},
layout_to_constellation_chan: self.layout_sender.clone(), layout_to_constellation_chan: self.layout_sender.clone(),
scheduler_chan: self.scheduler_chan.clone(), scheduler_chan: self.scheduler_chan.clone(),
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(), compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
@ -807,9 +813,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
} }
fn add_pending_change(&mut self, change: SessionHistoryChange) fn add_pending_change(&mut self, change: SessionHistoryChange) {
{ self.handle_load_start_msg(change.top_level_browsing_context_id, change.new_pipeline_id);
self.handle_load_start_msg(change.new_pipeline_id);
self.pending_changes.push(change); self.pending_changes.push(change);
} }
@ -817,7 +822,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn handle_request(&mut self) { fn handle_request(&mut self) {
enum Request { enum Request {
Script(FromScriptMsg), Script((PipelineId, FromScriptMsg)),
Compositor(FromCompositorMsg), Compositor(FromCompositorMsg),
Layout(FromLayoutMsg), Layout(FromLayoutMsg),
NetworkListener((PipelineId, FetchResponseMsg)), NetworkListener((PipelineId, FetchResponseMsg)),
@ -934,9 +939,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Load a new page from a typed url // Load a new page from a typed url
// If there is already a pending page (self.pending_changes), it will not be overridden; // If there is already a pending page (self.pending_changes), it will not be overridden;
// However, if the id is not encompassed by another change, it will be. // However, if the id is not encompassed by another change, it will be.
FromCompositorMsg::LoadUrl(source_id, load_data) => { FromCompositorMsg::LoadUrl(top_level_browsing_context_id, url) => {
debug!("constellation got URL load message from compositor"); debug!("constellation got URL load message from compositor");
self.handle_load_url_msg(source_id, load_data, false); let load_data = LoadData::new(url, None, None, None);
let ctx_id = BrowsingContextId::from(top_level_browsing_context_id);
let pipeline_id = match self.browsing_contexts.get(&ctx_id) {
Some(ctx) => ctx.pipeline_id,
None => return warn!("LoadUrl for unknow browsing context: {:?}", top_level_browsing_context_id),
};
self.handle_load_url_msg(top_level_browsing_context_id, pipeline_id, load_data, false);
} }
FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => { FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => {
let is_ready = self.handle_is_ready_to_save_image(pipeline_states); let is_ready = self.handle_is_ready_to_save_image(pipeline_states);
@ -950,10 +961,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
println!("sent response"); println!("sent response");
} }
} }
// This should only be called once per constellation, and only by the browser // Create a new top level browsing context. Will use response_chan to return
FromCompositorMsg::InitLoadUrl(url) => { // the browsing context id.
FromCompositorMsg::NewBrowser(url, response_chan) => {
debug!("constellation got init load URL message"); debug!("constellation got init load URL message");
self.handle_init_load(url); self.handle_new_top_level_browsing_context(url, response_chan);
}
// Send frame tree to WebRender. Make it visible.
FromCompositorMsg::SelectBrowser(top_level_browsing_context_id) => {
self.send_frame_tree(top_level_browsing_context_id);
} }
// Handle a forward or back request // Handle a forward or back request
FromCompositorMsg::TraverseHistory(top_level_browsing_context_id, direction) => { FromCompositorMsg::TraverseHistory(top_level_browsing_context_id, direction) => {
@ -989,14 +1005,26 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
} }
fn handle_request_from_script(&mut self, message: FromScriptMsg) { fn handle_request_from_script(&mut self, message: (PipelineId, FromScriptMsg)) {
match message { let (source_pipeline_id, content) = message;
FromScriptMsg::PipelineExited(pipeline_id) => { let source_top_ctx_id = match self.pipelines.get(&source_pipeline_id)
self.handle_pipeline_exited(pipeline_id); .map(|pipeline| pipeline.top_level_browsing_context_id) {
None => return warn!("ScriptMsg from closed pipeline {:?}.", source_pipeline_id),
Some(ctx) => ctx,
};
let source_is_top_level_pipeline = self.browsing_contexts
.get(&BrowsingContextId::from(source_top_ctx_id))
.map(|ctx| ctx.pipeline_id == source_pipeline_id)
.unwrap_or(false);
match content {
FromScriptMsg::PipelineExited => {
self.handle_pipeline_exited(source_pipeline_id);
} }
FromScriptMsg::InitiateNavigateRequest(req_init, pipeline_id) => { FromScriptMsg::InitiateNavigateRequest(req_init) => {
debug!("constellation got initiate navigate request message"); debug!("constellation got initiate navigate request message");
self.handle_navigate_request(req_init, pipeline_id); self.handle_navigate_request(source_pipeline_id, req_init);
} }
FromScriptMsg::ScriptLoadedURLInIFrame(load_info) => { FromScriptMsg::ScriptLoadedURLInIFrame(load_info) => {
debug!("constellation got iframe URL load message {:?} {:?} {:?}", debug!("constellation got iframe URL load message {:?} {:?} {:?}",
@ -1011,40 +1039,40 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
load_info.new_pipeline_id); load_info.new_pipeline_id);
self.handle_script_new_iframe(load_info, layout_sender); self.handle_script_new_iframe(load_info, layout_sender);
} }
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => { FromScriptMsg::ChangeRunningAnimationsState(animation_state) => {
self.handle_change_running_animations_state(pipeline_id, animation_state) self.handle_change_running_animations_state(source_pipeline_id, animation_state)
} }
// Load a new page from a mouse click // Load a new page from a mouse click
// If there is already a pending page (self.pending_changes), it will not be overridden; // If there is already a pending page (self.pending_changes), it will not be overridden;
// However, if the id is not encompassed by another change, it will be. // However, if the id is not encompassed by another change, it will be.
FromScriptMsg::LoadUrl(source_id, load_data, replace) => { FromScriptMsg::LoadUrl(load_data, replace) => {
debug!("constellation got URL load message from script"); debug!("constellation got URL load message from script");
self.handle_load_url_msg(source_id, load_data, replace); self.handle_load_url_msg(source_top_ctx_id, source_pipeline_id, load_data, replace);
} }
// A page loaded has completed all parsing, script, and reflow messages have been sent. // A page loaded has completed all parsing, script, and reflow messages have been sent.
FromScriptMsg::LoadComplete(pipeline_id) => { FromScriptMsg::LoadComplete => {
debug!("constellation got load complete message"); debug!("constellation got load complete message");
self.handle_load_complete_msg(pipeline_id) self.handle_load_complete_msg(source_top_ctx_id, source_pipeline_id)
} }
// Handle a forward or back request // Handle a forward or back request
FromScriptMsg::TraverseHistory(top_level_browsing_context_id, direction) => { FromScriptMsg::TraverseHistory(direction) => {
debug!("constellation got traverse history message from script"); debug!("constellation got traverse history message from script");
self.handle_traverse_history_msg(top_level_browsing_context_id, direction); self.handle_traverse_history_msg(source_top_ctx_id, direction);
} }
// Handle a joint session history length request. // Handle a joint session history length request.
FromScriptMsg::JointSessionHistoryLength(top_level_browsing_context_id, sender) => { FromScriptMsg::JointSessionHistoryLength(sender) => {
debug!("constellation got joint session history length message from script"); debug!("constellation got joint session history length message from script");
self.handle_joint_session_history_length(top_level_browsing_context_id, sender); self.handle_joint_session_history_length(source_top_ctx_id, sender);
} }
// Notification that the new document is ready to become active // Notification that the new document is ready to become active
FromScriptMsg::ActivateDocument(pipeline_id) => { FromScriptMsg::ActivateDocument => {
debug!("constellation got activate document message"); debug!("constellation got activate document message");
self.handle_activate_document_msg(pipeline_id); self.handle_activate_document_msg(source_pipeline_id);
} }
// Update pipeline url after redirections // Update pipeline url after redirections
FromScriptMsg::SetFinalUrl(pipeline_id, final_url) => { FromScriptMsg::SetFinalUrl(final_url) => {
// The script may have finished loading after we already started shutting down. // The script may have finished loading after we already started shutting down.
if let Some(ref mut pipeline) = self.pipelines.get_mut(&pipeline_id) { if let Some(ref mut pipeline) = self.pipelines.get_mut(&source_pipeline_id) {
debug!("constellation got set final url message"); debug!("constellation got set final url message");
pipeline.url = final_url; pipeline.url = final_url;
} else { } else {
@ -1055,22 +1083,22 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
debug!("constellation got postMessage message"); debug!("constellation got postMessage message");
self.handle_post_message_msg(browsing_context_id, origin, data); self.handle_post_message_msg(browsing_context_id, origin, data);
} }
FromScriptMsg::MozBrowserEvent(pipeline_id, top_level_browsing_context_id, event) => { FromScriptMsg::MozBrowserEvent(pipeline_id, event) => {
debug!("constellation got mozbrowser event message"); debug!("constellation got mozbrowser event message");
self.handle_mozbrowser_event_msg(pipeline_id, top_level_browsing_context_id, event); self.handle_mozbrowser_event_msg(pipeline_id, source_top_ctx_id, event);
} }
FromScriptMsg::Focus(pipeline_id) => { FromScriptMsg::Focus => {
debug!("constellation got focus message"); debug!("constellation got focus message");
self.handle_focus_msg(pipeline_id); self.handle_focus_msg(source_pipeline_id);
} }
FromScriptMsg::ForwardEvent(pipeline_id, event) => { FromScriptMsg::ForwardEvent(dest_id, event) => {
let msg = ConstellationControlMsg::SendEvent(pipeline_id, event); let msg = ConstellationControlMsg::SendEvent(dest_id, event);
let result = match self.pipelines.get(&pipeline_id) { let result = match self.pipelines.get(&dest_id) {
None => { debug!("Pipeline {:?} got event after closure.", pipeline_id); return; } None => { debug!("Pipeline {:?} got event after closure.", dest_id); return; }
Some(pipeline) => pipeline.event_loop.send(msg), Some(pipeline) => pipeline.event_loop.send(msg),
}; };
if let Err(e) = result { if let Err(e) = result {
self.handle_send_error(pipeline_id, e); self.handle_send_error(dest_id, e);
} }
} }
FromScriptMsg::GetClipboardContents(sender) => { FromScriptMsg::GetClipboardContents(sender) => {
@ -1095,13 +1123,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
} }
} }
FromScriptMsg::SetVisible(pipeline_id, visible) => { FromScriptMsg::SetVisible(visible) => {
debug!("constellation got set visible messsage"); debug!("constellation got set visible messsage");
self.handle_set_visible_msg(pipeline_id, visible); self.handle_set_visible_msg(source_pipeline_id, visible);
} }
FromScriptMsg::VisibilityChangeComplete(pipeline_id, visible) => { FromScriptMsg::VisibilityChangeComplete(visible) => {
debug!("constellation got set visibility change complete message"); debug!("constellation got set visibility change complete message");
self.handle_visibility_change_complete(pipeline_id, visible); self.handle_visibility_change_complete(source_pipeline_id, visible);
} }
FromScriptMsg::RemoveIFrame(browsing_context_id, sender) => { FromScriptMsg::RemoveIFrame(browsing_context_id, sender) => {
debug!("constellation got remove iframe message"); debug!("constellation got remove iframe message");
@ -1112,11 +1140,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
FromScriptMsg::NewFavicon(url) => { FromScriptMsg::NewFavicon(url) => {
debug!("constellation got new favicon message"); debug!("constellation got new favicon message");
self.compositor_proxy.send(ToCompositorMsg::NewFavicon(url)); if source_is_top_level_pipeline {
self.compositor_proxy.send(ToCompositorMsg::NewFavicon(source_top_ctx_id, url));
}
} }
FromScriptMsg::HeadParsed => { FromScriptMsg::HeadParsed => {
debug!("constellation got head parsed message"); debug!("constellation got head parsed message");
self.compositor_proxy.send(ToCompositorMsg::HeadParsed); if source_is_top_level_pipeline {
self.compositor_proxy.send(ToCompositorMsg::HeadParsed(source_top_ctx_id));
}
} }
FromScriptMsg::CreateCanvasPaintThread(size, sender) => { FromScriptMsg::CreateCanvasPaintThread(size, sender) => {
debug!("constellation got create-canvas-paint-thread message"); debug!("constellation got create-canvas-paint-thread message");
@ -1128,15 +1160,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
FromScriptMsg::NodeStatus(message) => { FromScriptMsg::NodeStatus(message) => {
debug!("constellation got NodeStatus message"); debug!("constellation got NodeStatus message");
self.compositor_proxy.send(ToCompositorMsg::Status(message)); self.compositor_proxy.send(ToCompositorMsg::Status(source_top_ctx_id, message));
} }
FromScriptMsg::SetDocumentState(pipeline_id, state) => { FromScriptMsg::SetDocumentState(state) => {
debug!("constellation got SetDocumentState message"); debug!("constellation got SetDocumentState message");
self.document_states.insert(pipeline_id, state); self.document_states.insert(source_pipeline_id, state);
} }
FromScriptMsg::Alert(pipeline_id, message, sender) => { FromScriptMsg::Alert(message, sender) => {
debug!("constellation got Alert message"); debug!("constellation got Alert message");
self.handle_alert(pipeline_id, message, sender); self.handle_alert(source_top_ctx_id, message, sender);
} }
FromScriptMsg::ScrollFragmentPoint(scroll_root_id, point, smooth) => { FromScriptMsg::ScrollFragmentPoint(scroll_root_id, point, smooth) => {
@ -1146,30 +1178,33 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
FromScriptMsg::GetClientWindow(send) => { FromScriptMsg::GetClientWindow(send) => {
self.compositor_proxy.send(ToCompositorMsg::GetClientWindow(send)); self.compositor_proxy.send(ToCompositorMsg::GetClientWindow(source_top_ctx_id, send));
} }
FromScriptMsg::MoveTo(point) => { FromScriptMsg::MoveTo(point) => {
self.compositor_proxy.send(ToCompositorMsg::MoveTo(point)); self.compositor_proxy.send(ToCompositorMsg::MoveTo(source_top_ctx_id, point));
} }
FromScriptMsg::ResizeTo(size) => { FromScriptMsg::ResizeTo(size) => {
self.compositor_proxy.send(ToCompositorMsg::ResizeTo(size)); self.compositor_proxy.send(ToCompositorMsg::ResizeTo(source_top_ctx_id, size));
} }
FromScriptMsg::Exit => { FromScriptMsg::Exit => {
self.compositor_proxy.send(ToCompositorMsg::Exit); self.compositor_proxy.send(ToCompositorMsg::Exit);
} }
FromScriptMsg::LogEntry(top_level_browsing_context_id, thread_name, entry) => { FromScriptMsg::LogEntry(thread_name, entry) => {
self.handle_log_entry(top_level_browsing_context_id, thread_name, entry); self.handle_log_entry(Some(source_top_ctx_id), thread_name, entry);
} }
FromScriptMsg::SetTitle(pipeline_id, title) => { FromScriptMsg::SetTitle(title) => {
self.compositor_proxy.send(ToCompositorMsg::ChangePageTitle(pipeline_id, title)) if source_is_top_level_pipeline {
self.compositor_proxy.send(ToCompositorMsg::ChangePageTitle(source_top_ctx_id, title))
}
} }
FromScriptMsg::SendKeyEvent(ch, key, key_state, key_modifiers) => { FromScriptMsg::SendKeyEvent(ch, key, key_state, key_modifiers) => {
self.compositor_proxy.send(ToCompositorMsg::KeyEvent(ch, key, key_state, key_modifiers)) let event = ToCompositorMsg::KeyEvent(Some(source_top_ctx_id), ch, key, key_state, key_modifiers);
self.compositor_proxy.send(event);
} }
FromScriptMsg::TouchEventProcessed(result) => { FromScriptMsg::TouchEventProcessed(result) => {
@ -1198,11 +1233,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
warn!("Unable to forward DOMMessage for postMessage call"); warn!("Unable to forward DOMMessage for postMessage call");
} }
} }
FromScriptMsg::BroadcastStorageEvent(pipeline_id, storage, url, key, old_value, new_value) => { FromScriptMsg::BroadcastStorageEvent(storage, url, key, old_value, new_value) => {
self.handle_broadcast_storage_event(pipeline_id, storage, url, key, old_value, new_value); self.handle_broadcast_storage_event(source_pipeline_id, storage, url, key, old_value, new_value);
} }
FromScriptMsg::SetFullscreenState(state) => { FromScriptMsg::SetFullscreenState(state) => {
self.compositor_proxy.send(ToCompositorMsg::SetFullscreenState(state)); self.compositor_proxy.send(ToCompositorMsg::SetFullscreenState(source_top_ctx_id, state));
} }
} }
} }
@ -1468,14 +1503,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
} }
fn handle_init_load(&mut self, url: ServoUrl) { fn handle_new_top_level_browsing_context(&mut self, url: ServoUrl, reply: IpcSender<TopLevelBrowsingContextId>) {
let window_size = self.window_size.initial_viewport; let window_size = self.window_size.initial_viewport;
let pipeline_id = PipelineId::new(); let pipeline_id = PipelineId::new();
let top_level_browsing_context_id = TopLevelBrowsingContextId::new(); let top_level_browsing_context_id = TopLevelBrowsingContextId::new();
if let Err(e) = reply.send(top_level_browsing_context_id) {
warn!("Failed to send newly created top level browsing context ({}).", e);
}
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
let load_data = LoadData::new(url.clone(), None, None, None); let load_data = LoadData::new(url.clone(), None, None, None);
let sandbox = IFrameSandboxState::IFrameUnsandboxed; let sandbox = IFrameSandboxState::IFrameUnsandboxed;
if self.focus_pipeline_id.is_none() {
self.focus_pipeline_id = Some(pipeline_id); self.focus_pipeline_id = Some(pipeline_id);
}
self.new_pipeline(pipeline_id, self.new_pipeline(pipeline_id,
browsing_context_id, browsing_context_id,
top_level_browsing_context_id, top_level_browsing_context_id,
@ -1528,8 +1568,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
fn handle_navigate_request(&self, fn handle_navigate_request(&self,
req_init: RequestInit, id: PipelineId,
id: PipelineId) { req_init: RequestInit) {
let listener = NetworkListener::new( let listener = NetworkListener::new(
req_init, req_init,
id, id,
@ -1687,14 +1727,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
fn handle_alert(&mut self, fn handle_alert(&mut self,
pipeline_id: PipelineId, top_level_browsing_context_id: TopLevelBrowsingContextId,
message: String, message: String,
sender: IpcSender<bool>) { sender: IpcSender<bool>) {
let top_level_browsing_context_id = self.pipelines.get(&pipeline_id) let browser_pipeline_id = self.browsing_contexts.get(&BrowsingContextId::from(top_level_browsing_context_id))
.map(|pipeline| pipeline.top_level_browsing_context_id);
let browser_pipeline_id = top_level_browsing_context_id
.map(BrowsingContextId::from)
.and_then(|browsing_context_id| self.browsing_contexts.get(&browsing_context_id))
.and_then(|browsing_context| self.pipelines.get(&browsing_context.pipeline_id)) .and_then(|browsing_context| self.pipelines.get(&browsing_context.pipeline_id))
.and_then(|pipeline| pipeline.parent_info) .and_then(|pipeline| pipeline.parent_info)
.map(|(browser_pipeline_id, _)| browser_pipeline_id); .map(|(browser_pipeline_id, _)| browser_pipeline_id);
@ -1708,24 +1744,32 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let event = MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value); let event = MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value);
match browser_pipeline_id.and_then(|id| self.pipelines.get(&id)) { match browser_pipeline_id.and_then(|id| self.pipelines.get(&id)) {
None => warn!("Alert sent after browser pipeline closure."), None => warn!("Alert sent after browser pipeline closure."),
Some(pipeline) => pipeline.trigger_mozbrowser_event(top_level_browsing_context_id, event), Some(pipeline) => pipeline.trigger_mozbrowser_event(Some(top_level_browsing_context_id), event),
} }
} }
let result = sender.send(!mozbrowser_modal_prompt); let result = sender.send(!mozbrowser_modal_prompt);
if let Err(e) = result { if let Err(e) = result {
let ctx_id = BrowsingContextId::from(top_level_browsing_context_id);
let pipeline_id = match self.browsing_contexts.get(&ctx_id) {
Some(ctx) => ctx.pipeline_id,
None => return warn!("Alert sent for unknown browsing context."),
};
self.handle_send_error(pipeline_id, e); self.handle_send_error(pipeline_id, e);
} }
} }
fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData, replace: bool) { fn handle_load_url_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId,
self.load_url(source_id, load_data, replace); load_data: LoadData, replace: bool) {
self.load_url(top_level_browsing_context_id, source_id, load_data, replace);
} }
fn load_url(&mut self, source_id: PipelineId, load_data: LoadData, replace: bool) -> Option<PipelineId> { fn load_url(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId,
load_data: LoadData, replace: bool) -> Option<PipelineId> {
// Allow the embedder to handle the url itself // Allow the embedder to handle the url itself
let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); let (chan, port) = ipc::channel().expect("Failed to create IPC channel!");
self.compositor_proxy.send(ToCompositorMsg::AllowNavigation(load_data.url.clone(), chan)); let msg = ToCompositorMsg::AllowNavigation(top_level_browsing_context_id, load_data.url.clone(), chan);
self.compositor_proxy.send(msg);
if let Ok(false) = port.recv() { if let Ok(false) = port.recv() {
return None; return None;
} }
@ -1815,11 +1859,16 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
} }
fn handle_load_start_msg(&mut self, _pipeline_id: PipelineId) { fn handle_load_start_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId,
self.compositor_proxy.send(ToCompositorMsg::LoadStart); pipeline_id: PipelineId) {
if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() {
// Notify embedder top level document started loading.
self.compositor_proxy.send(ToCompositorMsg::LoadStart(top_level_browsing_context_id));
}
} }
fn handle_load_complete_msg(&mut self, pipeline_id: PipelineId) { fn handle_load_complete_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId,
pipeline_id: PipelineId) {
let mut webdriver_reset = false; let mut webdriver_reset = false;
if let Some((expected_pipeline_id, ref reply_chan)) = self.webdriver.load_channel { if let Some((expected_pipeline_id, ref reply_chan)) = self.webdriver.load_channel {
debug!("Sending load to WebDriver"); debug!("Sending load to WebDriver");
@ -1831,7 +1880,25 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
if webdriver_reset { if webdriver_reset {
self.webdriver.load_channel = None; self.webdriver.load_channel = None;
} }
self.compositor_proxy.send(ToCompositorMsg::LoadComplete);
// Notify the embedder that the TopLevelBrowsingContext current document
// has finished loading.
// We need to make sure the pipeline that has finished loading is the current
// pipeline and that no pending pipeline will replace the current one.
let pipeline_is_top_level_pipeline = self.browsing_contexts
.get(&BrowsingContextId::from(top_level_browsing_context_id))
.map(|ctx| ctx.pipeline_id == pipeline_id)
.unwrap_or(false);
if pipeline_is_top_level_pipeline {
// Is there any pending pipeline that will replace the current top level pipeline
let current_top_level_pipeline_will_be_replaced = self.pending_changes.iter()
.any(|change| change.browsing_context_id == top_level_browsing_context_id);
if !current_top_level_pipeline_will_be_replaced {
// Notify embedder top level document finished loading.
self.compositor_proxy.send(ToCompositorMsg::LoadComplete(top_level_browsing_context_id));
}
}
self.handle_subframe_loaded(pipeline_id); self.handle_subframe_loaded(pipeline_id);
} }
@ -1897,7 +1964,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
}, },
None => { None => {
let event = ToCompositorMsg::KeyEvent(ch, key, state, mods); let event = ToCompositorMsg::KeyEvent(None, ch, key, state, mods);
self.compositor_proxy.clone_compositor_proxy().send(event); self.compositor_proxy.clone_compositor_proxy().send(event);
} }
} }
@ -2088,9 +2155,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
WebDriverCommandMsg::GetWindowSize(_, reply) => { WebDriverCommandMsg::GetWindowSize(_, reply) => {
let _ = reply.send(self.window_size); let _ = reply.send(self.window_size);
}, },
WebDriverCommandMsg::SetWindowSize(_, size, reply) => { WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, reply) => {
self.webdriver.resize_channel = Some(reply); self.webdriver.resize_channel = Some(reply);
self.compositor_proxy.send(ToCompositorMsg::ResizeTo(size)); self.compositor_proxy.send(ToCompositorMsg::ResizeTo(top_level_browsing_context_id, size));
}, },
WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, reply) => { WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, reply) => {
self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, false); self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, false);
@ -2247,7 +2314,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.notify_history_changed(top_level_id); self.notify_history_changed(top_level_id);
// Set paint permissions correctly for the compositor layers. // Set paint permissions correctly for the compositor layers.
if let Some(id) = self.active_browser_id {
if id == top_level_id {
self.send_frame_tree(top_level_id); self.send_frame_tree(top_level_id);
}
}
// Update the owning iframe to point to the new pipeline id. // Update the owning iframe to point to the new pipeline id.
// This makes things like contentDocument work correctly. // This makes things like contentDocument work correctly.
@ -2324,7 +2395,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
.map(&keep_load_data_if_top_browsing_context) .map(&keep_load_data_if_top_browsing_context)
.scan(current_load_data.clone(), &resolve_load_data)); .scan(current_load_data.clone(), &resolve_load_data));
self.compositor_proxy.send(ToCompositorMsg::HistoryChanged(entries, current_index)); let msg = ToCompositorMsg::HistoryChanged(top_level_browsing_context_id, entries, current_index);
self.compositor_proxy.send(msg);
} }
fn load_url_for_webdriver(&mut self, fn load_url_for_webdriver(&mut self,
@ -2338,7 +2410,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
Some(browsing_context) => browsing_context.pipeline_id, Some(browsing_context) => browsing_context.pipeline_id,
None => return warn!("Webdriver load for closed browsing context {}.", browsing_context_id), None => return warn!("Webdriver load for closed browsing context {}.", browsing_context_id),
}; };
if let Some(new_pipeline_id) = self.load_url(pipeline_id, load_data, replace) { if let Some(new_pipeline_id) = self.load_url(top_level_browsing_context_id, pipeline_id, load_data, replace) {
self.webdriver.load_channel = Some((new_pipeline_id, reply)); self.webdriver.load_channel = Some((new_pipeline_id, reply));
} }
} }
@ -2405,8 +2477,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
// Build frame tree // Build frame tree
if let Some(id) = self.active_browser_id {
if id == change.top_level_browsing_context_id {
self.send_frame_tree(change.top_level_browsing_context_id ); self.send_frame_tree(change.top_level_browsing_context_id );
} }
}
}
fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) { fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) {
debug!("Document ready to activate {}", pipeline_id); debug!("Document ready to activate {}", pipeline_id);
@ -2842,6 +2918,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn send_frame_tree(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { fn send_frame_tree(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) {
// This might be a mozbrowser iframe, so we need to climb the parent hierarchy, // This might be a mozbrowser iframe, so we need to climb the parent hierarchy,
// even though it's a top-level browsing context. // even though it's a top-level browsing context.
self.active_browser_id = Some(top_level_browsing_context_id);
let mut browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); let mut browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
let mut pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { let mut pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
Some(browsing_context) => browsing_context.pipeline_id, Some(browsing_context) => browsing_context.pipeline_id,

View file

@ -21,10 +21,10 @@ use net_traits::{IpcSend, ResourceThreads};
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
use profile_traits::mem as profile_mem; use profile_traits::mem as profile_mem;
use profile_traits::time; use profile_traits::time;
use script_traits::{ConstellationControlMsg, DiscardBrowsingContext}; use script_traits::{ConstellationControlMsg, DiscardBrowsingContext, ScriptToConstellationChan};
use script_traits::{DocumentActivity, InitialScriptState}; use script_traits::{DocumentActivity, InitialScriptState};
use script_traits::{LayoutControlMsg, LayoutMsg, LoadData, MozBrowserEvent}; use script_traits::{LayoutControlMsg, LayoutMsg, LoadData, MozBrowserEvent};
use script_traits::{NewLayoutInfo, SWManagerMsg, SWManagerSenders, ScriptMsg}; use script_traits::{NewLayoutInfo, SWManagerMsg, SWManagerSenders};
use script_traits::{ScriptThreadFactory, TimerSchedulerMsg, WindowSizeData}; use script_traits::{ScriptThreadFactory, TimerSchedulerMsg, WindowSizeData};
use servo_config::opts::{self, Opts}; use servo_config::opts::{self, Opts};
use servo_config::prefs::{PREFS, Pref}; use servo_config::prefs::{PREFS, Pref};
@ -112,7 +112,7 @@ pub struct InitialPipelineState {
pub parent_info: Option<(PipelineId, FrameType)>, pub parent_info: Option<(PipelineId, FrameType)>,
/// A channel to the associated constellation. /// A channel to the associated constellation.
pub constellation_chan: IpcSender<ScriptMsg>, pub script_to_constellation_chan: ScriptToConstellationChan,
/// A channel for the layout thread to send messages to the constellation. /// A channel for the layout thread to send messages to the constellation.
pub layout_to_constellation_chan: IpcSender<LayoutMsg>, pub layout_to_constellation_chan: IpcSender<LayoutMsg>,
@ -246,7 +246,7 @@ impl Pipeline {
browsing_context_id: state.browsing_context_id, browsing_context_id: state.browsing_context_id,
top_level_browsing_context_id: state.top_level_browsing_context_id, top_level_browsing_context_id: state.top_level_browsing_context_id,
parent_info: state.parent_info, parent_info: state.parent_info,
constellation_chan: state.constellation_chan, script_to_constellation_chan: state.script_to_constellation_chan.clone(),
scheduler_chan: state.scheduler_chan, scheduler_chan: state.scheduler_chan,
devtools_chan: script_to_devtools_chan, devtools_chan: script_to_devtools_chan,
bluetooth_thread: state.bluetooth_thread, bluetooth_thread: state.bluetooth_thread,
@ -446,7 +446,7 @@ pub struct UnprivilegedPipelineContent {
top_level_browsing_context_id: TopLevelBrowsingContextId, top_level_browsing_context_id: TopLevelBrowsingContextId,
browsing_context_id: BrowsingContextId, browsing_context_id: BrowsingContextId,
parent_info: Option<(PipelineId, FrameType)>, parent_info: Option<(PipelineId, FrameType)>,
constellation_chan: IpcSender<ScriptMsg>, script_to_constellation_chan: ScriptToConstellationChan,
layout_to_constellation_chan: IpcSender<LayoutMsg>, layout_to_constellation_chan: IpcSender<LayoutMsg>,
scheduler_chan: IpcSender<TimerSchedulerMsg>, scheduler_chan: IpcSender<TimerSchedulerMsg>,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
@ -487,7 +487,7 @@ impl UnprivilegedPipelineContent {
parent_info: self.parent_info, parent_info: self.parent_info,
control_chan: self.script_chan.clone(), control_chan: self.script_chan.clone(),
control_port: self.script_port, control_port: self.script_port,
constellation_chan: self.constellation_chan, script_to_constellation_chan: self.script_to_constellation_chan.clone(),
layout_to_constellation_chan: self.layout_to_constellation_chan.clone(), layout_to_constellation_chan: self.layout_to_constellation_chan.clone(),
scheduler_chan: self.scheduler_chan, scheduler_chan: self.scheduler_chan,
bluetooth_thread: self.bluetooth_thread, bluetooth_thread: self.bluetooth_thread,
@ -595,8 +595,8 @@ impl UnprivilegedPipelineContent {
} }
} }
pub fn constellation_chan(&self) -> IpcSender<ScriptMsg> { pub fn script_to_constellation_chan(&self) -> &ScriptToConstellationChan {
self.constellation_chan.clone() &self.script_to_constellation_chan
} }
pub fn opts(&self) -> Opts { pub fn opts(&self) -> Opts {

View file

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::channel;
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::{ScriptToConstellationChan, ScriptMsg};
use std::borrow::ToOwned; use std::borrow::ToOwned;
pub trait ClipboardProvider { pub trait ClipboardProvider {
@ -13,14 +13,14 @@ pub trait ClipboardProvider {
fn set_clipboard_contents(&mut self, String); fn set_clipboard_contents(&mut self, String);
} }
impl ClipboardProvider for IpcSender<ConstellationMsg> { impl ClipboardProvider for ScriptToConstellationChan {
fn clipboard_contents(&mut self) -> String { fn clipboard_contents(&mut self) -> String {
let (tx, rx) = ipc::channel().unwrap(); let (tx, rx) = channel().unwrap();
self.send(ConstellationMsg::GetClipboardContents(tx)).unwrap(); self.send(ScriptMsg::GetClipboardContents(tx)).unwrap();
rx.recv().unwrap() rx.recv().unwrap()
} }
fn set_clipboard_contents(&mut self, s: String) { fn set_clipboard_contents(&mut self, s: String) {
self.send(ConstellationMsg::SetClipboardContents(s)).unwrap(); self.send(ScriptMsg::SetClipboardContents(s)).unwrap();
} }
} }

View file

@ -73,7 +73,7 @@ use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_layout_interface::OpaqueStyleAndLayoutData; use script_layout_interface::OpaqueStyleAndLayoutData;
use script_layout_interface::reporter::CSSErrorReporter; use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::rpc::LayoutRPC; use script_layout_interface::rpc::LayoutRPC;
use script_traits::{DocumentActivity, TimerEventId, TimerSource, TouchpadPressurePhase}; use script_traits::{DocumentActivity, ScriptToConstellationChan, TimerEventId, TimerSource, TouchpadPressurePhase};
use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType}; use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::DrawAPaintImageResult; use script_traits::DrawAPaintImageResult;
use selectors::matching::ElementSelectorFlags; use selectors::matching::ElementSelectorFlags;
@ -400,6 +400,7 @@ unsafe_no_jsmanaged_fields!(WebGLTextureId);
unsafe_no_jsmanaged_fields!(WebGLVertexArrayId); unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
unsafe_no_jsmanaged_fields!(MediaList); unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(WebVRGamepadHand); unsafe_no_jsmanaged_fields!(WebVRGamepadHand);
unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
unsafe impl<'a> JSTraceable for &'a str { unsafe impl<'a> JSTraceable for &'a str {
#[inline] #[inline]

View file

@ -42,7 +42,7 @@ use net_traits::image_cache::ImageResponse;
use net_traits::image_cache::ImageState; use net_traits::image_cache::ImageState;
use net_traits::image_cache::UsePlaceholder; use net_traits::image_cache::UsePlaceholder;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::ScriptMsg;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::{cmp, fmt, mem}; use std::{cmp, fmt, mem};
use std::cell::Cell; use std::cell::Cell;
@ -130,9 +130,9 @@ impl CanvasRenderingContext2D {
-> CanvasRenderingContext2D { -> CanvasRenderingContext2D {
debug!("Creating new canvas rendering context."); debug!("Creating new canvas rendering context.");
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let constellation_chan = global.constellation_chan(); let script_to_constellation_chan = global.script_to_constellation_chan();
debug!("Asking constellation to create new canvas thread."); debug!("Asking constellation to create new canvas thread.");
constellation_chan.send(ConstellationMsg::CreateCanvasPaintThread(size, sender)).unwrap(); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap();
let ipc_renderer = receiver.recv().unwrap(); let ipc_renderer = receiver.recv().unwrap();
debug!("Done."); debug!("Done.");
CanvasRenderingContext2D { CanvasRenderingContext2D {

View file

@ -17,7 +17,7 @@ use ipc_channel::ipc;
use js::jsapi::{JSContext, HandleValue}; use js::jsapi::{JSContext, HandleValue};
use js::jsval::{JSVal, UndefinedValue}; use js::jsval::{JSVal, UndefinedValue};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::ScriptMsg;
use servo_url::ImmutableOrigin; use servo_url::ImmutableOrigin;
use servo_url::MutableOrigin; use servo_url::MutableOrigin;
use servo_url::ServoUrl; use servo_url::ServoUrl;
@ -54,7 +54,7 @@ impl DissimilarOriginWindow {
global_to_clone_from.devtools_chan().cloned(), global_to_clone_from.devtools_chan().cloned(),
global_to_clone_from.mem_profiler_chan().clone(), global_to_clone_from.mem_profiler_chan().clone(),
global_to_clone_from.time_profiler_chan().clone(), global_to_clone_from.time_profiler_chan().clone(),
global_to_clone_from.constellation_chan().clone(), global_to_clone_from.script_to_constellation_chan().clone(),
global_to_clone_from.scheduler_chan().clone(), global_to_clone_from.scheduler_chan().clone(),
global_to_clone_from.resource_threads().clone(), global_to_clone_from.resource_threads().clone(),
timer_event_chan, timer_event_chan,
@ -184,9 +184,9 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
impl DissimilarOriginWindow { impl DissimilarOriginWindow {
pub fn post_message(&self, origin: Option<ImmutableOrigin>, data: StructuredCloneData) { pub fn post_message(&self, origin: Option<ImmutableOrigin>, data: StructuredCloneData) {
let msg = ConstellationMsg::PostMessage(self.window_proxy.browsing_context_id(), let msg = ScriptMsg::PostMessage(self.window_proxy.browsing_context_id(),
origin, origin,
data.move_to_arraybuffer()); data.move_to_arraybuffer());
let _ = self.upcast::<GlobalScope>().constellation_chan().send(msg); let _ = self.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
} }
} }

View file

@ -115,7 +115,7 @@ use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
use script_thread::{MainThreadScriptMsg, Runnable, ScriptThread}; use script_thread::{MainThreadScriptMsg, Runnable, ScriptThread};
use script_traits::{AnimationState, CompositorEvent, DocumentActivity}; use script_traits::{AnimationState, CompositorEvent, DocumentActivity};
use script_traits::{MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TouchpadPressurePhase}; use script_traits::{MsDuration, ScriptMsg, TouchpadPressurePhase};
use script_traits::{TouchEventType, TouchId}; use script_traits::{TouchEventType, TouchId};
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
use servo_arc::Arc; use servo_arc::Arc;
@ -795,9 +795,7 @@ impl Document {
// Update the focus state for all elements in the focus chain. // Update the focus state for all elements in the focus chain.
// https://html.spec.whatwg.org/multipage/#focus-chain // https://html.spec.whatwg.org/multipage/#focus-chain
if focus_type == FocusType::Element { if focus_type == FocusType::Element {
let global_scope = self.window.upcast::<GlobalScope>(); self.send_to_constellation(ScriptMsg::Focus);
let event = ConstellationMsg::Focus(global_scope.pipeline_id());
global_scope.constellation_chan().send(event).unwrap();
} }
} }
} }
@ -808,19 +806,14 @@ impl Document {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsertitlechange // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsertitlechange
self.trigger_mozbrowser_event(MozBrowserEvent::TitleChange(String::from(self.Title()))); self.trigger_mozbrowser_event(MozBrowserEvent::TitleChange(String::from(self.Title())));
self.send_title_to_compositor(); self.send_title_to_constellation();
} }
} }
/// Sends this document's title to the compositor. /// Sends this document's title to the constellation.
pub fn send_title_to_compositor(&self) { pub fn send_title_to_constellation(&self) {
let window = self.window(); let title = Some(String::from(self.Title()));
let global_scope = window.upcast::<GlobalScope>(); self.send_to_constellation(ScriptMsg::SetTitle(title));
global_scope
.constellation_chan()
.send(ConstellationMsg::SetTitle(global_scope.pipeline_id(),
Some(String::from(self.Title()))))
.unwrap();
} }
pub fn dirty_all_nodes(&self) { pub fn dirty_all_nodes(&self) {
@ -872,8 +865,8 @@ impl Document {
let child_point = client_point - child_origin; let child_point = client_point - child_origin;
let event = CompositorEvent::MouseButtonEvent(mouse_event_type, button, child_point); let event = CompositorEvent::MouseButtonEvent(mouse_event_type, button, child_point);
let event = ConstellationMsg::ForwardEvent(pipeline_id, event); let event = ScriptMsg::ForwardEvent(pipeline_id, event);
self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); self.send_to_constellation(event);
} }
return; return;
} }
@ -1029,8 +1022,8 @@ impl Document {
let event = CompositorEvent::TouchpadPressureEvent(child_point, let event = CompositorEvent::TouchpadPressureEvent(child_point,
pressure, pressure,
phase_now); phase_now);
let event = ConstellationMsg::ForwardEvent(pipeline_id, event); let event = ScriptMsg::ForwardEvent(pipeline_id, event);
self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); self.send_to_constellation(event);
} }
return; return;
} }
@ -1131,8 +1124,8 @@ impl Document {
let child_point = client_point - child_origin; let child_point = client_point - child_origin;
let event = CompositorEvent::MouseMoveEvent(Some(child_point)); let event = CompositorEvent::MouseMoveEvent(Some(child_point));
let event = ConstellationMsg::ForwardEvent(pipeline_id, event); let event = ScriptMsg::ForwardEvent(pipeline_id, event);
self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); self.send_to_constellation(event);
} }
return; return;
} }
@ -1238,8 +1231,8 @@ impl Document {
let child_point = point - child_origin; let child_point = point - child_origin;
let event = CompositorEvent::TouchEvent(event_type, touch_id, child_point); let event = CompositorEvent::TouchEvent(event_type, touch_id, child_point);
let event = ConstellationMsg::ForwardEvent(pipeline_id, event); let event = ScriptMsg::ForwardEvent(pipeline_id, event);
self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); self.send_to_constellation(event);
} }
return TouchEventResult::Forwarded; return TouchEventResult::Forwarded;
} }
@ -1330,8 +1323,7 @@ impl Document {
ch: Option<char>, ch: Option<char>,
key: Key, key: Key,
state: KeyState, state: KeyState,
modifiers: KeyModifiers, modifiers: KeyModifiers) {
constellation: &IpcSender<ConstellationMsg>) {
let focused = self.get_focused_element(); let focused = self.get_focused_element();
let body = self.GetBody(); let body = self.GetBody();
@ -1407,7 +1399,8 @@ impl Document {
} }
if cancel_state == EventDefault::Allowed { if cancel_state == EventDefault::Allowed {
constellation.send(ConstellationMsg::SendKeyEvent(ch, key, state, modifiers)).unwrap(); let msg = ScriptMsg::SendKeyEvent(ch, key, state, modifiers);
self.send_to_constellation(msg);
// This behavior is unspecced // This behavior is unspecced
// We are supposed to dispatch synthetic click activation for Space and/or Return, // We are supposed to dispatch synthetic click activation for Space and/or Return,
@ -1525,11 +1518,8 @@ impl Document {
pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) { pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) {
if PREFS.is_mozbrowser_enabled() { if PREFS.is_mozbrowser_enabled() {
if let Some((parent_pipeline_id, _)) = self.window.parent_info() { if let Some((parent_pipeline_id, _)) = self.window.parent_info() {
let top_level_browsing_context_id = self.window.window_proxy().top_level_browsing_context_id(); let event = ScriptMsg::MozBrowserEvent(parent_pipeline_id, event);
let event = ConstellationMsg::MozBrowserEvent(parent_pipeline_id, self.send_to_constellation(event);
top_level_browsing_context_id,
event);
self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap();
} }
} }
} }
@ -1559,11 +1549,8 @@ impl Document {
// This reduces CPU usage by avoiding needless thread wakeups in the common case of // This reduces CPU usage by avoiding needless thread wakeups in the common case of
// repeated rAF. // repeated rAF.
let global_scope = self.window.upcast::<GlobalScope>(); let event = ScriptMsg::ChangeRunningAnimationsState(AnimationState::AnimationCallbacksPresent);
let event = ConstellationMsg::ChangeRunningAnimationsState( self.send_to_constellation(event);
global_scope.pipeline_id(),
AnimationState::AnimationCallbacksPresent);
global_scope.constellation_chan().send(event).unwrap();
} }
ident ident
@ -1629,11 +1616,8 @@ impl Document {
(!was_faking_animation_frames && self.is_faking_animation_frames()) { (!was_faking_animation_frames && self.is_faking_animation_frames()) {
mem::swap(&mut *self.animation_frame_list.borrow_mut(), mem::swap(&mut *self.animation_frame_list.borrow_mut(),
&mut *animation_frame_list); &mut *animation_frame_list);
let global_scope = self.window.upcast::<GlobalScope>(); let event = ScriptMsg::ChangeRunningAnimationsState(AnimationState::NoAnimationCallbacksPresent);
let event = ConstellationMsg::ChangeRunningAnimationsState( self.send_to_constellation(event);
global_scope.pipeline_id(),
AnimationState::NoAnimationCallbacksPresent);
global_scope.constellation_chan().send(event).unwrap();
} }
// Update the counter of spurious animation frames. // Update the counter of spurious animation frames.
@ -1896,10 +1880,7 @@ impl Document {
} }
pub fn notify_constellation_load(&self) { pub fn notify_constellation_load(&self) {
let global_scope = self.window.upcast::<GlobalScope>(); self.send_to_constellation(ScriptMsg::LoadComplete);
let pipeline_id = global_scope.pipeline_id();
let load_event = ConstellationMsg::LoadComplete(pipeline_id);
global_scope.constellation_chan().send(load_event).unwrap();
} }
pub fn set_current_parser(&self, script: Option<&ServoParser>) { pub fn set_current_parser(&self, script: Option<&ServoParser>) {
@ -2024,6 +2005,11 @@ impl Document {
registry.lookup_definition(local_name, is) registry.lookup_definition(local_name, is)
} }
fn send_to_constellation(&self, msg: ScriptMsg) {
let global_scope = self.window.upcast::<GlobalScope>();
global_scope.script_to_constellation_chan().send(msg).unwrap();
}
} }
#[derive(PartialEq, HeapSizeOf)] #[derive(PartialEq, HeapSizeOf)]
@ -2525,8 +2511,8 @@ impl Document {
let window = self.window(); let window = self.window();
// Step 6 // Step 6
if !error { if !error {
let event = ConstellationMsg::SetFullscreenState(true); let event = ScriptMsg::SetFullscreenState(true);
window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); self.send_to_constellation(event);
} }
// Step 7 // Step 7
@ -2558,8 +2544,8 @@ impl Document {
let window = self.window(); let window = self.window();
// Step 8 // Step 8
let event = ConstellationMsg::SetFullscreenState(false); let event = ScriptMsg::SetFullscreenState(false);
window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); self.send_to_constellation(event);
// Step 9 // Step 9
let trusted_element = Trusted::new(element.r()); let trusted_element = Trusted::new(element.r());

View file

@ -37,7 +37,7 @@ use net_traits::{CoreResourceThread, ResourceThreads, IpcSend};
use profile_traits::{mem, time}; use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread}; use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEvent}; use script_traits::{MsDuration, ScriptToConstellationChan, TimerEvent};
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource}; use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
use servo_url::{MutableOrigin, ServoUrl}; use servo_url::{MutableOrigin, ServoUrl};
use std::cell::Cell; use std::cell::Cell;
@ -80,7 +80,7 @@ pub struct GlobalScope {
/// A handle for communicating messages to the constellation thread. /// A handle for communicating messages to the constellation thread.
#[ignore_heap_size_of = "channels are hard"] #[ignore_heap_size_of = "channels are hard"]
constellation_chan: IpcSender<ConstellationMsg>, script_to_constellation_chan: ScriptToConstellationChan,
#[ignore_heap_size_of = "channels are hard"] #[ignore_heap_size_of = "channels are hard"]
scheduler_chan: IpcSender<TimerSchedulerMsg>, scheduler_chan: IpcSender<TimerSchedulerMsg>,
@ -104,7 +104,7 @@ impl GlobalScope {
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
mem_profiler_chan: mem::ProfilerChan, mem_profiler_chan: mem::ProfilerChan,
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
constellation_chan: IpcSender<ConstellationMsg>, script_to_constellation_chan: ScriptToConstellationChan,
scheduler_chan: IpcSender<TimerSchedulerMsg>, scheduler_chan: IpcSender<TimerSchedulerMsg>,
resource_threads: ResourceThreads, resource_threads: ResourceThreads,
timer_event_chan: IpcSender<TimerEvent>, timer_event_chan: IpcSender<TimerEvent>,
@ -120,7 +120,7 @@ impl GlobalScope {
devtools_chan: devtools_chan, devtools_chan: devtools_chan,
mem_profiler_chan: mem_profiler_chan, mem_profiler_chan: mem_profiler_chan,
time_profiler_chan: time_profiler_chan, time_profiler_chan: time_profiler_chan,
constellation_chan: constellation_chan, script_to_constellation_chan: script_to_constellation_chan,
scheduler_chan: scheduler_chan.clone(), scheduler_chan: scheduler_chan.clone(),
in_error_reporting_mode: Default::default(), in_error_reporting_mode: Default::default(),
resource_threads: resource_threads, resource_threads: resource_threads,
@ -231,8 +231,8 @@ impl GlobalScope {
} }
/// Get a sender to the constellation thread. /// Get a sender to the constellation thread.
pub fn constellation_chan(&self) -> &IpcSender<ConstellationMsg> { pub fn script_to_constellation_chan(&self) -> &ScriptToConstellationChan {
&self.constellation_chan &self.script_to_constellation_chan
} }
pub fn scheduler_chan(&self) -> &IpcSender<TimerSchedulerMsg> { pub fn scheduler_chan(&self) -> &IpcSender<TimerSchedulerMsg> {

View file

@ -15,7 +15,7 @@ use dom::window::Window;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc; use ipc_channel::ipc;
use msg::constellation_msg::TraversalDirection; use msg::constellation_msg::TraversalDirection;
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::ScriptMsg;
// https://html.spec.whatwg.org/multipage/#the-history-interface // https://html.spec.whatwg.org/multipage/#the-history-interface
#[dom_struct] #[dom_struct]
@ -44,9 +44,8 @@ impl History {
if !self.window.Document().is_fully_active() { if !self.window.Document().is_fully_active() {
return Err(Error::Security); return Err(Error::Security);
} }
let top_level_browsing_context_id = self.window.window_proxy().top_level_browsing_context_id(); let msg = ScriptMsg::TraverseHistory(direction);
let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction); let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
let _ = self.window.upcast::<GlobalScope>().constellation_chan().send(msg);
Ok(()) Ok(())
} }
} }
@ -57,10 +56,9 @@ impl HistoryMethods for History {
if !self.window.Document().is_fully_active() { if !self.window.Document().is_fully_active() {
return Err(Error::Security); return Err(Error::Security);
} }
let top_level_browsing_context_id = self.window.window_proxy().top_level_browsing_context_id();
let (sender, recv) = ipc::channel().expect("Failed to create channel to send jsh length."); let (sender, recv) = ipc::channel().expect("Failed to create channel to send jsh length.");
let msg = ConstellationMsg::JointSessionHistoryLength(top_level_browsing_context_id, sender); let msg = ScriptMsg::JointSessionHistoryLength(sender);
let _ = self.window.upcast::<GlobalScope>().constellation_chan().send(msg); let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
Ok(recv.recv().unwrap()) Ok(recv.recv().unwrap())
} }

View file

@ -19,7 +19,7 @@ use dom::node::{Node, document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::ScriptMsg;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use style::attr::AttrValue; use style::attr::AttrValue;
use time; use time;
@ -138,8 +138,8 @@ impl VirtualMethods for HTMLBodyElement {
let window = window_from_node(self); let window = window_from_node(self);
let document = window.Document(); let document = window.Document();
document.set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY); document.set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
let event = ConstellationMsg::HeadParsed; let event = ScriptMsg::HeadParsed;
window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); window.upcast::<GlobalScope>().script_to_constellation_chan().send(event).unwrap();
} }
fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue { fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {

View file

@ -45,7 +45,7 @@ use net_traits::response::HttpsState;
use script_layout_interface::message::ReflowQueryType; use script_layout_interface::message::ReflowQueryType;
use script_thread::{ScriptThread, Runnable}; use script_thread::{ScriptThread, Runnable};
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData, UpdatePipelineIdReason}; use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData, UpdatePipelineIdReason};
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg as ConstellationMsg}; use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg};
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed}; use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use servo_atoms::Atom; use servo_atoms::Atom;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
@ -170,8 +170,8 @@ impl HTMLIFrameElement {
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap(); let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
global_scope global_scope
.constellation_chan() .script_to_constellation_chan()
.send(ConstellationMsg::ScriptNewIFrame(load_info, pipeline_sender)) .send(ScriptMsg::ScriptNewIFrame(load_info, pipeline_sender))
.unwrap(); .unwrap();
let new_layout_info = NewLayoutInfo { let new_layout_info = NewLayoutInfo {
@ -197,8 +197,8 @@ impl HTMLIFrameElement {
sandbox: sandboxed, sandbox: sandboxed,
}; };
global_scope global_scope
.constellation_chan() .script_to_constellation_chan()
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info)) .send(ScriptMsg::ScriptLoadedURLInIFrame(load_info))
.unwrap(); .unwrap();
} }
} }
@ -349,11 +349,9 @@ impl HTMLIFrameElement {
} }
pub fn set_visible(&self, visible: bool) { pub fn set_visible(&self, visible: bool) {
if let Some(pipeline_id) = self.pipeline_id.get() { let msg = ScriptMsg::SetVisible(visible);
let window = window_from_node(self); let window = window_from_node(self);
let msg = ConstellationMsg::SetVisible(pipeline_id, visible); window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg).unwrap();
window.upcast::<GlobalScope>().constellation_chan().send(msg).unwrap();
}
} }
/// https://html.spec.whatwg.org/multipage/#iframe-load-event-steps steps 1-4 /// https://html.spec.whatwg.org/multipage/#iframe-load-event-steps steps 1-4
@ -540,10 +538,10 @@ unsafe fn build_mozbrowser_event_detail(event: MozBrowserEvent,
pub fn Navigate(iframe: &HTMLIFrameElement, direction: TraversalDirection) -> ErrorResult { pub fn Navigate(iframe: &HTMLIFrameElement, direction: TraversalDirection) -> ErrorResult {
if iframe.Mozbrowser() { if iframe.Mozbrowser() {
if let Some(top_level_browsing_context_id) = iframe.top_level_browsing_context_id() { if let Some(_) = iframe.top_level_browsing_context_id() {
let window = window_from_node(iframe); let window = window_from_node(iframe);
let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction); let msg = ScriptMsg::TraverseHistory(direction);
window.upcast::<GlobalScope>().constellation_chan().send(msg).unwrap(); window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg).unwrap();
return Ok(()); return Ok(());
} }
} }
@ -795,8 +793,8 @@ impl VirtualMethods for HTMLIFrameElement {
}; };
debug!("Unbinding frame {}.", browsing_context_id); debug!("Unbinding frame {}.", browsing_context_id);
let msg = ConstellationMsg::RemoveIFrame(browsing_context_id, sender); let msg = ScriptMsg::RemoveIFrame(browsing_context_id, sender);
window.upcast::<GlobalScope>().constellation_chan().send(msg).unwrap(); window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg).unwrap();
let exited_pipeline_ids = receiver.recv().unwrap(); let exited_pipeline_ids = receiver.recv().unwrap();
// The spec for discarding is synchronous, // The spec for discarding is synchronous,

View file

@ -38,13 +38,13 @@ use dom::validitystate::ValidationFlags;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::channel;
use mime_guess; use mime_guess;
use net_traits::{CoreResourceMsg, IpcSend}; use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin; use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern}; use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
use script_layout_interface::rpc::TextIndexResponse; use script_layout_interface::rpc::TextIndexResponse;
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::ScriptToConstellationChan;
use servo_atoms::Atom; use servo_atoms::Atom;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
@ -94,7 +94,7 @@ pub struct HTMLInputElement {
maxlength: Cell<i32>, maxlength: Cell<i32>,
minlength: Cell<i32>, minlength: Cell<i32>,
#[ignore_heap_size_of = "#7193"] #[ignore_heap_size_of = "#7193"]
textinput: DOMRefCell<TextInput<IpcSender<ConstellationMsg>>>, textinput: DOMRefCell<TextInput<ScriptToConstellationChan>>,
activation_state: DOMRefCell<InputActivationState>, activation_state: DOMRefCell<InputActivationState>,
// https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag // https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag
value_dirty: Cell<bool>, value_dirty: Cell<bool>,
@ -136,7 +136,7 @@ static DEFAULT_MIN_LENGTH: i32 = -1;
impl HTMLInputElement { impl HTMLInputElement {
fn new_inherited(local_name: LocalName, prefix: Option<Prefix>, document: &Document) -> HTMLInputElement { fn new_inherited(local_name: LocalName, prefix: Option<Prefix>, document: &Document) -> HTMLInputElement {
let chan = document.window().upcast::<GlobalScope>().constellation_chan().clone(); let chan = document.window().upcast::<GlobalScope>().script_to_constellation_chan().clone();
HTMLInputElement { HTMLInputElement {
htmlelement: htmlelement:
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE | IN_READ_WRITE_STATE, HTMLElement::new_inherited_with_state(IN_ENABLED_STATE | IN_READ_WRITE_STATE,
@ -814,7 +814,7 @@ impl HTMLInputElement {
if self.Multiple() { if self.Multiple() {
let opt_test_paths = opt_test_paths.map(|paths| paths.iter().map(|p| p.to_string()).collect()); let opt_test_paths = opt_test_paths.map(|paths| paths.iter().map(|p| p.to_string()).collect());
let (chan, recv) = ipc::channel().expect("Error initializing channel"); let (chan, recv) = channel().expect("Error initializing channel");
let msg = FileManagerThreadMsg::SelectFiles(filter, chan, origin, opt_test_paths); let msg = FileManagerThreadMsg::SelectFiles(filter, chan, origin, opt_test_paths);
let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)).unwrap(); let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)).unwrap();
@ -838,7 +838,7 @@ impl HTMLInputElement {
None => None, None => None,
}; };
let (chan, recv) = ipc::channel().expect("Error initializing channel"); let (chan, recv) = channel().expect("Error initializing channel");
let msg = FileManagerThreadMsg::SelectFile(filter, chan, origin, opt_test_path); let msg = FileManagerThreadMsg::SelectFile(filter, chan, origin, opt_test_path);
let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)).unwrap(); let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)).unwrap();

View file

@ -25,7 +25,7 @@ use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use net_traits::ReferrerPolicy; use net_traits::ReferrerPolicy;
use script_layout_interface::message::Msg; use script_layout_interface::message::Msg;
use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg}; use script_traits::{MozBrowserEvent, ScriptMsg};
use servo_arc::Arc; use servo_arc::Arc;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::borrow::ToOwned; use std::borrow::ToOwned;
@ -309,8 +309,8 @@ impl HTMLLinkElement {
let document = document_from_node(self); let document = document_from_node(self);
match document.base_url().join(href) { match document.base_url().join(href) {
Ok(url) => { Ok(url) => {
let event = ConstellationMsg::NewFavicon(url.clone()); let event = ScriptMsg::NewFavicon(url.clone());
document.window().upcast::<GlobalScope>().constellation_chan().send(event).unwrap(); document.window().upcast::<GlobalScope>().script_to_constellation_chan().send(event).unwrap();
let mozbrowser_event = match *sizes { let mozbrowser_event = match *sizes {
Some(ref sizes) => MozBrowserEvent::IconChange(rel.to_owned(), url.to_string(), sizes.to_owned()), Some(ref sizes) => MozBrowserEvent::IconChange(rel.to_owned(), url.to_string(), sizes.to_owned()),

View file

@ -27,8 +27,7 @@ use dom::validation::Validatable;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use ipc_channel::ipc::IpcSender; use script_traits::ScriptToConstellationChan;
use script_traits::ScriptMsg as ConstellationMsg;
use std::cell::Cell; use std::cell::Cell;
use std::default::Default; use std::default::Default;
use std::ops::Range; use std::ops::Range;
@ -40,7 +39,7 @@ use textinput::{KeyReaction, Lines, SelectionDirection, TextInput};
pub struct HTMLTextAreaElement { pub struct HTMLTextAreaElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
#[ignore_heap_size_of = "#7193"] #[ignore_heap_size_of = "#7193"]
textinput: DOMRefCell<TextInput<IpcSender<ConstellationMsg>>>, textinput: DOMRefCell<TextInput<ScriptToConstellationChan>>,
placeholder: DOMRefCell<DOMString>, placeholder: DOMRefCell<DOMString>,
// https://html.spec.whatwg.org/multipage/#concept-textarea-dirty // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
value_changed: Cell<bool>, value_changed: Cell<bool>,
@ -109,7 +108,7 @@ impl HTMLTextAreaElement {
fn new_inherited(local_name: LocalName, fn new_inherited(local_name: LocalName,
prefix: Option<Prefix>, prefix: Option<Prefix>,
document: &Document) -> HTMLTextAreaElement { document: &Document) -> HTMLTextAreaElement {
let chan = document.window().upcast::<GlobalScope>().constellation_chan().clone(); let chan = document.window().upcast::<GlobalScope>().script_to_constellation_chan().clone();
HTMLTextAreaElement { HTMLTextAreaElement {
htmlelement: htmlelement:
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE | IN_READ_WRITE_STATE, HTMLElement::new_inherited_with_state(IN_ENABLED_STATE | IN_READ_WRITE_STATE,

View file

@ -93,7 +93,7 @@ impl ServiceWorkerMethods for ServiceWorker {
let msg_vec = DOMMessage(data.move_to_arraybuffer()); let msg_vec = DOMMessage(data.move_to_arraybuffer());
let _ = let _ =
self.global() self.global()
.constellation_chan() .script_to_constellation_chan()
.send(ScriptMsg::ForwardDOMMessage(msg_vec, self.scope_url.clone())); .send(ScriptMsg::ForwardDOMMessage(msg_vec, self.scope_url.clone()));
Ok(()) Ok(())
} }

View file

@ -151,11 +151,10 @@ impl Storage {
/// https://html.spec.whatwg.org/multipage/#send-a-storage-notification /// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
fn broadcast_change_notification(&self, key: Option<String>, old_value: Option<String>, fn broadcast_change_notification(&self, key: Option<String>, old_value: Option<String>,
new_value: Option<String>) { new_value: Option<String>) {
let pipeline_id = self.global().pipeline_id();
let storage = self.storage_type; let storage = self.storage_type;
let url = self.get_url(); let url = self.get_url();
let msg = ScriptMsg::BroadcastStorageEvent(pipeline_id, storage, url, key, old_value, new_value); let msg = ScriptMsg::BroadcastStorageEvent(storage, url, key, old_value, new_value);
self.global().constellation_chan().send(msg).unwrap(); self.global().script_to_constellation_chan().send(msg).unwrap();
} }
/// https://html.spec.whatwg.org/multipage/#send-a-storage-notification /// https://html.spec.whatwg.org/multipage/#send-a-storage-notification

View file

@ -50,7 +50,7 @@ use js::typedarray::{TypedArray, TypedArrayElement, Float32, Int32};
use net_traits::image::base::PixelFormat; use net_traits::image::base::PixelFormat;
use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageResponse;
use offscreen_gl_context::{GLContextAttributes, GLLimits}; use offscreen_gl_context::{GLContextAttributes, GLLimits};
use script_traits::ScriptMsg as ConstellationMsg; use script_traits::ScriptMsg;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashMap; use std::collections::HashMap;
@ -172,8 +172,8 @@ impl WebGLRenderingContext {
} }
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let constellation_chan = window.upcast::<GlobalScope>().constellation_chan(); let script_to_constellation_chan = window.upcast::<GlobalScope>().script_to_constellation_chan();
constellation_chan.send(ConstellationMsg::CreateWebGLPaintThread(size, attrs, sender)) script_to_constellation_chan.send(ScriptMsg::CreateWebGLPaintThread(size, attrs, sender))
.unwrap(); .unwrap();
let result = receiver.recv().unwrap(); let result = receiver.recv().unwrap();

View file

@ -80,7 +80,7 @@ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventC
use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Runnable}; use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Runnable};
use script_thread::{RunnableWrapper, ScriptThread, SendableMainThreadScriptChan}; use script_thread::{RunnableWrapper, ScriptThread, SendableMainThreadScriptChan};
use script_traits::{ConstellationControlMsg, DocumentState, LoadData, MozBrowserEvent}; use script_traits::{ConstellationControlMsg, DocumentState, LoadData, MozBrowserEvent};
use script_traits::{ScriptMsg as ConstellationMsg, ScrollState, TimerEvent, TimerEventId}; use script_traits::{ScriptToConstellationChan, ScriptMsg, ScrollState, TimerEvent, TimerEventId};
use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType}; use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use selectors::attr::CaseSensitivity; use selectors::attr::CaseSensitivity;
@ -515,11 +515,7 @@ impl WindowMethods for Window {
} }
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let global_scope = self.upcast::<GlobalScope>(); self.send_to_constellation(ScriptMsg::Alert(s.to_string(), sender));
global_scope
.constellation_chan()
.send(ConstellationMsg::Alert(global_scope.pipeline_id(), s.to_string(), sender))
.unwrap();
let should_display_alert_dialog = receiver.recv().unwrap(); let should_display_alert_dialog = receiver.recv().unwrap();
if should_display_alert_dialog { if should_display_alert_dialog {
@ -918,10 +914,7 @@ impl WindowMethods for Window {
// Step 1 // Step 1
//TODO determine if this operation is allowed //TODO determine if this operation is allowed
let size = Size2D::new(x.to_u32().unwrap_or(1), y.to_u32().unwrap_or(1)); let size = Size2D::new(x.to_u32().unwrap_or(1), y.to_u32().unwrap_or(1));
self.upcast::<GlobalScope>() self.send_to_constellation(ScriptMsg::ResizeTo(size));
.constellation_chan()
.send(ConstellationMsg::ResizeTo(size))
.unwrap()
} }
// https://drafts.csswg.org/cssom-view/#dom-window-resizeby // https://drafts.csswg.org/cssom-view/#dom-window-resizeby
@ -936,10 +929,7 @@ impl WindowMethods for Window {
// Step 1 // Step 1
//TODO determine if this operation is allowed //TODO determine if this operation is allowed
let point = Point2D::new(x, y); let point = Point2D::new(x, y);
self.upcast::<GlobalScope>() self.send_to_constellation(ScriptMsg::MoveTo(point));
.constellation_chan()
.send(ConstellationMsg::MoveTo(point))
.unwrap()
} }
// https://drafts.csswg.org/cssom-view/#dom-window-moveby // https://drafts.csswg.org/cssom-view/#dom-window-moveby
@ -1159,9 +1149,8 @@ impl Window {
scroll_offset: Vector2D::new(-x, -y), scroll_offset: Vector2D::new(-x, -y),
})).unwrap(); })).unwrap();
let global_scope = self.upcast::<GlobalScope>(); let message = ScriptMsg::ScrollFragmentPoint(scroll_root_id, point, smooth);
let message = ConstellationMsg::ScrollFragmentPoint(scroll_root_id, point, smooth); self.send_to_constellation(message);
global_scope.constellation_chan().send(message).unwrap();
} }
pub fn update_viewport_for_scroll(&self, x: f32, y: f32) { pub fn update_viewport_for_scroll(&self, x: f32, y: f32) {
@ -1172,10 +1161,7 @@ impl Window {
pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) {
let (send, recv) = ipc::channel::<(Size2D<u32>, Point2D<i32>)>().unwrap(); let (send, recv) = ipc::channel::<(Size2D<u32>, Point2D<i32>)>().unwrap();
self.upcast::<GlobalScope>() self.send_to_constellation(ScriptMsg::GetClientWindow(send));
.constellation_chan()
.send(ConstellationMsg::GetClientWindow(send))
.unwrap();
recv.recv().unwrap_or((Size2D::zero(), Point2D::zero())) recv.recv().unwrap_or((Size2D::zero(), Point2D::zero()))
} }
@ -1371,9 +1357,8 @@ impl Window {
let pending_images = self.pending_layout_images.borrow().is_empty(); let pending_images = self.pending_layout_images.borrow().is_empty();
if ready_state == DocumentReadyState::Complete && !reftest_wait && pending_images { if ready_state == DocumentReadyState::Complete && !reftest_wait && pending_images {
let global_scope = self.upcast::<GlobalScope>(); let event = ScriptMsg::SetDocumentState(DocumentState::Idle);
let event = ConstellationMsg::SetDocumentState(global_scope.pipeline_id(), DocumentState::Idle); self.send_to_constellation(event);
global_scope.constellation_chan().send(event).unwrap();
} }
} }
@ -1779,6 +1764,13 @@ impl Window {
self.navigation_start.set(now); self.navigation_start.set(now);
self.navigation_start_precise.set(time::precise_time_ns() as f64); self.navigation_start_precise.set(time::precise_time_ns() as f64);
} }
fn send_to_constellation(&self, msg: ScriptMsg) {
self.upcast::<GlobalScope>()
.script_to_constellation_chan()
.send(msg)
.unwrap();
}
} }
impl Window { impl Window {
@ -1797,7 +1789,7 @@ impl Window {
mem_profiler_chan: MemProfilerChan, mem_profiler_chan: MemProfilerChan,
time_profiler_chan: TimeProfilerChan, time_profiler_chan: TimeProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
constellation_chan: IpcSender<ConstellationMsg>, constellation_chan: ScriptToConstellationChan,
control_chan: IpcSender<ConstellationControlMsg>, control_chan: IpcSender<ConstellationControlMsg>,
scheduler_chan: IpcSender<TimerSchedulerMsg>, scheduler_chan: IpcSender<TimerSchedulerMsg>,
timer_event_chan: IpcSender<TimerEvent>, timer_event_chan: IpcSender<TimerEvent>,

View file

@ -55,7 +55,7 @@ pub fn prepare_workerscope_init(global: &GlobalScope,
to_devtools_sender: global.devtools_chan().cloned(), to_devtools_sender: global.devtools_chan().cloned(),
time_profiler_chan: global.time_profiler_chan().clone(), time_profiler_chan: global.time_profiler_chan().clone(),
from_devtools_sender: devtools_sender, from_devtools_sender: devtools_sender,
constellation_chan: global.constellation_chan().clone(), script_to_constellation_chan: global.script_to_constellation_chan().clone(),
scheduler_chan: global.scheduler_chan().clone(), scheduler_chan: global.scheduler_chan().clone(),
worker_id: global.get_next_worker_id(), worker_id: global.get_next_worker_id(),
pipeline_id: global.pipeline_id(), pipeline_id: global.pipeline_id(),
@ -107,7 +107,7 @@ impl WorkerGlobalScope {
init.to_devtools_sender, init.to_devtools_sender,
init.mem_profiler_chan, init.mem_profiler_chan,
init.time_profiler_chan, init.time_profiler_chan,
init.constellation_chan, init.script_to_constellation_chan,
init.scheduler_chan, init.scheduler_chan,
init.resource_threads, init.resource_threads,
timer_event_chan, timer_event_chan,

View file

@ -609,7 +609,7 @@ impl WorkletThread {
if old_counter == 1 { if old_counter == 1 {
debug!("Resolving promise."); debug!("Resolving promise.");
let msg = MainThreadScriptMsg::WorkletLoaded(pipeline_id); let msg = MainThreadScriptMsg::WorkletLoaded(pipeline_id);
self.global_init.script_sender.send(msg).expect("Worklet thread outlived script thread."); self.global_init.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread.");
self.run_in_script_thread(promise.resolve_runnable(())); self.run_in_script_thread(promise.resolve_runnable(()));
} }
} }
@ -651,7 +651,7 @@ impl WorkletThread {
{ {
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable); let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable);
let msg = MainThreadScriptMsg::Common(msg); let msg = MainThreadScriptMsg::Common(msg);
self.global_init.script_sender.send(msg).expect("Worklet thread outlived script thread."); self.global_init.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread.");
} }
} }

View file

@ -31,6 +31,7 @@ use script_thread::MainThreadScriptMsg;
use script_thread::Runnable; use script_thread::Runnable;
use script_thread::ScriptThread; use script_thread::ScriptThread;
use script_traits::ScriptMsg; use script_traits::ScriptMsg;
use script_traits::ScriptToConstellationChan;
use script_traits::TimerSchedulerMsg; use script_traits::TimerSchedulerMsg;
use servo_url::ImmutableOrigin; use servo_url::ImmutableOrigin;
use servo_url::MutableOrigin; use servo_url::MutableOrigin;
@ -49,7 +50,7 @@ pub struct WorkletGlobalScope {
microtask_queue: MicrotaskQueue, microtask_queue: MicrotaskQueue,
/// Sender back to the script thread /// Sender back to the script thread
#[ignore_heap_size_of = "channels are hard"] #[ignore_heap_size_of = "channels are hard"]
script_sender: Sender<MainThreadScriptMsg>, to_script_thread_sender: Sender<MainThreadScriptMsg>,
/// Worklet task executor /// Worklet task executor
executor: WorkletExecutor, executor: WorkletExecutor,
} }
@ -63,19 +64,23 @@ impl WorkletGlobalScope {
-> WorkletGlobalScope { -> WorkletGlobalScope {
// Any timer events fired on this global are ignored. // Any timer events fired on this global are ignored.
let (timer_event_chan, _) = ipc::channel().unwrap(); let (timer_event_chan, _) = ipc::channel().unwrap();
let script_to_constellation_chan = ScriptToConstellationChan {
sender: init.to_constellation_sender.clone(),
pipeline_id: pipeline_id,
};
WorkletGlobalScope { WorkletGlobalScope {
globalscope: GlobalScope::new_inherited(pipeline_id, globalscope: GlobalScope::new_inherited(pipeline_id,
init.devtools_chan.clone(), init.devtools_chan.clone(),
init.mem_profiler_chan.clone(), init.mem_profiler_chan.clone(),
init.time_profiler_chan.clone(), init.time_profiler_chan.clone(),
init.constellation_chan.clone(), script_to_constellation_chan,
init.scheduler_chan.clone(), init.scheduler_chan.clone(),
init.resource_threads.clone(), init.resource_threads.clone(),
timer_event_chan, timer_event_chan,
MutableOrigin::new(ImmutableOrigin::new_opaque())), MutableOrigin::new(ImmutableOrigin::new_opaque())),
base_url: base_url, base_url: base_url,
microtask_queue: MicrotaskQueue::default(), microtask_queue: MicrotaskQueue::default(),
script_sender: init.script_sender.clone(), to_script_thread_sender: init.to_script_thread_sender.clone(),
executor: executor, executor: executor,
} }
} }
@ -98,7 +103,7 @@ impl WorkletGlobalScope {
{ {
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable); let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable);
let msg = MainThreadScriptMsg::Common(msg); let msg = MainThreadScriptMsg::Common(msg);
self.script_sender.send(msg).expect("Worklet thread outlived script thread."); self.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread.");
} }
/// Send a message to layout. /// Send a message to layout.
@ -156,7 +161,7 @@ impl WorkletGlobalScope {
#[derive(Clone)] #[derive(Clone)]
pub struct WorkletGlobalScopeInit { pub struct WorkletGlobalScopeInit {
/// Channel to the main script thread /// Channel to the main script thread
pub script_sender: Sender<MainThreadScriptMsg>, pub to_script_thread_sender: Sender<MainThreadScriptMsg>,
/// Channel to a resource thread /// Channel to a resource thread
pub resource_threads: ResourceThreads, pub resource_threads: ResourceThreads,
/// Channel to the memory profiler /// Channel to the memory profiler
@ -166,7 +171,7 @@ pub struct WorkletGlobalScopeInit {
/// Channel to devtools /// Channel to devtools
pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
/// Messages to send to constellation /// Messages to send to constellation
pub constellation_chan: IpcSender<ScriptMsg>, pub to_constellation_sender: IpcSender<(PipelineId, ScriptMsg)>,
/// Message to send to the scheduler /// Message to send to the scheduler
pub scheduler_chan: IpcSender<TimerSchedulerMsg>, pub scheduler_chan: IpcSender<TimerSchedulerMsg>,
/// The image cache /// The image cache

View file

@ -87,7 +87,7 @@ use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
use script_traits::{CompositorEvent, ConstellationControlMsg}; use script_traits::{CompositorEvent, ConstellationControlMsg};
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult}; use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg, UpdatePipelineIdReason}; use script_traits::{NewLayoutInfo, ScriptToConstellationChan, ScriptMsg, UpdatePipelineIdReason};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource}; use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource};
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType}; use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent}; use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
@ -462,7 +462,7 @@ pub struct ScriptThread {
control_port: Receiver<ConstellationControlMsg>, control_port: Receiver<ConstellationControlMsg>,
/// For communicating load url messages to the constellation /// For communicating load url messages to the constellation
constellation_chan: IpcSender<ConstellationMsg>, script_sender: IpcSender<(PipelineId, ScriptMsg)>,
/// A sender for new layout threads to communicate to the constellation. /// A sender for new layout threads to communicate to the constellation.
layout_to_constellation_chan: IpcSender<LayoutMsg>, layout_to_constellation_chan: IpcSender<LayoutMsg>,
@ -733,12 +733,12 @@ impl ScriptThread {
let script_thread = unsafe { &*root.get().unwrap() }; let script_thread = unsafe { &*root.get().unwrap() };
script_thread.worklet_thread_pool.borrow_mut().get_or_insert_with(|| { script_thread.worklet_thread_pool.borrow_mut().get_or_insert_with(|| {
let init = WorkletGlobalScopeInit { let init = WorkletGlobalScopeInit {
script_sender: script_thread.chan.0.clone(), to_script_thread_sender: script_thread.chan.0.clone(),
resource_threads: script_thread.resource_threads.clone(), resource_threads: script_thread.resource_threads.clone(),
mem_profiler_chan: script_thread.mem_profiler_chan.clone(), mem_profiler_chan: script_thread.mem_profiler_chan.clone(),
time_profiler_chan: script_thread.time_profiler_chan.clone(), time_profiler_chan: script_thread.time_profiler_chan.clone(),
devtools_chan: script_thread.devtools_chan.clone(), devtools_chan: script_thread.devtools_chan.clone(),
constellation_chan: script_thread.constellation_chan.clone(), to_constellation_sender: script_thread.script_sender.clone(),
scheduler_chan: script_thread.scheduler_chan.clone(), scheduler_chan: script_thread.scheduler_chan.clone(),
image_cache: script_thread.image_cache.clone(), image_cache: script_thread.image_cache.clone(),
}; };
@ -855,7 +855,7 @@ impl ScriptThread {
control_chan: state.control_chan, control_chan: state.control_chan,
control_port: control_port, control_port: control_port,
constellation_chan: state.constellation_chan, script_sender: state.script_to_constellation_chan.sender.clone(),
time_profiler_chan: state.time_profiler_chan, time_profiler_chan: state.time_profiler_chan,
mem_profiler_chan: state.mem_profiler_chan, mem_profiler_chan: state.mem_profiler_chan,
@ -1543,7 +1543,7 @@ impl ScriptThread {
fn handle_visibility_change_msg(&self, id: PipelineId, visible: bool) { fn handle_visibility_change_msg(&self, id: PipelineId, visible: bool) {
// Separate message sent since parent script thread could be different (Iframe of different // Separate message sent since parent script thread could be different (Iframe of different
// domain) // domain)
self.constellation_chan.send(ConstellationMsg::VisibilityChangeComplete(id, visible)).unwrap(); self.script_sender.send((id, ScriptMsg::VisibilityChangeComplete(visible))).unwrap();
let window = self.documents.borrow().find_window(id); let window = self.documents.borrow().find_window(id);
match window { match window {
@ -1643,13 +1643,13 @@ impl ScriptThread {
/// constellation to shut down the pipeline, which will clean everything up /// constellation to shut down the pipeline, which will clean everything up
/// normally. If we do exit, we will tear down the DOM nodes, possibly at a point /// normally. If we do exit, we will tear down the DOM nodes, possibly at a point
/// where layout is still accessing them. /// where layout is still accessing them.
fn handle_exit_window_msg(&self, _: PipelineId) { fn handle_exit_window_msg(&self, id: PipelineId) {
debug!("script thread handling exit window msg"); debug!("script thread handling exit window msg");
// TODO(tkuehn): currently there is only one window, // TODO(tkuehn): currently there is only one window,
// so this can afford to be naive and just shut down the // so this can afford to be naive and just shut down the
// constellation. In the future it'll need to be smarter. // constellation. In the future it'll need to be smarter.
self.constellation_chan.send(ConstellationMsg::Exit).unwrap(); self.script_sender.send((id, ScriptMsg::Exit)).unwrap();
} }
/// We have received notification that the response associated with a load has completed. /// We have received notification that the response associated with a load has completed.
@ -1701,7 +1701,7 @@ impl ScriptThread {
let script_url = maybe_registration.get_installed().get_script_url(); let script_url = maybe_registration.get_installed().get_script_url();
let scope_things = ServiceWorkerRegistration::create_scope_things(window.upcast(), script_url); let scope_things = ServiceWorkerRegistration::create_scope_things(window.upcast(), script_url);
let _ = self.constellation_chan.send(ConstellationMsg::RegisterServiceWorker(scope_things, scope.clone())); let _ = self.script_sender.send((pipeline_id, ScriptMsg::RegisterServiceWorker(scope_things, scope.clone())));
} }
pub fn dispatch_job_queue(&self, job_handler: Box<AsyncJobHandler>) { pub fn dispatch_job_queue(&self, job_handler: Box<AsyncJobHandler>) {
@ -1718,7 +1718,7 @@ impl ScriptThread {
Some(document) => document, Some(document) => document,
None => return warn!("Message sent to closed pipeline {}.", pipeline_id), None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
}; };
document.send_title_to_compositor(); document.send_title_to_constellation();
} }
/// Handles a request to exit a pipeline and shut down layout. /// Handles a request to exit a pipeline and shut down layout.
@ -1758,7 +1758,7 @@ impl ScriptThread {
debug!("shutting down layout for page {}", id); debug!("shutting down layout for page {}", id);
let _ = response_port.recv(); let _ = response_port.recv();
chan.send(message::Msg::ExitNow).ok(); chan.send(message::Msg::ExitNow).ok();
self.constellation_chan.send(ConstellationMsg::PipelineExited(id)).ok(); self.script_sender.send((id, ScriptMsg::PipelineExited)).ok();
debug!("Exited pipeline {}.", id); debug!("Exited pipeline {}.", id);
} }
@ -1883,15 +1883,15 @@ impl ScriptThread {
fn ask_constellation_for_browsing_context_id(&self, pipeline_id: PipelineId) -> Option<BrowsingContextId> { fn ask_constellation_for_browsing_context_id(&self, pipeline_id: PipelineId) -> Option<BrowsingContextId> {
let (result_sender, result_receiver) = ipc::channel().unwrap(); let (result_sender, result_receiver) = ipc::channel().unwrap();
let msg = ConstellationMsg::GetBrowsingContextId(pipeline_id, result_sender); let msg = ScriptMsg::GetBrowsingContextId(pipeline_id, result_sender);
self.constellation_chan.send(msg).expect("Failed to send to constellation."); self.script_sender.send((pipeline_id, msg)).expect("Failed to send to constellation.");
result_receiver.recv().expect("Failed to get frame id from constellation.") result_receiver.recv().expect("Failed to get frame id from constellation.")
} }
fn ask_constellation_for_parent_info(&self, pipeline_id: PipelineId) -> Option<(PipelineId, FrameType)> { fn ask_constellation_for_parent_info(&self, pipeline_id: PipelineId) -> Option<(PipelineId, FrameType)> {
let (result_sender, result_receiver) = ipc::channel().unwrap(); let (result_sender, result_receiver) = ipc::channel().unwrap();
let msg = ConstellationMsg::GetParentInfo(pipeline_id, result_sender); let msg = ScriptMsg::GetParentInfo(pipeline_id, result_sender);
self.constellation_chan.send(msg).expect("Failed to send to constellation."); self.script_sender.send((pipeline_id, msg)).expect("Failed to send to constellation.");
result_receiver.recv().expect("Failed to get frame id from constellation.") result_receiver.recv().expect("Failed to get frame id from constellation.")
} }
@ -1976,8 +1976,8 @@ impl ScriptThread {
.unwrap(); .unwrap();
// update the pipeline url // update the pipeline url
self.constellation_chan self.script_sender
.send(ConstellationMsg::SetFinalUrl(incomplete.pipeline_id, final_url.clone())) .send((incomplete.pipeline_id, ScriptMsg::SetFinalUrl(final_url.clone())))
.unwrap(); .unwrap();
} }
debug!("ScriptThread: loading {} on pipeline {:?}", incomplete.url, incomplete.pipeline_id); debug!("ScriptThread: loading {} on pipeline {:?}", incomplete.url, incomplete.pipeline_id);
@ -1997,6 +1997,11 @@ impl ScriptThread {
MutableOrigin::new(final_url.origin()) MutableOrigin::new(final_url.origin())
}; };
let script_to_constellation_chan = ScriptToConstellationChan {
sender: self.script_sender.clone(),
pipeline_id: incomplete.pipeline_id,
};
// Create the window and document objects. // Create the window and document objects.
let window = Window::new(self.js_runtime.clone(), let window = Window::new(self.js_runtime.clone(),
MainThreadScriptChan(sender.clone()), MainThreadScriptChan(sender.clone()),
@ -2012,7 +2017,7 @@ impl ScriptThread {
self.mem_profiler_chan.clone(), self.mem_profiler_chan.clone(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
self.devtools_chan.clone(), self.devtools_chan.clone(),
self.constellation_chan.clone(), script_to_constellation_chan,
self.control_chan.clone(), self.control_chan.clone(),
self.scheduler_chan.clone(), self.scheduler_chan.clone(),
ipc_timer_event_chan, ipc_timer_event_chan,
@ -2082,8 +2087,8 @@ impl ScriptThread {
window.init_document(&document); window.init_document(&document);
self.constellation_chan self.script_sender
.send(ConstellationMsg::ActivateDocument(incomplete.pipeline_id)) .send((incomplete.pipeline_id, ScriptMsg::ActivateDocument))
.unwrap(); .unwrap();
// Notify devtools that a new script global exists. // Notify devtools that a new script global exists.
@ -2210,8 +2215,8 @@ impl ScriptThread {
url.join(&value).map(|url| url.to_string()).ok() url.join(&value).map(|url| url.to_string()).ok()
}); });
let event = ConstellationMsg::NodeStatus(status); let event = ScriptMsg::NodeStatus(status);
self.constellation_chan.send(event).unwrap(); self.script_sender.send((pipeline_id, event)).unwrap();
state_already_changed = true; state_already_changed = true;
} }
@ -2224,8 +2229,8 @@ impl ScriptThread {
.inclusive_ancestors() .inclusive_ancestors()
.filter_map(Root::downcast::<HTMLAnchorElement>) .filter_map(Root::downcast::<HTMLAnchorElement>)
.next() { .next() {
let event = ConstellationMsg::NodeStatus(None); let event = ScriptMsg::NodeStatus(None);
self.constellation_chan.send(event).unwrap(); self.script_sender.send((pipeline_id, event)).unwrap();
} }
} }
} }
@ -2240,8 +2245,8 @@ impl ScriptThread {
} else { } else {
EventResult::DefaultPrevented EventResult::DefaultPrevented
}; };
let message = ConstellationMsg::TouchEventProcessed(result); let message = ScriptMsg::TouchEventProcessed(result);
self.constellation_chan.send(message).unwrap(); self.script_sender.send((pipeline_id, message)).unwrap();
} }
_ => { _ => {
// TODO: Calling preventDefault on a touchup event should prevent clicks. // TODO: Calling preventDefault on a touchup event should prevent clicks.
@ -2262,7 +2267,7 @@ impl ScriptThread {
Some(document) => document, Some(document) => document,
None => return warn!("Message sent to closed pipeline {}.", pipeline_id), None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
}; };
document.dispatch_key_event(ch, key, state, modifiers, &self.constellation_chan); document.dispatch_key_event(ch, key, state, modifiers);
} }
} }
} }
@ -2310,8 +2315,8 @@ impl ScriptThread {
} }
} }
None => { None => {
self.constellation_chan self.script_sender
.send(ConstellationMsg::LoadUrl(parent_pipeline_id, load_data, replace)) .send((parent_pipeline_id, ScriptMsg::LoadUrl(load_data, replace)))
.unwrap(); .unwrap();
} }
} }
@ -2371,7 +2376,7 @@ impl ScriptThread {
let context = ParserContext::new(id, load_data.url); let context = ParserContext::new(id, load_data.url);
self.incomplete_parser_contexts.borrow_mut().push((id, context)); self.incomplete_parser_contexts.borrow_mut().push((id, context));
self.constellation_chan.send(ConstellationMsg::InitiateNavigateRequest(req_init, id)).unwrap(); self.script_sender.send((id, ScriptMsg::InitiateNavigateRequest(req_init))).unwrap();
self.incomplete_loads.borrow_mut().push(incomplete); self.incomplete_loads.borrow_mut().push(incomplete);
} }

View file

@ -45,6 +45,7 @@ use gfx_traits::Epoch;
use heapsize::HeapSizeOf; use heapsize::HeapSizeOf;
use hyper::header::Headers; use hyper::header::Headers;
use hyper::method::Method; use hyper::method::Method;
use ipc_channel::{Error as IpcError};
use ipc_channel::ipc::{IpcReceiver, IpcSender}; use ipc_channel::ipc::{IpcReceiver, IpcSender};
use libc::c_void; use libc::c_void;
use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, FrameType, Key, KeyModifiers, KeyState}; use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, FrameType, Key, KeyModifiers, KeyState};
@ -500,7 +501,7 @@ pub struct InitialScriptState {
/// A port on which messages sent by the constellation to script can be received. /// A port on which messages sent by the constellation to script can be received.
pub control_port: IpcReceiver<ConstellationControlMsg>, pub control_port: IpcReceiver<ConstellationControlMsg>,
/// A channel on which messages can be sent to the constellation from script. /// A channel on which messages can be sent to the constellation from script.
pub constellation_chan: IpcSender<ScriptMsg>, pub script_to_constellation_chan: ScriptToConstellationChan,
/// A sender for the layout thread to communicate to the constellation. /// A sender for the layout thread to communicate to the constellation.
pub layout_to_constellation_chan: IpcSender<LayoutMsg>, pub layout_to_constellation_chan: IpcSender<LayoutMsg>,
/// A channel to schedule timer events. /// A channel to schedule timer events.
@ -740,14 +741,12 @@ pub enum ConstellationMsg {
/// Request that the constellation send the current focused top-level browsing context id, /// Request that the constellation send the current focused top-level browsing context id,
/// over a provided channel. /// over a provided channel.
GetFocusTopLevelBrowsingContext(IpcSender<Option<TopLevelBrowsingContextId>>), GetFocusTopLevelBrowsingContext(IpcSender<Option<TopLevelBrowsingContextId>>),
/// Request to load the initial page.
InitLoadUrl(ServoUrl),
/// Query the constellation to see if the current compositor output is stable /// Query the constellation to see if the current compositor output is stable
IsReadyToSaveImage(HashMap<PipelineId, Epoch>), IsReadyToSaveImage(HashMap<PipelineId, Epoch>),
/// Inform the constellation of a key event. /// Inform the constellation of a key event.
KeyEvent(Option<char>, Key, KeyState, KeyModifiers), KeyEvent(Option<char>, Key, KeyState, KeyModifiers),
/// Request to load a page. /// Request to load a page.
LoadUrl(PipelineId, LoadData), LoadUrl(TopLevelBrowsingContextId, ServoUrl),
/// Request to traverse the joint session history of the provided browsing context. /// Request to traverse the joint session history of the provided browsing context.
TraverseHistory(TopLevelBrowsingContextId, TraversalDirection), TraverseHistory(TopLevelBrowsingContextId, TraversalDirection),
/// Inform the constellation of a window being resized. /// Inform the constellation of a window being resized.
@ -764,6 +763,10 @@ pub enum ConstellationMsg {
SetWebVRThread(IpcSender<WebVRMsg>), SetWebVRThread(IpcSender<WebVRMsg>),
/// Dispatch WebVR events to the subscribed script threads. /// Dispatch WebVR events to the subscribed script threads.
WebVREvents(Vec<PipelineId>, Vec<WebVREvent>), WebVREvents(Vec<PipelineId>, Vec<WebVREvent>),
/// Create a new top level browsing context.
NewBrowser(ServoUrl, IpcSender<TopLevelBrowsingContextId>),
/// Make browser visible.
SelectBrowser(TopLevelBrowsingContextId),
} }
/// Resources required by workerglobalscopes /// Resources required by workerglobalscopes
@ -780,7 +783,7 @@ pub struct WorkerGlobalScopeInit {
/// From devtools sender /// From devtools sender
pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>, pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
/// Messages to send to constellation /// Messages to send to constellation
pub constellation_chan: IpcSender<ScriptMsg>, pub script_to_constellation_chan: ScriptToConstellationChan,
/// Message to send to the scheduler /// Message to send to the scheduler
pub scheduler_chan: IpcSender<TimerSchedulerMsg>, pub scheduler_chan: IpcSender<TimerSchedulerMsg>,
/// The worker id /// The worker id
@ -843,3 +846,19 @@ pub struct DrawAPaintImageResult {
/// Drawing the image might have requested loading some image URLs. /// Drawing the image might have requested loading some image URLs.
pub missing_image_urls: Vec<ServoUrl>, pub missing_image_urls: Vec<ServoUrl>,
} }
/// A Script to Constellation channel.
#[derive(Deserialize, Serialize, Clone)]
pub struct ScriptToConstellationChan {
/// Sender for communicating with constellation thread.
pub sender: IpcSender<(PipelineId, ScriptMsg)>,
/// 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: ScriptMsg) -> Result<(), IpcError> {
self.sender.send((self.pipeline_id, msg))
}
}

View file

@ -16,7 +16,7 @@ use canvas_traits::CanvasMsg;
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use euclid::{Point2D, Size2D, TypedSize2D}; use euclid::{Point2D, Size2D, TypedSize2D};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, FrameType, PipelineId, TraversalDirection}; use msg::constellation_msg::{BrowsingContextId, FrameType, PipelineId, TraversalDirection};
use msg::constellation_msg::{Key, KeyModifiers, KeyState}; use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use net_traits::CoreResourceMsg; use net_traits::CoreResourceMsg;
use net_traits::request::RequestInit; use net_traits::request::RequestInit;
@ -69,12 +69,12 @@ pub enum LogEntry {
pub enum ScriptMsg { pub enum ScriptMsg {
/// Requests are sent to constellation and fetches are checked manually /// Requests are sent to constellation and fetches are checked manually
/// for cross-origin loads /// for cross-origin loads
InitiateNavigateRequest(RequestInit, PipelineId), InitiateNavigateRequest(RequestInit),
/// Broadcast a storage event to every same-origin pipeline. /// Broadcast a storage event to every same-origin pipeline.
/// The strings are key, old value and new value. /// The strings are key, old value and new value.
BroadcastStorageEvent(PipelineId, StorageType, ServoUrl, Option<String>, Option<String>, Option<String>), BroadcastStorageEvent(StorageType, ServoUrl, Option<String>, Option<String>, Option<String>),
/// Indicates whether this pipeline is currently running animations. /// Indicates whether this pipeline is currently running animations.
ChangeRunningAnimationsState(PipelineId, AnimationState), ChangeRunningAnimationsState(AnimationState),
/// Requests that a new 2D canvas thread be created. (This is done in the constellation because /// 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.) /// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.)
CreateCanvasPaintThread(Size2D<i32>, IpcSender<IpcSender<CanvasMsg>>), CreateCanvasPaintThread(Size2D<i32>, IpcSender<IpcSender<CanvasMsg>>),
@ -84,7 +84,7 @@ pub enum ScriptMsg {
GLContextAttributes, GLContextAttributes,
IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>), IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>),
/// Notifies the constellation that this frame has received focus. /// Notifies the constellation that this frame has received focus.
Focus(PipelineId), Focus,
/// Forward an event that was sent to the parent window. /// Forward an event that was sent to the parent window.
ForwardEvent(PipelineId, CompositorEvent), ForwardEvent(PipelineId, CompositorEvent),
/// Requests that the constellation retrieve the current contents of the clipboard /// Requests that the constellation retrieve the current contents of the clipboard
@ -97,18 +97,18 @@ pub enum ScriptMsg {
HeadParsed, HeadParsed,
/// All pending loads are complete, and the `load` event for this pipeline /// All pending loads are complete, and the `load` event for this pipeline
/// has been dispatched. /// has been dispatched.
LoadComplete(PipelineId), LoadComplete,
/// A new load has been requested, with an option to replace the current entry once loaded /// A new load has been requested, with an option to replace the current entry once loaded
/// instead of adding a new entry. /// instead of adding a new entry.
LoadUrl(PipelineId, LoadData, bool), LoadUrl(LoadData, bool),
/// Post a message to the currently active window of a given browsing context. /// Post a message to the currently active window of a given browsing context.
PostMessage(BrowsingContextId, Option<ImmutableOrigin>, Vec<u8>), PostMessage(BrowsingContextId, Option<ImmutableOrigin>, Vec<u8>),
/// Dispatch a mozbrowser event to the parent of a mozbrowser iframe. /// Dispatch a mozbrowser event to the parent of a mozbrowser iframe.
MozBrowserEvent(PipelineId, TopLevelBrowsingContextId, MozBrowserEvent), MozBrowserEvent(PipelineId, MozBrowserEvent),
/// HTMLIFrameElement Forward or Back traversal. /// HTMLIFrameElement Forward or Back traversal.
TraverseHistory(TopLevelBrowsingContextId, TraversalDirection), TraverseHistory(TraversalDirection),
/// Gets the length of the joint session history from the constellation. /// Gets the length of the joint session history from the constellation.
JointSessionHistoryLength(TopLevelBrowsingContextId, IpcSender<u32>), JointSessionHistoryLength(IpcSender<u32>),
/// Favicon detected /// Favicon detected
NewFavicon(ServoUrl), NewFavicon(ServoUrl),
/// Status message to be displayed in the chrome, eg. a link URL on mouseover. /// Status message to be displayed in the chrome, eg. a link URL on mouseover.
@ -117,9 +117,9 @@ pub enum ScriptMsg {
/// Returns a list of pipelines which were closed. /// Returns a list of pipelines which were closed.
RemoveIFrame(BrowsingContextId, IpcSender<Vec<PipelineId>>), RemoveIFrame(BrowsingContextId, IpcSender<Vec<PipelineId>>),
/// Change pipeline visibility /// Change pipeline visibility
SetVisible(PipelineId, bool), SetVisible(bool),
/// Notifies constellation that an iframe's visibility has been changed. /// Notifies constellation that an iframe's visibility has been changed.
VisibilityChangeComplete(PipelineId, bool), VisibilityChangeComplete(bool),
/// A load has been requested in an IFrame. /// A load has been requested in an IFrame.
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData), ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
/// A load of the initial `about:blank` has been completed in an IFrame. /// A load of the initial `about:blank` has been completed in an IFrame.
@ -127,18 +127,18 @@ pub enum ScriptMsg {
/// Requests that the constellation set the contents of the clipboard /// Requests that the constellation set the contents of the clipboard
SetClipboardContents(String), SetClipboardContents(String),
/// Mark a new document as active /// Mark a new document as active
ActivateDocument(PipelineId), ActivateDocument,
/// Set the document state for a pipeline (used by screenshot / reftests) /// Set the document state for a pipeline (used by screenshot / reftests)
SetDocumentState(PipelineId, DocumentState), SetDocumentState(DocumentState),
/// Update the pipeline Url, which can change after redirections. /// Update the pipeline Url, which can change after redirections.
SetFinalUrl(PipelineId, ServoUrl), SetFinalUrl(ServoUrl),
/// Check if an alert dialog box should be presented /// Check if an alert dialog box should be presented
Alert(PipelineId, String, IpcSender<bool>), Alert(String, IpcSender<bool>),
/// Scroll a page in a window /// Scroll a page in a window
ScrollFragmentPoint(ClipId, Point2D<f32>, bool), ScrollFragmentPoint(ClipId, Point2D<f32>, bool),
/// Set title of current page /// Set title of current page
/// https://html.spec.whatwg.org/multipage/#document.title /// https://html.spec.whatwg.org/multipage/#document.title
SetTitle(PipelineId, Option<String>), SetTitle(Option<String>),
/// Send a key event /// Send a key event
SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers), SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers),
/// Get Window Informations size and position /// Get Window Informations size and position
@ -150,9 +150,9 @@ pub enum ScriptMsg {
/// Script has handled a touch event, and either prevented or allowed default actions. /// Script has handled a touch event, and either prevented or allowed default actions.
TouchEventProcessed(EventResult), TouchEventProcessed(EventResult),
/// A log entry, with the top-level browsing context id and thread name /// A log entry, with the top-level browsing context id and thread name
LogEntry(Option<TopLevelBrowsingContextId>, Option<String>, LogEntry), LogEntry(Option<String>, LogEntry),
/// Notifies the constellation that this pipeline has exited. /// Notifies the constellation that this pipeline has exited.
PipelineExited(PipelineId), PipelineExited,
/// Send messages from postMessage calls from serviceworker /// Send messages from postMessage calls from serviceworker
/// to constellation for storing in service worker manager /// to constellation for storing in service worker manager
ForwardDOMMessage(DOMMessage, ServoUrl), ForwardDOMMessage(DOMMessage, ServoUrl),

View file

@ -5,16 +5,16 @@
//! Servo, the mighty web browser engine from the future. //! Servo, the mighty web browser engine from the future.
//! //!
//! This is a very simple library that wires all of Servo's components //! This is a very simple library that wires all of Servo's components
//! together as type `Browser`, along with a generic client //! together as type `Servo`, along with a generic client
//! implementing the `WindowMethods` trait, to create a working web //! implementing the `WindowMethods` trait, to create a working web
//! browser. //! browser.
//! //!
//! The `Browser` type is responsible for configuring a //! The `Servo` type is responsible for configuring a
//! `Constellation`, which does the heavy lifting of coordinating all //! `Constellation`, which does the heavy lifting of coordinating all
//! of Servo's internal subsystems, including the `ScriptThread` and the //! of Servo's internal subsystems, including the `ScriptThread` and the
//! `LayoutThread`, as well maintains the navigation context. //! `LayoutThread`, as well maintains the navigation context.
//! //!
//! The `Browser` is fed events from a generic type that implements the //! `Servo` is fed events from a generic type that implements the
//! `WindowMethods` trait. //! `WindowMethods` trait.
extern crate env_logger; extern crate env_logger;
@ -88,11 +88,10 @@ use profile::mem as profile_mem;
use profile::time as profile_time; use profile::time as profile_time;
use profile_traits::mem; use profile_traits::mem;
use profile_traits::time; use profile_traits::time;
use script_traits::{ConstellationMsg, SWManagerSenders, ScriptMsg}; use script_traits::{ConstellationMsg, SWManagerSenders, ScriptToConstellationChan};
use servo_config::opts; use servo_config::opts;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_config::resource_files::resources_dir_path; use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl;
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::max; use std::cmp::max;
use std::path::PathBuf; use std::path::PathBuf;
@ -104,6 +103,7 @@ use webvr::{WebVRThread, WebVRCompositorHandler};
pub use gleam::gl; pub use gleam::gl;
pub use servo_config as config; pub use servo_config as config;
pub use servo_url as url; pub use servo_url as url;
pub use msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
/// The in-process interface to Servo. /// The in-process interface to Servo.
/// ///
@ -111,18 +111,18 @@ pub use servo_url as url;
/// orchestrating the interaction between JavaScript, CSS layout, /// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window. /// rendering, and the client window.
/// ///
/// Clients create a `Browser` for a given reference-counted type /// Clients create a `Servo` instance for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever /// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event /// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and /// loop to pump messages between the embedding application and
/// various browser components. /// various browser components.
pub struct Browser<Window: WindowMethods + 'static> { pub struct Servo<Window: WindowMethods + 'static> {
compositor: IOCompositor<Window>, compositor: IOCompositor<Window>,
constellation_chan: Sender<ConstellationMsg>, constellation_chan: Sender<ConstellationMsg>,
} }
impl<Window> Browser<Window> where Window: WindowMethods + 'static { impl<Window> Servo<Window> where Window: WindowMethods + 'static {
pub fn new(window: Rc<Window>, target_url: ServoUrl) -> Browser<Window> { pub fn new(window: Rc<Window>) -> Servo<Window> {
// Global configuration options, parsed from the command line. // Global configuration options, parsed from the command line.
let opts = opts::get(); let opts = opts::get();
@ -205,7 +205,6 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
// as the navigation context. // as the navigation context.
let (constellation_chan, sw_senders) = create_constellation(opts.user_agent.clone(), let (constellation_chan, sw_senders) = create_constellation(opts.user_agent.clone(),
opts.config_dir.clone(), opts.config_dir.clone(),
target_url,
compositor_proxy.clone_compositor_proxy(), compositor_proxy.clone_compositor_proxy(),
time_profiler_chan.clone(), time_profiler_chan.clone(),
mem_profiler_chan.clone(), mem_profiler_chan.clone(),
@ -238,7 +237,7 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
webrender_api, webrender_api,
}); });
Browser { Servo {
compositor: compositor, compositor: compositor,
constellation_chan: constellation_chan, constellation_chan: constellation_chan,
} }
@ -283,7 +282,6 @@ fn create_compositor_channel(event_loop_waker: Box<compositor_thread::EventLoopW
fn create_constellation(user_agent: Cow<'static, str>, fn create_constellation(user_agent: Cow<'static, str>,
config_dir: Option<PathBuf>, config_dir: Option<PathBuf>,
url: ServoUrl,
compositor_proxy: CompositorProxy, compositor_proxy: CompositorProxy,
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan, mem_profiler_chan: mem::ProfilerChan,
@ -335,8 +333,6 @@ fn create_constellation(user_agent: Cow<'static, str>,
constellation_chan.send(ConstellationMsg::SetWebVRThread(webvr_thread)).unwrap(); constellation_chan.send(ConstellationMsg::SetWebVRThread(webvr_thread)).unwrap();
} }
constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
// channels to communicate with Service Worker Manager // channels to communicate with Service Worker Manager
let sw_senders = SWManagerSenders { let sw_senders = SWManagerSenders {
swmanager_sender: from_swmanager_sender, swmanager_sender: from_swmanager_sender,
@ -361,10 +357,10 @@ impl<Log1, Log2> Log for BothLogger<Log1, Log2> where Log1: Log, Log2: Log {
} }
} }
pub fn set_logger(constellation_chan: IpcSender<ScriptMsg>) { pub fn set_logger(script_to_constellation_chan: ScriptToConstellationChan) {
log::set_logger(|max_log_level| { log::set_logger(|max_log_level| {
let env_logger = EnvLogger::new(); let env_logger = EnvLogger::new();
let con_logger = FromScriptLogger::new(constellation_chan); let con_logger = FromScriptLogger::new(script_to_constellation_chan);
let filter = max(env_logger.filter(), con_logger.filter()); let filter = max(env_logger.filter(), con_logger.filter());
let logger = BothLogger(env_logger, con_logger); let logger = BothLogger(env_logger, con_logger);
max_log_level.set(filter); max_log_level.set(filter);
@ -383,7 +379,7 @@ pub fn run_content_process(token: String) {
let unprivileged_content = unprivileged_content_receiver.recv().unwrap(); let unprivileged_content = unprivileged_content_receiver.recv().unwrap();
opts::set_defaults(unprivileged_content.opts()); opts::set_defaults(unprivileged_content.opts());
PREFS.extend(unprivileged_content.prefs()); PREFS.extend(unprivileged_content.prefs());
set_logger(unprivileged_content.constellation_chan()); set_logger(unprivileged_content.script_to_constellation_chan().clone());
// Enter the sandbox if necessary. // Enter the sandbox if necessary.
if opts::get().sandbox { if opts::get().sandbox {

View file

@ -9,7 +9,8 @@ use interfaces::{CefBrowser, CefBrowserHost, CefClient, CefFrame, CefRequestCont
use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t}; use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t};
use interfaces::{cef_request_context_t}; use interfaces::{cef_request_context_t};
use msg::constellation_msg::TraversalDirection; use msg::constellation_msg::TraversalDirection;
use servo::Browser; use servo::{BrowserId, Servo};
use servo::ipc_channel::ipc;
use servo::servo_url::ServoUrl; use servo::servo_url::ServoUrl;
use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t}; use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t};
use window; use window;
@ -29,26 +30,34 @@ thread_local!(pub static BROWSERS: RefCell<Vec<CefBrowser>> = RefCell::new(vec!(
pub enum ServoBrowser { pub enum ServoBrowser {
Invalid, Invalid,
OnScreen(Browser<glutin_app::window::Window>), OnScreen(Servo<glutin_app::window::Window>, BrowserId),
OffScreen(Browser<window::Window>), OffScreen(Servo<window::Window>, BrowserId),
} }
impl ServoBrowser { impl ServoBrowser {
fn handle_event(&mut self, event: WindowEvent) { fn handle_event(&mut self, event: WindowEvent) {
match *self { match *self {
ServoBrowser::OnScreen(ref mut browser) => { browser.handle_events(vec![event]); } ServoBrowser::OnScreen(ref mut browser, _) => { browser.handle_events(vec![event]); }
ServoBrowser::OffScreen(ref mut browser) => { browser.handle_events(vec![event]); } ServoBrowser::OffScreen(ref mut browser, _) => { browser.handle_events(vec![event]); }
ServoBrowser::Invalid => {} ServoBrowser::Invalid => {}
} }
} }
pub fn pinch_zoom_level(&self) -> f32 { pub fn pinch_zoom_level(&self) -> f32 {
match *self { match *self {
ServoBrowser::OnScreen(ref browser) => browser.pinch_zoom_level(), ServoBrowser::OnScreen(ref browser, _) => browser.pinch_zoom_level(),
ServoBrowser::OffScreen(ref browser) => browser.pinch_zoom_level(), ServoBrowser::OffScreen(ref browser, _) => browser.pinch_zoom_level(),
ServoBrowser::Invalid => 1.0, ServoBrowser::Invalid => 1.0,
} }
} }
pub fn get_browser_id(&self) -> BrowserId {
match *self {
ServoBrowser::Invalid => unreachable!(),
ServoBrowser::OnScreen(_, id) => id,
ServoBrowser::OffScreen(_, id) => id,
}
}
} }
cef_class_impl! { cef_class_impl! {
@ -70,11 +79,11 @@ cef_class_impl! {
}} }}
fn go_back(&this,) -> () {{ fn go_back(&this,) -> () {{
this.send_window_event(WindowEvent::Navigation(TraversalDirection::Back(1))); this.send_window_event(WindowEvent::Navigation(this.get_browser_id(), TraversalDirection::Back(1)));
}} }}
fn go_forward(&this,) -> () {{ fn go_forward(&this,) -> () {{
this.send_window_event(WindowEvent::Navigation(TraversalDirection::Forward(1))); this.send_window_event(WindowEvent::Navigation(this.get_browser_id(), TraversalDirection::Forward(1)));
}} }}
// Returns the main (top-level) frame for the browser window. // Returns the main (top-level) frame for the browser window.
@ -124,9 +133,13 @@ impl ServoCefBrowser {
let (glutin_window, servo_browser) = if window_info.windowless_rendering_enabled == 0 { let (glutin_window, servo_browser) = if window_info.windowless_rendering_enabled == 0 {
let parent_window = glutin_app::WindowID::new(window_info.parent_window as *mut _); let parent_window = glutin_app::WindowID::new(window_info.parent_window as *mut _);
let glutin_window = glutin_app::create_window(Some(parent_window)); let glutin_window = glutin_app::create_window(Some(parent_window));
let servo_browser = Browser::new(glutin_window.clone(), target_url); let mut servo_browser = Servo::new(glutin_window.clone());
let (sender, receiver) = ipc::channel().unwrap();
servo_browser.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]);
let browser_id = receiver.recv().unwrap();
servo_browser.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]);
window_handle = glutin_window.platform_window().window as cef_window_handle_t; window_handle = glutin_window.platform_window().window as cef_window_handle_t;
(Some(glutin_window), ServoBrowser::OnScreen(servo_browser)) (Some(glutin_window), ServoBrowser::OnScreen(servo_browser, browser_id))
} else { } else {
(None, ServoBrowser::Invalid) (None, ServoBrowser::Invalid)
}; };
@ -155,6 +168,7 @@ impl ServoCefBrowser {
pub trait ServoCefBrowserExtensions { pub trait ServoCefBrowserExtensions {
fn init(&self, window_info: &cef_window_info_t); fn init(&self, window_info: &cef_window_info_t);
fn get_browser_id(&self) -> BrowserId;
fn send_window_event(&self, event: WindowEvent); fn send_window_event(&self, event: WindowEvent);
fn pinch_zoom_level(&self) -> f32; fn pinch_zoom_level(&self) -> f32;
} }
@ -165,8 +179,12 @@ impl ServoCefBrowserExtensions for CefBrowser {
let window = window::Window::new(window_info.width, window_info.height); let window = window::Window::new(window_info.width, window_info.height);
window.set_browser(self.clone()); window.set_browser(self.clone());
let home_url = ServoUrl::parse("about:blank").unwrap(); let home_url = ServoUrl::parse("about:blank").unwrap();
let servo_browser = Browser::new(window.clone(), home_url); let mut servo_browser = Servo::new(window.clone());
*self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser); let (sender, receiver) = ipc::channel().unwrap();
servo_browser.handle_events(vec![WindowEvent::NewBrowser(home_url, sender)]);
let browser_id = receiver.recv().unwrap();
servo_browser.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]);
*self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser, browser_id);
} }
self.downcast().host.set_browser((*self).clone()); self.downcast().host.set_browser((*self).clone());
@ -176,6 +194,10 @@ impl ServoCefBrowserExtensions for CefBrowser {
} }
} }
fn get_browser_id(&self) -> BrowserId {
self.downcast().servo_browser.borrow().get_browser_id()
}
fn send_window_event(&self, event: WindowEvent) { fn send_window_event(&self, event: WindowEvent) {
let browser = self.downcast(); let browser = self.downcast();

View file

@ -8,6 +8,7 @@ use interfaces::{CefBrowser, CefFrame, CefStringVisitor, cef_frame_t, cef_string
use types::{cef_string_t, cef_string_userfree_t}; use types::{cef_string_t, cef_string_userfree_t};
use compositing::windowing::WindowEvent; use compositing::windowing::WindowEvent;
use servo::servo_url::ServoUrl;
use std::cell::RefCell; use std::cell::RefCell;
pub struct ServoCefFrame { pub struct ServoCefFrame {
@ -34,7 +35,9 @@ full_cef_class_impl! {
let this = this.downcast(); let this = this.downcast();
let url = String::from_utf16(url).unwrap(); let url = String::from_utf16(url).unwrap();
*this.url.borrow_mut() = url.clone(); *this.url.borrow_mut() = url.clone();
let event = WindowEvent::LoadUrl(url); let id = this.browser.borrow().as_ref().unwrap().get_browser_id();
let url = ServoUrl::parse(&url).or(ServoUrl::parse("about:blank")).unwrap();
let event = WindowEvent::LoadUrl(id, url);
this.browser.borrow_mut().as_mut().unwrap().send_window_event(event); this.browser.borrow_mut().as_mut().unwrap().send_window_event(event);
}} }}
fn get_url(&this,) -> cef_string_userfree_t {{ fn get_url(&this,) -> cef_string_userfree_t {{
@ -60,7 +63,10 @@ impl ServoCefFrameExtensions for CefFrame {
*self.downcast().browser.borrow_mut() = Some(browser) *self.downcast().browser.borrow_mut() = Some(browser)
} }
fn load(&self) { fn load(&self) {
let event = WindowEvent::LoadUrl(self.downcast().url.borrow().clone()); let id = self.downcast().browser.borrow().as_ref().unwrap().get_browser_id();
let url = self.downcast().url.borrow();
let url = ServoUrl::parse(&*url).or(ServoUrl::parse("about:blank")).unwrap();
let event = WindowEvent::LoadUrl(id, url);
self.downcast().browser.borrow_mut().as_mut().unwrap().send_window_event(event); self.downcast().browser.borrow_mut().as_mut().unwrap().send_window_event(event);
} }
} }

View file

@ -24,6 +24,7 @@ use gleam::gl;
use msg::constellation_msg::{Key, KeyModifiers}; use msg::constellation_msg::{Key, KeyModifiers};
use net_traits::net_error_list::NetError; use net_traits::net_error_list::NetError;
use script_traits::LoadData; use script_traits::LoadData;
use servo::BrowserId;
use servo::ipc_channel::ipc::IpcSender; use servo::ipc_channel::ipc::IpcSender;
use servo_geometry::DeviceIndependentPixel; use servo_geometry::DeviceIndependentPixel;
use std::cell::RefCell; use std::cell::RefCell;
@ -233,7 +234,7 @@ impl WindowMethods for Window {
} }
} }
fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { fn client_window(&self, _: BrowserId) -> (Size2D<u32>, Point2D<i32>) {
let size = self.size().to_untyped(); let size = self.size().to_untyped();
let width = size.width as u32; let width = size.width as u32;
let height = size.height as u32; let height = size.height as u32;
@ -241,15 +242,15 @@ impl WindowMethods for Window {
(Size2D::new(width, height), Point2D::zero()) (Size2D::new(width, height), Point2D::zero())
} }
fn set_inner_size(&self, _size: Size2D<u32>) { fn set_inner_size(&self, _: BrowserId, _size: Size2D<u32>) {
} }
fn set_position(&self, _point: Point2D<i32>) { fn set_position(&self, _: BrowserId, _point: Point2D<i32>) {
} }
fn set_fullscreen_state(&self, _state: bool) { fn set_fullscreen_state(&self, _: BrowserId, _state: bool) {
} }
fn present(&self) { fn present(&self) {
@ -327,7 +328,7 @@ impl WindowMethods for Window {
} }
} }
fn set_favicon(&self, url: ServoUrl) { fn set_favicon(&self, _: BrowserId, url: ServoUrl) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -336,7 +337,7 @@ impl WindowMethods for Window {
browser.downcast().favicons.borrow_mut().push(url.into_string()); browser.downcast().favicons.borrow_mut().push(url.into_string());
} }
fn status(&self, info: Option<String>) { fn status(&self, _: BrowserId, info: Option<String>) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -353,7 +354,7 @@ impl WindowMethods for Window {
} }
} }
fn load_start(&self) { fn load_start(&self, _: BrowserId) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -372,7 +373,7 @@ impl WindowMethods for Window {
} }
} }
fn load_end(&self) { fn load_end(&self, _: BrowserId) {
// FIXME(pcwalton): The status code 200 is a lie. // FIXME(pcwalton): The status code 200 is a lie.
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
@ -398,7 +399,7 @@ impl WindowMethods for Window {
} }
} }
fn load_error(&self, code: NetError, url: String) { fn load_error(&self, _: BrowserId, code: NetError, url: String) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -415,7 +416,7 @@ impl WindowMethods for Window {
} }
} }
fn head_parsed(&self) { fn head_parsed(&self, _: BrowserId) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -427,7 +428,7 @@ impl WindowMethods for Window {
} }
} }
fn set_page_title(&self, string: Option<String>) { fn set_page_title(&self, _: BrowserId, string: Option<String>) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -448,7 +449,7 @@ impl WindowMethods for Window {
*frame.title.borrow_mut() = str; *frame.title.borrow_mut() = str;
} }
fn history_changed(&self, history: Vec<LoadData>, current: usize) { fn history_changed(&self, _: BrowserId, history: Vec<LoadData>, current: usize) {
let browser = self.cef_browser.borrow(); let browser = self.cef_browser.borrow();
let browser = match *browser { let browser = match *browser {
None => return, None => return,
@ -470,7 +471,7 @@ impl WindowMethods for Window {
} }
} }
fn handle_key(&self, _: Option<char>, _: Key, _: KeyModifiers) { fn handle_key(&self, _: Option<BrowserId>, _: Option<char>, _: Key, _: KeyModifiers) {
// TODO(negge) // TODO(negge)
} }
@ -491,7 +492,7 @@ impl WindowMethods for Window {
} }
} }
fn allow_navigation(&self, _: ServoUrl, response_chan: IpcSender<bool>) { fn allow_navigation(&self, _: BrowserId, _: ServoUrl, response_chan: IpcSender<bool>) {
if let Err(e) = response_chan.send(true) { if let Err(e) = response_chan.send(true) {
warn!("Failed to send allow_navigation() response: {}", e); warn!("Failed to send allow_navigation() response: {}", e);
}; };

View file

@ -19,7 +19,7 @@ use glutin::ScanCode;
use glutin::TouchPhase; use glutin::TouchPhase;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use glutin::os::macos::{ActivationPolicy, WindowBuilderExt}; use glutin::os::macos::{ActivationPolicy, WindowBuilderExt};
use msg::constellation_msg::{self, Key}; use msg::constellation_msg::{self, Key, TopLevelBrowsingContextId as BrowserId};
use msg::constellation_msg::{ALT, CONTROL, KeyState, NONE, SHIFT, SUPER, TraversalDirection}; use msg::constellation_msg::{ALT, CONTROL, KeyState, NONE, SHIFT, SUPER, TraversalDirection};
use net_traits::net_error_list::NetError; use net_traits::net_error_list::NetError;
#[cfg(any(target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "linux", target_os = "macos"))]
@ -182,6 +182,10 @@ pub struct Window {
mouse_down_point: Cell<Point2D<i32>>, mouse_down_point: Cell<Point2D<i32>>,
event_queue: RefCell<Vec<WindowEvent>>, event_queue: RefCell<Vec<WindowEvent>>,
/// id of the top level browsing context. It is unique as tabs
/// are not supported yet. None until created.
browser_id: Cell<Option<BrowserId>>,
mouse_pos: Cell<Point2D<i32>>, mouse_pos: Cell<Point2D<i32>>,
key_modifiers: Cell<KeyModifiers>, key_modifiers: Cell<KeyModifiers>,
current_url: RefCell<Option<ServoUrl>>, current_url: RefCell<Option<ServoUrl>>,
@ -217,6 +221,10 @@ fn window_creation_scale_factor() -> ScaleFactor<f32, DeviceIndependentPixel, De
impl Window { impl Window {
pub fn set_browser_id(&self, browser_id: BrowserId) {
self.browser_id.set(Some(browser_id));
}
pub fn new(is_foreground: bool, pub fn new(is_foreground: bool,
window_size: TypedSize2D<u32, DeviceIndependentPixel>, window_size: TypedSize2D<u32, DeviceIndependentPixel>,
parent: Option<glutin::WindowID>) -> Rc<Window> { parent: Option<glutin::WindowID>) -> Rc<Window> {
@ -309,6 +317,8 @@ impl Window {
mouse_down_button: Cell::new(None), mouse_down_button: Cell::new(None),
mouse_down_point: Cell::new(Point2D::new(0, 0)), mouse_down_point: Cell::new(Point2D::new(0, 0)),
browser_id: Cell::new(None),
mouse_pos: Cell::new(Point2D::new(0, 0)), mouse_pos: Cell::new(Point2D::new(0, 0)),
key_modifiers: Cell::new(KeyModifiers::empty()), key_modifiers: Cell::new(KeyModifiers::empty()),
current_url: RefCell::new(None), current_url: RefCell::new(None),
@ -929,20 +939,22 @@ impl Window {
} }
#[cfg(not(target_os = "win"))] #[cfg(not(target_os = "win"))]
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) { fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers, browser_id: BrowserId) {
match (mods, key) { match (mods, key) {
(CMD_OR_CONTROL, Key::LeftBracket) => { (CMD_OR_CONTROL, Key::LeftBracket) => {
self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Back(1))); let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1));
self.event_queue.borrow_mut().push(event);
} }
(CMD_OR_CONTROL, Key::RightBracket) => { (CMD_OR_CONTROL, Key::RightBracket) => {
self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Forward(1))); let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1));
self.event_queue.borrow_mut().push(event);
} }
_ => {} _ => {}
} }
} }
#[cfg(target_os = "win")] #[cfg(target_os = "win")]
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) { fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers, browser_id: BrowserId) {
} }
} }
@ -995,7 +1007,7 @@ impl WindowMethods for Window {
} }
} }
fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { fn client_window(&self, _: BrowserId) -> (Size2D<u32>, Point2D<i32>) {
match self.kind { match self.kind {
WindowKind::Window(ref window) => { WindowKind::Window(ref window) => {
// TODO(ajeffrey): can this fail? // TODO(ajeffrey): can this fail?
@ -1018,7 +1030,7 @@ impl WindowMethods for Window {
self.animation_state.set(state); self.animation_state.set(state);
} }
fn set_inner_size(&self, size: Size2D<u32>) { fn set_inner_size(&self, _: BrowserId, size: Size2D<u32>) {
match self.kind { match self.kind {
WindowKind::Window(ref window) => { WindowKind::Window(ref window) => {
window.set_inner_size(size.width as u32, size.height as u32) window.set_inner_size(size.width as u32, size.height as u32)
@ -1027,7 +1039,7 @@ impl WindowMethods for Window {
} }
} }
fn set_position(&self, point: Point2D<i32>) { fn set_position(&self, _: BrowserId, point: Point2D<i32>) {
match self.kind { match self.kind {
WindowKind::Window(ref window) => { WindowKind::Window(ref window) => {
window.set_position(point.x, point.y) window.set_position(point.x, point.y)
@ -1036,7 +1048,7 @@ impl WindowMethods for Window {
} }
} }
fn set_fullscreen_state(&self, _state: bool) { fn set_fullscreen_state(&self, _: BrowserId, _state: bool) {
match self.kind { match self.kind {
WindowKind::Window(..) => { WindowKind::Window(..) => {
warn!("Fullscreen is not implemented!") warn!("Fullscreen is not implemented!")
@ -1098,7 +1110,7 @@ impl WindowMethods for Window {
ScaleFactor::new(ppi as f32 / 96.0) ScaleFactor::new(ppi as f32 / 96.0)
} }
fn set_page_title(&self, title: Option<String>) { fn set_page_title(&self, _: BrowserId, title: Option<String>) {
match self.kind { match self.kind {
WindowKind::Window(ref window) => { WindowKind::Window(ref window) => {
let fallback_title: String = if let Some(ref current_url) = *self.current_url.borrow() { let fallback_title: String = if let Some(ref current_url) = *self.current_url.borrow() {
@ -1118,13 +1130,13 @@ impl WindowMethods for Window {
} }
} }
fn status(&self, _: Option<String>) { fn status(&self, _: BrowserId, _: Option<String>) {
} }
fn load_start(&self) { fn load_start(&self, _: BrowserId) {
} }
fn load_end(&self) { fn load_end(&self, _: BrowserId) {
if opts::get().no_native_titlebar { if opts::get().no_native_titlebar {
match self.kind { match self.kind {
WindowKind::Window(ref window) => { WindowKind::Window(ref window) => {
@ -1135,14 +1147,14 @@ impl WindowMethods for Window {
} }
} }
fn history_changed(&self, history: Vec<LoadData>, current: usize) { fn history_changed(&self, _: BrowserId, history: Vec<LoadData>, current: usize) {
*self.current_url.borrow_mut() = Some(history[current].url.clone()); *self.current_url.borrow_mut() = Some(history[current].url.clone());
} }
fn load_error(&self, _: NetError, _: String) { fn load_error(&self, _: BrowserId, _: NetError, _: String) {
} }
fn head_parsed(&self) { fn head_parsed(&self, _: BrowserId) {
} }
/// Has no effect on Android. /// Has no effect on Android.
@ -1194,7 +1206,7 @@ impl WindowMethods for Window {
} }
} }
fn set_favicon(&self, _: ServoUrl) { fn set_favicon(&self, _: BrowserId, _: ServoUrl) {
} }
fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool { fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
@ -1202,7 +1214,11 @@ impl WindowMethods for Window {
} }
/// Helper function to handle keyboard events. /// Helper function to handle keyboard events.
fn handle_key(&self, ch: Option<char>, key: Key, mods: constellation_msg::KeyModifiers) { fn handle_key(&self, _: Option<BrowserId>, ch: Option<char>, key: Key, mods: constellation_msg::KeyModifiers) {
let browser_id = match self.browser_id.get() {
Some(id) => id,
None => { unreachable!("Can't get keys without a browser"); }
};
match (mods, ch, key) { match (mods, ch, key) {
(_, Some('+'), _) => { (_, Some('+'), _) => {
if mods & !SHIFT == CMD_OR_CONTROL { if mods & !SHIFT == CMD_OR_CONTROL {
@ -1222,10 +1238,12 @@ impl WindowMethods for Window {
} }
(NONE, None, Key::NavigateForward) => { (NONE, None, Key::NavigateForward) => {
self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Forward(1))); let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1));
self.event_queue.borrow_mut().push(event);
} }
(NONE, None, Key::NavigateBackward) => { (NONE, None, Key::NavigateBackward) => {
self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Back(1))); let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1));
self.event_queue.borrow_mut().push(event);
} }
(NONE, None, Key::Escape) => { (NONE, None, Key::Escape) => {
@ -1235,10 +1253,12 @@ impl WindowMethods for Window {
} }
(CMD_OR_ALT, None, Key::Right) => { (CMD_OR_ALT, None, Key::Right) => {
self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Forward(1))); let event = WindowEvent::Navigation(browser_id, TraversalDirection::Forward(1));
self.event_queue.borrow_mut().push(event);
} }
(CMD_OR_ALT, None, Key::Left) => { (CMD_OR_ALT, None, Key::Left) => {
self.event_queue.borrow_mut().push(WindowEvent::Navigation(TraversalDirection::Back(1))); let event = WindowEvent::Navigation(browser_id, TraversalDirection::Back(1));
self.event_queue.borrow_mut().push(event);
} }
(NONE, None, Key::PageDown) => { (NONE, None, Key::PageDown) => {
@ -1284,7 +1304,7 @@ impl WindowMethods for Window {
} }
(CMD_OR_CONTROL, Some('r'), _) => { (CMD_OR_CONTROL, Some('r'), _) => {
if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() { if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
self.event_queue.borrow_mut().push(WindowEvent::Reload); self.event_queue.borrow_mut().push(WindowEvent::Reload(browser_id));
} }
} }
(CMD_OR_CONTROL, Some('q'), _) => { (CMD_OR_CONTROL, Some('q'), _) => {
@ -1297,12 +1317,12 @@ impl WindowMethods for Window {
} }
_ => { _ => {
self.platform_handle_key(key, mods); self.platform_handle_key(key, mods, browser_id);
} }
} }
} }
fn allow_navigation(&self, _: ServoUrl, response_chan: IpcSender<bool>) { fn allow_navigation(&self, _: BrowserId, _: ServoUrl, response_chan: IpcSender<bool>) {
if let Err(e) = response_chan.send(true) { if let Err(e) = response_chan.send(true) {
warn!("Failed to send allow_navigation() response: {}", e); warn!("Failed to send allow_navigation() response: {}", e);
}; };

View file

@ -4,7 +4,7 @@
//! The `servo` test application. //! The `servo` test application.
//! //!
//! Creates a `Browser` instance with a simple implementation of //! Creates a `Servo` instance with a simple implementation of
//! the compositor's `WindowMethods` to create a working web browser. //! the compositor's `WindowMethods` to create a working web browser.
//! //!
//! This browser's implementation of `WindowMethods` is built on top //! This browser's implementation of `WindowMethods` is built on top
@ -31,12 +31,13 @@ extern crate servo;
extern crate sig; extern crate sig;
use backtrace::Backtrace; use backtrace::Backtrace;
use servo::Browser; use servo::Servo;
use servo::compositing::windowing::WindowEvent; use servo::compositing::windowing::WindowEvent;
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
use servo::config; use servo::config;
use servo::config::opts::{self, ArgumentParsingResult, parse_url_or_filename}; use servo::config::opts::{self, ArgumentParsingResult, parse_url_or_filename};
use servo::config::servo_version; use servo::config::servo_version;
use servo::ipc_channel::ipc;
use servo::servo_config::prefs::PREFS; use servo::servo_config::prefs::PREFS;
use servo::servo_url::ServoUrl; use servo::servo_url::ServoUrl;
use std::env; use std::env;
@ -155,20 +156,26 @@ fn main() {
let target_url = cmdline_url.or(pref_url).or(blank_url).unwrap(); let target_url = cmdline_url.or(pref_url).or(blank_url).unwrap();
// Our wrapper around `Browser` that also implements some // Our wrapper around `ServoWrapper` that also implements some
// callbacks required by the glutin window implementation. // callbacks required by the glutin window implementation.
let mut browser = BrowserWrapper { let mut servo_wrapper = ServoWrapper {
browser: Browser::new(window.clone(), target_url) servo: Servo::new(window.clone())
}; };
browser.browser.setup_logging(); let (sender, receiver) = ipc::channel().unwrap();
servo_wrapper.servo.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]);
let browser_id = receiver.recv().unwrap();
window.set_browser_id(browser_id);
servo_wrapper.servo.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]);
register_glutin_resize_handler(&window, &mut browser); servo_wrapper.servo.setup_logging();
register_glutin_resize_handler(&window, &mut servo_wrapper);
// Feed events from the window to the browser until the browser // Feed events from the window to the browser until the browser
// says to stop. // says to stop.
loop { loop {
let should_continue = browser.browser.handle_events(window.wait_events()); let should_continue = servo_wrapper.servo.handle_events(window.wait_events());
if !should_continue { if !should_continue {
break; break;
} }
@ -179,7 +186,7 @@ fn main() {
platform::deinit() platform::deinit()
} }
fn register_glutin_resize_handler(window: &Rc<app::window::Window>, browser: &mut BrowserWrapper) { fn register_glutin_resize_handler(window: &Rc<app::window::Window>, browser: &mut ServoWrapper) {
unsafe { unsafe {
window.set_nested_event_loop_listener(browser); window.set_nested_event_loop_listener(browser);
} }
@ -191,21 +198,21 @@ fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
} }
} }
struct BrowserWrapper { struct ServoWrapper {
browser: Browser<app::window::Window>, servo: Servo<app::window::Window>,
} }
impl app::NestedEventLoopListener for BrowserWrapper { impl app::NestedEventLoopListener for ServoWrapper {
fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool { fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool {
let is_resize = match event { let is_resize = match event {
WindowEvent::Resize(..) => true, WindowEvent::Resize(..) => true,
_ => false, _ => false,
}; };
if !self.browser.handle_events(vec![event]) { if !self.servo.handle_events(vec![event]) {
return false; return false;
} }
if is_resize { if is_resize {
self.browser.repaint_synchronously() self.servo.repaint_synchronously()
} }
true true
} }