move msg to embedder_traits, use in script, handle send error in embedder

This commit is contained in:
Gregory Terzian 2018-04-28 22:48:14 +08:00
parent a297e8f288
commit d438240772
31 changed files with 362 additions and 337 deletions

11
Cargo.lock generated
View file

@ -182,6 +182,7 @@ dependencies = [
"bluetooth_traits 0.0.1",
"compositing 0.0.1",
"device 0.0.1 (git+https://github.com/servo/devices)",
"embedder_traits 0.0.1",
"ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
@ -419,6 +420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "compositing"
version = "0.0.1"
dependencies = [
"embedder_traits 0.0.1",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"gleam 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -770,7 +772,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "embedder_traits"
version = "0.0.1"
dependencies = [
"ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_url 0.0.1",
"style_traits 0.0.1",
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1850,7 +1859,6 @@ version = "0.0.1"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"compositing 0.0.1",
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"devtools_traits 0.0.1",
"embedder_traits 0.0.1",
@ -2601,6 +2609,7 @@ dependencies = [
"canvas_traits 0.0.1",
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"devtools_traits 0.0.1",
"embedder_traits 0.0.1",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -14,8 +14,12 @@ bitflags = "1.0"
bluetooth_traits = {path = "../bluetooth_traits"}
compositing = {path = "../compositing"}
device = {git = "https://github.com/servo/devices", features = ["bluetooth-test"]}
embedder_traits = {path = "../embedder_traits"}
ipc-channel = "0.10"
log = "0.4"
servo_config = {path = "../config"}
servo_rand = {path = "../rand"}
uuid = {version = "0.6", features = ["v4"]}
[dev-dependencies]
embedder_traits = { path = "../embedder_traits", features = ["tests"]}

View file

@ -5,8 +5,8 @@
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate compositing;
extern crate device;
extern crate embedder_traits;
extern crate ipc_channel;
#[macro_use]
extern crate log;
@ -21,9 +21,9 @@ use bluetooth_traits::{BluetoothDeviceMsg, BluetoothRequest, BluetoothResponse,
use bluetooth_traits::{BluetoothError, BluetoothResponseResult, BluetoothResult};
use bluetooth_traits::blocklist::{uuid_is_blocklisted, Blocklist};
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
use compositing::compositor_thread::{EmbedderMsg, EmbedderProxy};
use device::bluetooth::{BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic};
use device::bluetooth::{BluetoothGATTDescriptor, BluetoothGATTService};
use embedder_traits::{EmbedderMsg, EmbedderProxy};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use servo_config::opts;
use servo_config::prefs::PREFS;

View file

@ -14,6 +14,7 @@ path = "lib.rs"
default = []
[dependencies]
embedder_traits = {path = "../embedder_traits"}
euclid = "0.17"
gfx_traits = {path = "../gfx_traits"}
gleam = {version = "0.5", optional = true}
@ -36,3 +37,6 @@ webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
[build-dependencies]
toml = "0.4.5"
[dev-dependencies]
embedder_traits = { path = "../embedder_traits", features = ["tests"]}

View file

@ -6,68 +6,21 @@
use SendableFrameTree;
use compositor::CompositingReason;
use embedder_traits::EventLoopWaker;
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{InputMethodType, Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId};
use net_traits::filemanager_thread::FilterPattern;
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
use net_traits::image::base::Image;
use profile_traits::mem;
use profile_traits::time;
use script_traits::{AnimationState, ConstellationMsg, EventResult, LoadData};
use servo_url::ServoUrl;
use script_traits::{AnimationState, ConstellationMsg, EventResult};
use std::fmt::{Debug, Error, Formatter};
use std::sync::mpsc::{Receiver, Sender};
use style_traits::cursor::CursorKind;
use style_traits::viewport::ViewportConstraints;
use webrender;
use webrender_api::{self, DeviceIntPoint, DeviceUintSize};
/// Used to wake up the event loop, provided by the servo port/embedder.
pub trait EventLoopWaker : 'static + Send {
fn clone(&self) -> Box<EventLoopWaker + Send>;
fn wake(&self);
}
/// Sends messages to the embedder.
pub struct EmbedderProxy {
pub sender: Sender<EmbedderMsg>,
pub event_loop_waker: Box<EventLoopWaker>,
}
impl EmbedderProxy {
pub fn send(&self, msg: EmbedderMsg) {
// Send a message and kick the OS event loop awake.
if let Err(err) = self.sender.send(msg) {
warn!("Failed to send response ({}).", err);
}
self.event_loop_waker.wake();
}
}
impl Clone for EmbedderProxy {
fn clone(&self) -> EmbedderProxy {
EmbedderProxy {
sender: self.sender.clone(),
event_loop_waker: self.event_loop_waker.clone(),
}
}
}
/// The port that the embedder receives messages on.
pub struct EmbedderReceiver {
pub receiver: Receiver<EmbedderMsg>
}
impl EmbedderReceiver {
pub fn try_recv_embedder_msg(&mut self) -> Option<EmbedderMsg> {
self.receiver.try_recv().ok()
}
pub fn recv_embedder_msg(&mut self) -> EmbedderMsg {
self.receiver.recv().unwrap()
}
}
/// Sends messages to the compositor.
pub struct CompositorProxy {
pub sender: Sender<Msg>,
@ -113,47 +66,6 @@ impl CompositorProxy {
}
}
pub enum EmbedderMsg {
/// A status message to be displayed by the browser chrome.
Status(TopLevelBrowsingContextId, Option<String>),
/// Alerts the embedder that the current page has changed its title.
ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
/// Move the window to a point
MoveTo(TopLevelBrowsingContextId, DeviceIntPoint),
/// Resize the window to size
ResizeTo(TopLevelBrowsingContextId, DeviceUintSize),
/// Wether or not to follow a link
AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
/// Sends an unconsumed key event back to the embedder.
KeyEvent(Option<TopLevelBrowsingContextId>, Option<char>, Key, KeyState, KeyModifiers),
/// Changes the cursor.
SetCursor(CursorKind),
/// A favicon was detected
NewFavicon(TopLevelBrowsingContextId, ServoUrl),
/// <head> tag finished parsing
HeadParsed(TopLevelBrowsingContextId),
/// The history state has changed.
HistoryChanged(TopLevelBrowsingContextId, Vec<LoadData>, usize),
/// Enter or exit fullscreen
SetFullscreenState(TopLevelBrowsingContextId, bool),
/// The load of a page has begun
LoadStart(TopLevelBrowsingContextId),
/// The load of a page has completed
LoadComplete(TopLevelBrowsingContextId),
/// A pipeline panicked. First string is the reason, second one is the backtrace.
Panic(TopLevelBrowsingContextId, String, Option<String>),
/// Open dialog to select bluetooth device.
GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>),
/// Open file dialog to select files. Set boolean flag to true allows to select multiple files.
SelectFiles(Vec<FilterPattern>, bool, IpcSender<Option<Vec<String>>>),
/// Request to present an IME to the user when an editable element is focused.
ShowIME(TopLevelBrowsingContextId, InputMethodType),
/// Request to hide the IME when the editable element is blurred.
HideIME(TopLevelBrowsingContextId),
/// Servo has shut down
Shutdown,
}
/// Messages from the painting thread and the constellation thread to the compositor thread.
pub enum Msg {
/// Requests that the compositor shut down.
@ -233,32 +145,6 @@ impl Debug for Msg {
}
}
impl Debug for EmbedderMsg {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match *self {
EmbedderMsg::Status(..) => write!(f, "Status"),
EmbedderMsg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"),
EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"),
EmbedderMsg::AllowNavigation(..) => write!(f, "AllowNavigation"),
EmbedderMsg::KeyEvent(..) => write!(f, "KeyEvent"),
EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"),
EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"),
EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"),
EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"),
EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
EmbedderMsg::Panic(..) => write!(f, "Panic"),
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
EmbedderMsg::HideIME(..) => write!(f, "HideIME"),
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
}
}
}
/// Data used to construct a compositor.
pub struct InitialCompositorState {
/// A channel to the compositor.

View file

@ -4,6 +4,7 @@
#![deny(unsafe_code)]
extern crate embedder_traits;
extern crate euclid;
extern crate gfx_traits;
#[cfg(feature = "gleam")]

View file

@ -4,7 +4,7 @@
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
use compositor_thread::EventLoopWaker;
use embedder_traits::EventLoopWaker;
use euclid::TypedScale;
#[cfg(feature = "gleam")]
use gleam::gl;
@ -78,6 +78,8 @@ pub enum WindowEvent {
NewBrowser(ServoUrl, IpcSender<TopLevelBrowsingContextId>),
/// Close a top level browsing context
CloseBrowser(TopLevelBrowsingContextId),
/// Panic a top level browsing context.
SendError(Option<TopLevelBrowsingContextId>, String),
/// Make a top level browsing context visible, hiding the previous
/// visible one.
SelectBrowser(TopLevelBrowsingContextId),
@ -106,6 +108,7 @@ impl Debug for WindowEvent {
WindowEvent::Quit => write!(f, "Quit"),
WindowEvent::Reload(..) => write!(f, "Reload"),
WindowEvent::NewBrowser(..) => write!(f, "NewBrowser"),
WindowEvent::SendError(..) => write!(f, "SendError"),
WindowEvent::CloseBrowser(..) => write!(f, "CloseBrowser"),
WindowEvent::SelectBrowser(..) => write!(f, "SelectBrowser"),
WindowEvent::ToggleWebRenderDebug(..) => write!(f, "ToggleWebRenderDebug"),

View file

@ -98,10 +98,11 @@ use canvas_traits::canvas::CanvasId;
use canvas_traits::canvas::CanvasMsg;
use clipboard::{ClipboardContext, ClipboardProvider};
use compositing::SendableFrameTree;
use compositing::compositor_thread::{CompositorProxy, EmbedderMsg, EmbedderProxy};
use compositing::compositor_thread::CompositorProxy;
use compositing::compositor_thread::Msg as ToCompositorMsg;
use debugger;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
use embedder_traits::{EmbedderMsg, EmbedderProxy};
use euclid::{Size2D, TypedSize2D, TypedScale};
use event_loop::EventLoop;
use gfx::font_cache_thread::FontCacheThread;
@ -969,6 +970,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromCompositorMsg::CloseBrowser(top_level_browsing_context_id) => {
self.handle_close_top_level_browsing_context(top_level_browsing_context_id);
}
// Panic a top level browsing context.
FromCompositorMsg::SendError(top_level_browsing_context_id, error) => {
debug!("constellation got SendError message");
if let Some(id) = top_level_browsing_context_id {
self.handle_panic(id, error, None);
} else {
warn!("constellation got a SendError message without top level id");
}
}
// Send frame tree to WebRender. Make it visible.
FromCompositorMsg::SelectBrowser(top_level_browsing_context_id) => {
self.send_frame_tree(top_level_browsing_context_id);
@ -1014,12 +1024,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
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::ForwardToEmbedder(embedder_msg) => {
self.embedder_proxy.send(embedder_msg);
}
FromScriptMsg::PipelineExited => {
self.handle_pipeline_exited(source_pipeline_id);
}
@ -1119,34 +1127,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
warn!("Error replying to remove iframe ({})", e);
}
}
FromScriptMsg::NewFavicon(url) => {
if source_is_top_level_pipeline {
self.embedder_proxy.send(EmbedderMsg::NewFavicon(source_top_ctx_id, url));
}
}
FromScriptMsg::HeadParsed => {
if source_is_top_level_pipeline {
self.embedder_proxy.send(EmbedderMsg::HeadParsed(source_top_ctx_id));
}
}
FromScriptMsg::CreateCanvasPaintThread(size, sender) => {
self.handle_create_canvas_paint_thread_msg(&size, sender)
}
FromScriptMsg::NodeStatus(message) => {
self.embedder_proxy.send(EmbedderMsg::Status(source_top_ctx_id, message));
}
FromScriptMsg::SetDocumentState(state) => {
self.document_states.insert(source_pipeline_id, state);
}
FromScriptMsg::Alert(message, sender) => {
self.handle_alert(source_top_ctx_id, message, sender);
}
FromScriptMsg::MoveTo(point) => {
self.embedder_proxy.send(EmbedderMsg::MoveTo(source_top_ctx_id, point));
}
FromScriptMsg::ResizeTo(size) => {
self.embedder_proxy.send(EmbedderMsg::ResizeTo(source_top_ctx_id, size));
}
FromScriptMsg::GetClientWindow(send) => {
self.compositor_proxy.send(ToCompositorMsg::GetClientWindow(send));
}
@ -1162,15 +1148,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::LogEntry(thread_name, entry) => {
self.handle_log_entry(Some(source_top_ctx_id), thread_name, entry);
}
FromScriptMsg::SetTitle(title) => {
if source_is_top_level_pipeline {
self.embedder_proxy.send(EmbedderMsg::ChangePageTitle(source_top_ctx_id, title))
}
}
FromScriptMsg::SendKeyEvent(ch, key, key_state, key_modifiers) => {
let event = EmbedderMsg::KeyEvent(Some(source_top_ctx_id), ch, key, key_state, key_modifiers);
self.embedder_proxy.send(event);
}
FromScriptMsg::TouchEventProcessed(result) => {
self.compositor_proxy.send(ToCompositorMsg::TouchEventProcessed(result))
}
@ -1208,15 +1185,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::BroadcastStorageEvent(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) => {
self.embedder_proxy.send(EmbedderMsg::SetFullscreenState(source_top_ctx_id, state));
}
FromScriptMsg::ShowIME(kind) => {
self.embedder_proxy.send(EmbedderMsg::ShowIME(source_top_ctx_id, kind));
}
FromScriptMsg::HideIME => {
self.embedder_proxy.send(EmbedderMsg::HideIME(source_top_ctx_id));
}
}
}
@ -1727,23 +1695,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
}
fn handle_alert(&mut self,
top_level_browsing_context_id: TopLevelBrowsingContextId,
_message: String,
sender: IpcSender<bool>) {
// FIXME: forward alert event to embedder
// https://github.com/servo/servo/issues/19992
let result = sender.send(true);
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);
}
}
fn handle_load_url_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId,
load_data: LoadData, replace: bool) {
self.load_url(top_level_browsing_context_id, source_id, load_data, replace);
@ -2451,8 +2402,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
entries.extend(session_history.future.iter().rev()
.scan(current_load_data.clone(), &resolve_load_data_future));
let msg = EmbedderMsg::HistoryChanged(top_level_browsing_context_id, entries, current_index);
let urls = entries.iter().map(|entry| entry.url.clone()).collect();
let msg = EmbedderMsg::HistoryChanged(top_level_browsing_context_id, urls, current_index);
self.embedder_proxy.send(msg);
}

