diff options
author | Delan Azabani <dazabani@igalia.com> | 2025-02-26 19:07:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-26 11:07:05 +0000 |
commit | b4e2037dbe0bb46999e94680294e2416f6035b0b (patch) | |
tree | 6f9a49fabc8d3e890abae87291e068a1bbdc43eb /components/script/dom/windowproxy.rs | |
parent | 3d459badc0e59ac3a35d6f8502ad35ecb1b7af68 (diff) | |
download | servo-b4e2037dbe0bb46999e94680294e2416f6035b0b.tar.gz servo-b4e2037dbe0bb46999e94680294e2416f6035b0b.zip |
Make auxiliary webviews exist in the constellation immediately (#35672)
To allow embedders to interact with webviews as soon as they are
created, we need to ensure that they exist in both the compositor and
the constellation before those interactions happen. #35662 does this
for the compositor, while this patch does this for the constellation.
When a webview opens another webview (via <a target>, <form target>,
window.open(), etc), the embedder creates an “auxiliary” webview,
which previously went as follows:
- script create_auxiliary_browsing_context
- libservo AllowOpeningWebView
- embedder request_open_auxiliary_webview (→ constellation FocusWebView)
- script create_auxiliary_browsing_context
- constellation ScriptNewAuxiliary
In that model, the constellation may receive FocusWebView before it
receives ScriptNewAuxiliary. Now they are created as follows:
- script create_auxiliary_browsing_context
- constellation CreateAuxiliaryWebView
- libservo AllowOpeningWebView
- embedder request_open_auxiliary_webview (→ constellation FocusWebView)
- constellation CreateAuxiliaryWebView
- script create_auxiliary_browsing_context
Since these messages are all synchronous and the constellation will
have set up the webview before handling any new messages, the webview
will always exist by the time we handle the embedder’s FocusWebView.
Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/script/dom/windowproxy.rs')
-rw-r--r-- | components/script/dom/windowproxy.rs | 106 |
1 files changed, 48 insertions, 58 deletions
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<DomRoot<WindowProxy>> { - 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 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 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 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); + } + if noopener { + new_window_proxy.disown(); } - None + Some(new_window_proxy) } /// <https://html.spec.whatwg.org/multipage/#delaying-load-events-mode> |