diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 003bdceda3f..65453eb7403 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -138,14 +138,14 @@ use net_traits::{self, IpcSend, ReferrerPolicy, ResourceThreads}; use profile_traits::{mem, time}; use script_layout_interface::{LayoutFactory, ScriptThreadFactory}; use script_traits::{ - AnimationState, AnimationTickType, AuxiliaryBrowsingContextLoadInfo, BroadcastMsg, - ConstellationInputEvent, DiscardBrowsingContext, DocumentActivity, DocumentState, - IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, IFrameSizeMsg, Job, - LayoutMsg as FromLayoutMsg, LoadData, LoadOrigin, LogEntry, MessagePortMsg, - NavigationHistoryBehavior, PortMessageTask, SWManagerMsg, SWManagerSenders, - ScriptMsg as FromScriptMsg, ScriptThreadMessage, ScriptToConstellationChan, - ServiceWorkerManagerFactory, ServiceWorkerMsg, StructuredSerializedData, - UpdatePipelineIdReason, WindowSizeData, WindowSizeType, + AnimationState, AnimationTickType, AuxiliaryWebViewCreationRequest, + AuxiliaryWebViewCreationResponse, BroadcastMsg, ConstellationInputEvent, + DiscardBrowsingContext, DocumentActivity, DocumentState, IFrameLoadInfo, + IFrameLoadInfoWithData, IFrameSandboxState, IFrameSizeMsg, Job, LayoutMsg as FromLayoutMsg, + LoadData, LoadOrigin, LogEntry, MessagePortMsg, NavigationHistoryBehavior, PortMessageTask, + SWManagerMsg, SWManagerSenders, ScriptMsg as FromScriptMsg, ScriptThreadMessage, + ScriptToConstellationChan, ServiceWorkerManagerFactory, ServiceWorkerMsg, + StructuredSerializedData, UpdatePipelineIdReason, WindowSizeData, WindowSizeType, }; use serde::{Deserialize, Serialize}; use servo_config::{opts, pref}; @@ -1538,7 +1538,7 @@ where FromScriptMsg::ScriptNewIFrame(load_info) => { self.handle_script_new_iframe(load_info); }, - FromScriptMsg::ScriptNewAuxiliary(load_info) => { + FromScriptMsg::CreateAuxiliaryWebView(load_info) => { self.handle_script_new_auxiliary(load_info); }, FromScriptMsg::ChangeRunningAnimationsState(animation_state) => { @@ -3324,15 +3324,35 @@ where feature = "tracing", tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace") )] - fn handle_script_new_auxiliary(&mut self, load_info: AuxiliaryBrowsingContextLoadInfo) { - let AuxiliaryBrowsingContextLoadInfo { + fn handle_script_new_auxiliary(&mut self, load_info: AuxiliaryWebViewCreationRequest) { + let AuxiliaryWebViewCreationRequest { load_data, + opener_webview_id, opener_pipeline_id, - new_top_level_browsing_context_id, - new_browsing_context_id, - new_pipeline_id, + response_sender, } = load_info; + let (webview_id_sender, webview_id_receiver) = match ipc::channel() { + Ok(result) => result, + Err(error) => { + warn!("Failed to create channel: {error:?}"); + let _ = response_sender.send(None); + return; + }, + }; + self.embedder_proxy.send(EmbedderMsg::AllowOpeningWebView( + opener_webview_id, + webview_id_sender, + )); + let new_webview_id = match webview_id_receiver.recv() { + Ok(Some(webview_id)) => webview_id, + Ok(None) | Err(_) => { + let _ = response_sender.send(None); + return; + }, + }; + let new_browsing_context_id = BrowsingContextId::from(new_webview_id); + let (script_sender, opener_browsing_context_id) = match self.pipelines.get(&opener_pipeline_id) { Some(pipeline) => (pipeline.event_loop.clone(), pipeline.browsing_context_id), @@ -3353,21 +3373,26 @@ where ); }, }; + let new_pipeline_id = PipelineId::new(); let pipeline = Pipeline::new( new_pipeline_id, new_browsing_context_id, - new_top_level_browsing_context_id, + new_webview_id, Some(opener_browsing_context_id), script_sender, self.compositor_proxy.clone(), is_opener_throttled, load_data, ); + let _ = response_sender.send(Some(AuxiliaryWebViewCreationResponse { + new_webview_id, + new_pipeline_id, + })); assert!(!self.pipelines.contains_key(&new_pipeline_id)); self.pipelines.insert(new_pipeline_id, pipeline); self.webviews.add( - new_top_level_browsing_context_id, + new_webview_id, WebView { focused_browsing_context_id: new_browsing_context_id, session_history: JointSessionHistory::new(), @@ -3391,10 +3416,10 @@ where }; bc_group .top_level_browsing_context_set - .insert(new_top_level_browsing_context_id); + .insert(new_webview_id); self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: new_top_level_browsing_context_id, + top_level_browsing_context_id: new_webview_id, browsing_context_id: new_browsing_context_id, new_pipeline_id, replace: None, diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs index 30d4981fe9d..31c798758c4 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -167,7 +167,7 @@ mod from_script { Self::SetThrottledComplete(..) => target!("SetThrottledComplete"), Self::ScriptLoadedURLInIFrame(..) => target!("ScriptLoadedURLInIFrame"), Self::ScriptNewIFrame(..) => target!("ScriptNewIFrame"), - Self::ScriptNewAuxiliary(..) => target!("ScriptNewAuxiliary"), + Self::CreateAuxiliaryWebView(..) => target!("ScriptNewAuxiliary"), Self::ActivateDocument => target!("ActivateDocument"), Self::SetDocumentState(..) => target!("SetDocumentState"), Self::SetLayoutEpoch(..) => target!("SetLayoutEpoch"), diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs index 493947e4185..09a3ea942d9 100644 --- a/components/script/dom/windowproxy.rs +++ b/components/script/dom/windowproxy.rs @@ -7,7 +7,6 @@ use std::ptr; use base::id::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId}; use dom_struct::dom_struct; -use embedder_traits::EmbedderMsg; use html5ever::local_name; use indexmap::map::IndexMap; use ipc_channel::ipc; @@ -31,7 +30,7 @@ use js::JSCLASS_IS_GLOBAL; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use net_traits::request::Referrer; use script_traits::{ - AuxiliaryBrowsingContextLoadInfo, LoadData, LoadOrigin, NavigationHistoryBehavior, + AuxiliaryWebViewCreationRequest, LoadData, LoadOrigin, NavigationHistoryBehavior, NewLayoutInfo, ScriptMsg, }; use serde::{Deserialize, Serialize}; @@ -285,70 +284,61 @@ impl WindowProxy { name: DOMString, noopener: bool, ) -> Option> { - let (chan, port) = ipc::channel().unwrap(); + let (response_sender, response_receiver) = ipc::channel().unwrap(); let window = self .currently_active .get() .and_then(ScriptThread::find_document) .map(|doc| DomRoot::from_ref(doc.window())) .unwrap(); - let msg = EmbedderMsg::AllowOpeningWebView(window.webview_id(), chan); - window.send_to_embedder(msg); - if let Some(new_top_level_browsing_context_id) = port.recv().unwrap() { - let new_browsing_context_id = - BrowsingContextId::from(new_top_level_browsing_context_id); - let new_pipeline_id = PipelineId::new(); - let document = self - .currently_active - .get() - .and_then(ScriptThread::find_document) - .expect("A WindowProxy creating an auxiliary to have an active document"); - let blank_url = ServoUrl::parse("about:blank").ok().unwrap(); - let load_data = LoadData::new( - LoadOrigin::Script(document.origin().immutable().clone()), - blank_url, - None, - document.global().get_referrer(), - document.get_referrer_policy(), - None, // Doesn't inherit secure context - None, - ); - let load_info = AuxiliaryBrowsingContextLoadInfo { - load_data: load_data.clone(), - opener_pipeline_id: self.currently_active.get().unwrap(), - new_browsing_context_id, - new_top_level_browsing_context_id, - new_pipeline_id, - }; + let document = self + .currently_active + .get() + .and_then(ScriptThread::find_document) + .expect("A WindowProxy creating an auxiliary to have an active document"); + let blank_url = ServoUrl::parse("about:blank").ok().unwrap(); + let load_data = LoadData::new( + LoadOrigin::Script(document.origin().immutable().clone()), + blank_url, + None, + document.global().get_referrer(), + document.get_referrer_policy(), + None, // Doesn't inherit secure context + None, + ); + let load_info = AuxiliaryWebViewCreationRequest { + load_data: load_data.clone(), + opener_webview_id: window.webview_id(), + opener_pipeline_id: self.currently_active.get().unwrap(), + response_sender, + }; + let constellation_msg = ScriptMsg::CreateAuxiliaryWebView(load_info); + window.send_to_constellation(constellation_msg); - let new_layout_info = NewLayoutInfo { - parent_info: None, - new_pipeline_id, - browsing_context_id: new_browsing_context_id, - top_level_browsing_context_id: new_top_level_browsing_context_id, - opener: Some(self.browsing_context_id), - load_data, - window_size: window.window_size(), - }; - let constellation_msg = ScriptMsg::ScriptNewAuxiliary(load_info); - window.send_to_constellation(constellation_msg); - ScriptThread::process_attach_layout(new_layout_info, document.origin().clone()); - // TODO: if noopener is false, copy the sessionStorage storage area of the creator origin. - // See step 14 of https://html.spec.whatwg.org/multipage/#creating-a-new-browsing-context - let auxiliary = - ScriptThread::find_document(new_pipeline_id).and_then(|doc| doc.browsing_context()); - if let Some(proxy) = auxiliary { - if name.to_lowercase() != "_blank" { - proxy.set_name(name); - } - if noopener { - proxy.disown(); - } - return Some(proxy); - } + let response = response_receiver.recv().unwrap()?; + let new_browsing_context_id = BrowsingContextId::from(response.new_webview_id); + let new_layout_info = NewLayoutInfo { + parent_info: None, + new_pipeline_id: response.new_pipeline_id, + browsing_context_id: new_browsing_context_id, + top_level_browsing_context_id: response.new_webview_id, + opener: Some(self.browsing_context_id), + load_data, + window_size: window.window_size(), + }; + ScriptThread::process_attach_layout(new_layout_info, document.origin().clone()); + // TODO: if noopener is false, copy the sessionStorage storage area of the creator origin. + // See step 14 of https://html.spec.whatwg.org/multipage/#creating-a-new-browsing-context + let new_window_proxy = ScriptThread::find_document(response.new_pipeline_id) + .and_then(|doc| doc.browsing_context())?; + if name.to_lowercase() != "_blank" { + new_window_proxy.set_name(name); } - None + if noopener { + new_window_proxy.disown(); + } + Some(new_window_proxy) } /// diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs index f022f4eeb35..7ccee71153e 100644 --- a/components/shared/script/lib.rs +++ b/components/shared/script/lib.rs @@ -22,7 +22,7 @@ use background_hang_monitor_api::BackgroundHangMonitorRegister; use base::cross_process_instant::CrossProcessInstant; use base::id::{ BlobId, BrowsingContextId, HistoryStateId, MessagePortId, PipelineId, PipelineNamespaceId, - TopLevelBrowsingContextId, + TopLevelBrowsingContextId, WebViewId, }; use base::Epoch; use bitflags::bitflags; @@ -561,16 +561,23 @@ pub enum IFrameSandboxState { /// Specifies the information required to load an auxiliary browsing context. #[derive(Debug, Deserialize, Serialize)] -pub struct AuxiliaryBrowsingContextLoadInfo { +pub struct AuxiliaryWebViewCreationRequest { /// Load data containing the url to load pub load_data: LoadData, + /// The webview that caused this request. + pub opener_webview_id: WebViewId, /// The pipeline opener browsing context. pub opener_pipeline_id: PipelineId, - /// The new top-level ID for the auxiliary. - pub new_top_level_browsing_context_id: TopLevelBrowsingContextId, - /// The new browsing context ID. - pub new_browsing_context_id: BrowsingContextId, - /// The new pipeline ID for the auxiliary. + /// Sender for the constellation’s response to our request. + pub response_sender: IpcSender>, +} + +/// Constellation’s response to auxiliary browsing context creation requests. +#[derive(Debug, Deserialize, Serialize)] +pub struct AuxiliaryWebViewCreationResponse { + /// The new webview ID. + pub new_webview_id: WebViewId, + /// The new pipeline ID. pub new_pipeline_id: PipelineId, } diff --git a/components/shared/script/script_msg.rs b/components/shared/script/script_msg.rs index 9321b623cbd..42258f6f155 100644 --- a/components/shared/script/script_msg.rs +++ b/components/shared/script/script_msg.rs @@ -28,7 +28,7 @@ use style_traits::CSSPixel; use webgpu::{wgc, WebGPU, WebGPUResponse}; use crate::{ - AnimationState, AuxiliaryBrowsingContextLoadInfo, BroadcastMsg, DocumentState, + AnimationState, AuxiliaryWebViewCreationRequest, BroadcastMsg, DocumentState, IFrameLoadInfoWithData, LoadData, MessagePortMsg, NavigationHistoryBehavior, PortMessageTask, StructuredSerializedData, WindowSizeType, WorkerGlobalScopeInit, WorkerScriptLoadOrigin, }; @@ -207,7 +207,7 @@ pub enum ScriptMsg { /// A load of the initial `about:blank` has been completed in an IFrame. ScriptNewIFrame(IFrameLoadInfoWithData), /// Script has opened a new auxiliary browsing context. - ScriptNewAuxiliary(AuxiliaryBrowsingContextLoadInfo), + CreateAuxiliaryWebView(AuxiliaryWebViewCreationRequest), /// Mark a new document as active ActivateDocument, /// Set the document state for a pipeline (used by screenshot / reftests) @@ -289,7 +289,7 @@ impl fmt::Debug for ScriptMsg { SetThrottledComplete(..) => "SetThrottledComplete", ScriptLoadedURLInIFrame(..) => "ScriptLoadedURLInIFrame", ScriptNewIFrame(..) => "ScriptNewIFrame", - ScriptNewAuxiliary(..) => "ScriptNewAuxiliary", + CreateAuxiliaryWebView(..) => "ScriptNewAuxiliary", ActivateDocument => "ActivateDocument", SetDocumentState(..) => "SetDocumentState", SetLayoutEpoch(..) => "SetLayoutEpoch",