diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 7dd06342790..93192981dc7 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -912,11 +912,15 @@ impl Constellation { // and pass the event to that script task. match msg { WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, reply) => { - let new_pipeline_id = self.load_url(pipeline_id, load_data); - if let Some(id) = new_pipeline_id { - self.webdriver.load_channel = Some((id, reply)); - } + self.load_url_for_webdriver(pipeline_id, load_data, reply); }, + WebDriverCommandMsg::Refresh(pipeline_id, reply) => { + let load_data = { + let pipeline = self.pipeline(pipeline_id); + LoadData::new(pipeline.url.clone()) + }; + self.load_url_for_webdriver(pipeline_id, load_data, reply); + } WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd) => { let pipeline = self.pipeline(pipeline_id); let control_msg = ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, cmd); @@ -937,6 +941,16 @@ impl Constellation { } } + fn load_url_for_webdriver(&mut self, + pipeline_id: PipelineId, + load_data:LoadData, + reply: IpcSender) { + let new_pipeline_id = self.load_url(pipeline_id, load_data); + if let Some(id) = new_pipeline_id { + self.webdriver.load_channel = Some((id, reply)); + } + } + fn add_or_replace_pipeline_in_frame_tree(&mut self, frame_change: FrameChange) { // If the currently focused pipeline is the one being changed (or a child diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 52b883615e5..16c90b670d1 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -336,6 +336,7 @@ impl MozBrowserEvent { #[derive(Deserialize, Serialize)] pub enum WebDriverCommandMsg { LoadUrl(PipelineId, LoadData, IpcSender), + Refresh(PipelineId, IpcSender), ScriptCommand(PipelineId, WebDriverScriptCommand), TakeScreenshot(PipelineId, IpcSender>) } diff --git a/components/msg/webdriver_msg.rs b/components/msg/webdriver_msg.rs index 0c2d8860a96..dd90a3492d9 100644 --- a/components/msg/webdriver_msg.rs +++ b/components/msg/webdriver_msg.rs @@ -6,6 +6,7 @@ use constellation_msg::{PipelineId, SubpageId}; use ipc_channel::ipc::IpcSender; use rustc_serialize::json::{Json, ToJson}; +use url::Url; #[derive(Deserialize, Serialize)] pub enum WebDriverScriptCommand { @@ -17,6 +18,7 @@ pub enum WebDriverScriptCommand { GetElementTagName(String, IpcSender>), GetElementText(String, IpcSender>), GetFrameId(WebDriverFrameId, IpcSender, ()>>), + GetUrl(IpcSender), GetTitle(IpcSender) } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index b1f7357a613..4ba2efddef0 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -873,6 +873,8 @@ impl ScriptTask { webdriver_handlers::handle_get_text(&page, pipeline_id, node_id, reply), WebDriverScriptCommand::GetFrameId(frame_id, reply) => webdriver_handlers::handle_get_frame_id(&page, pipeline_id, frame_id, reply), + WebDriverScriptCommand::GetUrl(reply) => + webdriver_handlers::handle_get_url(&page, pipeline_id, reply), WebDriverScriptCommand::GetTitle(reply) => webdriver_handlers::handle_get_title(&page, pipeline_id, reply), WebDriverScriptCommand::ExecuteAsyncScript(script, reply) => diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 591e38eb52b..e3b50cb2aaf 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -24,6 +24,7 @@ use js::jsval::UndefinedValue; use ipc_channel::ipc::IpcSender; use std::rc::Rc; +use url::Url; fn find_node_by_unique_id(page: &Rc, pipeline: PipelineId, node_id: String) -> Option> { let page = get_page(&*page, pipeline); @@ -179,3 +180,10 @@ pub fn handle_get_name(page: &Rc, None => Err(()) }).unwrap(); } + +pub fn handle_get_url(page: &Rc, + _pipeline: PipelineId, + reply: IpcSender) { + let url = page.document().r().url(); + reply.send(url).unwrap(); +} diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 6713fbfe453..91506de0330 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -35,7 +35,7 @@ use webdriver::server::{self, WebDriverHandler, Session}; use webdriver::error::{WebDriverResult, WebDriverError, ErrorStatus}; use util::task::spawn_named; use uuid::Uuid; -use ipc_channel::ipc::{self, IpcReceiver}; +use ipc_channel::ipc::{self, IpcSender, IpcReceiver}; use std::borrow::ToOwned; use rustc_serialize::json::{Json, ToJson}; @@ -134,12 +134,12 @@ impl Handler { } fn get_pipeline(&self, frame_id: Option) -> Option { - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; const_chan.send(ConstellationMsg::GetPipeline(frame_id, sender)).unwrap(); - reciever.recv().unwrap() + receiver.recv().unwrap() } fn handle_new_session(&mut self) -> WebDriverResult { @@ -148,6 +148,9 @@ impl Handler { let mut capabilities = BTreeMap::new(); capabilities.insert("browserName".to_owned(), "servo".to_json()); capabilities.insert("browserVersion".to_owned(), "0.0.1".to_json()); + capabilities.insert("acceptSslCerts".to_owned(), false.to_json()); + capabilities.insert("takeScreenshot".to_owned(), true.to_json()); + capabilities.insert("takeElementScreenshot".to_owned(), false.to_json()); let rv = Ok(WebDriverResponse::NewSession( NewSessionResponse::new( session.id.to_string(), @@ -169,28 +172,49 @@ impl Handler { let pipeline_id = try!(self.get_root_pipeline()); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let load_data = LoadData::new(url); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone()); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); + self.wait_for_load(sender, receiver) + } + + fn wait_for_load(&self, + sender: IpcSender, + receiver: IpcReceiver) -> WebDriverResult { let timeout = self.load_timeout; - let timeout_chan = sender.clone(); + let timeout_chan = sender; thread::spawn(move || { sleep_ms(timeout); let _ = timeout_chan.send(LoadStatus::LoadTimeout); }); //Wait to get a load event - match reciever.recv().unwrap() { + match receiver.recv().unwrap() { LoadStatus::LoadComplete => Ok(WebDriverResponse::Void), LoadStatus::LoadTimeout => Err(WebDriverError::new(ErrorStatus::Timeout, "Load timed out")) } } + fn handle_get_current_url(&self) -> WebDriverResult { + let pipeline_id = try!(self.get_root_pipeline()); + + let (sender, receiver) = ipc::channel().unwrap(); + + let ConstellationChan(ref const_chan) = self.constellation_chan; + let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, + WebDriverScriptCommand::GetUrl(sender)); + const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); + + let url = receiver.recv().unwrap(); + + Ok(WebDriverResponse::Generic(ValueResponse::new(url.serialize().to_json()))) + } + fn handle_go_back(&self) -> WebDriverResult { let ConstellationChan(ref const_chan) = self.constellation_chan; const_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Back)).unwrap(); @@ -203,15 +227,27 @@ impl Handler { Ok(WebDriverResponse::Void) } + fn handle_refresh(&self) -> WebDriverResult { + let pipeline_id = try!(self.get_root_pipeline()); + + let (sender, receiver) = ipc::channel().unwrap(); + + let ConstellationChan(ref const_chan) = self.constellation_chan; + let cmd_msg = WebDriverCommandMsg::Refresh(pipeline_id, sender.clone()); + const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); + + self.wait_for_load(sender, receiver) + } + fn handle_get_title(&self) -> WebDriverResult { let pipeline_id = try!(self.get_root_pipeline()); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, WebDriverScriptCommand::GetTitle(sender)); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - let value = reciever.recv().unwrap(); + let value = receiver.recv().unwrap(); Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))) } @@ -237,12 +273,12 @@ impl Handler { "Unsupported locator strategy")) } - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd = WebDriverScriptCommand::FindElementCSS(parameters.value.clone(), sender); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - match reciever.recv().unwrap() { + match receiver.recv().unwrap() { Ok(value) => { let value_resp = value.map(|x| WebElement::new(x).to_json()).to_json(); Ok(WebDriverResponse::Generic(ValueResponse::new(value_resp))) @@ -277,7 +313,7 @@ impl Handler { "Selecting frame by id not supported")); } let pipeline_id = try!(self.get_frame_pipeline()); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let cmd = WebDriverScriptCommand::GetFrameId(frame_id, sender); { let ConstellationChan(ref const_chan) = self.constellation_chan; @@ -285,12 +321,12 @@ impl Handler { WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd))).unwrap(); } - let frame = match reciever.recv().unwrap() { + let frame = match receiver.recv().unwrap() { Ok(Some((pipeline_id, subpage_id))) => { - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; const_chan.send(ConstellationMsg::GetFrame(pipeline_id, subpage_id, sender)).unwrap(); - reciever.recv().unwrap() + receiver.recv().unwrap() }, Ok(None) => None, Err(_) => { @@ -312,12 +348,12 @@ impl Handler { "Unsupported locator strategy")) } - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd = WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(), sender); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - match reciever.recv().unwrap() { + match receiver.recv().unwrap() { Ok(value) => { let resp_value: Vec = value.into_iter().map( |x| WebElement::new(x).to_json()).collect(); @@ -331,12 +367,12 @@ impl Handler { fn handle_get_element_text(&self, element: &WebElement) -> WebDriverResult { let pipeline_id = try!(self.get_frame_pipeline()); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd = WebDriverScriptCommand::GetElementText(element.id.clone(), sender); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - match reciever.recv().unwrap() { + match receiver.recv().unwrap() { Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, "Unable to find element in document")) @@ -346,24 +382,24 @@ impl Handler { fn handle_get_active_element(&self) -> WebDriverResult { let pipeline_id = try!(self.get_frame_pipeline()); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd = WebDriverScriptCommand::GetActiveElement(sender); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - let value = reciever.recv().unwrap().map(|x| WebElement::new(x).to_json()); + let value = receiver.recv().unwrap().map(|x| WebElement::new(x).to_json()); Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))) } fn handle_get_element_tag_name(&self, element: &WebElement) -> WebDriverResult { let pipeline_id = try!(self.get_frame_pipeline()); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd = WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - match reciever.recv().unwrap() { + match receiver.recv().unwrap() { Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, "Unable to find element in document")) @@ -393,9 +429,9 @@ impl Handler { // it with a vec of arguments. let script = format!("(function() {{ {} }})({})", func_body, args_string); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let command = WebDriverScriptCommand::ExecuteScript(script, sender); - self.execute_script(command, reciever) + self.execute_script(command, receiver) } fn handle_execute_async_script(&self, @@ -407,14 +443,14 @@ impl Handler { "setTimeout(webdriverTimeout, {}); (function(callback) {{ {} }})({})", self.script_timeout, func_body, args_string); - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let command = WebDriverScriptCommand::ExecuteAsyncScript(script, sender); - self.execute_script(command, reciever) + self.execute_script(command, receiver) } fn execute_script(&self, command: WebDriverScriptCommand, - reciever: IpcReceiver) + receiver: IpcReceiver) -> WebDriverResult { let pipeline_id = try!(self.get_frame_pipeline()); @@ -422,7 +458,7 @@ impl Handler { let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, command); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - match reciever.recv().unwrap() { + match receiver.recv().unwrap() { Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Err(WebDriverJSError::Timeout) => Err(WebDriverError::new(ErrorStatus::Timeout, "")), Err(WebDriverJSError::UnknownType) => Err(WebDriverError::new( @@ -438,12 +474,12 @@ impl Handler { let iterations = 30_000 / interval; for _ in 0..iterations { - let (sender, reciever) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; let cmd_msg = WebDriverCommandMsg::TakeScreenshot(pipeline_id, sender); const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); - if let Some(x) = reciever.recv().unwrap() { + if let Some(x) = receiver.recv().unwrap() { img = Some(x); break; }; @@ -489,8 +525,10 @@ impl WebDriverHandler for Handler { match msg.command { WebDriverCommand::NewSession => self.handle_new_session(), WebDriverCommand::Get(ref parameters) => self.handle_get(parameters), + WebDriverCommand::GetCurrentUrl => self.handle_get_current_url(), WebDriverCommand::GoBack => self.handle_go_back(), WebDriverCommand::GoForward => self.handle_go_forward(), + WebDriverCommand::Refresh => self.handle_refresh(), WebDriverCommand::GetTitle => self.handle_get_title(), WebDriverCommand::GetWindowHandle => self.handle_get_window_handle(), WebDriverCommand::GetWindowHandles => self.handle_get_window_handles(),