mirror of
https://github.com/servo/servo.git
synced 2025-07-07 15:33:46 +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,
|
can_gc,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
WebDriverScriptCommand::GetParentFrameId(reply) => {
|
||||||
|
webdriver_handlers::handle_get_parent_frame_id(&documents, pipeline_id, reply)
|
||||||
|
},
|
||||||
WebDriverScriptCommand::GetBrowsingContextId(webdriver_frame_id, reply) => {
|
WebDriverScriptCommand::GetBrowsingContextId(webdriver_frame_id, reply) => {
|
||||||
webdriver_handlers::handle_get_browsing_context_id(
|
webdriver_handlers::handle_get_browsing_context_id(
|
||||||
&documents,
|
&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(
|
pub(crate) fn handle_get_browsing_context_id(
|
||||||
documents: &DocumentCollection,
|
documents: &DocumentCollection,
|
||||||
pipeline: PipelineId,
|
pipeline: PipelineId,
|
||||||
|
@ -594,9 +618,20 @@ pub(crate) fn handle_get_browsing_context_id(
|
||||||
) {
|
) {
|
||||||
reply
|
reply
|
||||||
.send(match webdriver_frame_id {
|
.send(match webdriver_frame_id {
|
||||||
WebDriverFrameId::Short(_) => {
|
WebDriverFrameId::Short(id) => {
|
||||||
// This isn't supported yet
|
// Step 5. If id is not a supported property index of window,
|
||||||
Err(ErrorStatus::UnsupportedOperation)
|
// 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) => {
|
WebDriverFrameId::Element(element_id) => {
|
||||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
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)
|
.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();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,7 @@ pub enum WebDriverScriptCommand {
|
||||||
WebDriverFrameId,
|
WebDriverFrameId,
|
||||||
IpcSender<Result<BrowsingContextId, ErrorStatus>>,
|
IpcSender<Result<BrowsingContextId, ErrorStatus>>,
|
||||||
),
|
),
|
||||||
|
GetParentFrameId(IpcSender<Result<BrowsingContextId, ErrorStatus>>),
|
||||||
GetUrl(IpcSender<ServoUrl>),
|
GetUrl(IpcSender<ServoUrl>),
|
||||||
GetPageSource(IpcSender<Result<String, ErrorStatus>>),
|
GetPageSource(IpcSender<Result<String, ErrorStatus>>),
|
||||||
IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
|
IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
|
||||||
|
@ -240,7 +241,6 @@ pub type WebDriverJSResult = Result<WebDriverJSValue, WebDriverJSError>;
|
||||||
pub enum WebDriverFrameId {
|
pub enum WebDriverFrameId {
|
||||||
Short(u16),
|
Short(u16),
|
||||||
Element(String),
|
Element(String),
|
||||||
Parent,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
|
|
@ -1079,33 +1079,62 @@ impl Handler {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webdriver/#dfn-switch-to-frame>
|
||||||
fn handle_switch_to_frame(
|
fn handle_switch_to_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
parameters: &SwitchToFrameParameters,
|
parameters: &SwitchToFrameParameters,
|
||||||
) -> WebDriverResult<WebDriverResponse> {
|
) -> WebDriverResult<WebDriverResponse> {
|
||||||
self.verify_top_level_browsing_context_is_open(self.session()?.webview_id)?;
|
|
||||||
|
|
||||||
use webdriver::common::FrameId;
|
use webdriver::common::FrameId;
|
||||||
let frame_id = match parameters.id {
|
let frame_id = match parameters.id {
|
||||||
|
// id is null
|
||||||
FrameId::Top => {
|
FrameId::Top => {
|
||||||
let session = self.session_mut()?;
|
let webview_id = self.session()?.webview_id;
|
||||||
session.browsing_context_id = BrowsingContextId::from(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);
|
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()),
|
FrameId::Element(ref x) => WebDriverFrameId::Element(x.to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.switch_to_frame(frame_id)
|
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> {
|
fn handle_switch_to_parent_frame(&mut self) -> WebDriverResult<WebDriverResponse> {
|
||||||
let webview_id = self.session()?.webview_id;
|
let webview_id = self.session()?.webview_id;
|
||||||
self.verify_top_level_browsing_context_is_open(webview_id)?;
|
let browsing_context = self.session()?.browsing_context_id;
|
||||||
if self.session()?.browsing_context_id == webview_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);
|
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
|
// https://w3c.github.io/webdriver/#switch-to-window
|
||||||
|
@ -1141,13 +1170,6 @@ impl Handler {
|
||||||
&mut self,
|
&mut self,
|
||||||
frame_id: WebDriverFrameId,
|
frame_id: WebDriverFrameId,
|
||||||
) -> WebDriverResult<WebDriverResponse> {
|
) -> 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 (sender, receiver) = ipc::channel().unwrap();
|
||||||
let cmd = WebDriverScriptCommand::GetBrowsingContextId(frame_id, sender);
|
let cmd = WebDriverScriptCommand::GetBrowsingContextId(frame_id, sender);
|
||||||
self.browsing_context_script_command::<true>(cmd)?;
|
self.browsing_context_script_command::<true>(cmd)?;
|
||||||
|
|
|
@ -4,6 +4,3 @@
|
||||||
|
|
||||||
[test_textarea_append]
|
[test_textarea_append]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_date]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -20,8 +20,5 @@
|
||||||
[test_disabled]
|
[test_disabled]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_transparent_element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_readonly_element]
|
[test_readonly_element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
[test_no_browsing_context]
|
[test_no_browsing_context]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_no_such_element_with_startnode_from_other_frame]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_find_element[xpath-//a\]]
|
[test_find_element[xpath-//a\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
[test_no_browsing_context]
|
[test_no_browsing_context]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_no_such_shadow_root_with_shadow_root_from_other_frame]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_find_element[open-xpath-//a\]]
|
[test_find_element[open-xpath-//a\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
[test_no_browsing_context]
|
[test_no_browsing_context]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_no_such_element_with_startnode_from_other_frame]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_find_elements[xpath-//a\]]
|
[test_find_elements[xpath-//a\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
[test_no_browsing_context]
|
[test_no_browsing_context]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_no_such_shadow_root_with_shadow_root_from_other_frame]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_find_elements[open-xpath-//a\]]
|
[test_find_elements[open-xpath-//a\]]
|
||||||
expected: FAIL
|
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