diff options
author | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-05-22 09:40:17 -0500 |
---|---|---|
committer | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-05-25 17:14:28 -0500 |
commit | 79743b5358c989da23c11c025509dd2c46dba48b (patch) | |
tree | f8a05416245fb9d5b56fbc6ac73fe56b20fddb4f /components/webdriver_server | |
parent | 3c267d7fddd036f6bcc9ebf000ed37665cf7496d (diff) | |
download | servo-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.rs | 221 |
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 = ¶meters.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() { |