View file

@ -14,7 +14,7 @@ extern crate clipboard;
extern crate compositing;
extern crate debugger;
extern crate devtools_traits;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
#[cfg(not(target_os = "ios"))]
extern crate embedder_traits;
extern crate euclid;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]

View file

@ -13,4 +13,11 @@ path = "lib.rs"
tests = []
[dependencies]
ipc-channel = "0.10"
lazy_static = "1"
log = "0.4"
msg = {path = "../msg"}
serde = "1.0"
servo_url = {path = "../url"}
style_traits = {path = "../style_traits"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}

View file

@ -2,6 +2,146 @@
* 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/. */
#[macro_use] extern crate lazy_static;
extern crate ipc_channel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate msg;
#[macro_use]
extern crate serde;
extern crate servo_url;
extern crate style_traits;
extern crate webrender_api;
pub mod resources;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{InputMethodType, Key, KeyModifiers, KeyState, TopLevelBrowsingContextId};
use servo_url::ServoUrl;
use std::fmt::{Debug, Error, Formatter};
use std::sync::mpsc::{Receiver, Sender};
use style_traits::cursor::CursorKind;
use webrender_api::{DeviceIntPoint, DeviceUintSize};
/// Used to wake up the event loop, provided by the servo port/embedder.
pub trait EventLoopWaker : 'static + Send {
fn clone(&self) -> Box<EventLoopWaker + Send>;
fn wake(&self);
}
/// Sends messages to the embedder.
pub struct EmbedderProxy {
pub sender: Sender<EmbedderMsg>,
pub event_loop_waker: Box<EventLoopWaker>,
}
impl EmbedderProxy {
pub fn send(&self, msg: EmbedderMsg) {
// Send a message and kick the OS event loop awake.
if let Err(err) = self.sender.send(msg) {
warn!("Failed to send response ({}).", err);
}
self.event_loop_waker.wake();
}
}
impl Clone for EmbedderProxy {
fn clone(&self) -> EmbedderProxy {
EmbedderProxy {
sender: self.sender.clone(),
event_loop_waker: self.event_loop_waker.clone(),
}
}
}
/// The port that the embedder receives messages on.
pub struct EmbedderReceiver {
pub receiver: Receiver<EmbedderMsg>
}
impl EmbedderReceiver {
pub fn try_recv_embedder_msg(&mut self) -> Option<EmbedderMsg> {
self.receiver.try_recv().ok()
}
pub fn recv_embedder_msg(&mut self) -> EmbedderMsg {
self.receiver.recv().unwrap()
}
}
#[derive(Deserialize, Serialize)]
pub enum EmbedderMsg {
/// A status message to be displayed by the browser chrome.
Status(TopLevelBrowsingContextId, Option<String>),
/// Alerts the embedder that the current page has changed its title.
ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
/// Move the window to a point
MoveTo(TopLevelBrowsingContextId, DeviceIntPoint),
/// Resize the window to size
ResizeTo(TopLevelBrowsingContextId, DeviceUintSize),
// Show an alert message.
Alert(TopLevelBrowsingContextId, String, IpcSender<()>),
/// Wether or not to follow a link
AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
/// Sends an unconsumed key event back to the embedder.
KeyEvent(Option<TopLevelBrowsingContextId>, Option<char>, Key, KeyState, KeyModifiers),
/// Changes the cursor.
SetCursor(CursorKind),
/// A favicon was detected
NewFavicon(TopLevelBrowsingContextId, ServoUrl),
/// <head> tag finished parsing
HeadParsed(TopLevelBrowsingContextId),
/// The history state has changed.
HistoryChanged(TopLevelBrowsingContextId, Vec<ServoUrl>, usize),
/// Enter or exit fullscreen
SetFullscreenState(TopLevelBrowsingContextId, bool),
/// The load of a page has begun
LoadStart(TopLevelBrowsingContextId),
/// The load of a page has completed
LoadComplete(TopLevelBrowsingContextId),
/// A pipeline panicked. First string is the reason, second one is the backtrace.
Panic(TopLevelBrowsingContextId, String, Option<String>),
/// Open dialog to select bluetooth device.
GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>),
/// Open file dialog to select files. Set boolean flag to true allows to select multiple files.
SelectFiles(Vec<FilterPattern>, bool, IpcSender<Option<Vec<String>>>),
/// Request to present an IME to the user when an editable element is focused.
ShowIME(TopLevelBrowsingContextId, InputMethodType),
/// Request to hide the IME when the editable element is blurred.
HideIME(TopLevelBrowsingContextId),
/// Servo has shut down
Shutdown,
}
impl Debug for EmbedderMsg {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match *self {
EmbedderMsg::Status(..) => write!(f, "Status"),
EmbedderMsg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"),
EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"),
EmbedderMsg::Alert(..) => write!(f, "Alert"),
EmbedderMsg::AllowNavigation(..) => write!(f, "AllowNavigation"),
EmbedderMsg::KeyEvent(..) => write!(f, "KeyEvent"),
EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"),
EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"),
EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"),
EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"),
EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
EmbedderMsg::Panic(..) => write!(f, "Panic"),
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
EmbedderMsg::HideIME(..) => write!(f, "HideIME"),
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
}
}
}
/// Filter for file selection;
/// the `String` content is expected to be extension (e.g, "doc", without the prefixing ".")
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FilterPattern(pub String);

