///|
/// Whether current context has an inline handler that closes window.
fn BidiProtocol::context_has_window_close_handler(
self : BidiProtocol,
ctx_id : String,
attribute_name : String,
) -> Bool {
match self.manager.get_session(ctx_id) {
Some(session) => {
let doc = session.get_tree().get_document()
let selector = "[" + attribute_name + "]"
match session.get_tree().query_selector_all(doc, selector) {
Ok(nodes) =>
for node in nodes {
match session.get_tree().get_attribute(node, attribute_name) {
Ok(Some(attr)) => if attr.contains("window.close") { return true }
_ => ()
}
}
Err(_) => ()
}
false
}
None => false
}
}
///|
/// Whether current context has an inline keydown handler that closes window.
fn BidiProtocol::context_has_window_close_onkeydown(
self : BidiProtocol,
ctx_id : String,
) -> Bool {
self.context_has_window_close_handler(ctx_id, "onkeydown")
}
///|
/// Whether current context has an inline mousedown handler that closes window.
fn BidiProtocol::context_has_window_close_onmousedown(
self : BidiProtocol,
ctx_id : String,
) -> Bool {
self.context_has_window_close_handler(ctx_id, "onmousedown")
}
///|
/// Whether current context has an inline pointerdown handler that closes window.
fn BidiProtocol::context_has_window_close_onpointerdown(
self : BidiProtocol,
ctx_id : String,
) -> Bool {
self.context_has_window_close_handler(ctx_id, "onpointerdown")
}
///|
/// Navigate current context when inline event handler assigns window.location.
fn BidiProtocol::handle_inline_attribute_navigation(
self : BidiProtocol,
ctx_id : String,
attribute_name : String,
) -> Bool {
set_runtime_context(ctx_id)
self.apply_effective_viewport_to_runtime_context(ctx_id, ctx_id)
let destination = get_runtime_inline_navigation_url(attribute_name).unwrap_or(
"",
)
if destination == "" {
return false
}
match self.manager.get_session(ctx_id) {
Some(session) =>
match session.navigate_to(destination) {
Ok(_) => ()
Err(_) => ()
}
None => return false
}
reset_runtime_event_buffers(ctx_id)
self.load_data_url_content(ctx_id, destination)
self.drop_child_contexts(ctx_id, true)
self.refresh_child_contexts_from_iframes(ctx_id)
// Full navigation tears down all owned realms (window/sandbox/worker).
self.remove_all_realms_for_context(ctx_id)
let window_realm_id = self.assign_new_realm(ctx_id)
self.emit_default_realm(ctx_id)
self.emit_worker_realms_from_scripts(ctx_id, window_realm_id)
let nav_id = self.next_navigation_id.to_string()
self.next_navigation_id += 1
self.emit_navigation_events(ctx_id, destination, nav_id)
true
}
///|
/// Emit navigation events when click target resolves to an anchor href.
fn BidiProtocol::handle_pointer_click_navigation(
self : BidiProtocol,
ctx_id : String,
target_shared : String,
x : Double,
y : Double,
) -> Unit {
let shared_href = get_runtime_shared_node_href(target_shared).unwrap_or("")
let clicked_href = get_runtime_last_click_href().unwrap_or("")
let point_href = get_runtime_href_at_point(x, y).unwrap_or("")
let destination = if shared_href != "" {
shared_href
} else if clicked_href != "" {
clicked_href
} else if point_href != "" {
point_href
} else {
return
}
if destination == "" {
return
}
match self.manager.get_session(ctx_id) {
Some(session) =>
match session.navigate_to(destination) {
Ok(_) => ()
Err(_) => ()
}
None => ()
}
self.load_data_url_content(ctx_id, destination)
let nav_id = self.next_navigation_id.to_string()
self.next_navigation_id += 1
self.emit_navigation_events(ctx_id, destination, nav_id)
// Push the destination as a synthetic-navigation marker so the
// adapter's `flushPendingNavigation` picks it up on the next
// `script.evaluate` boundary and mirrors it onto `page.url()`.
// The shim `click()` path doesn't run for `input.performActions`
// pointer simulation, so without this `page.click(selector)`
// would leave `page.url()` stale even after the server-side
// session URL advanced. (#208)
push_synthetic_navigation(destination)
}