mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Auto merge of #11179 - asajeffrey:webdriver-resize-window, r=jgraham
Implemented webdriver SetWindowSize. Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #10467 (github issue number if applicable). Either: - [ ] There are tests for these changes OR - [X] These changes do not require tests because the new tests are in https://github.com/w3c/web-platform-tests/pull/3024 Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11179) <!-- Reviewable:end -->
This commit is contained in:
commit
2063bde0a4
9 changed files with 61 additions and 26 deletions
|
@ -292,13 +292,15 @@ impl<'a> Iterator for FrameTreeIterator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WebDriverData {
|
struct WebDriverData {
|
||||||
load_channel: Option<(PipelineId, IpcSender<webdriver_msg::LoadStatus>)>
|
load_channel: Option<(PipelineId, IpcSender<webdriver_msg::LoadStatus>)>,
|
||||||
|
resize_channel: Option<IpcSender<WindowSizeData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebDriverData {
|
impl WebDriverData {
|
||||||
fn new() -> WebDriverData {
|
fn new() -> WebDriverData {
|
||||||
WebDriverData {
|
WebDriverData {
|
||||||
load_channel: None
|
load_channel: None,
|
||||||
|
resize_channel: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1484,6 +1486,13 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
// Find the script channel for the given parent pipeline,
|
// Find the script channel for the given parent pipeline,
|
||||||
// and pass the event to that script thread.
|
// and pass the event to that script thread.
|
||||||
match msg {
|
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) => {
|
WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, reply) => {
|
||||||
self.load_url_for_webdriver(pipeline_id, load_data, reply);
|
self.load_url_for_webdriver(pipeline_id, load_data, reply);
|
||||||
},
|
},
|
||||||
|
@ -1703,6 +1712,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(resize_channel) = self.webdriver.resize_channel.take() {
|
||||||
|
let _ = resize_channel.send(new_size);
|
||||||
|
}
|
||||||
|
|
||||||
self.window_size = new_size;
|
self.window_size = new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
//! reduce coupling between these two components.
|
//! reduce coupling between these two components.
|
||||||
|
|
||||||
use euclid::scale_factor::ScaleFactor;
|
use euclid::scale_factor::ScaleFactor;
|
||||||
use euclid::size::TypedSize2D;
|
use euclid::size::{Size2D, TypedSize2D};
|
||||||
use hyper::header::Headers;
|
use hyper::header::Headers;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
||||||
|
@ -188,10 +188,12 @@ bitflags! {
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum WebDriverCommandMsg {
|
pub enum WebDriverCommandMsg {
|
||||||
|
GetWindowSize(PipelineId, IpcSender<WindowSizeData>),
|
||||||
LoadUrl(PipelineId, LoadData, IpcSender<LoadStatus>),
|
LoadUrl(PipelineId, LoadData, IpcSender<LoadStatus>),
|
||||||
Refresh(PipelineId, IpcSender<LoadStatus>),
|
Refresh(PipelineId, IpcSender<LoadStatus>),
|
||||||
ScriptCommand(PipelineId, WebDriverScriptCommand),
|
ScriptCommand(PipelineId, WebDriverScriptCommand),
|
||||||
SendKeys(PipelineId, Vec<(Key, KeyModifiers, KeyState)>),
|
SendKeys(PipelineId, Vec<(Key, KeyModifiers, KeyState)>),
|
||||||
|
SetWindowSize(PipelineId, Size2D<u32>, IpcSender<WindowSizeData>),
|
||||||
TakeScreenshot(PipelineId, IpcSender<Option<Image>>),
|
TakeScreenshot(PipelineId, IpcSender<Option<Image>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use constellation_msg::{PipelineId, WindowSizeData};
|
use constellation_msg::PipelineId;
|
||||||
use euclid::rect::Rect;
|
use euclid::rect::Rect;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use rustc_serialize::json::{Json, ToJson};
|
use rustc_serialize::json::{Json, ToJson};
|
||||||
|
@ -23,7 +23,6 @@ pub enum WebDriverScriptCommand {
|
||||||
GetElementText(String, IpcSender<Result<String, ()>>),
|
GetElementText(String, IpcSender<Result<String, ()>>),
|
||||||
GetFrameId(WebDriverFrameId, IpcSender<Result<Option<PipelineId>, ()>>),
|
GetFrameId(WebDriverFrameId, IpcSender<Result<Option<PipelineId>, ()>>),
|
||||||
GetUrl(IpcSender<Url>),
|
GetUrl(IpcSender<Url>),
|
||||||
GetWindowSize(IpcSender<Option<WindowSizeData>>),
|
|
||||||
IsEnabled(String, IpcSender<Result<bool, ()>>),
|
IsEnabled(String, IpcSender<Result<bool, ()>>),
|
||||||
IsSelected(String, IpcSender<Result<bool, ()>>),
|
IsSelected(String, IpcSender<Result<bool, ()>>),
|
||||||
GetTitle(IpcSender<String>)
|
GetTitle(IpcSender<String>)
|
||||||
|
|
|
@ -1045,8 +1045,6 @@ impl ScriptThread {
|
||||||
webdriver_handlers::handle_get_frame_id(&context, pipeline_id, frame_id, reply),
|
webdriver_handlers::handle_get_frame_id(&context, pipeline_id, frame_id, reply),
|
||||||
WebDriverScriptCommand::GetUrl(reply) =>
|
WebDriverScriptCommand::GetUrl(reply) =>
|
||||||
webdriver_handlers::handle_get_url(&context, pipeline_id, 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) =>
|
WebDriverScriptCommand::IsEnabled(element_id, reply) =>
|
||||||
webdriver_handlers::handle_is_enabled(&context, pipeline_id, element_id, reply),
|
webdriver_handlers::handle_is_enabled(&context, pipeline_id, element_id, reply),
|
||||||
WebDriverScriptCommand::IsSelected(element_id, reply) =>
|
WebDriverScriptCommand::IsSelected(element_id, reply) =>
|
||||||
|
|
|
@ -30,7 +30,7 @@ use ipc_channel::ipc::IpcSender;
|
||||||
use js::jsapi::JSContext;
|
use js::jsapi::JSContext;
|
||||||
use js::jsapi::{HandleValue, RootedValue};
|
use js::jsapi::{HandleValue, RootedValue};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use msg::constellation_msg::{PipelineId, WindowSizeData};
|
use msg::constellation_msg::PipelineId;
|
||||||
use msg::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue};
|
use msg::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue};
|
||||||
use script_thread::get_browsing_context;
|
use script_thread::get_browsing_context;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -282,14 +282,6 @@ pub fn handle_get_url(context: &BrowsingContext,
|
||||||
reply.send((*url).clone()).unwrap();
|
reply.send((*url).clone()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_get_window_size(context: &BrowsingContext,
|
|
||||||
_pipeline: PipelineId,
|
|
||||||
reply: IpcSender<Option<WindowSizeData>>) {
|
|
||||||
let window = context.active_window();
|
|
||||||
let size = window.window_size();
|
|
||||||
reply.send(size).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_is_enabled(context: &BrowsingContext,
|
pub fn handle_is_enabled(context: &BrowsingContext,
|
||||||
pipeline: PipelineId,
|
pipeline: PipelineId,
|
||||||
element_id: String,
|
element_id: String,
|
||||||
|
|
1
components/servo/Cargo.lock
generated
1
components/servo/Cargo.lock
generated
|
@ -2483,6 +2483,7 @@ name = "webdriver_server"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compositing 0.0.1",
|
"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)",
|
"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)",
|
"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)",
|
"ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)",
|
||||||
|
|
|
@ -13,6 +13,7 @@ compositing = {path = "../compositing"}
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
plugins = {path = "../plugins"}
|
plugins = {path = "../plugins"}
|
||||||
util = {path = "../util"}
|
util = {path = "../util"}
|
||||||
|
euclid = {version = "0.6.4", features = ["plugins"]}
|
||||||
ipc-channel = {git = "https://github.com/servo/ipc-channel"}
|
ipc-channel = {git = "https://github.com/servo/ipc-channel"}
|
||||||
image = "0.10"
|
image = "0.10"
|
||||||
log = "0.3.5"
|
log = "0.3.5"
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
extern crate compositing;
|
extern crate compositing;
|
||||||
|
extern crate euclid;
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
extern crate image;
|
extern crate image;
|
||||||
extern crate ipc_channel;
|
extern crate ipc_channel;
|
||||||
|
@ -25,6 +26,7 @@ extern crate webdriver;
|
||||||
mod keys;
|
mod keys;
|
||||||
|
|
||||||
use compositing::CompositorMsg as ConstellationMsg;
|
use compositing::CompositorMsg as ConstellationMsg;
|
||||||
|
use euclid::Size2D;
|
||||||
use hyper::method::Method::{self, Post};
|
use hyper::method::Method::{self, Post};
|
||||||
use image::{DynamicImage, ImageFormat, RgbImage};
|
use image::{DynamicImage, ImageFormat, RgbImage};
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
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 util::thread::spawn_named;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use webdriver::command::{GetParameters, JavascriptCommandParameters, LocatorParameters};
|
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::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverMessage};
|
||||||
use webdriver::common::{LocatorStrategy, WebElement};
|
use webdriver::common::{LocatorStrategy, WebElement};
|
||||||
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
|
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
|
||||||
|
@ -80,6 +83,7 @@ struct Handler {
|
||||||
constellation_chan: Sender<ConstellationMsg>,
|
constellation_chan: Sender<ConstellationMsg>,
|
||||||
script_timeout: u32,
|
script_timeout: u32,
|
||||||
load_timeout: u32,
|
load_timeout: u32,
|
||||||
|
resize_timeout: u32,
|
||||||
implicit_wait_timeout: u32
|
implicit_wait_timeout: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +223,7 @@ impl Handler {
|
||||||
constellation_chan: constellation_chan,
|
constellation_chan: constellation_chan,
|
||||||
script_timeout: 30_000,
|
script_timeout: 30_000,
|
||||||
load_timeout: 300_000,
|
load_timeout: 300_000,
|
||||||
|
resize_timeout: 500,
|
||||||
implicit_wait_timeout: 0
|
implicit_wait_timeout: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,17 +359,39 @@ impl Handler {
|
||||||
|
|
||||||
fn handle_window_size(&self) -> WebDriverResult<WebDriverResponse> {
|
fn handle_window_size(&self) -> WebDriverResult<WebDriverResponse> {
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
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() {
|
let window_size = receiver.recv().unwrap();
|
||||||
Some(window_size) => {
|
|
||||||
let vp = window_size.visible_viewport;
|
let vp = window_size.visible_viewport;
|
||||||
let window_size_response = WindowSizeResponse::new(vp.width.get() as u64, vp.height.get() as u64);
|
let window_size_response = WindowSizeResponse::new(vp.width.get() as u64, vp.height.get() as u64);
|
||||||
Ok(WebDriverResponse::WindowSize(window_size_response))
|
Ok(WebDriverResponse::WindowSize(window_size_response))
|
||||||
},
|
|
||||||
None => Err(WebDriverError::new(ErrorStatus::NoSuchWindow, "Unable to determine window size"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_set_window_size(&self, params: &WindowSizeParameters) -> WebDriverResult<WebDriverResponse> {
|
||||||
|
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<WebDriverResponse> {
|
fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
|
||||||
|
@ -767,6 +794,7 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
|
||||||
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
|
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
|
||||||
WebDriverCommand::GetCurrentUrl => self.handle_current_url(),
|
WebDriverCommand::GetCurrentUrl => self.handle_current_url(),
|
||||||
WebDriverCommand::GetWindowSize => self.handle_window_size(),
|
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::IsEnabled(ref element) => self.handle_is_enabled(element),
|
||||||
WebDriverCommand::IsSelected(ref element) => self.handle_is_selected(element),
|
WebDriverCommand::IsSelected(ref element) => self.handle_is_selected(element),
|
||||||
WebDriverCommand::GoBack => self.handle_go_back(),
|
WebDriverCommand::GoBack => self.handle_go_back(),
|
||||||
|
|
1
ports/cef/Cargo.lock
generated
1
ports/cef/Cargo.lock
generated
|
@ -2344,6 +2344,7 @@ name = "webdriver_server"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compositing 0.0.1",
|
"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)",
|
"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)",
|
"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)",
|
"ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue