mirror of
https://github.com/servo/servo.git
synced 2025-07-07 07:23:38 +01:00
[WebDriver] Fully implement "switch to (parent) frame" (#37685)
1. Separate the handling of ["switch to parent frame"](https://w3c.github.io/webdriver/#switch-to-parent-frame) from the rest as the processing is a bit different 2. Implement "Select frame by 16-bits numbered ID" for ["switch to frame"](https://w3c.github.io/webdriver/#switch-to-frame) 3. Implement other missing steps Testing: All WebDriver Conformance test with new passing cases --------- Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
parent
253fb247f5
commit
f9880637e9
11 changed files with 79 additions and 61 deletions
|
@ -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,
|
||||
|
|
|
@ -586,6 +586,30 @@ pub(crate) fn handle_execute_async_script(
|
|||
}
|
||||
}
|
||||
|
||||
/// Get BrowsingContextId for <https://w3c.github.io/webdriver/#switch-to-parent-frame>
|
||||
pub(crate) fn handle_get_parent_frame_id(
|
||||
documents: &DocumentCollection,
|
||||
pipeline: PipelineId,
|
||||
reply: IpcSender<Result<BrowsingContextId, ErrorStatus>>,
|
||||
) {
|
||||
// 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 <https://w3c.github.io/webdriver/#dfn-switch-to-frame>
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -198,6 +198,7 @@ pub enum WebDriverScriptCommand {
|
|||
WebDriverFrameId,
|
||||
IpcSender<Result<BrowsingContextId, ErrorStatus>>,
|
||||
),
|
||||
GetParentFrameId(IpcSender<Result<BrowsingContextId, ErrorStatus>>),
|
||||
GetUrl(IpcSender<ServoUrl>),
|
||||
GetPageSource(IpcSender<Result<String, ErrorStatus>>),
|
||||
IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
|
||||
|
@ -240,7 +241,6 @@ pub type WebDriverJSResult = Result<WebDriverJSValue, WebDriverJSError>;
|
|||
pub enum WebDriverFrameId {
|
||||
Short(u16),
|
||||
Element(String),
|
||||
Parent,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
|
|
|
@ -1079,33 +1079,62 @@ impl Handler {
|
|||
}))
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-switch-to-frame>
|
||||
fn handle_switch_to_frame(
|
||||
&mut self,
|
||||
parameters: &SwitchToFrameParameters,
|
||||
) -> WebDriverResult<WebDriverResponse> {
|
||||
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)
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#switch-to-parent-frame>
|
||||
fn handle_switch_to_parent_frame(&mut self) -> WebDriverResult<WebDriverResponse> {
|
||||
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::<true>(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<WebDriverResponse> {
|
||||
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::<true>(cmd)?;
|
||||
|
|
|
@ -4,6 +4,3 @@
|
|||
|
||||
[test_textarea_append]
|
||||
expected: FAIL
|
||||
|
||||
[test_date]
|
||||
expected: FAIL
|
||||
|
|
|
@ -20,8 +20,5 @@
|
|||
[test_disabled]
|
||||
expected: FAIL
|
||||
|
||||
[test_transparent_element]
|
||||
expected: FAIL
|
||||
|
||||
[test_readonly_element]
|
||||
expected: FAIL
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue