diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 971c072476e..8bb83e31eff 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -2494,6 +2494,9 @@ impl ScriptThread { can_gc, ) }, + WebDriverScriptCommand::GetParentFrameId(reply) => { + webdriver_handlers::handle_get_parent_frame_id(&documents, pipeline_id, reply) + }, WebDriverScriptCommand::GetBrowsingContextId(webdriver_frame_id, reply) => { webdriver_handlers::handle_get_browsing_context_id( &documents, diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 718b1200586..d36b6605f70 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -586,6 +586,30 @@ pub(crate) fn handle_execute_async_script( } } +/// Get BrowsingContextId for +pub(crate) fn handle_get_parent_frame_id( + documents: &DocumentCollection, + pipeline: PipelineId, + reply: IpcSender>, +) { + // Step 2. If session's current parent browsing context is no longer open, + // return error with error code no such window. + reply + .send( + documents + .find_window(pipeline) + .and_then(|window| { + window + .window_proxy() + .parent() + .map(|parent| parent.browsing_context_id()) + }) + .ok_or(ErrorStatus::NoSuchWindow), + ) + .unwrap(); +} + +/// Get the BrowsingContextId for pub(crate) fn handle_get_browsing_context_id( documents: &DocumentCollection, pipeline: PipelineId, @@ -594,9 +618,20 @@ pub(crate) fn handle_get_browsing_context_id( ) { reply .send(match webdriver_frame_id { - WebDriverFrameId::Short(_) => { - // This isn't supported yet - Err(ErrorStatus::UnsupportedOperation) + WebDriverFrameId::Short(id) => { + // Step 5. If id is not a supported property index of window, + // return error with error code no such frame. + documents + .find_document(pipeline) + .ok_or(ErrorStatus::NoSuchWindow) + .and_then(|document| { + document + .iframes() + .iter() + .nth(id as usize) + .and_then(|iframe| iframe.browsing_context_id()) + .ok_or(ErrorStatus::NoSuchFrame) + }) }, WebDriverFrameId::Element(element_id) => { get_known_element(documents, pipeline, element_id).and_then(|element| { @@ -606,15 +641,6 @@ pub(crate) fn handle_get_browsing_context_id( .ok_or(ErrorStatus::NoSuchFrame) }) }, - WebDriverFrameId::Parent => documents - .find_window(pipeline) - .and_then(|window| { - window - .window_proxy() - .parent() - .map(|parent| parent.browsing_context_id()) - }) - .ok_or(ErrorStatus::NoSuchFrame), }) .unwrap(); } diff --git a/components/shared/embedder/webdriver.rs b/components/shared/embedder/webdriver.rs index 7610b7bb39a..181abe8b62c 100644 --- a/components/shared/embedder/webdriver.rs +++ b/components/shared/embedder/webdriver.rs @@ -198,6 +198,7 @@ pub enum WebDriverScriptCommand { WebDriverFrameId, IpcSender>, ), + GetParentFrameId(IpcSender>), GetUrl(IpcSender), GetPageSource(IpcSender>), IsEnabled(String, IpcSender>), @@ -240,7 +241,6 @@ pub type WebDriverJSResult = Result; pub enum WebDriverFrameId { Short(u16), Element(String), - Parent, } #[derive(Debug, Deserialize, Serialize)] diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index dcfe4797103..e6e0cbfa4fb 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -1079,33 +1079,62 @@ impl Handler { })) } + /// fn handle_switch_to_frame( &mut self, parameters: &SwitchToFrameParameters, ) -> WebDriverResult { - self.verify_top_level_browsing_context_is_open(self.session()?.webview_id)?; - use webdriver::common::FrameId; let frame_id = match parameters.id { + // id is null FrameId::Top => { - let session = self.session_mut()?; - session.browsing_context_id = BrowsingContextId::from(session.webview_id); + let webview_id = self.session()?.webview_id; + // Step 1. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(webview_id)?; + // (SKIP) Step 2. Try to handle any user prompts with session. + + // Step 3. Set the current browsing context with session and + // session's current top-level browsing context. + self.session_mut()?.browsing_context_id = BrowsingContextId::from(webview_id); return Ok(WebDriverResponse::Void); }, - FrameId::Short(ref x) => WebDriverFrameId::Short(*x), + // id is a Number object + FrameId::Short(ref x) => { + // (Already handled when deserializing in webdriver-crate) + // Step 1. If id is less than 0 or greater than 2^16 – 1, + // return error with error code invalid argument. + WebDriverFrameId::Short(*x) + }, FrameId::Element(ref x) => WebDriverFrameId::Element(x.to_string()), }; self.switch_to_frame(frame_id) } + /// fn handle_switch_to_parent_frame(&mut self) -> WebDriverResult { let webview_id = self.session()?.webview_id; - self.verify_top_level_browsing_context_is_open(webview_id)?; - if self.session()?.browsing_context_id == webview_id { + let browsing_context = self.session()?.browsing_context_id; + // Step 1. If session's current browsing context is already the top-level browsing context: + if browsing_context == webview_id { + // Step 1.1. If session's current browsing context is no longer open, + // return error with error code no such window. + self.verify_browsing_context_is_open(browsing_context)?; + // Step 1.2. Return success with data null. return Ok(WebDriverResponse::Void); } - self.switch_to_frame(WebDriverFrameId::Parent) + let (sender, receiver) = ipc::channel().unwrap(); + let cmd = WebDriverScriptCommand::GetParentFrameId(sender); + // TODO: Track Parent Browsing Context directly in the session, as expected by Spec. + self.browsing_context_script_command::(cmd)?; + match wait_for_script_response(receiver)? { + Ok(browsing_context_id) => { + self.session_mut()?.browsing_context_id = browsing_context_id; + Ok(WebDriverResponse::Void) + }, + Err(error) => Err(WebDriverError::new(error, "")), + } } // https://w3c.github.io/webdriver/#switch-to-window @@ -1141,13 +1170,6 @@ impl Handler { &mut self, frame_id: WebDriverFrameId, ) -> WebDriverResult { - if let WebDriverFrameId::Short(_) = frame_id { - return Err(WebDriverError::new( - ErrorStatus::UnsupportedOperation, - "Selecting frame by id not supported", - )); - } - let (sender, receiver) = ipc::channel().unwrap(); let cmd = WebDriverScriptCommand::GetBrowsingContextId(frame_id, sender); self.browsing_context_script_command::(cmd)?; diff --git a/tests/wpt/meta/webdriver/tests/classic/element_send_keys/form_controls.py.ini b/tests/wpt/meta/webdriver/tests/classic/element_send_keys/form_controls.py.ini index 1dea194f9b2..5d4a3bd4de5 100644 --- a/tests/wpt/meta/webdriver/tests/classic/element_send_keys/form_controls.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/element_send_keys/form_controls.py.ini @@ -4,6 +4,3 @@ [test_textarea_append] expected: FAIL - - [test_date] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/element_send_keys/interactability.py.ini b/tests/wpt/meta/webdriver/tests/classic/element_send_keys/interactability.py.ini index 921b8c5cb5d..8698a74cdbf 100644 --- a/tests/wpt/meta/webdriver/tests/classic/element_send_keys/interactability.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/element_send_keys/interactability.py.ini @@ -20,8 +20,5 @@ [test_disabled] expected: FAIL - [test_transparent_element] - expected: FAIL - [test_readonly_element] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini b/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini index 71745169f3f..d3786ff5851 100644 --- a/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini @@ -2,9 +2,6 @@ [test_no_browsing_context] expected: FAIL - [test_no_such_element_with_startnode_from_other_frame] - expected: FAIL - [test_find_element[xpath-//a\]] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/find_element_from_shadow_root/find.py.ini b/tests/wpt/meta/webdriver/tests/classic/find_element_from_shadow_root/find.py.ini index 4c3d23530dd..95572375a3c 100644 --- a/tests/wpt/meta/webdriver/tests/classic/find_element_from_shadow_root/find.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/find_element_from_shadow_root/find.py.ini @@ -2,9 +2,6 @@ [test_no_browsing_context] expected: FAIL - [test_no_such_shadow_root_with_shadow_root_from_other_frame] - expected: FAIL - [test_find_element[open-xpath-//a\]] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini b/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini index b7871113dd7..1ddbffa1dee 100644 --- a/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini @@ -2,9 +2,6 @@ [test_no_browsing_context] expected: FAIL - [test_no_such_element_with_startnode_from_other_frame] - expected: FAIL - [test_find_elements[xpath-//a\]] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/find_elements_from_shadow_root/find.py.ini b/tests/wpt/meta/webdriver/tests/classic/find_elements_from_shadow_root/find.py.ini index f39cfb16aa6..10233bfa9c3 100644 --- a/tests/wpt/meta/webdriver/tests/classic/find_elements_from_shadow_root/find.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/find_elements_from_shadow_root/find.py.ini @@ -2,9 +2,6 @@ [test_no_browsing_context] expected: FAIL - [test_no_such_shadow_root_with_shadow_root_from_other_frame] - expected: FAIL - [test_find_elements[open-xpath-//a\]] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/switch_to_frame/switch_number.py.ini b/tests/wpt/meta/webdriver/tests/classic/switch_to_frame/switch_number.py.ini deleted file mode 100644 index 408f2eb2568..00000000000 --- a/tests/wpt/meta/webdriver/tests/classic/switch_to_frame/switch_number.py.ini +++ /dev/null @@ -1,15 +0,0 @@ -[switch_number.py] - [test_frame_id_number_index_out_of_bounds[1\]] - expected: FAIL - - [test_frame_id_number_index_out_of_bounds[65535\]] - expected: FAIL - - [test_frame_id_number_index[0-foo\]] - expected: FAIL - - [test_frame_id_number_index[1-bar\]] - expected: FAIL - - [test_frame_id_number_index_nested] - expected: FAIL