diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index e3e69b69182..d0cd2973001 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -292,13 +292,15 @@ impl<'a> Iterator for FrameTreeIterator<'a> { } struct WebDriverData { - load_channel: Option<(PipelineId, IpcSender)> + load_channel: Option<(PipelineId, IpcSender)>, + resize_channel: Option>, } impl WebDriverData { fn new() -> WebDriverData { WebDriverData { - load_channel: None + load_channel: None, + resize_channel: None, } } } @@ -1484,6 +1486,13 @@ impl Constellation // Find the script channel for the given parent pipeline, // and pass the event to that script thread. match msg { + WebDriverCommandMsg::GetWindowSize(_, reply) => { + let _ = reply.send(self.window_size); + }, + WebDriverCommandMsg::SetWindowSize(_, size, reply) => { + self.webdriver.resize_channel = Some(reply); + self.compositor_proxy.send(ToCompositorMsg::ResizeTo(size)); + }, WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, reply) => { self.load_url_for_webdriver(pipeline_id, load_data, reply); }, @@ -1703,6 +1712,10 @@ impl Constellation } } + if let Some(resize_channel) = self.webdriver.resize_channel.take() { + let _ = resize_channel.send(new_size); + } + self.window_size = new_size; } diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 3433b6915f0..543e4277f23 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -6,7 +6,7 @@ //! reduce coupling between these two components. use euclid::scale_factor::ScaleFactor; -use euclid::size::TypedSize2D; +use euclid::size::{Size2D, TypedSize2D}; use hyper::header::Headers; use hyper::method::Method; use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; @@ -188,10 +188,12 @@ bitflags! { #[derive(Deserialize, Serialize)] pub enum WebDriverCommandMsg { + GetWindowSize(PipelineId, IpcSender), LoadUrl(PipelineId, LoadData, IpcSender), Refresh(PipelineId, IpcSender), ScriptCommand(PipelineId, WebDriverScriptCommand), SendKeys(PipelineId, Vec<(Key, KeyModifiers, KeyState)>), + SetWindowSize(PipelineId, Size2D, IpcSender), TakeScreenshot(PipelineId, IpcSender>), } diff --git a/components/msg/webdriver_msg.rs b/components/msg/webdriver_msg.rs index fb59de4a922..a6c94c3a439 100644 --- a/components/msg/webdriver_msg.rs +++ b/components/msg/webdriver_msg.rs @@ -2,7 +2,7 @@ * 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 constellation_msg::{PipelineId, WindowSizeData}; +use constellation_msg::PipelineId; use euclid::rect::Rect; use ipc_channel::ipc::IpcSender; use rustc_serialize::json::{Json, ToJson}; @@ -23,7 +23,6 @@ pub enum WebDriverScriptCommand { GetElementText(String, IpcSender>), GetFrameId(WebDriverFrameId, IpcSender, ()>>), GetUrl(IpcSender), - GetWindowSize(IpcSender>), IsEnabled(String, IpcSender>), IsSelected(String, IpcSender>), GetTitle(IpcSender) diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index f7bb765651d..644f320f19e 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1045,8 +1045,6 @@ impl ScriptThread { webdriver_handlers::handle_get_frame_id(&context, pipeline_id, frame_id, reply), WebDriverScriptCommand::GetUrl(reply) => webdriver_handlers::handle_get_url(&context, pipeline_id, reply), - WebDriverScriptCommand::GetWindowSize(reply) => - webdriver_handlers::handle_get_window_size(&context, pipeline_id, reply), WebDriverScriptCommand::IsEnabled(element_id, reply) => webdriver_handlers::handle_is_enabled(&context, pipeline_id, element_id, reply), WebDriverScriptCommand::IsSelected(element_id, reply) => diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 2defda98743..6a7492492e2 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -30,7 +30,7 @@ use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use js::jsapi::{HandleValue, RootedValue}; use js::jsval::UndefinedValue; -use msg::constellation_msg::{PipelineId, WindowSizeData}; +use msg::constellation_msg::PipelineId; use msg::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue}; use script_thread::get_browsing_context; use url::Url; @@ -282,14 +282,6 @@ pub fn handle_get_url(context: &BrowsingContext, reply.send((*url).clone()).unwrap(); } -pub fn handle_get_window_size(context: &BrowsingContext, - _pipeline: PipelineId, - reply: IpcSender>) { - let window = context.active_window(); - let size = window.window_size(); - reply.send(size).unwrap(); -} - pub fn handle_is_enabled(context: &BrowsingContext, pipeline: PipelineId, element_id: String, diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 1ca99477ab0..56818a0e569 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -2483,6 +2483,7 @@ name = "webdriver_server" version = "0.0.1" dependencies = [ "compositing 0.0.1", + "euclid 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index d9cd38f9979..de365ebdae3 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -13,6 +13,7 @@ compositing = {path = "../compositing"} msg = {path = "../msg"} plugins = {path = "../plugins"} util = {path = "../util"} +euclid = {version = "0.6.4", features = ["plugins"]} ipc-channel = {git = "https://github.com/servo/ipc-channel"} image = "0.10" log = "0.3.5" diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 85b499afd01..92c339fb7d5 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -11,6 +11,7 @@ #![deny(unsafe_code)] extern crate compositing; +extern crate euclid; extern crate hyper; extern crate image; extern crate ipc_channel; @@ -25,6 +26,7 @@ extern crate webdriver; mod keys; use compositing::CompositorMsg as ConstellationMsg; +use euclid::Size2D; use hyper::method::Method::{self, Post}; use image::{DynamicImage, ImageFormat, RgbImage}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -46,7 +48,8 @@ use util::prefs::{get_pref, reset_all_prefs, reset_pref, set_pref, PrefValue}; use util::thread::spawn_named; use uuid::Uuid; use webdriver::command::{GetParameters, JavascriptCommandParameters, LocatorParameters}; -use webdriver::command::{Parameters, SendKeysParameters, SwitchToFrameParameters, TimeoutsParameters}; +use webdriver::command::{Parameters, SendKeysParameters, SwitchToFrameParameters}; +use webdriver::command::{TimeoutsParameters, WindowSizeParameters}; use webdriver::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverMessage}; use webdriver::common::{LocatorStrategy, WebElement}; use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult}; @@ -80,6 +83,7 @@ struct Handler { constellation_chan: Sender, script_timeout: u32, load_timeout: u32, + resize_timeout: u32, implicit_wait_timeout: u32 } @@ -219,6 +223,7 @@ impl Handler { constellation_chan: constellation_chan, script_timeout: 30_000, load_timeout: 300_000, + resize_timeout: 500, implicit_wait_timeout: 0 } } @@ -354,17 +359,39 @@ impl Handler { fn handle_window_size(&self) -> WebDriverResult { let (sender, receiver) = ipc::channel().unwrap(); + let pipeline_id = try!(self.root_pipeline()); + let cmd_msg = WebDriverCommandMsg::GetWindowSize(pipeline_id, sender); - try!(self.root_script_command(WebDriverScriptCommand::GetWindowSize(sender))); + self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - match receiver.recv().unwrap() { - Some(window_size) => { - let vp = window_size.visible_viewport; - let window_size_response = WindowSizeResponse::new(vp.width.get() as u64, vp.height.get() as u64); - Ok(WebDriverResponse::WindowSize(window_size_response)) - }, - None => Err(WebDriverError::new(ErrorStatus::NoSuchWindow, "Unable to determine window size")) - } + let window_size = receiver.recv().unwrap(); + let vp = window_size.visible_viewport; + let window_size_response = WindowSizeResponse::new(vp.width.get() as u64, vp.height.get() as u64); + Ok(WebDriverResponse::WindowSize(window_size_response)) + } + + fn handle_set_window_size(&self, params: &WindowSizeParameters) -> WebDriverResult { + let (sender, receiver) = ipc::channel().unwrap(); + let size = Size2D::new(params.width as u32, params.height as u32); + let pipeline_id = try!(self.root_pipeline()); + let cmd_msg = WebDriverCommandMsg::SetWindowSize(pipeline_id, size, sender.clone()); + + self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); + + let timeout = self.resize_timeout; + let constellation_chan = self.constellation_chan.clone(); + thread::spawn(move || { + // On timeout, we send a GetWindowSize message to the constellation, + // which will give the current window size. + thread::sleep(Duration::from_millis(timeout as u64)); + let cmd_msg = WebDriverCommandMsg::GetWindowSize(pipeline_id, sender); + constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); + }); + + let window_size = receiver.recv().unwrap(); + let vp = window_size.visible_viewport; + let window_size_response = WindowSizeResponse::new(vp.width.get() as u64, vp.height.get() as u64); + Ok(WebDriverResponse::WindowSize(window_size_response)) } fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult { @@ -767,6 +794,7 @@ impl WebDriverHandler for Handler { WebDriverCommand::Get(ref parameters) => self.handle_get(parameters), WebDriverCommand::GetCurrentUrl => self.handle_current_url(), WebDriverCommand::GetWindowSize => self.handle_window_size(), + WebDriverCommand::SetWindowSize(ref size) => self.handle_set_window_size(size), WebDriverCommand::IsEnabled(ref element) => self.handle_is_enabled(element), WebDriverCommand::IsSelected(ref element) => self.handle_is_selected(element), WebDriverCommand::GoBack => self.handle_go_back(), diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index cd25b630fa9..89983eaf1b2 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -2344,6 +2344,7 @@ name = "webdriver_server" version = "0.0.1" dependencies = [ "compositing 0.0.1", + "euclid 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)",