aboutsummaryrefslogtreecommitdiffstats
path: root/components/webdriver_server
diff options
context:
space:
mode:
authorAlan Jeffrey <ajeffrey@mozilla.com>2017-05-22 09:40:17 -0500
committerAlan Jeffrey <ajeffrey@mozilla.com>2017-05-25 17:14:28 -0500
commit79743b5358c989da23c11c025509dd2c46dba48b (patch)
treef8a05416245fb9d5b56fbc6ac73fe56b20fddb4f /components/webdriver_server
parent3c267d7fddd036f6bcc9ebf000ed37665cf7496d (diff)
downloadservo-79743b5358c989da23c11c025509dd2c46dba48b.tar.gz
servo-79743b5358c989da23c11c025509dd2c46dba48b.zip
Webdriver uses browsing context ids rather than pipeline ids.
Diffstat (limited to 'components/webdriver_server')
-rw-r--r--components/webdriver_server/lib.rs221
1 files changed, 106 insertions, 115 deletions
diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs
index 404f965bbb9..8f085e507ab 100644
--- a/components/webdriver_server/lib.rs
+++ b/components/webdriver_server/lib.rs
@@ -32,7 +32,7 @@ use hyper::method::Method::{self, Post};
use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use keys::keycodes_to_keys;
-use msg::constellation_msg::{BrowsingContextId, PipelineId, TraversalDirection};
+use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection};
use net_traits::image::base::PixelFormat;
use regex::Captures;
use rustc_serialize::json::{Json, ToJson};
@@ -102,7 +102,8 @@ pub fn start_server(port: u16, constellation_chan: Sender<ConstellationMsg>) {
/// Represents the current WebDriver session and holds relevant session state.
struct WebDriverSession {
id: Uuid,
- browsing_context_id: Option<BrowsingContextId>,
+ browsing_context_id: BrowsingContextId,
+ top_level_browsing_context_id: TopLevelBrowsingContextId,
/// Time to wait for injected scripts to run before interrupting them. A [`None`] value
/// specifies that the script should run indefinitely.
@@ -117,10 +118,14 @@ struct WebDriverSession {
}
impl WebDriverSession {
- pub fn new() -> WebDriverSession {
+ pub fn new(browsing_context_id: BrowsingContextId,
+ top_level_browsing_context_id: TopLevelBrowsingContextId)
+ -> WebDriverSession
+ {
WebDriverSession {
id: Uuid::new_v4(),
- browsing_context_id: None,
+ browsing_context_id: browsing_context_id,
+ top_level_browsing_context_id: top_level_browsing_context_id,
script_timeout: Some(30_000),
load_timeout: Some(300_000),
@@ -264,33 +269,28 @@ impl Handler {
}
}
- fn pipeline_id(&self, frame_id: Option<BrowsingContextId>) -> WebDriverResult<PipelineId> {
+ fn focus_top_level_browsing_context_id(&self) -> WebDriverResult<TopLevelBrowsingContextId> {
+ debug!("Getting focused context.");
let interval = 20;
let iterations = 30_000 / interval;
let (sender, receiver) = ipc::channel().unwrap();
for _ in 0..iterations {
- let msg = ConstellationMsg::GetPipeline(frame_id, sender.clone());
+ let msg = ConstellationMsg::GetFocusTopLevelBrowsingContext(sender.clone());
self.constellation_chan.send(msg).unwrap();
- // Wait until the document is ready before returning the pipeline id.
+ // Wait until the document is ready before returning the top-level browsing context id.
if let Some(x) = receiver.recv().unwrap() {
+ debug!("Focused context is {}", x);
return Ok(x);
}
thread::sleep(Duration::from_millis(interval));
}
+ debug!("Timed out getting focused context.");
Err(WebDriverError::new(ErrorStatus::Timeout,
"Failed to get window handle"))
}
- fn root_pipeline(&self) -> WebDriverResult<PipelineId> {
- self.pipeline_id(None)
- }
-
- fn frame_pipeline(&self) -> WebDriverResult<PipelineId> {
- self.pipeline_id(self.session.as_ref().and_then(|session| session.browsing_context_id))
- }
-
fn session(&self) -> WebDriverResult<&WebDriverSession> {
match self.session {
Some(ref x) => Ok(x),
@@ -299,31 +299,30 @@ impl Handler {
}
}
- fn set_browsing_context_id(&mut self, browsing_context_id: Option<BrowsingContextId>) -> WebDriverResult<()> {
+ fn session_mut(&mut self) -> WebDriverResult<&mut WebDriverSession> {
match self.session {
- Some(ref mut x) => {
- x.browsing_context_id = browsing_context_id;
- Ok(())
- },
+ Some(ref mut x) => Ok(x),
None => Err(WebDriverError::new(ErrorStatus::SessionNotCreated,
"Session not created"))
}
}
fn handle_new_session(&mut self) -> WebDriverResult<WebDriverResponse> {
+ debug!("new session");
if self.session.is_none() {
- let session = WebDriverSession::new();
+ let top_level_browsing_context_id = self.focus_top_level_browsing_context_id()?;
+ let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
+ let session = WebDriverSession::new(browsing_context_id, top_level_browsing_context_id);
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("acceptInsecureCerts".to_owned(), false.to_json());
- let rv = Ok(WebDriverResponse::NewSession(
- NewSessionResponse::new(
- session.id.to_string(),
- Json::Object(capabilities))));
+ let response = NewSessionResponse::new(session.id.to_string(), Json::Object(capabilities));
+ debug!("new session created {}.", session.id);
self.session = Some(session);
- rv
+ Ok(WebDriverResponse::NewSession(response))
} else {
+ debug!("new session failed.");
Err(WebDriverError::new(ErrorStatus::UnknownError,
"Session already created"))
}
@@ -334,16 +333,18 @@ impl Handler {
Ok(WebDriverResponse::Void)
}
- #[inline]
- fn frame_script_command(&self, cmd_msg: WebDriverScriptCommand) -> WebDriverResult<()> {
- Ok(self.constellation_chan.send(ConstellationMsg::WebDriverCommand(
- WebDriverCommandMsg::ScriptCommand(try!(self.frame_pipeline()), cmd_msg))).unwrap())
+ fn browsing_context_script_command(&self, cmd_msg: WebDriverScriptCommand) -> WebDriverResult<()> {
+ let browsing_context_id = self.session()?.browsing_context_id;
+ let msg = ConstellationMsg::WebDriverCommand(WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg));
+ self.constellation_chan.send(msg).unwrap();
+ Ok(())
}
- #[inline]
- fn root_script_command(&self, cmd_msg: WebDriverScriptCommand) -> WebDriverResult<()> {
- Ok(self.constellation_chan.send(ConstellationMsg::WebDriverCommand(
- WebDriverCommandMsg::ScriptCommand(try!(self.root_pipeline()), cmd_msg))).unwrap())
+ fn top_level_script_command(&self, cmd_msg: WebDriverScriptCommand) -> WebDriverResult<()> {
+ let browsing_context_id = BrowsingContextId::from(self.session()?.top_level_browsing_context_id);
+ let msg = ConstellationMsg::WebDriverCommand(WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg));
+ self.constellation_chan.send(msg).unwrap();
+ Ok(())
}
fn handle_get(&self, parameters: &GetParameters) -> WebDriverResult<WebDriverResponse> {
@@ -353,12 +354,12 @@ impl Handler {
"Invalid URL"))
};
- let pipeline_id = try!(self.root_pipeline());
+ let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
let (sender, receiver) = ipc::channel().unwrap();
- let load_data = LoadData::new(url, Some(pipeline_id), None, None);
- let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone());
+ let load_data = LoadData::new(url, None, None, None);
+ let cmd_msg = WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, sender.clone());
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
self.wait_for_load(sender, receiver)
@@ -368,15 +369,10 @@ impl Handler {
sender: IpcSender<LoadStatus>,
receiver: IpcReceiver<LoadStatus>)
-> WebDriverResult<WebDriverResponse> {
- let session = try!(self.session
- .as_ref()
- .ok_or(WebDriverError::new(ErrorStatus::SessionNotCreated, "")));
-
- let timeout = session.load_timeout;
- let timeout_chan = sender;
+ let timeout = self.session()?.load_timeout;
thread::spawn(move || {
thread::sleep(Duration::from_millis(timeout.unwrap()));
- let _ = timeout_chan.send(LoadStatus::LoadTimeout);
+ let _ = sender.send(LoadStatus::LoadTimeout);
});
// wait to get a load event
@@ -390,7 +386,7 @@ impl Handler {
fn handle_current_url(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.root_script_command(WebDriverScriptCommand::GetUrl(sender)));
+ self.top_level_script_command(WebDriverScriptCommand::GetUrl(sender))?;
let url = receiver.recv().unwrap();
@@ -399,8 +395,8 @@ impl Handler {
fn handle_window_size(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- let pipeline_id = try!(self.root_pipeline());
- let cmd_msg = WebDriverCommandMsg::GetWindowSize(pipeline_id, sender);
+ let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
+ let cmd_msg = WebDriverCommandMsg::GetWindowSize(top_level_browsing_context_id, sender);
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
@@ -413,8 +409,8 @@ impl Handler {
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());
+ let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
+ let cmd_msg = WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, sender.clone());
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
@@ -424,7 +420,7 @@ impl Handler {
// 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);
+ let cmd_msg = WebDriverCommandMsg::GetWindowSize(top_level_browsing_context_id, sender);
constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
});
@@ -437,7 +433,7 @@ impl Handler {
fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.root_script_command(WebDriverScriptCommand::IsEnabled(element.id.clone(), sender)));
+ self.top_level_script_command(WebDriverScriptCommand::IsEnabled(element.id.clone(), sender))?;
match receiver.recv().unwrap() {
Ok(is_enabled) => Ok(WebDriverResponse::Generic(ValueResponse::new(is_enabled.to_json()))),
@@ -448,7 +444,7 @@ impl Handler {
fn handle_is_selected(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.root_script_command(WebDriverScriptCommand::IsSelected(element.id.clone(), sender)));
+ self.top_level_script_command(WebDriverScriptCommand::IsSelected(element.id.clone(), sender))?;
match receiver.recv().unwrap() {
Ok(is_selected) => Ok(WebDriverResponse::Generic(ValueResponse::new(is_selected.to_json()))),
@@ -457,21 +453,27 @@ impl Handler {
}
fn handle_go_back(&self) -> WebDriverResult<WebDriverResponse> {
- self.constellation_chan.send(ConstellationMsg::TraverseHistory(None, TraversalDirection::Back(1))).unwrap();
+ let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
+ let direction = TraversalDirection::Back(1);
+ let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
+ self.constellation_chan.send(msg).unwrap();
Ok(WebDriverResponse::Void)
}
fn handle_go_forward(&self) -> WebDriverResult<WebDriverResponse> {
- self.constellation_chan.send(ConstellationMsg::TraverseHistory(None, TraversalDirection::Forward(1))).unwrap();
+ let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
+ let direction = TraversalDirection::Forward(1);
+ let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
+ self.constellation_chan.send(msg).unwrap();
Ok(WebDriverResponse::Void)
}
fn handle_refresh(&self) -> WebDriverResult<WebDriverResponse> {
- let pipeline_id = try!(self.root_pipeline());
+ let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
let (sender, receiver) = ipc::channel().unwrap();
- let cmd_msg = WebDriverCommandMsg::Refresh(pipeline_id, sender.clone());
+ let cmd_msg = WebDriverCommandMsg::Refresh(top_level_browsing_context_id, sender.clone());
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
self.wait_for_load(sender, receiver)
@@ -480,7 +482,7 @@ impl Handler {
fn handle_title(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.root_script_command(WebDriverScriptCommand::GetTitle(sender)));
+ self.top_level_script_command(WebDriverScriptCommand::GetTitle(sender))?;
let value = receiver.recv().unwrap();
Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json())))
@@ -508,8 +510,8 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::FindElementCSS(parameters.value.clone(),
- sender)));
+ let cmd = WebDriverScriptCommand::FindElementCSS(parameters.value.clone(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(value) => {
@@ -525,8 +527,9 @@ impl Handler {
use webdriver::common::FrameId;
let frame_id = match parameters.id {
FrameId::Null => {
- self.set_browsing_context_id(None).unwrap();
- return Ok(WebDriverResponse::Void)
+ let session = self.session_mut()?;
+ session.browsing_context_id = BrowsingContextId::from(session.top_level_browsing_context_id);
+ return Ok(WebDriverResponse::Void);
},
FrameId::Short(ref x) => WebDriverFrameId::Short(*x),
FrameId::Element(ref x) => WebDriverFrameId::Element(x.id.clone())
@@ -545,28 +548,15 @@ impl Handler {
return Err(WebDriverError::new(ErrorStatus::UnsupportedOperation,
"Selecting frame by id not supported"));
}
- let pipeline_id = try!(self.frame_pipeline());
+
let (sender, receiver) = ipc::channel().unwrap();
- let cmd = WebDriverScriptCommand::GetPipelineId(frame_id, sender);
- {
- self.constellation_chan.send(ConstellationMsg::WebDriverCommand(
- WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd))).unwrap();
- }
+ let cmd = WebDriverScriptCommand::GetBrowsingContextId(frame_id, sender);
+ self.browsing_context_script_command(cmd)?;
- let context_id = match receiver.recv().unwrap() {
- Ok(Some(pipeline_id)) => {
- let (sender, receiver) = ipc::channel().unwrap();
- self.constellation_chan.send(ConstellationMsg::GetBrowsingContext(pipeline_id, sender)).unwrap();
- receiver.recv().unwrap()
- },
- Ok(None) => None,
- Err(_) => {
- return Err(WebDriverError::new(ErrorStatus::NoSuchFrame,
- "Frame does not exist"));
- }
- };
+ let browsing_context_id = receiver.recv().unwrap()
+ .or(Err(WebDriverError::new(ErrorStatus::NoSuchFrame, "Frame does not exist")))?;
- self.set_browsing_context_id(context_id).unwrap();
+ self.session_mut()?.browsing_context_id = browsing_context_id;
Ok(WebDriverResponse::Void)
}
@@ -578,8 +568,8 @@ impl Handler {
}
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(),
- sender)));
+ let cmd = WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(value) => {
let resp_value: Vec<Json> = value.into_iter().map(
@@ -594,7 +584,8 @@ impl Handler {
// https://w3c.github.io/webdriver/webdriver-spec.html#get-element-rect
fn handle_element_rect(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetElementRect(element.id.clone(), sender)));
+ let cmd = WebDriverScriptCommand::GetElementRect(element.id.clone(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(rect) => {
let response = ElementRectResponse::new(rect.origin.x, rect.origin.y,
@@ -608,7 +599,8 @@ impl Handler {
fn handle_element_text(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetElementText(element.id.clone(), sender)));
+ let cmd = WebDriverScriptCommand::GetElementText(element.id.clone(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@@ -618,14 +610,16 @@ impl Handler {
fn handle_active_element(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetActiveElement(sender)));
+ let cmd = WebDriverScriptCommand::GetActiveElement(sender);
+ self.browsing_context_script_command(cmd)?;
let value = receiver.recv().unwrap().map(|x| WebElement::new(x).to_json());
Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json())))
}
fn handle_element_tag_name(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender)));
+ let cmd = WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@@ -635,8 +629,8 @@ impl Handler {
fn handle_element_attribute(&self, element: &WebElement, name: &str) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetElementAttribute(element.id.clone(), name.to_owned(),
- sender)));
+ let cmd = WebDriverScriptCommand::GetElementAttribute(element.id.clone(), name.to_owned(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@@ -646,8 +640,8 @@ impl Handler {
fn handle_element_css(&self, element: &WebElement, name: &str) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetElementCSS(element.id.clone(), name.to_owned(),
- sender)));
+ let cmd = WebDriverScriptCommand::GetElementCSS(element.id.clone(), name.to_owned(), sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@@ -657,7 +651,8 @@ impl Handler {
fn handle_get_cookies(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetCookies(sender)));
+ let cmd = WebDriverScriptCommand::GetCookies(sender);
+ self.browsing_context_script_command(cmd)?;
let cookies = receiver.recv().unwrap();
let response = cookies.into_iter().map(|cookie| {
cookie_msg_to_cookie(cookie.into_inner())
@@ -667,7 +662,8 @@ impl Handler {
fn handle_get_cookie(&self, name: &str) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
- try!(self.frame_script_command(WebDriverScriptCommand::GetCookie(name.to_owned(), sender)));
+ let cmd = WebDriverScriptCommand::GetCookie(name.to_owned(), sender);
+ self.browsing_context_script_command(cmd)?;
let cookies = receiver.recv().unwrap();
let response = cookies.into_iter().map(|cookie| {
cookie_msg_to_cookie(cookie.into_inner())
@@ -690,7 +686,8 @@ impl Handler {
_ => cookie.finish(),
};
- try!(self.frame_script_command(WebDriverScriptCommand::AddCookie(cookie, sender)));
+ let cmd = WebDriverScriptCommand::AddCookie(cookie, sender);
+ self.browsing_context_script_command(cmd)?;
match receiver.recv().unwrap() {
Ok(_) => Ok(WebDriverResponse::Void),
Err(response) => match response {
@@ -728,20 +725,18 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let command = WebDriverScriptCommand::ExecuteScript(script, sender);
- self.execute_script(command, receiver)
+ self.browsing_context_script_command(command)?;
+ let result = receiver.recv().unwrap();
+ self.postprocess_js_result(result)
}
fn handle_execute_async_script(&self,
parameters: &JavascriptCommandParameters)
-> WebDriverResult<WebDriverResponse> {
- let session = try!(self.session
- .as_ref()
- .ok_or(WebDriverError::new(ErrorStatus::SessionNotCreated, "")));
-
let func_body = &parameters.script;
let args_string = "window.webdriverCallback";
- let script = match session.script_timeout {
+ let script = match self.session()?.script_timeout {
Some(timeout) => {
format!("setTimeout(webdriverTimeout, {}); (function(callback) {{ {} }})({})",
timeout,
@@ -753,19 +748,13 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let command = WebDriverScriptCommand::ExecuteAsyncScript(script, sender);
- self.execute_script(command, receiver)
+ self.browsing_context_script_command(command)?;
+ let result = receiver.recv().unwrap();
+ self.postprocess_js_result(result)
}
- fn execute_script(&self,
- command: WebDriverScriptCommand,
- receiver: IpcReceiver<WebDriverJSResult>)
- -> WebDriverResult<WebDriverResponse> {
- let pipeline_id = try!(self.frame_pipeline());
-
- let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, command);
- self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
-
- match receiver.recv().unwrap() {
+ fn postprocess_js_result(&self, result: WebDriverJSResult) -> WebDriverResult<WebDriverResponse> {
+ match result {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(WebDriverJSError::Timeout) => Err(WebDriverError::new(ErrorStatus::Timeout, "")),
Err(WebDriverJSError::UnknownType) => Err(WebDriverError::new(
@@ -778,12 +767,12 @@ impl Handler {
fn handle_element_send_keys(&self,
element: &WebElement,
keys: &SendKeysParameters) -> WebDriverResult<WebDriverResponse> {
- let pipeline_id = try!(self.frame_pipeline());
+ let browsing_context_id = self.session()?.browsing_context_id;
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::FocusElement(element.id.clone(), sender);
- let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
+ let cmd_msg = WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd);
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
// TODO: distinguish the not found and not focusable cases
@@ -793,7 +782,9 @@ impl Handler {
let keys = try!(keycodes_to_keys(&keys.value).or_else(|_|
Err(WebDriverError::new(ErrorStatus::UnsupportedOperation, "Failed to convert keycodes"))));
- let cmd_msg = WebDriverCommandMsg::SendKeys(pipeline_id, keys);
+ // TODO: there's a race condition caused by these being two separate messages,
+ // so the constellation may have changed state between them.
+ let cmd_msg = WebDriverCommandMsg::SendKeys(browsing_context_id, keys);
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
Ok(WebDriverResponse::Void)
@@ -801,14 +792,14 @@ impl Handler {
fn handle_take_screenshot(&self) -> WebDriverResult<WebDriverResponse> {
let mut img = None;
- let pipeline_id = try!(self.root_pipeline());
+ let top_level_id = self.session()?.top_level_browsing_context_id;
let interval = 1000;
let iterations = 30_000 / interval;
for _ in 0..iterations {
let (sender, receiver) = ipc::channel().unwrap();
- let cmd_msg = WebDriverCommandMsg::TakeScreenshot(pipeline_id, sender);
+ let cmd_msg = WebDriverCommandMsg::TakeScreenshot(top_level_id, sender);
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
if let Some(x) = receiver.recv().unwrap() {