View file

@ -16,7 +16,6 @@ doctest = false
base64 = "0.6"
brotli = "1.0.6"
cookie = "0.10"
compositing = {path = "../compositing"}
devtools_traits = {path = "../devtools_traits"}
embedder_traits = { path = "../embedder_traits" }
flate2 = "1"

View file

@ -2,11 +2,11 @@
* 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/. */
use compositing::compositor_thread::{EmbedderMsg, EmbedderProxy};
use embedder_traits::{EmbedderMsg, EmbedderProxy, FilterPattern};
use ipc_channel::ipc::{self, IpcSender};
use mime_guess::guess_mime_type_opt;
use net_traits::blob_url_store::{BlobBuf, BlobURLStoreError};
use net_traits::filemanager_thread::{FileManagerResult, FileManagerThreadMsg, FileOrigin, FilterPattern};
use net_traits::filemanager_thread::{FileManagerResult, FileManagerThreadMsg, FileOrigin};
use net_traits::filemanager_thread::{FileManagerThreadError, ReadFileProgress, RelativePos, SelectedFile};
use servo_config::prefs::PREFS;
use std::collections::HashMap;

View file

@ -6,7 +6,6 @@
extern crate base64;
extern crate brotli;
extern crate compositing;
extern crate cookie as cookie_rs;
extern crate devtools_traits;
extern crate embedder_traits;

