aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-03-29 12:42:01 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2016-03-29 12:42:01 +0530
commitaac2da75f40f4c55a4b450b6d9d134429fcf741e (patch)
tree46b3d933d44726121af4f4079a80282b7b73018e
parentddc57fe641c3940ecdad98297ac5b2ff95c3340c (diff)
parenta5a299ea881cc589511f8a03f63d53f4b39cdf66 (diff)
downloadservo-aac2da75f40f4c55a4b450b6d9d134429fcf741e.tar.gz
servo-aac2da75f40f4c55a4b450b6d9d134429fcf741e.zip
Auto merge of #8641 - notriddle:no_headless, r=glennw
No more headless compositor. Just the normal one. Fixes #8573 <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8641) <!-- Reviewable:end -->
-rw-r--r--components/compositing/compositor.rs11
-rw-r--r--components/compositing/compositor_thread.rs29
-rw-r--r--components/compositing/constellation.rs14
-rw-r--r--components/compositing/headless.rs147
-rw-r--r--components/compositing/lib.rs1
-rw-r--r--components/compositing/pipeline.rs14
-rw-r--r--components/compositing/windowing.rs3
-rw-r--r--components/gfx/paint_thread.rs9
-rw-r--r--components/layout/layout_thread.rs4
-rw-r--r--components/script/dom/htmliframeelement.rs24
-rw-r--r--components/script/dom/window.rs2
-rw-r--r--components/script/script_thread.rs1
-rw-r--r--components/script_traits/lib.rs2
-rw-r--r--components/script_traits/script_msg.rs2
-rw-r--r--components/servo/Cargo.toml4
-rw-r--r--components/servo/lib.rs17
-rw-r--r--components/servo/main.rs50
-rw-r--r--ports/cef/browser.rs16
-rw-r--r--ports/cef/window.rs2
-rw-r--r--ports/glutin/Cargo.toml4
-rw-r--r--ports/glutin/lib.rs4
-rw-r--r--ports/glutin/window.rs177
-rw-r--r--ports/gonk/src/main.rs20
-rw-r--r--ports/gonk/src/window.rs4
-rw-r--r--python/servo/build_commands.py32
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html.ini2
26 files changed, 121 insertions, 474 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index b5df18b2564..7f6c28c178e 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -525,6 +525,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
(Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties),
ShutdownState::NotShuttingDown) => {
+ debug!("initializing layers for pipeline: {:?}", pipeline_id);
self.pipeline_details(pipeline_id).current_epoch = epoch;
self.collect_old_layers(pipeline_id, &properties);
@@ -542,7 +543,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
(Msg::GetNativeDisplay(chan),
ShutdownState::NotShuttingDown) => {
- chan.send(Some(self.native_display.clone())).unwrap();
+ chan.send(self.native_display.clone()).unwrap();
}
(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id),
@@ -641,7 +642,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
reply.send(img).unwrap();
}
- (Msg::PaintThreadExited(pipeline_id), ShutdownState::NotShuttingDown) => {
+ (Msg::PaintThreadExited(pipeline_id), _) => {
+ debug!("compositor learned about paint thread exiting: {:?}", pipeline_id);
self.remove_pipeline_root_layer(pipeline_id);
}
@@ -690,8 +692,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
reports_chan.send(reports);
}
- (Msg::PipelineExited(pipeline_id), _) => {
+ (Msg::PipelineExited(pipeline_id, sender), _) => {
+ debug!("Compositor got pipeline exited: {:?}", pipeline_id);
self.pending_subpages.remove(&pipeline_id);
+ self.remove_pipeline_root_layer(pipeline_id);
+ sender.send(()).unwrap();
}
// When we are shutting_down, we need to avoid performing operations
diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs
index eb0020c366d..fdfd4c633bf 100644
--- a/components/compositing/compositor_thread.rs
+++ b/components/compositing/compositor_thread.rs
@@ -9,7 +9,6 @@ use compositor::{self, CompositingReason};
use euclid::point::Point2D;
use euclid::size::Size2D;
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerProperties, PaintListener};
-use headless;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use layers::layers::{BufferRequest, LayerBufferSet};
use layers::platform::surface::{NativeDisplay, NativeSurface};
@@ -98,6 +97,8 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
ScriptToCompositorMsg::TouchEventProcessed(result) => {
compositor_proxy.send(Msg::TouchEventProcessed(result))
}
+
+ ScriptToCompositorMsg::Exited => break,
}
}
}
@@ -123,7 +124,7 @@ impl PaintListener for Box<CompositorProxy + 'static + Send> {
// just return None in this case, since the paint thread
// will exit shortly and never actually be requested
// to paint buffers by the compositor.
- port.recv().unwrap_or(None)
+ port.recv().ok()
}
fn assign_painted_buffers(&mut self,
@@ -174,9 +175,7 @@ pub enum Msg {
/// Requests the compositor's graphics metadata. Graphics metadata is what the painter needs
/// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this
/// is the pixel format.
- ///
- /// The headless compositor returns `None`.
- GetNativeDisplay(Sender<Option<NativeDisplay>>),
+ GetNativeDisplay(Sender<NativeDisplay>),
/// Tells the compositor to create or update the layers for a pipeline if necessary
/// (i.e. if no layer with that ID exists).
@@ -233,7 +232,11 @@ pub enum Msg {
/// Resize the window to size
ResizeTo(Size2D<u32>),
/// A pipeline was shut down.
- PipelineExited(PipelineId),
+ // This message acts as a synchronization point between the constellation,
+ // when it shuts down a pipeline, to the compositor; when the compositor
+ // sends a reply on the IpcSender, the constellation knows it's safe to
+ // tear down the other threads associated with this pipeline.
+ PipelineExited(PipelineId, IpcSender<()>),
}
impl Debug for Msg {
@@ -276,20 +279,12 @@ impl Debug for Msg {
pub struct CompositorThread;
impl CompositorThread {
- pub fn create<Window>(window: Option<Rc<Window>>,
+ pub fn create<Window>(window: Rc<Window>,
state: InitialCompositorState)
-> Box<CompositorEventListener + 'static>
where Window: WindowMethods + 'static {
- match window {
- Some(window) => {
- box compositor::IOCompositor::create(window, state)
- as Box<CompositorEventListener>
- }
- None => {
- box headless::NullCompositor::create(state)
- as Box<CompositorEventListener>
- }
- }
+ box compositor::IOCompositor::create(window, state)
+ as Box<CompositorEventListener>
}
}
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs
index f1876e660c7..159477e34cb 100644
--- a/components/compositing/constellation.rs
+++ b/components/compositing/constellation.rs
@@ -648,8 +648,13 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
}
// Update pipeline url after redirections
Request::Script(FromScriptMsg::SetFinalUrl(pipeline_id, final_url)) => {
- debug!("constellation got set final url message");
- self.mut_pipeline(pipeline_id).url = final_url;
+ // The script may have finished loading after we already started shutting down.
+ if let Some(ref mut pipeline) = self.pipelines.get_mut(&pipeline_id) {
+ debug!("constellation got set final url message");
+ pipeline.url = final_url;
+ } else {
+ debug!("constellation got set final url message for dead pipeline");
+ }
}
Request::Script(FromScriptMsg::MozBrowserEvent(pipeline_id,
subpage_id,
@@ -693,9 +698,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
}
}
}
- Request::Script(FromScriptMsg::RemoveIFrame(pipeline_id)) => {
+ Request::Script(FromScriptMsg::RemoveIFrame(pipeline_id, sender)) => {
debug!("constellation got remove iframe message");
self.handle_remove_iframe_msg(pipeline_id);
+ if let Some(sender) = sender {
+ sender.send(()).unwrap();
+ }
}
Request::Script(FromScriptMsg::NewFavicon(url)) => {
debug!("constellation got new favicon message");
diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs
deleted file mode 100644
index c46bdd52262..00000000000
--- a/components/compositing/headless.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use AnimationTickType;
-use CompositorMsg as ConstellationMsg;
-use compositor_thread::{CompositorEventListener, CompositorReceiver};
-use compositor_thread::{InitialCompositorState, Msg};
-use euclid::scale_factor::ScaleFactor;
-use euclid::{Point2D, Size2D};
-use msg::constellation_msg::WindowSizeData;
-use profile_traits::mem;
-use profile_traits::time;
-use script_traits::AnimationState;
-use std::sync::mpsc::Sender;
-use util::opts;
-use windowing::WindowEvent;
-
-/// Starts the compositor, which listens for messages on the specified port.
-///
-/// This is the null compositor which doesn't draw anything to the screen.
-/// It's intended for headless testing.
-pub struct NullCompositor {
- /// The port on which we receive messages.
- pub port: Box<CompositorReceiver>,
- /// A channel to the constellation.
- constellation_chan: Sender<ConstellationMsg>,
- /// A channel to the time profiler.
- time_profiler_chan: time::ProfilerChan,
- /// A channel to the memory profiler.
- mem_profiler_chan: mem::ProfilerChan,
-}
-
-impl NullCompositor {
- fn new(state: InitialCompositorState) -> NullCompositor {
- NullCompositor {
- port: state.receiver,
- constellation_chan: state.constellation_chan,
- time_profiler_chan: state.time_profiler_chan,
- mem_profiler_chan: state.mem_profiler_chan,
- }
- }
-
- pub fn create(state: InitialCompositorState) -> NullCompositor {
- let compositor = NullCompositor::new(state);
-
- // Tell the constellation about the initial fake size.
- {
- compositor.constellation_chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
- initial_viewport: Size2D::typed(800_f32, 600_f32),
- visible_viewport: Size2D::typed(800_f32, 600_f32),
- device_pixel_ratio:
- ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)),
- })).unwrap();
- }
-
- compositor
- }
-}
-
-impl CompositorEventListener for NullCompositor {
- fn handle_events(&mut self, _: Vec<WindowEvent>) -> bool {
- match self.port.recv_compositor_msg() {
- Msg::Exit(chan) => {
- debug!("shutting down the constellation");
- self.constellation_chan.send(ConstellationMsg::Exit).unwrap();
- chan.send(()).unwrap();
- }
-
- Msg::ShutdownComplete => {
- debug!("constellation completed shutdown");
-
- // Drain compositor port, sometimes messages contain channels that are blocking
- // another thread from finishing (i.e. SetIds)
- while self.port.try_recv_compositor_msg().is_some() {}
-
- self.time_profiler_chan.send(time::ProfilerMsg::Exit);
- self.mem_profiler_chan.send(mem::ProfilerMsg::Exit);
-
- return false
- }
-
- Msg::GetNativeDisplay(chan) => {
- chan.send(None).unwrap();
- }
-
- Msg::SetFrameTree(_, response_chan, _) => {
- response_chan.send(()).unwrap();
- }
-
- Msg::GetClientWindow(send) => {
- let rect = (Size2D::zero(), Point2D::zero());
- send.send(rect).unwrap();
- }
-
- Msg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
- match animation_state {
- AnimationState::AnimationsPresent |
- AnimationState::NoAnimationsPresent |
- AnimationState::NoAnimationCallbacksPresent => {}
- AnimationState::AnimationCallbacksPresent => {
- let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Script);
- self.constellation_chan.send(msg).unwrap()
- }
- }
- }
-
- // Explicitly list ignored messages so that when we add a new one,
- // we'll notice and think about whether it needs a response, like
- // SetFrameTree.
-
- Msg::InitializeLayersForPipeline(..) |
- Msg::AssignPaintedBuffers(..) |
- Msg::ScrollFragmentPoint(..) |
- Msg::Status(..) |
- Msg::LoadStart(..) |
- Msg::LoadComplete(..) |
- Msg::DelayedCompositionTimeout(..) |
- Msg::Recomposite(..) |
- Msg::ChangePageTitle(..) |
- Msg::ChangePageUrl(..) |
- Msg::KeyEvent(..) |
- Msg::TouchEventProcessed(..) |
- Msg::SetCursor(..) |
- Msg::ViewportConstrained(..) => {}
- Msg::CreatePng(..) |
- Msg::PaintThreadExited(..) |
- Msg::MoveTo(..) |
- Msg::ResizeTo(..) |
- Msg::IsReadyToSaveImageReply(..) => {}
- Msg::NewFavicon(..) => {}
- Msg::HeadParsed => {}
- Msg::ReturnUnusedNativeSurfaces(..) => {}
- Msg::CollectMemoryReports(..) => {}
- Msg::PipelineExited(..) => {}
- }
- true
- }
-
- fn repaint_synchronously(&mut self) {}
-
- fn pinch_zoom_level(&self) -> f32 {
- 1.0
- }
-
- fn title_for_main_frame(&self) {}
-}
diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs
index c5fc7537e0a..d72c2bace6c 100644
--- a/components/compositing/lib.rs
+++ b/components/compositing/lib.rs
@@ -68,7 +68,6 @@ mod compositor_layer;
pub mod compositor_thread;
pub mod constellation;
mod delayed_composition;
-mod headless;
pub mod pipeline;
#[cfg(not(target_os = "windows"))]
pub mod sandboxing;
diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs
index bbf892048c8..40b1a2baa6a 100644
--- a/components/compositing/pipeline.rs
+++ b/components/compositing/pipeline.rs
@@ -28,13 +28,13 @@ use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg};
use script_traits::{ScriptToCompositorMsg, ScriptThreadFactory, TimerEventRequest};
use std::mem;
use std::sync::mpsc::{Receiver, Sender, channel};
-use std::thread;
use url::Url;
use util;
use util::geometry::{PagePx, ViewportPx};
use util::ipc::OptionalIpcSender;
use util::opts::{self, Opts};
use util::prefs;
+use util::thread;
use webrender_traits;
/// A uniquely-identifiable pipeline of script thread, layout thread, and paint thread.
@@ -290,6 +290,13 @@ impl Pipeline {
pub fn exit(&self) {
debug!("pipeline {:?} exiting", self.id);
+ // The compositor wants to know when pipelines shut down too.
+ // It may still have messages to process from these other threads
+ // before they can be safely shut down.
+ let (sender, receiver) = ipc::channel().unwrap();
+ self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id, sender));
+ receiver.recv().unwrap();
+
// Script thread handles shutting down layout, and layout handles shutting down the painter.
// For now, if the script thread has failed, we give up on clean shutdown.
if self.script_chan
@@ -300,9 +307,6 @@ impl Pipeline {
let _ = self.paint_shutdown_port.recv();
let _ = self.layout_shutdown_port.recv();
}
-
- // The compositor wants to know when pipelines shut down too.
- self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id))
}
pub fn freeze(&self) {
@@ -472,7 +476,7 @@ impl PrivilegedPipelineContent {
let compositor_proxy_for_script_listener_thread =
self.compositor_proxy.clone_compositor_proxy();
let script_to_compositor_port = self.script_to_compositor_port;
- thread::spawn(move || {
+ thread::spawn_named("CompositorScriptListener".to_owned(), move || {
compositor_thread::run_script_listener_thread(
compositor_proxy_for_script_listener_thread,
script_to_compositor_port)
diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs
index 02eda99b521..8719db56a03 100644
--- a/components/compositing/windowing.rs
+++ b/components/compositing/windowing.rs
@@ -15,7 +15,6 @@ use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use net_traits::net_error_list::NetError;
use script_traits::{MouseButton, TouchEventType, TouchId};
use std::fmt::{Debug, Error, Formatter};
-use std::rc::Rc;
use style_traits::cursor::Cursor;
use url::Url;
use util::geometry::ScreenPx;
@@ -142,7 +141,7 @@ pub trait WindowMethods {
///
/// This is part of the windowing system because its implementation often involves OS-specific
/// magic to wake the up window's event loop.
- fn create_compositor_channel(_: &Option<Rc<Self>>)
+ fn create_compositor_channel(&self)
-> (Box<CompositorProxy + Send>, Box<CompositorReceiver>);
/// Requests that the window system prepare a composite. Typically this will involve making
diff --git a/components/gfx/paint_thread.rs b/components/gfx/paint_thread.rs
index 3f945c3898c..50afd79bd58 100644
--- a/components/gfx/paint_thread.rs
+++ b/components/gfx/paint_thread.rs
@@ -342,7 +342,7 @@ pub enum Msg {
#[derive(Deserialize, Serialize)]
pub enum LayoutToPaintMsg {
PaintInit(Epoch, Arc<DisplayList>),
- Exit(IpcSender<()>),
+ Exit,
}
pub enum ChromeToPaintMsg {
@@ -505,21 +505,20 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
// FIXME(njn): should eventually measure the paint thread.
channel.send(Vec::new())
}
- Msg::FromLayout(LayoutToPaintMsg::Exit(ref response_channel)) => {
+ Msg::FromLayout(LayoutToPaintMsg::Exit) => {
// Ask the compositor to remove any layers it is holding for this paint thread.
// FIXME(mrobinson): This can probably move back to the constellation now.
+ debug!("PaintThread: Exiting.");
self.compositor.notify_paint_thread_exiting(self.id);
- debug!("PaintThread: Exiting.");
- let _ = response_channel.send(());
break;
}
Msg::FromChrome(ChromeToPaintMsg::Exit) => {
// Ask the compositor to remove any layers it is holding for this paint thread.
// FIXME(mrobinson): This can probably move back to the constellation now.
+ debug!("PaintThread: Exiting.");
self.compositor.notify_paint_thread_exiting(self.id);
- debug!("PaintThread: Exiting.");
break;
}
}
diff --git a/components/layout/layout_thread.rs b/components/layout/layout_thread.rs
index e6412348e6c..6e8ab8635f9 100644
--- a/components/layout/layout_thread.rs
+++ b/components/layout/layout_thread.rs
@@ -777,9 +777,7 @@ impl LayoutThread {
traversal.shutdown()
}
- let (response_chan, response_port) = ipc::channel().unwrap();
- self.paint_chan.send(LayoutToPaintMsg::Exit(response_chan)).unwrap();
- response_port.recv().unwrap()
+ self.paint_chan.send(LayoutToPaintMsg::Exit).unwrap();
}
fn handle_add_stylesheet<'a, 'b>(&self,
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index a4ccafd2d4c..4e7e6108785 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -28,6 +28,7 @@ use dom::node::{Node, UnbindContext, window_from_node, document_from_node};
use dom::urlhelper::UrlHelper;
use dom::virtualmethods::VirtualMethods;
use dom::window::{ReflowReason, Window};
+use ipc_channel::ipc;
use js::jsapi::{JSAutoCompartment, JSAutoRequest, RootedValue, JSContext, MutableHandleValue};
use js::jsval::{UndefinedValue, NullValue};
use layout_interface::ReflowQueryType;
@@ -559,9 +560,30 @@ impl VirtualMethods for HTMLIFrameElement {
let window = window_from_node(self);
let window = window.r();
+ // The only reason we're waiting for the iframe to be totally
+ // removed is to ensure the script thread can't add iframes faster
+ // than the compositor can remove them.
+ //
+ // Since most of this cleanup doesn't happen on same-origin
+ // iframes, and since that would cause a deadlock, don't do it.
let ConstellationChan(ref chan) = window.constellation_chan();
- let msg = ConstellationMsg::RemoveIFrame(pipeline_id);
+ let same_origin = if let Some(self_url) = self.get_url() {
+ let win_url = window_from_node(self).get_url();
+ UrlHelper::SameOrigin(&self_url, &win_url)
+ } else {
+ false
+ };
+ let (sender, receiver) = if same_origin {
+ (None, None)
+ } else {
+ let (sender, receiver) = ipc::channel().unwrap();
+ (Some(sender), Some(receiver))
+ };
+ let msg = ConstellationMsg::RemoveIFrame(pipeline_id, sender);
chan.send(msg).unwrap();
+ if let Some(receiver) = receiver {
+ receiver.recv().unwrap()
+ }
// Resetting the subpage id to None is required here so that
// if this iframe is subsequently re-added to the document
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 9ee7fd81160..1e79620fb29 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -1060,7 +1060,7 @@ impl Window {
// When all these conditions are met, notify the constellation
// that this pipeline is ready to write the image (from the script thread
// perspective at least).
- if opts::get().output_file.is_some() && for_display {
+ if (opts::get().output_file.is_some() || opts::get().exit_after_load) && for_display {
let document = self.Document();
// Checks if the html element has reftest-wait attribute present.
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 5876f7d16c9..c591cd955a3 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -548,6 +548,7 @@ impl ScriptThreadFactory for ScriptThread {
let reporter_name = format!("script-reporter-{}", id);
mem_profiler_chan.run_with_memory_reporting(|| {
script_thread.start();
+ let _ = script_thread.compositor.borrow_mut().send(ScriptToCompositorMsg::Exited);
let _ = script_thread.content_process_shutdown_chan.send(());
}, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports);
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 6aeca4068ec..e61c83b4e6b 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -365,6 +365,8 @@ pub enum ScriptToCompositorMsg {
TouchEventProcessed(EventResult),
/// Requests that the compositor shut down.
Exit,
+ /// Allow the compositor to free script-specific resources.
+ Exited,
}
/// Whether a DOM event was prevented by web content
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index 5b6afa3db1e..7c82de027bf 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -74,7 +74,7 @@ pub enum ScriptMsg {
/// Status message to be displayed in the chrome, eg. a link URL on mouseover.
NodeStatus(Option<String>),
/// Notification that this iframe should be removed.
- RemoveIFrame(PipelineId),
+ RemoveIFrame(PipelineId, Option<IpcSender<()>>),
/// A load has been requested in an IFrame.
ScriptLoadedURLInIFrame(IFrameLoadInfo),
/// Requests that the constellation set the contents of the clipboard
diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml
index c547e09a071..6591a0bd898 100644
--- a/components/servo/Cargo.toml
+++ b/components/servo/Cargo.toml
@@ -60,9 +60,7 @@ git = "https://github.com/servo/webrender_traits"
git = "https://github.com/servo/webrender"
[features]
-default = ["glutin_app", "window", "webdriver"]
-window = ["glutin_app/window"]
-headless = ["glutin_app/headless"]
+default = ["glutin_app", "webdriver"]
webdriver = ["webdriver_server"]
energy-profiling = ["profile_traits/energy-profiling"]
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 6a18419d581..6ddcd58222a 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -79,7 +79,6 @@ use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
-use std::borrow::Borrow;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use util::opts;
@@ -103,7 +102,7 @@ pub struct Browser {
}
impl Browser {
- pub fn new<Window>(window: Option<Rc<Window>>) -> Browser
+ pub fn new<Window>(window: Rc<Window>) -> Browser
where Window: WindowMethods + 'static {
// Global configuration options, parsed from the command line.
let opts = opts::get();
@@ -115,14 +114,8 @@ impl Browser {
// messages to client may need to pump a platform-specific event loop
// to deliver the message.
let (compositor_proxy, compositor_receiver) =
- WindowMethods::create_compositor_channel(&window);
- let supports_clipboard = match window {
- Some(ref win_rc) => {
- let win: &Window = win_rc.borrow();
- win.supports_clipboard()
- }
- None => false
- };
+ window.create_compositor_channel();
+ let supports_clipboard = window.supports_clipboard();
let time_profiler_chan = profile_time::Profiler::create(opts.time_profiler_period);
let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
let devtools_chan = opts.devtools_port.map(|port| {
@@ -134,9 +127,7 @@ impl Browser {
resource_path.push("shaders");
// TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
- let hidpi_factor = window.as_ref()
- .map(|window| window.hidpi_factor().get())
- .unwrap_or(1.0);
+ let hidpi_factor = window.hidpi_factor().get();
let device_pixel_ratio = match opts.device_pixels_per_px {
Some(device_pixels_per_px) => device_pixels_per_px,
None => match opts.output_file {
diff --git a/components/servo/main.rs b/components/servo/main.rs
index 8033110e7f1..08ed645b246 100644
--- a/components/servo/main.rs
+++ b/components/servo/main.rs
@@ -32,21 +32,11 @@ extern crate offscreen_gl_context;
// The Servo engine
extern crate servo;
-use gleam::gl;
-use offscreen_gl_context::{GLContext, NativeGLContext};
use servo::Browser;
use servo::compositing::windowing::WindowEvent;
use servo::util::opts::{self, ArgumentParsingResult};
use std::rc::Rc;
-#[cfg(not(target_os = "android"))]
-fn load_gl_when_headless() {
- gl::load_with(|addr| GLContext::<NativeGLContext>::get_proc_address(addr) as *const _);
-}
-
-#[cfg(target_os = "android")]
-fn load_gl_when_headless() {}
-
fn main() {
// Parse the command line options and store them globally
let opts_result = opts::from_cmdline_args(&*args());
@@ -69,14 +59,7 @@ fn main() {
return servo::run_content_process(token)
}
- let window = if opts::get().headless {
- // Load gl functions even when in headless mode,
- // to avoid crashing with WebGL
- load_gl_when_headless();
- None
- } else {
- Some(app::create_window(None))
- };
+ let window = app::create_window(None);
// Our wrapper around `Browser` that also implements some
// callbacks required by the glutin window implementation.
@@ -84,45 +67,32 @@ fn main() {
browser: Browser::new(window.clone()),
};
- maybe_register_glutin_resize_handler(&window, &mut browser);
+ register_glutin_resize_handler(&window, &mut browser);
browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);
// Feed events from the window to the browser until the browser
// says to stop.
loop {
- let should_continue = match window {
- None => browser.browser.handle_events(Vec::new()),
- Some(ref window) => browser.browser.handle_events(window.wait_events()),
- };
+ let should_continue = browser.browser.handle_events(window.wait_events());
if !should_continue {
break
}
};
- maybe_unregister_glutin_resize_handler(&window);
+ unregister_glutin_resize_handler(&window);
}
-fn maybe_register_glutin_resize_handler(window: &Option<Rc<app::window::Window>>,
+fn register_glutin_resize_handler(window: &Rc<app::window::Window>,
browser: &mut BrowserWrapper) {
- match *window {
- None => {}
- Some(ref window) => {
- unsafe {
- window.set_nested_event_loop_listener(browser);
- }
- }
+ unsafe {
+ window.set_nested_event_loop_listener(browser);
}
}
-fn maybe_unregister_glutin_resize_handler(window: &Option<Rc<app::window::Window>>) {
- match *window {
- None => {}
- Some(ref window) => {
- unsafe {
- window.remove_nested_event_loop_listener();
- }
- }
+fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
+ unsafe {
+ window.remove_nested_event_loop_listener();
}
}
diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs
index 3adbe7451a9..39b360a3744 100644
--- a/ports/cef/browser.rs
+++ b/ports/cef/browser.rs
@@ -126,19 +126,15 @@ impl ServoCefBrowser {
let frame = ServoCefFrame::new().as_cef_interface();
let host = ServoCefBrowserHost::new(client.clone()).as_cef_interface();
let mut window_handle: cef_window_handle_t = get_null_window_handle();
- let mut glutin_window: Option<Rc<glutin_app::window::Window>> = None;
- let 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 _);
- glutin_window = Some(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());
- window_handle = match glutin_window {
- Some(ref win) => win.platform_window().window as cef_window_handle_t,
- None => get_null_window_handle()
- };
- ServoBrowser::OnScreen(servo_browser)
+ window_handle = glutin_window.platform_window().window as cef_window_handle_t;
+ (Some(glutin_window), ServoBrowser::OnScreen(servo_browser))
} else {
- ServoBrowser::Invalid
+ (None, ServoBrowser::Invalid)
};
let id = ID_COUNTER.with(|counter| {
@@ -175,7 +171,7 @@ impl ServoCefBrowserExtensions for CefBrowser {
if window_info.windowless_rendering_enabled != 0 {
let window = window::Window::new(window_info.width, window_info.height);
window.set_browser(self.clone());
- let servo_browser = Browser::new(Some(window.clone()));
+ let servo_browser = Browser::new(window.clone());
*self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser);
}
diff --git a/ports/cef/window.rs b/ports/cef/window.rs
index 2854b4c84cb..57183164a86 100644
--- a/ports/cef/window.rs
+++ b/ports/cef/window.rs
@@ -297,7 +297,7 @@ impl WindowMethods for Window {
NativeDisplay::new()
}
- fn create_compositor_channel(_: &Option<Rc<Window>>)
+ fn create_compositor_channel(&self)
-> (Box<CompositorProxy+Send>, Box<CompositorReceiver>) {
let (sender, receiver) = channel();
(box CefCompositorProxy {
diff --git a/ports/glutin/Cargo.toml b/ports/glutin/Cargo.toml
index 082708bacd0..c292f105a0c 100644
--- a/ports/glutin/Cargo.toml
+++ b/ports/glutin/Cargo.toml
@@ -7,10 +7,6 @@ authors = ["The Servo Project Developers"]
name = "glutin_app"
path = "lib.rs"
-[features]
-window = []
-headless = ["servo-glutin/headless"]
-
[dependencies]
bitflags = "0.4"
url = {version = "0.5.7", features = ["heap_size"]}
diff --git a/ports/glutin/lib.rs b/ports/glutin/lib.rs
index 785aefb10ea..d8c6a41ce5b 100644
--- a/ports/glutin/lib.rs
+++ b/ports/glutin/lib.rs
@@ -16,7 +16,7 @@ extern crate glutin;
extern crate layers;
extern crate msg;
extern crate net_traits;
-#[cfg(feature = "window")] extern crate script_traits;
+extern crate script_traits;
extern crate style_traits;
extern crate url;
extern crate util;
@@ -39,7 +39,7 @@ pub trait NestedEventLoopListener {
pub fn create_window(parent: Option<WindowID>) -> Rc<Window> {
// Read command-line options.
let opts = opts::get();
- let foreground = opts.output_file.is_none();
+ let foreground = opts.output_file.is_none() && !opts.headless;
let scale_factor = ScaleFactor::new(opts.device_pixels_per_px.unwrap_or(1.0));
let size = opts.initial_window_size.as_f32() * scale_factor;
diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs
index 840d7ec34fd..c8534710797 100644
--- a/ports/glutin/window.rs
+++ b/ports/glutin/window.rs
@@ -6,7 +6,6 @@
use NestedEventLoopListener;
use compositing::compositor_thread::{self, CompositorProxy, CompositorReceiver};
-#[cfg(feature = "window")]
use compositing::windowing::{MouseWindowEvent, WindowNavigateMsg};
use compositing::windowing::{WindowEvent, WindowMethods};
use euclid::scale_factor::ScaleFactor;
@@ -14,34 +13,25 @@ use euclid::size::TypedSize2D;
use euclid::{Size2D, Point2D};
use gleam::gl;
use glutin;
-#[cfg(feature = "window")]
use glutin::{Api, ElementState, Event, GlRequest, MouseButton, VirtualKeyCode, MouseScrollDelta};
use glutin::{TouchPhase};
use layers::geometry::DevicePixel;
use layers::platform::surface::NativeDisplay;
-#[cfg(feature = "window")]
use msg::constellation_msg::{KeyState, NONE, CONTROL, SHIFT, ALT, SUPER};
use msg::constellation_msg::{self, Key};
use net_traits::net_error_list::NetError;
-#[cfg(feature = "window")]
use script_traits::TouchEventType;
-#[cfg(feature = "window")]
use std::cell::{Cell, RefCell};
use std::os::raw::c_void;
-#[cfg(all(feature = "headless", target_os = "linux"))]
-use std::ptr;
use std::rc::Rc;
use std::sync::mpsc::{channel, Sender};
use style_traits::cursor::Cursor;
use url::Url;
use util::geometry::ScreenPx;
-#[cfg(feature = "window")]
use util::opts::{self, RenderApi};
-#[cfg(feature = "window")]
static mut g_nested_event_loop_listener: Option<*mut (NestedEventLoopListener + 'static)> = None;
-#[cfg(feature = "window")]
bitflags! {
flags KeyModifiers: u8 {
const LEFT_CONTROL = 1,
@@ -56,25 +46,23 @@ bitflags! {
}
// Some shortcuts use Cmd on Mac and Control on other systems.
-#[cfg(all(feature = "window", target_os = "macos"))]
+#[cfg(target_os = "macos")]
const CMD_OR_CONTROL: constellation_msg::KeyModifiers = SUPER;
-#[cfg(all(feature = "window", not(target_os = "macos")))]
+#[cfg(not(target_os = "macos"))]
const CMD_OR_CONTROL: constellation_msg::KeyModifiers = CONTROL;
// Some shortcuts use Cmd on Mac and Alt on other systems.
-#[cfg(all(feature = "window", target_os = "macos"))]
+#[cfg(target_os = "macos")]
const CMD_OR_ALT: constellation_msg::KeyModifiers = SUPER;
-#[cfg(all(feature = "window", not(target_os = "macos")))]
+#[cfg(not(target_os = "macos"))]
const CMD_OR_ALT: constellation_msg::KeyModifiers = ALT;
// This should vary by zoom level and maybe actual text size (focused or under cursor)
-#[cfg(feature = "window")]
const LINE_HEIGHT: f32 = 38.0;
const MULTISAMPLES: u16 = 16;
/// The type of a window.
-#[cfg(feature = "window")]
pub struct Window {
window: glutin::Window,
@@ -87,7 +75,6 @@ pub struct Window {
current_url: RefCell<Option<Url>>,
}
-#[cfg(feature = "window")]
impl Window {
pub fn new(is_foreground: bool,
window_size: TypedSize2D<DevicePixel, u32>,
@@ -391,7 +378,7 @@ impl Window {
// When writing to a file then exiting, use event
// polling so that we don't block on a GUI event
// such as mouse click.
- if opts::get().output_file.is_some() || opts::get().exit_after_load {
+ if opts::get().output_file.is_some() || opts::get().exit_after_load || opts::get().headless {
while let Some(event) = self.window.poll_events().next() {
close_event = self.handle_window_event(event) || close_event;
}
@@ -523,7 +510,7 @@ impl Window {
result
}
- #[cfg(all(feature = "window", not(target_os = "win")))]
+ #[cfg(not(target_os = "win"))]
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) {
match (mods, key) {
(CMD_OR_CONTROL, Key::LeftBracket) => {
@@ -536,24 +523,23 @@ impl Window {
}
}
- #[cfg(all(feature = "window", target_os = "win"))]
+ #[cfg(target_os = "win")]
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) {
}
}
// WindowProxy is not implemented for android yet
-#[cfg(all(feature = "window", target_os = "android"))]
-fn create_window_proxy(_: &Rc<Window>) -> Option<glutin::WindowProxy> {
+#[cfg(target_os = "android")]
+fn create_window_proxy(_: &Window) -> Option<glutin::WindowProxy> {
None
}
-#[cfg(all(feature = "window", not(target_os = "android")))]
-fn create_window_proxy(window: &Rc<Window>) -> Option<glutin::WindowProxy> {
+#[cfg(not(target_os = "android"))]
+fn create_window_proxy(window: &Window) -> Option<glutin::WindowProxy> {
Some(window.window.create_window_proxy())
}
-#[cfg(feature = "window")]
impl WindowMethods for Window {
fn framebuffer_size(&self) -> TypedSize2D<DevicePixel, u32> {
let scale_factor = self.window.hidpi_factor() as u32;
@@ -586,14 +572,11 @@ impl WindowMethods for Window {
self.window.swap_buffers().unwrap();
}
- fn create_compositor_channel(window: &Option<Rc<Window>>)
+ fn create_compositor_channel(&self)
-> (Box<CompositorProxy + Send>, Box<CompositorReceiver>) {
let (sender, receiver) = channel();
- let window_proxy = match window {
- &Some(ref window) => create_window_proxy(window),
- &None => None,
- };
+ let window_proxy = create_window_proxy(self);
(box GlutinCompositorProxy {
sender: sender,
@@ -796,139 +779,6 @@ impl WindowMethods for Window {
}
}
-/// The type of a window.
-#[cfg(feature = "headless")]
-pub struct Window {
- #[allow(dead_code)]
- context: glutin::HeadlessContext,
- width: u32,
- height: u32,
-}
-
-#[cfg(feature = "headless")]
-impl Window {
- pub fn new(_is_foreground: bool,
- window_size: TypedSize2D<DevicePixel, u32>,
- _parent: Option<glutin::WindowID>) -> Rc<Window> {
- let window_size = window_size.to_untyped();
- let headless_builder = glutin::HeadlessRendererBuilder::new(window_size.width,
- window_size.height);
- let headless_context = headless_builder.build().unwrap();
- unsafe { headless_context.make_current().expect("Failed to make context current!") };
-
- gl::load_with(|s| headless_context.get_proc_address(s) as *const c_void);
-
- let window = Window {
- context: headless_context,
- width: window_size.width,
- height: window_size.height,
- };
-
- Rc::new(window)
- }
-
- pub fn wait_events(&self) -> Vec<WindowEvent> {
- vec![WindowEvent::Idle]
- }
-
- pub unsafe fn set_nested_event_loop_listener(
- &self,
- _listener: *mut (NestedEventLoopListener + 'static)) {
- }
-
- pub unsafe fn remove_nested_event_loop_listener(&self) {
- }
-}
-
-#[cfg(feature = "headless")]
-impl WindowMethods for Window {
- fn framebuffer_size(&self) -> TypedSize2D<DevicePixel, u32> {
- Size2D::typed(self.width, self.height)
- }
-
- fn size(&self) -> TypedSize2D<ScreenPx, f32> {
- Size2D::typed(self.width as f32, self.height as f32)
- }
-
- fn present(&self) {
- }
-
- fn set_inner_size(&self, _: Size2D<u32>) {
-
- }
-
- fn set_position(&self, _: Point2D<i32>) {
-
- }
-
- fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) {
- let width = self.width;
- let height = self.height;
- (Size2D::new(width, height), Point2D::zero())
- }
-
- fn create_compositor_channel(_: &Option<Rc<Window>>)
- -> (Box<CompositorProxy + Send>, Box<CompositorReceiver>) {
- let (sender, receiver) = channel();
-
- (box GlutinCompositorProxy {
- sender: sender,
- window_proxy: None,
- } as Box<CompositorProxy + Send>,
- box receiver as Box<CompositorReceiver>)
- }
-
- fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
- ScaleFactor::new(1.0)
- }
-
- fn set_page_title(&self, _: Option<String>) {
- }
-
- fn set_page_url(&self, _: Url) {
- }
-
- fn load_start(&self, _: bool, _: bool) {
- }
- fn load_end(&self, _: bool, _: bool, _: bool) {
- }
- fn load_error(&self, _: NetError, _: String) {
- }
- fn head_parsed(&self) {
- }
-
- fn set_cursor(&self, _: Cursor) {
- }
-
- fn set_favicon(&self, _: Url) {
- }
-
- fn status(&self, _: Option<String>) {
- }
-
- fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
- true
- }
-
- #[cfg(target_os = "linux")]
- fn native_display(&self) -> NativeDisplay {
- NativeDisplay::new(ptr::null_mut())
- }
-
- #[cfg(not(target_os = "linux"))]
- fn native_display(&self) -> NativeDisplay {
- NativeDisplay::new()
- }
-
- /// Helper function to handle keyboard events.
- fn handle_key(&self, _: Key, _: constellation_msg::KeyModifiers) {
- }
-
- fn supports_clipboard(&self) -> bool {
- false
- }
-}
-
struct GlutinCompositorProxy {
sender: Sender<compositor_thread::Msg>,
window_proxy: Option<glutin::WindowProxy>,
@@ -953,7 +803,6 @@ impl CompositorProxy for GlutinCompositorProxy {
}
}
-#[cfg(feature = "window")]
fn glutin_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
match phase {
TouchPhase::Started => TouchEventType::Down,
diff --git a/ports/gonk/src/main.rs b/ports/gonk/src/main.rs
index d477c48f2a7..2d8cb9ca551 100644
--- a/ports/gonk/src/main.rs
+++ b/ports/gonk/src/main.rs
@@ -61,11 +61,7 @@ fn main() {
// Parse the command line options and store them globally
opts::from_cmdline_args(env::args().collect::<Vec<_>>().as_slice());
- let window = if opts::get().headless {
- None
- } else {
- Some(window::Window::new())
- };
+ let window = window::Window::new();
// Our wrapper around `Browser` that also implements some
// callbacks required by the glutin window implementation.
@@ -73,23 +69,15 @@ fn main() {
browser: Browser::new(window.clone()),
};
- match window {
- None => (),
- Some(ref window) => input::run_input_loop(&window.event_send)
- }
+ input::run_input_loop(&window.event_send);
browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);
// Feed events from the window to the browser until the browser
// says to stop.
loop {
- let should_continue = match window {
- None => browser.browser.handle_events(vec![WindowEvent::Idle]),
- Some(ref window) => {
- let events = window.wait_events();
- browser.browser.handle_events(events)
- }
- };
+ let events = window.wait_events();
+ let should_continue = browser.browser.handle_events(events);
if !should_continue {
break
}
diff --git a/ports/gonk/src/window.rs b/ports/gonk/src/window.rs
index fb362a73981..20394979965 100644
--- a/ports/gonk/src/window.rs
+++ b/ports/gonk/src/window.rs
@@ -840,12 +840,12 @@ impl WindowMethods for Window {
fn handle_key(&self, _: Key, _: KeyModifiers) {
}
- fn create_compositor_channel(window: &Option<Rc<Window>>)
+ fn create_compositor_channel(&self)
-> (Box<CompositorProxy + Send>, Box<CompositorReceiver>) {
let (sender, receiver) = channel();
(box GonkCompositorProxy {
sender: sender,
- event_sender: window.as_ref().unwrap().event_send.clone(),
+ event_sender: self.event_send.clone(),
} as Box<CompositorProxy + Send>,
box receiver as Box<CompositorReceiver>)
}
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index 581bbaf6821..ad8025dacdf 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -25,20 +25,6 @@ from mach.decorators import (
from servo.command_base import CommandBase, cd, call
-def is_headless_build():
- return int(os.getenv('SERVO_HEADLESS', 0)) == 1
-
-
-def headless_supported():
- supported = sys.platform.startswith("linux")
-
- if not supported:
- print("Headless mode (OSMesa) is not supported on your platform.")
- print("Building without headless mode.")
-
- return supported
-
-
def notify_linux(title, text):
try:
import dbus
@@ -136,10 +122,6 @@ class MachCommands(CommandBase):
@CommandArgument('--dev', '-d',
action='store_true',
help='Build in development mode')
- @CommandArgument('--headless',
- default=None,
- action='store_true',
- help='Enable headless mode (OSMesa)')
@CommandArgument('--jobs', '-j',
default=None,
help='Number of jobs to run in parallel')
@@ -161,7 +143,7 @@ class MachCommands(CommandBase):
@CommandArgument('params', nargs='...',
help="Command-line arguments to be passed through to Cargo")
def build(self, target=None, release=False, dev=False, jobs=None,
- features=None, headless=False, android=None, verbose=False, debug_mozjs=False, params=None):
+ features=None, android=None, verbose=False, debug_mozjs=False, params=None):
if android is None:
android = self.config["build"]["android"]
features = features or []
@@ -212,10 +194,6 @@ class MachCommands(CommandBase):
if debug_mozjs or self.config["build"]["debug-mozjs"]:
features += ["script/debugmozjs"]
- if (headless or is_headless_build()) and headless_supported():
- opts += ["--no-default-features"]
- features += ["headless"]
-
if android:
features += ["android_glue"]
@@ -378,20 +356,14 @@ class MachCommands(CommandBase):
@Command('build-tests',
description='Build the Servo test suites',
category='build')
- @CommandArgument('--headless',
- default=None,
- action='store_true',
- help='Enable headless mode (OSMesa)')
@CommandArgument('--jobs', '-j',
default=None,
help='Number of jobs to run in parallel')
@CommandArgument('--release', default=False, action="store_true",
help="Build tests with release mode")
- def build_tests(self, headless=False, jobs=None, verbose=False, release=False):
+ def build_tests(self, jobs=None, verbose=False, release=False):
self.ensure_bootstrapped()
args = ["cargo", "test", "--no-run"]
- if (headless or is_headless_build()) and headless_supported():
- args += ["--no-default-features", "--features", "headless"]
if release:
args += ["--release"]
return call(
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html.ini
index e7699f55db9..0b74e26325e 100644
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html.ini
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html.ini
@@ -1,5 +1,7 @@
[template-contents-owner-test-002.html]
type: testharness
+ disabled: https://github.com/servo/servo/issues/9723
+
[The template contents owner document must be different from template owner document, which has browsing context. Template element is created by createElement()]
expected: FAIL