[WebDriver] Grant top_level_script_command and browsing_context_script_command freedom to not verify existence of pipeline (#37632)

Sometimes, it is redundant to verify existence of pipeline over and over
again.
Sometimes, it is just wrong to check it. See [Switch to Parent
Frame](https://w3c.github.io/webdriver/#switch-to-parent-frame), where
we only care about existence of parent frame.
1. This PR adds a constant compile-time bool flag to enable this. This
will be essential to fix "no_browsing_context" next.
2. Fix some wrong usage of `top_level_script_command` in `is_selected`
and `is_enabled`.
3. Add and unify some WARN info related to pipeline in Constellation

Testing: All WebDriver test with new passing cases

---------

Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
Euclid Ye 2025-06-24 14:42:34 +08:00 committed by GitHub
parent e0f3679d55
commit 94a7428912
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 65 additions and 65 deletions

View file

@ -764,10 +764,9 @@ impl Handler {
web_element: &WebElement,
) -> Result<(i64, i64), ErrorStatus> {
let (sender, receiver) = ipc::channel().unwrap();
self.browsing_context_script_command(WebDriverScriptCommand::GetElementInViewCenterPoint(
web_element.to_string(),
sender,
))
self.browsing_context_script_command::<false>(
WebDriverScriptCommand::GetElementInViewCenterPoint(web_element.to_string(), sender),
)
.unwrap();
let response = match wait_for_script_response(receiver) {
Ok(response) => response,

View file

@ -703,7 +703,7 @@ impl Handler {
Ok(WebDriverResponse::DeleteSession)
}
// https://w3c.github.io/webdriver/#status
/// <https://w3c.github.io/webdriver/#status>
fn handle_status(&self) -> WebDriverResult<WebDriverResponse> {
Ok(WebDriverResponse::Generic(ValueResponse(
if self.session.is_none() {
@ -714,12 +714,16 @@ impl Handler {
)))
}
fn browsing_context_script_command(
/// Send command to Script Thread with session's current browsing context.
/// If CHECK_OPEN is true, it would verify the existence of browsing context before sending.
fn browsing_context_script_command<const CHECK_OPEN: bool>(
&self,
cmd_msg: WebDriverScriptCommand,
) -> WebDriverResult<()> {
let browsing_context_id = self.session()?.browsing_context_id;
self.verify_browsing_context_is_open(browsing_context_id)?;
if CHECK_OPEN {
self.verify_browsing_context_is_open(browsing_context_id)?;
}
let msg = EmbedderToConstellationMessage::WebDriverCommand(
WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg),
);
@ -727,9 +731,17 @@ impl Handler {
Ok(())
}
fn top_level_script_command(&self, cmd_msg: WebDriverScriptCommand) -> WebDriverResult<()> {
/// Send command to Script Thread with session's current top-level browsing context.
/// If CHECK_OPEN is true, it would verify the existence of top-level
/// browsing context before sending.
fn top_level_script_command<const CHECK_OPEN: bool>(
&self,
cmd_msg: WebDriverScriptCommand,
) -> WebDriverResult<()> {
let webview_id = self.session()?.webview_id;
self.verify_top_level_browsing_context_is_open(webview_id)?;
if CHECK_OPEN {
self.verify_top_level_browsing_context_is_open(webview_id)?;
}
let browsing_context_id = BrowsingContextId::from(webview_id);
let msg = EmbedderToConstellationMessage::WebDriverCommand(
WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg),
@ -780,7 +792,7 @@ impl Handler {
fn handle_current_url(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
self.top_level_script_command(WebDriverScriptCommand::GetUrl(sender))?;
self.top_level_script_command::<true>(WebDriverScriptCommand::GetUrl(sender))?;
let url = wait_for_script_response(receiver)?;
@ -861,13 +873,9 @@ impl Handler {
}
fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
// Step 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(self.session()?.browsing_context_id)?;
let (sender, receiver) = ipc::channel().unwrap();
self.top_level_script_command(WebDriverScriptCommand::IsEnabled(
self.browsing_context_script_command::<true>(WebDriverScriptCommand::IsEnabled(
element.to_string(),
sender,
))?;
@ -881,13 +889,9 @@ impl Handler {
}
fn handle_is_selected(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
// Step 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(self.session()?.browsing_context_id)?;
let (sender, receiver) = ipc::channel().unwrap();
self.top_level_script_command(WebDriverScriptCommand::IsSelected(
self.browsing_context_script_command::<true>(WebDriverScriptCommand::IsSelected(
element.to_string(),
sender,
))?;
@ -939,7 +943,7 @@ impl Handler {
fn handle_title(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
self.top_level_script_command(WebDriverScriptCommand::GetTitle(sender))?;
self.top_level_script_command::<true>(WebDriverScriptCommand::GetTitle(sender))?;
let value = wait_for_script_response(receiver)?;
Ok(WebDriverResponse::Generic(ValueResponse(
@ -991,7 +995,7 @@ impl Handler {
parameters.value.clone(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementLinkText(
@ -999,12 +1003,12 @@ impl Handler {
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::TagName => {
let cmd =
WebDriverScriptCommand::FindElementTagName(parameters.value.clone(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
_ => {
return Err(WebDriverError::new(
@ -1165,7 +1169,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetBrowsingContextId(frame_id, sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(browsing_context_id) => {
@ -1192,7 +1196,7 @@ impl Handler {
parameters.value.clone(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementsLinkText(
@ -1200,12 +1204,12 @@ impl Handler {
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::TagName => {
let cmd =
WebDriverScriptCommand::FindElementsTagName(parameters.value.clone(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
_ => {
return Err(WebDriverError::new(
@ -1245,7 +1249,7 @@ impl Handler {
element.to_string(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementElementLinkText(
@ -1254,7 +1258,7 @@ impl Handler {
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::TagName => {
let cmd = WebDriverScriptCommand::FindElementElementTagName(
@ -1262,7 +1266,7 @@ impl Handler {
element.to_string(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
_ => {
return Err(WebDriverError::new(
@ -1304,7 +1308,7 @@ impl Handler {
element.to_string(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementElementsLinkText(
@ -1313,7 +1317,7 @@ impl Handler {
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::TagName => {
let cmd = WebDriverScriptCommand::FindElementElementsTagName(
@ -1321,7 +1325,7 @@ impl Handler {
element.to_string(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
_ => {
return Err(WebDriverError::new(
@ -1364,7 +1368,7 @@ impl Handler {
shadow_root.to_string(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindShadowElementsLinkText(
@ -1373,7 +1377,7 @@ impl Handler {
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
LocatorStrategy::TagName => {
let cmd = WebDriverScriptCommand::FindShadowElementsTagName(
@ -1381,7 +1385,7 @@ impl Handler {
shadow_root.to_string(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
},
_ => {
return Err(WebDriverError::new(
@ -1432,7 +1436,7 @@ impl Handler {
fn handle_get_shadow_root(&self, element: WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetElementShadowRoot(element.to_string(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => {
let Some(value) = value else {
@ -1450,7 +1454,7 @@ impl Handler {
fn handle_element_rect(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetElementRect(element.to_string(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(rect) => {
let response = ElementRectResponse {
@ -1469,7 +1473,7 @@ impl Handler {
fn handle_element_text(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetElementText(element.to_string(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(
serde_json::to_value(value)?,
@ -1482,7 +1486,7 @@ impl Handler {
fn handle_active_element(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetActiveElement(sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
let value = wait_for_script_response(receiver)?
.map(|x| serde_json::to_value(WebElement(x)).unwrap());
// Step 4. If active element is a non-null element, return success
@ -1503,7 +1507,7 @@ impl Handler {
fn handle_computed_role(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetComputedRole(element.to_string(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(
serde_json::to_value(value)?,
@ -1515,7 +1519,7 @@ impl Handler {
fn handle_element_tag_name(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetElementTagName(element.to_string(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(
serde_json::to_value(value)?,
@ -1535,7 +1539,7 @@ impl Handler {
name.to_owned(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(
serde_json::to_value(value)?,
@ -1556,7 +1560,7 @@ impl Handler {
name.to_owned(),
sender,
);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(
@ -1574,7 +1578,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let cmd =
WebDriverScriptCommand::GetElementCSS(element.to_string(), name.to_owned(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(
serde_json::to_value(value)?,
@ -1586,7 +1590,7 @@ impl Handler {
fn handle_get_cookies(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetCookies(sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
let cookies = match wait_for_script_response(receiver)? {
Ok(cookies) => cookies,
Err(error) => return Err(WebDriverError::new(error, "")),
@ -1601,7 +1605,7 @@ impl Handler {
fn handle_get_cookie(&self, name: String) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetCookie(name, sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
let cookies = match wait_for_script_response(receiver)? {
Ok(cookies) => cookies,
Err(error) => return Err(WebDriverError::new(error, "")),
@ -1635,7 +1639,7 @@ impl Handler {
};
let cmd = WebDriverScriptCommand::AddCookie(cookie_builder.build(), sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(_) => Ok(WebDriverResponse::Void),
Err(error) => Err(WebDriverError::new(error, "")),
@ -1645,7 +1649,7 @@ impl Handler {
fn handle_delete_cookie(&self, name: String) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::DeleteCookie(name, sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(_) => Ok(WebDriverResponse::Void),
Err(error) => Err(WebDriverError::new(error, "")),
@ -1655,7 +1659,7 @@ impl Handler {
fn handle_delete_cookies(&self) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::DeleteCookies(sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(_) => Ok(WebDriverResponse::Void),
Err(error) => Err(WebDriverError::new(error, "")),
@ -1712,7 +1716,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetPageSource(sender);
self.browsing_context_script_command(cmd)?;
self.browsing_context_script_command::<true>(cmd)?;
match wait_for_script_response(receiver)? {
Ok(source) => Ok(WebDriverResponse::Generic(ValueResponse(
@ -1802,7 +1806,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let command = WebDriverScriptCommand::ExecuteScript(script, sender);
self.browsing_context_script_command(command)?;
self.browsing_context_script_command::<true>(command)?;
let result = wait_for_script_response(receiver)?;
self.postprocess_js_result(result)
}
@ -1846,7 +1850,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let command = WebDriverScriptCommand::ExecuteAsyncScript(script, sender);
self.browsing_context_script_command(command)?;
self.browsing_context_script_command::<true>(command)?;
let result = wait_for_script_response(receiver)?;
self.postprocess_js_result(result)
}
@ -1933,7 +1937,7 @@ impl Handler {
// Steps 1 - 7
let command = WebDriverScriptCommand::ElementClick(element.to_string(), sender);
self.browsing_context_script_command(command)?;
self.browsing_context_script_command::<true>(command)?;
match wait_for_script_response(receiver)? {
Ok(element_id) => match element_id {
@ -2086,7 +2090,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let command = WebDriverScriptCommand::GetBoundingClientRect(element.to_string(), sender);
self.browsing_context_script_command(command)?;
self.browsing_context_script_command::<true>(command)?;
match wait_for_script_response(receiver)? {
Ok(rect) => {