View file

@ -3,12 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! A thread that takes a URL and streams back the binary data.
use compositing::compositor_thread::EmbedderProxy;
use connector::{create_http_connector, create_ssl_client};
use cookie;
use cookie_rs;
use cookie_storage::CookieStorage;
use devtools_traits::DevtoolsControlMsg;
use embedder_traits::EmbedderProxy;
use embedder_traits::resources::{self, Resource};
use fetch::cors_cache::CorsCache;
use fetch::methods::{CancellationListener, FetchContext, fetch};

View file

@ -3,10 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use create_embedder_proxy;
use embedder_traits::FilterPattern;
use ipc_channel::ipc;
use net::filemanager_thread::FileManager;
use net_traits::blob_url_store::BlobURLStoreError;
use net_traits::filemanager_thread::{FilterPattern, FileManagerThreadMsg, FileManagerThreadError, ReadFileProgress};
use net_traits::filemanager_thread::{FileManagerThreadMsg, FileManagerThreadError, ReadFileProgress};
use servo_config::prefs::{PrefValue, PREFS};
use std::fs::File;
use std::io::Read;

View file

@ -4,7 +4,6 @@
#![cfg(test)]
extern crate compositing;
extern crate cookie as cookie_rs;
extern crate devtools_traits;
extern crate embedder_traits;
@ -35,8 +34,8 @@ mod mime_classifier;
mod resource_thread;
mod subresource_integrity;
use compositing::compositor_thread::{EmbedderProxy, EventLoopWaker};
use devtools_traits::DevtoolsControlMsg;
use embedder_traits::{EmbedderProxy, EventLoopWaker};
use embedder_traits::resources::{self, Resource};
use hyper::server::{Handler, Listening, Server};
use net::connector::create_ssl_client;

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use blob_url_store::{BlobBuf, BlobURLStoreError};
use embedder_traits::FilterPattern;
use ipc_channel::ipc::IpcSender;
use num_traits::ToPrimitive;
use std::cmp::{max, min};
@ -110,11 +111,6 @@ pub struct SelectedFile {
pub type_string: String,
}
/// Filter for file selection;
/// the `String` content is expected to be extension (e.g, "doc", without the prefixing ".")
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FilterPattern(pub String);
#[derive(Deserialize, Serialize)]
pub enum FileManagerThreadMsg {
/// Select a single file. Last field is pre-selected file path for testing

View file

@ -88,6 +88,7 @@ use dom::webglcontextevent::WebGLContextEvent;
use dom::window::{ReflowReason, Window};
use dom::windowproxy::WindowProxy;
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
use encoding_rs::{Encoding, UTF_8};
use euclid::Point2D;
use fetch::FetchCanceller;
@ -855,7 +856,8 @@ impl Document {
// Notify the embedder to hide the input method.
if elem.input_method_type().is_some() {
self.send_to_constellation(ScriptMsg::HideIME);
let top_level_browsing_context_id = self.window().top_level_browsing_context_id();
self.send_to_embedder(EmbedderMsg::HideIME(top_level_browsing_context_id));
}
}
@ -869,12 +871,13 @@ impl Document {
// Update the focus state for all elements in the focus chain.
// https://html.spec.whatwg.org/multipage/#focus-chain
if focus_type == FocusType::Element {
self.send_to_constellation(ScriptMsg::Focus);
self.window().send_to_constellation(ScriptMsg::Focus);
}
// Notify the embedder to display an input method.
if let Some(kind) = elem.input_method_type() {
self.send_to_constellation(ScriptMsg::ShowIME(kind));
let top_level_browsing_context_id = self.window().top_level_browsing_context_id();
self.send_to_embedder(EmbedderMsg::ShowIME(top_level_browsing_context_id, kind));
}
}
}
@ -882,14 +885,23 @@ impl Document {
/// Handles any updates when the document's title has changed.
pub fn title_changed(&self) {
if self.browsing_context().is_some() {
self.send_title_to_constellation();
self.send_title_to_embedder();
}
}
/// Sends this document's title to the constellation.
pub fn send_title_to_constellation(&self) {
let title = Some(String::from(self.Title()));
self.send_to_constellation(ScriptMsg::SetTitle(title));
pub fn send_title_to_embedder(&self) {
let window = self.window();
if window.is_top_level() {
let title = Some(String::from(self.Title()));
let top_level_browsing_context_id = window.top_level_browsing_context_id();
self.send_to_embedder(EmbedderMsg::ChangePageTitle(top_level_browsing_context_id, title));
}
}
fn send_to_embedder(&self, msg: EmbedderMsg) {
let window = self.window();
window.send_to_embedder(msg);
}
pub fn dirty_all_nodes(&self) {
@ -1352,8 +1364,9 @@ impl Document {
}
if cancel_state == EventDefault::Allowed {
let msg = ScriptMsg::SendKeyEvent(ch, key, state, modifiers);
self.send_to_constellation(msg);
let top_level_browsing_context_id = self.window().top_level_browsing_context_id();
let msg = EmbedderMsg::KeyEvent(Some(top_level_browsing_context_id), ch, key, state, modifiers);
self.send_to_embedder(msg);
// This behavior is unspecced
// We are supposed to dispatch synthetic click activation for Space and/or Return,
@ -1488,7 +1501,7 @@ impl Document {
// repeated rAF.
let event = ScriptMsg::ChangeRunningAnimationsState(AnimationState::AnimationCallbacksPresent);
self.send_to_constellation(event);
self.window().send_to_constellation(event);
}
ident
@ -1559,7 +1572,7 @@ impl Document {
);
}
let event = ScriptMsg::ChangeRunningAnimationsState(AnimationState::NoAnimationCallbacksPresent);
self.send_to_constellation(event);
self.window().send_to_constellation(event);
}
// Update the counter of spurious animation frames.
@ -2009,7 +2022,7 @@ impl Document {
}
pub fn notify_constellation_load(&self) {
self.send_to_constellation(ScriptMsg::LoadComplete);
self.window().send_to_constellation(ScriptMsg::LoadComplete);
}
pub fn set_current_parser(&self, script: Option<&ServoParser>) {
@ -2167,11 +2180,6 @@ impl Document {
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();
}
pub fn increment_throw_on_dynamic_markup_insertion_counter(&self) {
let counter = self.throw_on_dynamic_markup_insertion_counter.get();
self.throw_on_dynamic_markup_insertion_counter.set(counter + 1);
@ -2787,8 +2795,9 @@ impl Document {
let window = self.window();
// Step 6
if !error {
let event = ScriptMsg::SetFullscreenState(true);
self.send_to_constellation(event);
let top_level_browsing_context_id = self.window().top_level_browsing_context_id();
let event = EmbedderMsg::SetFullscreenState(top_level_browsing_context_id, true);
self.send_to_embedder(event);
}
let pipeline_id = self.window().pipeline_id();
@ -2822,8 +2831,9 @@ impl Document {
let window = self.window();
// Step 8
let event = ScriptMsg::SetFullscreenState(false);
self.send_to_constellation(event);
let top_level_browsing_context_id = self.window().top_level_browsing_context_id();
let event = EmbedderMsg::SetFullscreenState(top_level_browsing_context_id, true);
self.send_to_embedder(event);
// Step 9
let trusted_element = Trusted::new(element.r());

View file

@ -12,13 +12,12 @@ use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
use html5ever::{LocalName, Prefix};
use script_traits::ScriptMsg;
use servo_url::ServoUrl;
use style::attr::AttrValue;
use time;
@ -151,8 +150,11 @@ impl VirtualMethods for HTMLBodyElement {
let window = window_from_node(self);
let document = window.Document();
document.set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
let event = ScriptMsg::HeadParsed;
window.upcast::<GlobalScope>().script_to_constellation_chan().send(event).unwrap();
if window.is_top_level() {
let top_level_browsing_context_id = window.top_level_browsing_context_id();
let msg = EmbedderMsg::HeadParsed(top_level_browsing_context_id);
window.send_to_embedder(msg);
}
}
fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {

View file

@ -38,12 +38,13 @@ use dom::validation::Validatable;
use dom::validitystate::ValidationFlags;
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use embedder_traits::FilterPattern;
use html5ever::{LocalName, Prefix};
use mime_guess;
use msg::constellation_msg::InputMethodType;
use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
use net_traits::filemanager_thread::FileManagerThreadMsg;
use profile_traits::ipc;
use script_layout_interface::rpc::TextIndexResponse;
use script_traits::ScriptToConstellationChan;

View file

@ -16,15 +16,14 @@ use dom::document::Document;
use dom::domtokenlist::DOMTokenList;
use dom::element::{AttributeMutation, Element, ElementCreator};
use dom::element::{cors_setting_for_element, reflect_cross_origin_attribute, set_cross_origin_attribute};
use dom::globalscope::GlobalScope;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, UnbindContext, document_from_node, window_from_node};
use dom::stylesheet::StyleSheet as DOMStyleSheet;
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
use html5ever::{LocalName, Prefix};
use net_traits::ReferrerPolicy;
use script_traits::ScriptMsg;
use servo_arc::Arc;
use std::borrow::ToOwned;
use std::cell::Cell;
@ -306,8 +305,13 @@ impl HTMLLinkElement {
let document = document_from_node(self);
match document.base_url().join(href) {
Ok(url) => {
let event = ScriptMsg::NewFavicon(url.clone());
document.window().upcast::<GlobalScope>().script_to_constellation_chan().send(event).unwrap();
let window = document.window();
if window.is_top_level() {
let top_level_browsing_context_id = window.top_level_browsing_context_id();
let msg = EmbedderMsg::NewFavicon(top_level_browsing_context_id, url.clone());
window.send_to_embedder(msg);
}
}
Err(e) => debug!("Parsing url {} failed: {}", href, e)
}

View file

@ -48,6 +48,7 @@ use dom::windowproxy::WindowProxy;
use dom::worklet::Worklet;
use dom::workletglobalscope::WorkletGlobalScopeType;
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
use euclid::{Point2D, Vector2D, Rect, Size2D, TypedPoint2D, TypedScale, TypedSize2D};
use fetch;
use ipc_channel::ipc::IpcSender;
@ -58,7 +59,7 @@ use js::jsval::UndefinedValue;
use js::rust::HandleValue;
use layout_image::fetch_image_for_layout;
use microtask::MicrotaskQueue;
use msg::constellation_msg::PipelineId;
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
use net_traits::{ResourceThreads, ReferrerPolicy};
use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse};
use net_traits::image_cache::{PendingImageId, PendingImageResponse};
@ -114,8 +115,6 @@ use task_source::performance_timeline::PerformanceTimelineTaskSource;
use task_source::user_interaction::UserInteractionTaskSource;
use time;
use timers::{IsInterval, TimerCallback};
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
use tinyfiledialogs::{self, MessageBoxIcon};
use url::Position;
use webdriver_handlers::jsval_to_webdriver;
use webrender_api::{ExternalScrollId, DeviceIntPoint, DeviceUintSize, DocumentId};
@ -356,6 +355,11 @@ impl Window {
self.parent_info
}
pub fn top_level_browsing_context_id(&self) -> TopLevelBrowsingContextId {
let window_proxy = self.window_proxy.get().unwrap();
window_proxy.top_level_browsing_context_id()
}
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
let (tx, rx) = channel();
(Box::new(SendableMainThreadScriptChan(tx)), Box::new(rx))
@ -444,18 +448,6 @@ impl Window {
}
}
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
fn display_alert_dialog(message: &str) {
if !opts::get().headless {
tinyfiledialogs::message_box_ok("Alert!", message, MessageBoxIcon::Warning);
}
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn display_alert_dialog(_message: &str) {
// tinyfiledialogs not supported on Android
}
// https://html.spec.whatwg.org/multipage/#atob
pub fn base64_btoa(input: DOMString) -> Fallible<DOMString> {
// "The btoa() method must throw an InvalidCharacterError exception if
@ -541,14 +533,12 @@ impl WindowMethods for Window {
stdout.flush().unwrap();
stderr.flush().unwrap();
}
let (sender, receiver) = ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
self.send_to_constellation(ScriptMsg::Alert(s.to_string(), sender));
let should_display_alert_dialog = receiver.recv().unwrap();
if should_display_alert_dialog {
display_alert_dialog(&s);
}
let window_proxy = self.window_proxy.get().unwrap();
let top_level_browsing_context_id = window_proxy.top_level_browsing_context_id();
let msg = EmbedderMsg::Alert(top_level_browsing_context_id, s.to_string(), sender);
self.send_to_embedder(msg);
receiver.recv().unwrap();
}
// https://html.spec.whatwg.org/multipage/#dom-window-closed
@ -937,7 +927,8 @@ impl WindowMethods for Window {
//TODO determine if this operation is allowed
let dpr = self.device_pixel_ratio();
let size = TypedSize2D::new(width, height).to_f32() * dpr;
self.send_to_constellation(ScriptMsg::ResizeTo(size.to_u32()));
let top_level_browsing_context_id = self.top_level_browsing_context_id();
self.send_to_embedder(EmbedderMsg::ResizeTo(top_level_browsing_context_id, size.to_u32()));
}
// https://drafts.csswg.org/cssom-view/#dom-window-resizeby
@ -953,7 +944,10 @@ impl WindowMethods for Window {
//TODO determine if this operation is allowed
let dpr = self.device_pixel_ratio();
let point = TypedPoint2D::new(x, y).to_f32() * dpr;
self.send_to_constellation(ScriptMsg::MoveTo(point.to_i32()));
let window_proxy = self.window_proxy.get().unwrap();
let top_level_browsing_context_id = window_proxy.top_level_browsing_context_id();
let msg = EmbedderMsg::MoveTo(top_level_browsing_context_id, point.to_i32());
self.send_to_embedder(msg);
}
// https://drafts.csswg.org/cssom-view/#dom-window-moveby
@ -1742,7 +1736,11 @@ impl Window {
self.navigation_start_precise.set(time::precise_time_ns());
}
fn send_to_constellation(&self, msg: ScriptMsg) {
pub fn send_to_embedder(&self, msg: EmbedderMsg) {
self.send_to_constellation(ScriptMsg::ForwardToEmbedder(msg));
}
pub fn send_to_constellation(&self, msg: ScriptMsg) {
self.upcast::<GlobalScope>()
.script_to_constellation_chan()
.send(msg)

View file

@ -93,7 +93,7 @@ extern crate style;
extern crate style_traits;
extern crate swapper;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
#[cfg(target_os = "linux")]
extern crate tinyfiledialogs;
extern crate unicode_segmentation;
extern crate url;

View file

@ -62,6 +62,7 @@ use dom::windowproxy::WindowProxy;
use dom::worker::TrustedWorkerAddress;
use dom::worklet::WorkletThreadPool;
use dom::workletglobalscope::WorkletGlobalScopeInit;
use embedder_traits::EmbedderMsg;
use euclid::{Point2D, Vector2D, Rect};
use fetch::FetchCanceller;
use hyper::header::{ContentType, HttpDate, Headers, LastModified};
@ -1822,7 +1823,7 @@ impl ScriptThread {
Some(document) => document,
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
};
document.send_title_to_constellation();
document.send_title_to_embedder();
}
/// Handles a request to exit a pipeline and shut down layout.
@ -2282,6 +2283,8 @@ impl ScriptThread {
Some(document) => document,
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
};
let window = document.window();
let top_level_browsing_context_id = window.top_level_browsing_context_id();
// Get the previous target temporarily
let prev_mouse_over_target = self.topmost_mouse_over_target.get();
@ -2310,9 +2313,8 @@ impl ScriptThread {
let url = document.url();
url.join(&value).map(|url| url.to_string()).ok()
});
let event = ScriptMsg::NodeStatus(status);
self.script_sender.send((pipeline_id, event)).unwrap();
let event = EmbedderMsg::Status(top_level_browsing_context_id, status);
window.send_to_embedder(event);
state_already_changed = true;
}
@ -2325,8 +2327,8 @@ impl ScriptThread {
.inclusive_ancestors()
.filter_map(DomRoot::downcast::<HTMLAnchorElement>)
.next() {
let event = ScriptMsg::NodeStatus(None);
self.script_sender.send((pipeline_id, event)).unwrap();
let event = EmbedderMsg::Status(top_level_browsing_context_id, None);
window.send_to_embedder(event);
}
}
}

View file

@ -14,6 +14,7 @@ bluetooth_traits = {path = "../bluetooth_traits"}
canvas_traits = {path = "../canvas_traits"}
cookie = "0.10"
devtools_traits = {path = "../devtools_traits"}
embedder_traits = {path = "../embedder_traits"}
euclid = "0.17"
gfx_traits = {path = "../gfx_traits"}
hyper = "0.10"
@ -34,3 +35,6 @@ time = "0.1.12"
url = "1.2"
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"}
[dev-dependencies]
embedder_traits = { path = "../embedder_traits", features = ["tests"]}

View file

@ -13,6 +13,7 @@ extern crate bluetooth_traits;
extern crate canvas_traits;
extern crate cookie as cookie_rs;
extern crate devtools_traits;
extern crate embedder_traits;
extern crate euclid;
extern crate gfx_traits;
extern crate hyper;
@ -702,6 +703,8 @@ pub enum ConstellationMsg {
NewBrowser(ServoUrl, IpcSender<TopLevelBrowsingContextId>),
/// Close a top level browsing context.
CloseBrowser(TopLevelBrowsingContextId),
/// Panic a top level browsing context.
SendError(Option<TopLevelBrowsingContextId>, String),
/// Make browser visible.
SelectBrowser(TopLevelBrowsingContextId),
/// Forward an event to the script task of the given pipeline.
@ -730,6 +733,7 @@ impl fmt::Debug for ConstellationMsg {
WebVREvents(..) => "WebVREvents",
NewBrowser(..) => "NewBrowser",
CloseBrowser(..) => "CloseBrowser",
SendError(..) => "SendError",
SelectBrowser(..) => "SelectBrowser",
ForwardEvent(..) => "ForwardEvent",
SetCursor(..) => "SetCursor",

View file

@ -12,11 +12,11 @@ use WorkerGlobalScopeInit;
use WorkerScriptLoadOrigin;
use canvas_traits::canvas::{CanvasMsg, CanvasId};
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use embedder_traits::EmbedderMsg;
use euclid::{Size2D, TypedSize2D};
use gfx_traits::Epoch;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TraversalDirection};
use msg::constellation_msg::{InputMethodType, Key, KeyModifiers, KeyState};
use net_traits::CoreResourceMsg;
use net_traits::request::RequestInit;
use net_traits::storage_thread::StorageType;
@ -83,6 +83,8 @@ pub enum LogEntry {
/// Messages from the script to the constellation.
#[derive(Deserialize, Serialize)]
pub enum ScriptMsg {
/// Forward a message to the embedder.
ForwardToEmbedder(EmbedderMsg),
/// Requests are sent to constellation and fetches are checked manually
/// for cross-origin loads
InitiateNavigateRequest(RequestInit, /* cancellation_chan */ IpcReceiver<()>),
@ -104,8 +106,6 @@ pub enum ScriptMsg {
GetParentInfo(PipelineId, IpcSender<Option<PipelineId>>),
/// Get the nth child browsing context ID for a given browsing context, sorted in tree order.
GetChildBrowsingContextId(BrowsingContextId, usize, IpcSender<Option<BrowsingContextId>>),
/// <head> tag finished parsing
HeadParsed,
/// All pending loads are complete, and the `load` event for this pipeline
/// has been dispatched.
LoadComplete,
@ -124,10 +124,6 @@ pub enum ScriptMsg {
ReplaceHistoryState(HistoryStateId, ServoUrl),
/// Gets the length of the joint session history from the constellation.
JointSessionHistoryLength(IpcSender<u32>),
/// Favicon detected
NewFavicon(ServoUrl),
/// Status message to be displayed in the chrome, eg. a link URL on mouseover.
NodeStatus(Option<String>),
/// Notification that this iframe should be removed.
/// Returns a list of pipelines which were closed.
RemoveIFrame(BrowsingContextId, IpcSender<Vec<PipelineId>>),
@ -147,17 +143,6 @@ pub enum ScriptMsg {
SetDocumentState(DocumentState),
/// Update the pipeline Url, which can change after redirections.
SetFinalUrl(ServoUrl),
/// Check if an alert dialog box should be presented
Alert(String, IpcSender<bool>),
/// Set title of current page
/// <https://html.spec.whatwg.org/multipage/#document.title>
SetTitle(Option<String>),
/// Send a key event
SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers),
/// Move the window to a point
MoveTo(DeviceIntPoint),
/// Resize the window to size
ResizeTo(DeviceUintSize),
/// Script has handled a touch event, and either prevented or allowed default actions.
TouchEventProcessed(EventResult),
/// A log entry, with the top-level browsing context id and thread name
@ -171,18 +156,12 @@ pub enum ScriptMsg {
ForwardDOMMessage(DOMMessage, ServoUrl),
/// Store the data required to activate a service worker for the given scope
RegisterServiceWorker(ScopeThings, ServoUrl),
/// Enter or exit fullscreen
SetFullscreenState(bool),
/// Get Window Informations size and position
GetClientWindow(IpcSender<(DeviceUintSize, DeviceIntPoint)>),
/// Get the screen size (pixel)
GetScreenSize(IpcSender<(DeviceUintSize)>),
/// Get the available screen size (pixel)
GetScreenAvailSize(IpcSender<(DeviceUintSize)>),
/// Request to present an IME to the user when an editable element is focused.
ShowIME(InputMethodType),
/// Request to hide the IME when the editable element is blurred.
HideIME,
/// Requests that the compositor shut down.
Exit,
}
@ -191,6 +170,7 @@ impl fmt::Debug for ScriptMsg {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use self::ScriptMsg::*;
let variant = match *self {
ForwardToEmbedder(..) => "ForwardToEmbedder",
InitiateNavigateRequest(..) => "InitiateNavigateRequest",
BroadcastStorageEvent(..) => "BroadcastStorageEvent",
ChangeRunningAnimationsState(..) => "ChangeRunningAnimationsState",
@ -200,7 +180,6 @@ impl fmt::Debug for ScriptMsg {
GetBrowsingContextId(..) => "GetBrowsingContextId",
GetParentInfo(..) => "GetParentInfo",
GetChildBrowsingContextId(..) => "GetChildBrowsingContextId",
HeadParsed => "HeadParsed",
LoadComplete => "LoadComplete",
LoadUrl(..) => "LoadUrl",
AbortLoadUrl => "AbortLoadUrl",
@ -209,8 +188,6 @@ impl fmt::Debug for ScriptMsg {
PushHistoryState(..) => "PushHistoryState",
ReplaceHistoryState(..) => "ReplaceHistoryState",
JointSessionHistoryLength(..) => "JointSessionHistoryLength",
NewFavicon(..) => "NewFavicon",
NodeStatus(..) => "NodeStatus",
RemoveIFrame(..) => "RemoveIFrame",
SetVisible(..) => "SetVisible",
VisibilityChangeComplete(..) => "VisibilityChangeComplete",
@ -220,23 +197,15 @@ impl fmt::Debug for ScriptMsg {
ActivateDocument => "ActivateDocument",
SetDocumentState(..) => "SetDocumentState",
SetFinalUrl(..) => "SetFinalUrl",
Alert(..) => "Alert",
SetTitle(..) => "SetTitle",
SendKeyEvent(..) => "SendKeyEvent",
MoveTo(..) => "MoveTo",
ResizeTo(..) => "ResizeTo",
TouchEventProcessed(..) => "TouchEventProcessed",
LogEntry(..) => "LogEntry",
DiscardDocument => "DiscardDocument",
PipelineExited => "PipelineExited",
ForwardDOMMessage(..) => "ForwardDOMMessage",
RegisterServiceWorker(..) => "RegisterServiceWorker",
SetFullscreenState(..) => "SetFullscreenState",
GetClientWindow(..) => "GetClientWindow",
GetScreenSize(..) => "GetScreenSize",
GetScreenAvailSize(..) => "GetScreenAvailSize",
ShowIME(..) => "ShowIME",
HideIME => "HideIME",
Exit => "Exit",
};
write!(formatter, "ScriptMsg::{}", variant)

View file

@ -73,13 +73,13 @@ use bluetooth_traits::BluetoothRequest;
use canvas::gl_context::GLContextFactory;
use canvas::webgl_thread::WebGLThreads;
use compositing::{IOCompositor, ShutdownState, RenderNotifier};
use compositing::compositor_thread::{self, CompositorProxy, CompositorReceiver, InitialCompositorState};
use compositing::compositor_thread::{EmbedderMsg, EmbedderProxy, EmbedderReceiver};
use compositing::compositor_thread::{CompositorProxy, CompositorReceiver, InitialCompositorState};
use compositing::windowing::{WindowEvent, WindowMethods};
use constellation::{Constellation, InitialConstellationState, UnprivilegedPipelineContent};
use constellation::{FromCompositorLogger, FromScriptLogger};
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
use constellation::content_process_sandbox_profile;
use embedder_traits::{EmbedderMsg, EmbedderProxy, EmbedderReceiver, EventLoopWaker};
use env_logger::Builder as EnvLoggerBuilder;
use euclid::Length;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
@ -346,6 +346,13 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
warn!("Sending CloseBrowser message to constellation failed ({}).", e);
}
}
WindowEvent::SendError(ctx, e) => {
let msg = ConstellationMsg::SendError(ctx, e);
if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending CloseBrowser message to constellation failed ({}).", e);
}
}
}
}
@ -417,7 +424,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
}
}
fn create_embedder_channel(event_loop_waker: Box<compositor_thread::EventLoopWaker>)
fn create_embedder_channel(event_loop_waker: Box<EventLoopWaker>)
-> (EmbedderProxy, EmbedderReceiver) {
let (sender, receiver) = channel();
(EmbedderProxy {
@ -429,7 +436,7 @@ fn create_embedder_channel(event_loop_waker: Box<compositor_thread::EventLoopWak
})
}
fn create_compositor_channel(event_loop_waker: Box<compositor_thread::EventLoopWaker>)
fn create_compositor_channel(event_loop_waker: Box<EventLoopWaker>)
-> (CompositorProxy, CompositorReceiver) {
let (sender, receiver) = channel();
(CompositorProxy {

View file

@ -5,12 +5,10 @@
use euclid::{TypedPoint2D, TypedVector2D};
use glutin_app::keyutils::{CMD_OR_CONTROL, CMD_OR_ALT};
use glutin_app::window::{Window, LINE_HEIGHT};
use servo::compositing::compositor_thread::EmbedderMsg;
use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent};
use servo::ipc_channel::ipc::IpcSender;
use servo::embedder_traits::{EmbedderMsg, FilterPattern};
use servo::msg::constellation_msg::{Key, TopLevelBrowsingContextId as BrowserId};
use servo::msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
use servo::net_traits::filemanager_thread::FilterPattern;
use servo::net_traits::pub_domains::is_reg_domain;
use servo::script_traits::TouchEventType;
use servo::servo_config::opts;
@ -21,7 +19,8 @@ use std::mem;
use std::rc::Rc;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
use std::thread;
use tinyfiledialogs;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
use tinyfiledialogs::{self, MessageBoxIcon};
pub struct Browser {
current_url: Option<ServoUrl>,
@ -260,6 +259,13 @@ impl Browser {
EmbedderMsg::ResizeTo(_browser_id, size) => {
self.window.set_inner_size(size);
}
EmbedderMsg::Alert(browser_id, message, sender) => {
display_alert_dialog(message.to_owned());
if let Err(e) = sender.send(()) {
let reason = format!("Failed to send Alert response: {}", e);
self.event_queue.push(WindowEvent::SendError(Some(browser_id), reason));
}
}
EmbedderMsg::AllowNavigation(_browser_id, _url, response_chan) => {
if let Err(e) = response_chan.send(true) {
warn!("Failed to send allow_navigation() response: {}", e);
@ -277,8 +283,8 @@ impl Browser {
EmbedderMsg::HeadParsed(_browser_id, ) => {
self.loading_state = Some(LoadingState::Loading);
}
EmbedderMsg::HistoryChanged(_browser_id, entries, current) => {
self.current_url = Some(entries[current].url.clone());
EmbedderMsg::HistoryChanged(_browser_id, urls, current) => {
self.current_url = Some(urls[current].clone());
}
EmbedderMsg::SetFullscreenState(_browser_id, state) => {
self.window.set_fullscreen(state);
@ -295,13 +301,22 @@ impl Browser {
EmbedderMsg::Panic(_browser_id, _reason, _backtrace) => {
},
EmbedderMsg::GetSelectedBluetoothDevice(devices, sender) => {
platform_get_selected_devices(devices, sender);
let selected = platform_get_selected_devices(devices);
if let Err(e) = sender.send(selected) {
let reason = format!("Failed to send GetSelectedBluetoothDevice response: {}", e);
self.event_queue.push(WindowEvent::SendError(None, reason));
};
},
EmbedderMsg::SelectFiles(patterns, multiple_files, sender) => {
if opts::get().headless {
let _ = sender.send(None);
}
platform_get_selected_files(patterns, multiple_files, sender);
let res = match (opts::get().headless,
platform_get_selected_files(patterns, multiple_files)) {
(true, _) | (false, None) => sender.send(None),
(false, Some(files)) => sender.send(Some(files))
};
if let Err(e) = res {
let reason = format!("Failed to send SelectFiles response: {}", e);
self.event_queue.push(WindowEvent::SendError(None, reason));
};
}
EmbedderMsg::ShowIME(_browser_id, _kind) => {
debug!("ShowIME received");
@ -315,8 +330,22 @@ impl Browser {
}
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
fn display_alert_dialog(message: String) {
if !opts::get().headless {
let _ = thread::Builder::new().name("display alert dialog".to_owned()).spawn(move || {
tinyfiledialogs::message_box_ok("Alert!", &message, MessageBoxIcon::Warning);
}).unwrap().join().expect("Thread spawning failed");
}
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn display_alert_dialog(_message: String) {
// tinyfiledialogs not supported on Android
}
#[cfg(target_os = "linux")]
fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<String>>) {
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
let picker_name = "Choose a device";
thread::Builder::new().name(picker_name.to_owned()).spawn(move || {
@ -328,58 +357,54 @@ fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<
match tinyfiledialogs::list_dialog("Choose a device", &["Id", "Name"], dialog_rows) {
Some(device) => {
// The device string format will be "Address|Name". We need the first part of it.
let address = device.split("|").next().map(|s| s.to_string());
let _ = sender.send(address);
device.split("|").next().map(|s| s.to_string())
},
None => {
let _ = sender.send(None);
None
}
}
}).expect("Thread spawning failed");
}).unwrap().join().expect("Thread spawning failed")
}
#[cfg(not(target_os = "linux"))]
fn platform_get_selected_devices(devices: Vec<String>, sender: IpcSender<Option<String>>) {
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
for device in devices {
if let Some(address) = device.split("|").next().map(|s| s.to_string()) {
let _ = sender.send(Some(address));
return Some(address)
}
}
let _ = sender.send(None);
None
}
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
fn platform_get_selected_files(patterns: Vec<FilterPattern>,
multiple_files: bool,
sender: IpcSender<Option<Vec<String>>>) {
multiple_files: bool)
-> Option<Vec<String>> {
let picker_name = if multiple_files { "Pick files" } else { "Pick a file" };
thread::Builder::new().name(picker_name.to_owned()).spawn(move || {
let mut filter = vec![];
let mut filters = vec![];
for p in patterns {
let s = "*.".to_string() + &p.0;
filter.push(s)
filters.push(s)
}
let filter_ref = &(filter.iter().map(|s| s.as_str()).collect::<Vec<&str>>()[..]);
let filter_opt = if filter.len() > 0 { Some((filter_ref, "")) } else { None };
let filter_ref = &(filters.iter().map(|s| s.as_str()).collect::<Vec<&str>>()[..]);
let filter_opt = if filters.len() > 0 { Some((filter_ref, "")) } else { None };
if multiple_files {
let files = tinyfiledialogs::open_file_dialog_multi(picker_name, "", filter_opt);
let _ = sender.send(files);
tinyfiledialogs::open_file_dialog_multi(picker_name, "", filter_opt)
} else {
let file = tinyfiledialogs::open_file_dialog(picker_name, "", filter_opt);
let _ = sender.send(file.map(|x| vec![x]));
file.map(|x| vec![x])
}
}).expect("Thread spawning failed");
}).unwrap().join().expect("Thread spawning failed")
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn platform_get_selected_files(_patterns: Vec<FilterPattern>,
_multiple_files: bool,
sender: IpcSender<Option<Vec<String>>>) {
_multiple_files: bool)
-> Option<Vec<String>> {
warn!("File picker not implemented");
let _ = sender.send(None);
None
}
fn sanitize_url(request: &str) -> Option<ServoUrl> {

View file

@ -11,9 +11,9 @@ use gleam::gl;
use glutin::{Api, ContextBuilder, GlContext, GlRequest, GlWindow};
#[cfg(any(target_os = "linux", target_os = "macos"))]
use osmesa_sys;
use servo::compositing::compositor_thread::EventLoopWaker;
use servo::compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
use servo::embedder_traits::EventLoopWaker;
use servo::msg::constellation_msg::{Key, KeyState};
use servo::script_traits::TouchEventType;
use servo::servo_config::opts;