Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions moli-core/src/page/renderer_command_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,10 @@ impl Page {
self.start_page_command(RendererPageCommand::LayoutMetrics)
}

pub fn start_published_layout_metrics(&self) -> Result<PendingPageCommand> {
self.start_page_command(RendererPageCommand::PublishLayoutMetrics)
}

pub fn finish_layout_metrics(
&mut self,
completion: CompletedPageCommand,
Expand Down
18 changes: 17 additions & 1 deletion moli-core/src/runtime/navigation_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use moli_renderer_v8::{
RendererBrowserContextRuntime, RendererBrowserContextRuntimeOwner,
RendererBrowserContextRuntimeOwnerAccess, RendererDocumentReplacement,
RendererReservedServiceWorkerClient, RendererServiceWorkerMainResourceFetch,
RendererWebStorageHandles, SharedStorageBucketStore, WeakIndexedDbManager,
RendererTopLevelBrowsingContextState, RendererWebStorageHandles, SharedStorageBucketStore,
WeakIndexedDbManager,
network::{
BrowserResourceRuntime, BrowserResourceRuntimeOwner, PageNetworkPolicy,
navigation::{DocumentFetchContextSeed, NavigationResourceLoader},
Expand Down Expand Up @@ -424,6 +425,7 @@ pub struct NavigationEngine {
js_runtime: JsRuntime,
resource_runtime: Option<BrowserResourceRuntime>,
browser_context_access: RendererBrowserContextRuntimeOwnerAccess,
top_level_browsing_context: RendererTopLevelBrowsingContextState,
document_activity: moli_page_types::DocumentActivity,
// Standalone engines share this last-drop owner. BrowserContext engines
// leave it empty and borrow only the context's weak, bound access.
Expand Down Expand Up @@ -453,6 +455,15 @@ impl Default for NavigationEngine {
}

impl NavigationEngine {
pub fn top_level_window_name(&self) -> String {
self.top_level_browsing_context.window_name()
}

pub fn set_top_level_window_name(&self, value: impl Into<String>) {
self.top_level_browsing_context
.set_window_name(value.into());
}

/// Reserves a renderer Page identity before the corresponding creation
/// command is enqueued.
///
Expand Down Expand Up @@ -583,6 +594,7 @@ impl NavigationEngine {
js_runtime,
resource_runtime: Some(resource_runtime),
browser_context_access,
top_level_browsing_context: RendererTopLevelBrowsingContextState::default(),
document_activity: Default::default(),
standalone_lifetime_owner,
})
Expand Down Expand Up @@ -634,6 +646,7 @@ impl NavigationEngine {
js_runtime: renderer_owner_source.js_runtime.clone(),
resource_runtime: Some(resource_runtime),
browser_context_access: renderer_owner_source.browser_context_access.clone(),
top_level_browsing_context: RendererTopLevelBrowsingContextState::default(),
document_activity: Default::default(),
standalone_lifetime_owner: renderer_owner_source.standalone_lifetime_owner.clone(),
})
Expand Down Expand Up @@ -1535,6 +1548,7 @@ impl NavigationEngine {
top_level_storage_key,
moli_renderer_v8::RendererTopLevelNavigationDispatch::DelegateToBrowser,
moli_renderer_v8::RendererDocumentOptions {
top_level_browsing_context: self.top_level_browsing_context.clone(),
indexed_db_manager,
storage_bucket_store,
document_start_scripts,
Expand Down Expand Up @@ -1815,6 +1829,7 @@ impl NavigationEngine {
reserved_service_worker_client,
None,
moli_renderer_v8::RendererDocumentOptions {
top_level_browsing_context: self.top_level_browsing_context.clone(),
indexed_db_manager,
storage_bucket_store,
document_start_scripts,
Expand Down Expand Up @@ -2068,6 +2083,7 @@ impl NavigationEngine {
web_storage,
options.response_body,
moli_renderer_v8::RendererDocumentOptions {
top_level_browsing_context: self.top_level_browsing_context.clone(),
indexed_db_manager,
storage_bucket_store,
document_start_scripts: options.document_start_scripts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2581,3 +2581,74 @@ async fn webdriver_classic_new_window_user_prompt_behavior_matches_chromium_wpt(
.await;
}
}
#[tokio::test]
async fn webdriver_classic_named_popup_does_not_reuse_an_independent_tab() {
let app = build_router(test_state());
let session = classic_request_json(app.clone(), Method::POST, "/session").await;
let session_id = session["value"]["sessionId"]
.as_str()
.expect("classic session id");
let window_path = format!("/session/{session_id}/window");
let handles_path = format!("/session/{session_id}/window/handles");
let execute_path = format!("/session/{session_id}/execute/sync");

let original = classic_request_json(app.clone(), Method::GET, &window_path).await;
let original = original["value"]
.as_str()
.expect("original window handle")
.to_owned();
let named = classic_request_json_with_body(
app.clone(),
Method::POST,
&execute_path,
json!({
"script": "window.name = 'independent-report'; return window.name;",
"args": []
}),
)
.await;
assert_eq!(named, json!({ "value": "independent-report" }));

let independent = classic_request_json_with_body(
app.clone(),
Method::POST,
&format!("/session/{session_id}/window/new"),
json!({ "type": "tab" }),
)
.await;
let independent = independent["value"]["handle"]
.as_str()
.expect("independent tab handle")
.to_owned();
let switched = classic_request_json_with_body(
app.clone(),
Method::POST,
&window_path,
json!({ "handle": independent }),
)
.await;
assert_eq!(switched, json!({ "value": null }));

let opened = classic_request_json_with_body(
app.clone(),
Method::POST,
&execute_path,
json!({
"script": "const popup = window.open('about:blank#independent-popup', 'independent-report'); return popup !== null;",
"args": []
}),
)
.await;
assert_eq!(opened, json!({ "value": true }));
let handles = classic_request_json(app.clone(), Method::GET, &handles_path).await;
let handles = handles["value"].as_array().expect("window handles");
assert_eq!(
handles.len(),
3,
"an unrelated same-name tab must not be selected as the popup target: {handles:?}"
);
assert!(handles.contains(&json!(original)));
assert!(handles.contains(&json!(independent)));

let _ = classic_request_json(app, Method::DELETE, &format!("/session/{session_id}")).await;
}
1 change: 1 addition & 0 deletions moli-protocol-server/src/protocol_server/webdriver_bidi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,7 @@ async fn bidi_input_viewport_bounds(
target_id: Some(DevToolsTargetId::from(context_id)),
browser_context_id: None,
},
publish_layout: false,
});
match scheduler
.execute_devtools_command_with_protocol_messages(command)
Expand Down
1 change: 1 addition & 0 deletions moli-protocol-webdriver-classic/src/commands/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub fn create_initial_target_command(context: &ClassicDevToolsCommandContext) ->
pub fn layout_metrics_command(context: &ClassicDevToolsCommandContext) -> DevToolsCommand {
DevToolsCommand::GetLayoutMetrics(DevToolsGetLayoutMetricsCommand {
context: context.command_context(),
publish_layout: false,
})
}

Expand Down
1 change: 1 addition & 0 deletions moli-protocol/src/conn/dispatch_tests/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,7 @@ async fn devtools_command_executes_context_viewport_override() {
target_id: Some(target_id),
..context
},
publish_layout: false,
},
))
.await
Expand Down
8 changes: 7 additions & 1 deletion moli-protocol/src/conn/page_state/fetch_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl BrowserContext {
}

pub(crate) fn insert_page_target_host(&mut self, mut host: PageTargetHost) -> bool {
let target_id = host.target_id().to_owned();
if self.page_targets.is_empty() {
host.document_cookie_manager_surface =
self.default_document_cookie_manager_surface.clone();
Expand All @@ -69,7 +70,12 @@ impl BrowserContext {
let engine = self.new_page_navigation_engine(config);
host.install_navigation_engine(engine);
}
self.page_targets.insert(host)
let inserted = self.page_targets.insert(host);
if inserted {
self.target_browsing_context_group_ids
.insert(target_id.clone(), target_id);
}
inserted
}

#[cfg(test)]
Expand Down
Loading
Loading