Include WebViewId into EmbedderMsg variants where possible (#35211)

`EmbedderMsg` was previously paired with an implicit
`Option<WebViewId>`, even though almost all variants were either always
`Some` or always `None`, depending on whether there was a `WebView
involved.

This patch adds the `WebViewId` to as many `EmbedderMsg` variants as
possible, so we can call their associated `WebView` delegate methods
without needing to check and unwrap the `Option`. In many cases, this
required more changes to plumb through the `WebViewId`.

Notably, all `Request`s now explicitly need a `WebView` or not, in order
to ensure that it is passed when appropriate.

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Delan Azabani 2025-01-30 19:15:35 +08:00 committed by GitHub
parent 9eeb602f7a
commit 5e9de2cb61
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
70 changed files with 809 additions and 753 deletions

2
Cargo.lock generated
View file

@ -503,6 +503,7 @@ dependencies = [
name = "bluetooth" name = "bluetooth"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"base",
"bitflags 2.8.0", "bitflags 2.8.0",
"bluetooth_traits", "bluetooth_traits",
"blurdroid", "blurdroid",
@ -521,6 +522,7 @@ dependencies = [
name = "bluetooth_traits" name = "bluetooth_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"base",
"embedder_traits", "embedder_traits",
"ipc-channel", "ipc-channel",
"regex", "regex",

View file

@ -12,6 +12,7 @@ name = "bluetooth"
path = "lib.rs" path = "lib.rs"
[dependencies] [dependencies]
base = { workspace = true }
bitflags = { workspace = true } bitflags = { workspace = true }
bluetooth_traits = { workspace = true } bluetooth_traits = { workspace = true }
blurmock = { version = "0.1.2", optional = true } blurmock = { version = "0.1.2", optional = true }

View file

@ -19,6 +19,7 @@ use std::string::String;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use base::id::WebViewId;
use bitflags::bitflags; use bitflags::bitflags;
use bluetooth_traits::blocklist::{uuid_is_blocklisted, Blocklist}; use bluetooth_traits::blocklist::{uuid_is_blocklisted, Blocklist};
use bluetooth_traits::scanfilter::{ use bluetooth_traits::scanfilter::{
@ -387,6 +388,7 @@ impl BluetoothManager {
fn select_device( fn select_device(
&mut self, &mut self,
webview_id: WebViewId,
devices: Vec<BluetoothDevice>, devices: Vec<BluetoothDevice>,
adapter: &BluetoothAdapter, adapter: &BluetoothAdapter,
) -> Option<String> { ) -> Option<String> {
@ -408,11 +410,12 @@ impl BluetoothManager {
} }
let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!"); let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!");
let msg = ( self.embedder_proxy
None, .send(EmbedderMsg::GetSelectedBluetoothDevice(
EmbedderMsg::GetSelectedBluetoothDevice(dialog_rows, ipc_sender), webview_id,
); dialog_rows,
self.embedder_proxy.send(msg); ipc_sender,
));
match ipc_receiver.recv() { match ipc_receiver.recv() {
Ok(result) => result, Ok(result) => result,
@ -628,7 +631,7 @@ impl BluetoothManager {
} }
// Step 9. // Step 9.
if let Some(address) = self.select_device(matched_devices, &adapter) { if let Some(address) = self.select_device(options.webview_id(), matched_devices, &adapter) {
let device_id = match self.address_to_id.get(&address) { let device_id = match self.address_to_id.get(&address) {
Some(id) => id.clone(), Some(id) => id.clone(),
None => return Err(BluetoothError::NotFound), None => return Err(BluetoothError::NotFound),

View file

@ -425,9 +425,21 @@ impl IOCompositor {
Some(cursor) if cursor != self.cursor => cursor, Some(cursor) if cursor != self.cursor => cursor,
_ => return, _ => return,
}; };
let Some(webview_id) = self
.pipeline_details(result.pipeline_id)
.pipeline
.as_ref()
.map(|composition_pipeline| composition_pipeline.top_level_browsing_context_id)
else {
warn!(
"Updating cursor for not-yet-rendered pipeline: {}",
result.pipeline_id
);
return;
};
self.cursor = cursor; self.cursor = cursor;
let msg = ConstellationMsg::SetCursor(cursor); let msg = ConstellationMsg::SetCursor(webview_id, cursor);
if let Err(e) = self.constellation_chan.send(msg) { if let Err(e) = self.constellation_chan.send(msg) {
warn!("Sending event to constellation failed ({:?}).", e); warn!("Sending event to constellation failed ({:?}).", e);
} }

View file

@ -7,7 +7,7 @@
use std::fmt::{Debug, Error, Formatter}; use std::fmt::{Debug, Error, Formatter};
use std::time::Duration; use std::time::Duration;
use base::id::{PipelineId, TopLevelBrowsingContextId}; use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId};
use embedder_traits::{ use embedder_traits::{
ClipboardEventType, EventLoopWaker, GamepadEvent, MediaSessionActionType, MouseButton, Theme, ClipboardEventType, EventLoopWaker, GamepadEvent, MediaSessionActionType, MouseButton, Theme,
TouchEventType, TouchId, TraversalDirection, WheelDelta, TouchEventType, TouchId, TraversalDirection, WheelDelta,
@ -83,7 +83,7 @@ pub enum EmbedderEvent {
/// Sent when the user exits from fullscreen mode /// Sent when the user exits from fullscreen mode
ExitFullScreen(TopLevelBrowsingContextId), ExitFullScreen(TopLevelBrowsingContextId),
/// Sent when a key input state changes /// Sent when a key input state changes
Keyboard(KeyboardEvent), Keyboard(WebViewId, KeyboardEvent),
/// Sent for IME composition updates /// Sent for IME composition updates
IMEComposition(CompositionEvent), IMEComposition(CompositionEvent),
/// Sent when Ctr+R/Apple+R is called to reload the current page. /// Sent when Ctr+R/Apple+R is called to reload the current page.

View file

@ -1232,9 +1232,9 @@ where
)] )]
fn handle_request_from_background_hang_monitor(&self, message: HangMonitorAlert) { fn handle_request_from_background_hang_monitor(&self, message: HangMonitorAlert) {
match message { match message {
HangMonitorAlert::Profile(bytes) => self HangMonitorAlert::Profile(bytes) => {
.embedder_proxy self.embedder_proxy.send(EmbedderMsg::ReportProfile(bytes))
.send((None, EmbedderMsg::ReportProfile(bytes))), },
HangMonitorAlert::Hang(hang) => { HangMonitorAlert::Hang(hang) => {
// TODO: In case of a permanent hang being reported, add a "kill script" workflow, // TODO: In case of a permanent hang being reported, add a "kill script" workflow,
// via the embedder? // via the embedder?
@ -1271,8 +1271,8 @@ where
FromCompositorMsg::GetFocusTopLevelBrowsingContext(resp_chan) => { FromCompositorMsg::GetFocusTopLevelBrowsingContext(resp_chan) => {
let _ = resp_chan.send(self.webviews.focused_webview().map(|(id, _)| id)); let _ = resp_chan.send(self.webviews.focused_webview().map(|(id, _)| id));
}, },
FromCompositorMsg::Keyboard(key_event) => { FromCompositorMsg::Keyboard(webview_id, key_event) => {
self.handle_key_msg(key_event); self.handle_key_msg(webview_id, key_event);
}, },
FromCompositorMsg::IMECompositionEvent(ime_event) => { FromCompositorMsg::IMECompositionEvent(ime_event) => {
self.handle_ime_msg(ime_event); self.handle_ime_msg(ime_event);
@ -1391,11 +1391,8 @@ where
// A top level browsing context is created and opened in both constellation and // A top level browsing context is created and opened in both constellation and
// compositor. // compositor.
FromCompositorMsg::WebViewOpened(top_level_browsing_context_id) => { FromCompositorMsg::WebViewOpened(top_level_browsing_context_id) => {
let msg = ( self.embedder_proxy
Some(top_level_browsing_context_id), .send(EmbedderMsg::WebViewOpened(top_level_browsing_context_id));
EmbedderMsg::WebViewOpened(top_level_browsing_context_id),
);
self.embedder_proxy.send(msg);
}, },
// Close a top level browsing context. // Close a top level browsing context.
FromCompositorMsg::CloseWebView(top_level_browsing_context_id) => { FromCompositorMsg::CloseWebView(top_level_browsing_context_id) => {
@ -1414,8 +1411,7 @@ where
}, },
FromCompositorMsg::BlurWebView => { FromCompositorMsg::BlurWebView => {
self.webviews.unfocus(); self.webviews.unfocus();
self.embedder_proxy self.embedder_proxy.send(EmbedderMsg::WebViewBlurred);
.send((None, EmbedderMsg::WebViewBlurred));
}, },
// Handle a forward or back request // Handle a forward or back request
FromCompositorMsg::TraverseHistory(top_level_browsing_context_id, direction) => { FromCompositorMsg::TraverseHistory(top_level_browsing_context_id, direction) => {
@ -1442,7 +1438,9 @@ where
FromCompositorMsg::ForwardEvent(destination_pipeline_id, event) => { FromCompositorMsg::ForwardEvent(destination_pipeline_id, event) => {
self.forward_event(destination_pipeline_id, event); self.forward_event(destination_pipeline_id, event);
}, },
FromCompositorMsg::SetCursor(cursor) => self.handle_set_cursor_msg(cursor), FromCompositorMsg::SetCursor(webview_id, cursor) => {
self.handle_set_cursor_msg(webview_id, cursor)
},
FromCompositorMsg::ToggleProfiler(rate, max_duration) => { FromCompositorMsg::ToggleProfiler(rate, max_duration) => {
for background_monitor_control_sender in &self.background_monitor_control_senders { for background_monitor_control_sender in &self.background_monitor_control_senders {
if let Err(e) = background_monitor_control_sender.send( if let Err(e) = background_monitor_control_sender.send(
@ -1469,7 +1467,7 @@ where
) )
.entered(); .entered();
self.embedder_proxy self.embedder_proxy
.send((None, EmbedderMsg::ReadyToPresent(webview_ids))); .send(EmbedderMsg::ReadyToPresent(webview_ids));
}, },
FromCompositorMsg::Gamepad(gamepad_event) => { FromCompositorMsg::Gamepad(gamepad_event) => {
self.handle_gamepad_msg(gamepad_event); self.handle_gamepad_msg(gamepad_event);
@ -1557,8 +1555,7 @@ where
self.handle_schedule_broadcast(source_pipeline_id, router_id, message); self.handle_schedule_broadcast(source_pipeline_id, router_id, message);
}, },
FromScriptMsg::ForwardToEmbedder(embedder_msg) => { FromScriptMsg::ForwardToEmbedder(embedder_msg) => {
self.embedder_proxy self.embedder_proxy.send(embedder_msg);
.send((Some(source_top_ctx_id), embedder_msg));
}, },
FromScriptMsg::PipelineExited => { FromScriptMsg::PipelineExited => {
self.handle_pipeline_exited(source_pipeline_id); self.handle_pipeline_exited(source_pipeline_id);
@ -1756,10 +1753,8 @@ where
}; };
} }
self.active_media_session = Some(pipeline_id); self.active_media_session = Some(pipeline_id);
self.embedder_proxy.send(( self.embedder_proxy
Some(source_top_ctx_id), .send(EmbedderMsg::MediaSessionEvent(source_top_ctx_id, event));
EmbedderMsg::MediaSessionEvent(event),
));
}, },
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
FromScriptMsg::RequestAdapter(response_sender, options, ids) => self FromScriptMsg::RequestAdapter(response_sender, options, ids) => self
@ -2793,9 +2788,10 @@ where
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
self.embedder_proxy.send(( self.embedder_proxy.send(EmbedderMsg::Panic(
Some(top_level_browsing_context_id), top_level_browsing_context_id,
EmbedderMsg::Panic(reason.clone(), backtrace.clone()), reason.clone(),
backtrace.clone(),
)); ));
let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { let browsing_context = match self.browsing_contexts.get(&browsing_context_id) {
@ -2874,10 +2870,8 @@ where
return warn!("{top_level_browsing_context_id}: FocusWebView on unknown top-level browsing context"); return warn!("{top_level_browsing_context_id}: FocusWebView on unknown top-level browsing context");
} }
self.webviews.focus(top_level_browsing_context_id); self.webviews.focus(top_level_browsing_context_id);
self.embedder_proxy.send(( self.embedder_proxy
Some(top_level_browsing_context_id), .send(EmbedderMsg::WebViewFocused(top_level_browsing_context_id));
EmbedderMsg::WebViewFocused(top_level_browsing_context_id),
));
} }
#[cfg_attr( #[cfg_attr(
@ -2950,9 +2944,9 @@ where
Some(pipeline) => pipeline, Some(pipeline) => pipeline,
}; };
self.embedder_proxy.send(( self.embedder_proxy.send(EmbedderMsg::EventDelivered(
Some(pipeline.top_level_browsing_context_id), pipeline.top_level_browsing_context_id,
EmbedderMsg::EventDelivered((&event).into()), (&event).into(),
)); ));
if let Err(e) = pipeline.event_loop.send(ConstellationControlMsg::SendEvent( if let Err(e) = pipeline.event_loop.send(ConstellationControlMsg::SendEvent(
@ -3052,16 +3046,13 @@ where
self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal); self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal);
if self.webviews.focused_webview().map(|(id, _)| id) == Some(top_level_browsing_context_id) if self.webviews.focused_webview().map(|(id, _)| id) == Some(top_level_browsing_context_id)
{ {
self.embedder_proxy self.embedder_proxy.send(EmbedderMsg::WebViewBlurred);
.send((None, EmbedderMsg::WebViewBlurred));
} }
self.webviews.remove(top_level_browsing_context_id); self.webviews.remove(top_level_browsing_context_id);
self.compositor_proxy self.compositor_proxy
.send(CompositorMsg::RemoveWebView(top_level_browsing_context_id)); .send(CompositorMsg::RemoveWebView(top_level_browsing_context_id));
self.embedder_proxy.send(( self.embedder_proxy
Some(top_level_browsing_context_id), .send(EmbedderMsg::WebViewClosed(top_level_browsing_context_id));
EmbedderMsg::WebViewClosed(top_level_browsing_context_id),
));
let Some(browsing_context) = browsing_context else { let Some(browsing_context) = browsing_context else {
return; return;
@ -3431,9 +3422,9 @@ where
feature = "tracing", feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace") tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
)] )]
fn handle_set_cursor_msg(&mut self, cursor: Cursor) { fn handle_set_cursor_msg(&mut self, webview_id: WebViewId, cursor: Cursor) {
self.embedder_proxy self.embedder_proxy
.send((None, EmbedderMsg::SetCursor(cursor))) .send(EmbedderMsg::SetCursor(webview_id, cursor));
} }
#[cfg_attr( #[cfg_attr(
@ -3499,11 +3490,12 @@ where
}, },
}; };
// Allow the embedder to handle the url itself // Allow the embedder to handle the url itself
let msg = ( self.embedder_proxy
Some(top_level_browsing_context_id), .send(EmbedderMsg::AllowNavigationRequest(
EmbedderMsg::AllowNavigationRequest(source_id, load_data.url.clone()), top_level_browsing_context_id,
); source_id,
self.embedder_proxy.send(msg); load_data.url.clone(),
));
} }
#[cfg_attr( #[cfg_attr(
@ -4215,15 +4207,14 @@ where
feature = "tracing", feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true)) tracing::instrument(skip_all, fields(servo_profiling = true))
)] )]
fn handle_key_msg(&mut self, event: KeyboardEvent) { fn handle_key_msg(&mut self, webview_id: WebViewId, event: KeyboardEvent) {
// Send to the focused browsing contexts' current pipeline. If it // Send to the focused browsing contexts' current pipeline. If it
// doesn't exist, fall back to sending to the compositor. // doesn't exist, fall back to sending to the compositor.
let focused_browsing_context_id = self let Some(webview) = self.webviews.get(webview_id) else {
.webviews warn!("Handling keyboard event for unknown webview: {webview_id}");
.focused_webview() return;
.map(|(_, webview)| webview.focused_browsing_context_id); };
match focused_browsing_context_id { let browsing_context_id = webview.focused_browsing_context_id;
Some(browsing_context_id) => {
let event = CompositorEvent::KeyboardEvent(event); let event = CompositorEvent::KeyboardEvent(event);
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
Some(ctx) => ctx.pipeline_id, Some(ctx) => ctx.pipeline_id,
@ -4244,13 +4235,6 @@ where
if let Err(e) = result { if let Err(e) = result {
self.handle_send_error(pipeline_id, e); self.handle_send_error(pipeline_id, e);
} }
},
None => {
warn!("No focused browsing context! Falling back to sending key to compositor");
let event = (None, EmbedderMsg::Keyboard(event));
self.embedder_proxy.send(event);
},
}
} }
#[cfg_attr( #[cfg_attr(
@ -4410,10 +4394,8 @@ where
// Focus the top-level browsing context. // Focus the top-level browsing context.
self.webviews.focus(top_level_browsing_context_id); self.webviews.focus(top_level_browsing_context_id);
self.embedder_proxy.send(( self.embedder_proxy
Some(top_level_browsing_context_id), .send(EmbedderMsg::WebViewFocused(top_level_browsing_context_id));
EmbedderMsg::WebViewFocused(top_level_browsing_context_id),
));
// Update the webviews focused browsing context. // Update the webviews focused browsing context.
match self.webviews.get_mut(top_level_browsing_context_id) { match self.webviews.get_mut(top_level_browsing_context_id) {
@ -4557,13 +4539,13 @@ where
WebDriverCommandMsg::CloseWebView(top_level_browsing_context_id) => { WebDriverCommandMsg::CloseWebView(top_level_browsing_context_id) => {
self.handle_close_top_level_browsing_context(top_level_browsing_context_id); self.handle_close_top_level_browsing_context(top_level_browsing_context_id);
}, },
WebDriverCommandMsg::NewWebView(sender, load_sender) => { WebDriverCommandMsg::NewWebView(webview_id, sender, load_sender) => {
let (chan, port) = match ipc::channel() { let (chan, port) = match ipc::channel() {
Ok(result) => result, Ok(result) => result,
Err(error) => return warn!("Failed to create channel: {error:?}"), Err(error) => return warn!("Failed to create channel: {error:?}"),
}; };
self.embedder_proxy self.embedder_proxy
.send((None, EmbedderMsg::AllowOpeningWebView(chan))); .send(EmbedderMsg::AllowOpeningWebView(webview_id, chan));
let webview_id = match port.recv() { let webview_id = match port.recv() {
Ok(Some(webview_id)) => webview_id, Ok(Some(webview_id)) => webview_id,
Ok(None) => return warn!("Embedder refused to allow opening webview"), Ok(None) => return warn!("Embedder refused to allow opening webview"),
@ -4588,10 +4570,8 @@ where
response_sender, response_sender,
) => { ) => {
self.webdriver.resize_channel = Some(response_sender); self.webdriver.resize_channel = Some(response_sender);
self.embedder_proxy.send(( self.embedder_proxy
Some(top_level_browsing_context_id), .send(EmbedderMsg::ResizeTo(top_level_browsing_context_id, size));
EmbedderMsg::ResizeTo(size),
));
}, },
WebDriverCommandMsg::LoadUrl( WebDriverCommandMsg::LoadUrl(
top_level_browsing_context_id, top_level_browsing_context_id,
@ -4833,11 +4813,11 @@ where
.rev() .rev()
.scan(current_url, &resolve_url_future), .scan(current_url, &resolve_url_future),
); );
let msg = ( self.embedder_proxy.send(EmbedderMsg::HistoryChanged(
Some(top_level_browsing_context_id), top_level_browsing_context_id,
EmbedderMsg::HistoryChanged(entries, current_index), entries,
); current_index,
self.embedder_proxy.send(msg); ));
} }
#[cfg_attr( #[cfg_attr(

View file

@ -217,16 +217,16 @@ mod from_script {
Self::WebResourceRequested(..) => target_variant!("WebResourceRequested"), Self::WebResourceRequested(..) => target_variant!("WebResourceRequested"),
Self::AllowUnload(..) => target_variant!("AllowUnload"), Self::AllowUnload(..) => target_variant!("AllowUnload"),
Self::Keyboard(..) => target_variant!("Keyboard"), Self::Keyboard(..) => target_variant!("Keyboard"),
Self::ClearClipboardContents => target_variant!("ClearClipboardContents"), Self::ClearClipboardContents(..) => target_variant!("ClearClipboardContents"),
Self::GetClipboardContents(..) => target_variant!("GetClipboardContents"), Self::GetClipboardContents(..) => target_variant!("GetClipboardContents"),
Self::SetClipboardContents(..) => target_variant!("SetClipboardContents"), Self::SetClipboardContents(..) => target_variant!("SetClipboardContents"),
Self::SetCursor(..) => target_variant!("SetCursor"), Self::SetCursor(..) => target_variant!("SetCursor"),
Self::NewFavicon(..) => target_variant!("NewFavicon"), Self::NewFavicon(..) => target_variant!("NewFavicon"),
Self::HeadParsed => target_variant!("HeadParsed"), Self::HeadParsed(..) => target_variant!("HeadParsed"),
Self::HistoryChanged(..) => target_variant!("HistoryChanged"), Self::HistoryChanged(..) => target_variant!("HistoryChanged"),
Self::SetFullscreenState(..) => target_variant!("SetFullscreenState"), Self::SetFullscreenState(..) => target_variant!("SetFullscreenState"),
Self::LoadStart => target_variant!("LoadStart"), Self::LoadStart(..) => target_variant!("LoadStart"),
Self::LoadComplete => target_variant!("LoadComplete"), Self::LoadComplete(..) => target_variant!("LoadComplete"),
Self::Panic(..) => target_variant!("Panic"), Self::Panic(..) => target_variant!("Panic"),
Self::GetSelectedBluetoothDevice(..) => { Self::GetSelectedBluetoothDevice(..) => {
target_variant!("GetSelectedBluetoothDevice") target_variant!("GetSelectedBluetoothDevice")
@ -234,11 +234,12 @@ mod from_script {
Self::SelectFiles(..) => target_variant!("SelectFiles"), Self::SelectFiles(..) => target_variant!("SelectFiles"),
Self::PromptPermission(..) => target_variant!("PromptPermission"), Self::PromptPermission(..) => target_variant!("PromptPermission"),
Self::ShowIME(..) => target_variant!("ShowIME"), Self::ShowIME(..) => target_variant!("ShowIME"),
Self::HideIME => target_variant!("HideIME"), Self::HideIME(..) => target_variant!("HideIME"),
Self::Shutdown => target_variant!("Shutdown"), Self::Shutdown => target_variant!("Shutdown"),
Self::ReportProfile(..) => target_variant!("ReportProfile"), Self::ReportProfile(..) => target_variant!("ReportProfile"),
Self::MediaSessionEvent(..) => target_variant!("MediaSessionEvent"), Self::MediaSessionEvent(..) => target_variant!("MediaSessionEvent"),
Self::OnDevtoolsStarted(..) => target_variant!("OnDevtoolsStarted"), Self::OnDevtoolsStarted(..) => target_variant!("OnDevtoolsStarted"),
Self::RequestDevtoolsConnection(..) => target_variant!("RequestDevtoolsConnection"),
Self::ReadyToPresent(..) => target_variant!("ReadyToPresent"), Self::ReadyToPresent(..) => target_variant!("ReadyToPresent"),
Self::EventDelivered(..) => target_variant!("EventDelivered"), Self::EventDelivered(..) => target_variant!("EventDelivered"),
Self::PlayGamepadHapticEffect(..) => target_variant!("PlayGamepadHapticEffect"), Self::PlayGamepadHapticEffect(..) => target_variant!("PlayGamepadHapticEffect"),

View file

@ -26,7 +26,7 @@ use devtools_traits::{
DevtoolsControlMsg, DevtoolsPageInfo, LogLevel, NavigationState, NetworkEvent, PageError, DevtoolsControlMsg, DevtoolsPageInfo, LogLevel, NavigationState, NetworkEvent, PageError,
ScriptToDevtoolsControlMsg, WorkerId, ScriptToDevtoolsControlMsg, WorkerId,
}; };
use embedder_traits::{EmbedderMsg, EmbedderProxy, PromptDefinition, PromptOrigin, PromptResult}; use embedder_traits::{EmbedderMsg, EmbedderProxy};
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use log::{debug, trace, warn}; use log::{debug, trace, warn};
use serde::Serialize; use serde::Serialize;
@ -154,7 +154,7 @@ fn run_server(
let token = format!("{:X}", servo_rand::ServoRng::default().next_u32()); let token = format!("{:X}", servo_rand::ServoRng::default().next_u32());
let port = bound.as_ref().map(|(_, port)| *port).ok_or(()); let port = bound.as_ref().map(|(_, port)| *port).ok_or(());
embedder.send((None, EmbedderMsg::OnDevtoolsStarted(port, token.clone()))); embedder.send(EmbedderMsg::OnDevtoolsStarted(port, token.clone()));
let listener = match bound { let listener = match bound {
Some((l, _)) => l, Some((l, _)) => l,
@ -762,10 +762,7 @@ fn allow_devtools_client(stream: &mut TcpStream, embedder: &EmbedderProxy, token
}; };
// No token found. Prompt user // No token found. Prompt user
let (embedder_sender, receiver) = ipc::channel().expect("Failed to create IPC channel!"); let (request_sender, request_receiver) = ipc::channel().expect("Failed to create IPC channel!");
let message = "Accept incoming devtools connection?".to_owned(); embedder.send(EmbedderMsg::RequestDevtoolsConnection(request_sender));
let prompt = PromptDefinition::YesNo(message, embedder_sender); request_receiver.recv().unwrap()
let msg = EmbedderMsg::Prompt(prompt, PromptOrigin::Trusted);
embedder.send((None, msg));
receiver.recv().unwrap() == PromptResult::Primary
} }

View file

@ -9,6 +9,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use app_units::Au; use app_units::Au;
use base::id::WebViewId;
use fnv::FnvHasher; use fnv::FnvHasher;
use fonts_traits::WebFontLoadFinishedCallback; use fonts_traits::WebFontLoadFinishedCallback;
use log::{debug, trace}; use log::{debug, trace};
@ -358,6 +359,7 @@ impl FontContext {
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct WebFontDownloadState { pub(crate) struct WebFontDownloadState {
webview_id: WebViewId,
pub(crate) css_font_face_descriptors: Arc<CSSFontFaceDescriptors>, pub(crate) css_font_face_descriptors: Arc<CSSFontFaceDescriptors>,
remaining_sources: Vec<Source>, remaining_sources: Vec<Source>,
finished_callback: WebFontLoadFinishedCallback, finished_callback: WebFontLoadFinishedCallback,
@ -369,6 +371,7 @@ pub(crate) struct WebFontDownloadState {
pub trait FontContextWebFontMethods { pub trait FontContextWebFontMethods {
fn add_all_web_fonts_from_stylesheet( fn add_all_web_fonts_from_stylesheet(
&self, &self,
webview_id: WebViewId,
stylesheet: &DocumentStyleSheet, stylesheet: &DocumentStyleSheet,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
device: &Device, device: &Device,
@ -382,6 +385,7 @@ pub trait FontContextWebFontMethods {
impl FontContextWebFontMethods for Arc<FontContext> { impl FontContextWebFontMethods for Arc<FontContext> {
fn add_all_web_fonts_from_stylesheet( fn add_all_web_fonts_from_stylesheet(
&self, &self,
webview_id: WebViewId,
stylesheet: &DocumentStyleSheet, stylesheet: &DocumentStyleSheet,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
device: &Device, device: &Device,
@ -441,6 +445,7 @@ impl FontContextWebFontMethods for Arc<FontContext> {
.handle_web_font_load_started_for_stylesheet(stylesheet); .handle_web_font_load_started_for_stylesheet(stylesheet);
self.process_next_web_font_source(WebFontDownloadState { self.process_next_web_font_source(WebFontDownloadState {
webview_id,
css_font_face_descriptors: Arc::new(rule.into()), css_font_face_descriptors: Arc::new(rule.into()),
remaining_sources: sources, remaining_sources: sources,
finished_callback: finished_callback.clone(), finished_callback: finished_callback.clone(),
@ -623,7 +628,11 @@ impl RemoteWebFontDownloader {
}; };
// FIXME: This shouldn't use NoReferrer, but the current documents url // FIXME: This shouldn't use NoReferrer, but the current documents url
let request = RequestBuilder::new(url.clone().into(), Referrer::NoReferrer) let request = RequestBuilder::new(
Some(state.webview_id),
url.clone().into(),
Referrer::NoReferrer,
)
.destination(Destination::Font); .destination(Destination::Font);
debug!("Loading @font-face {} from {}", web_font_family_name, url); debug!("Loading @font-face {} from {}", web_font_family_name, url);

View file

@ -15,7 +15,7 @@ use std::sync::{Arc, LazyLock, Mutex};
use app_units::Au; use app_units::Au;
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::PipelineId; use base::id::{PipelineId, WebViewId};
use base::Epoch; use base::Epoch;
use embedder_traits::resources::{self, Resource}; use embedder_traits::resources::{self, Resource};
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D};
@ -119,6 +119,9 @@ pub struct LayoutThread {
/// The ID of the pipeline that we belong to. /// The ID of the pipeline that we belong to.
id: PipelineId, id: PipelineId,
/// The webview that contains the pipeline we belong to.
webview_id: WebViewId,
/// The URL of the pipeline that we belong to. /// The URL of the pipeline that we belong to.
url: ServoUrl, url: ServoUrl,
@ -195,18 +198,7 @@ pub struct LayoutFactoryImpl();
impl LayoutFactory for LayoutFactoryImpl { impl LayoutFactory for LayoutFactoryImpl {
fn create(&self, config: LayoutConfig) -> Box<dyn Layout> { fn create(&self, config: LayoutConfig) -> Box<dyn Layout> {
Box::new(LayoutThread::new( Box::new(LayoutThread::new(config))
config.id,
config.url,
config.is_iframe,
config.script_chan,
config.image_cache,
config.font_context,
config.time_profiler_chan,
config.compositor_api,
config.paint_time_metrics,
config.window_size,
))
} }
} }
@ -503,21 +495,11 @@ impl LayoutThread {
self.root_flow.borrow().clone() self.root_flow.borrow().clone()
} }
#[allow(clippy::too_many_arguments)] fn new(config: LayoutConfig) -> LayoutThread {
fn new(
id: PipelineId,
url: ServoUrl,
is_iframe: bool,
script_chan: IpcSender<ConstellationControlMsg>,
image_cache: Arc<dyn ImageCache>,
font_context: Arc<FontContext>,
time_profiler_chan: profile_time::ProfilerChan,
compositor_api: CrossProcessCompositorApi,
paint_time_metrics: PaintTimeMetrics,
window_size: WindowSizeData,
) -> LayoutThread {
// Let webrender know about this pipeline by sending an empty display list. // Let webrender know about this pipeline by sending an empty display list.
compositor_api.send_initial_transaction(id.into()); config
.compositor_api
.send_initial_transaction(config.id.into());
let mut font = Font::initial_values(); let mut font = Font::initial_values();
let default_font_size = pref!(fonts_default_size); let default_font_size = pref!(fonts_default_size);
@ -530,8 +512,8 @@ impl LayoutThread {
let device = Device::new( let device = Device::new(
MediaType::screen(), MediaType::screen(),
QuirksMode::NoQuirks, QuirksMode::NoQuirks,
window_size.initial_viewport, config.window_size.initial_viewport,
Scale::new(window_size.device_pixel_ratio.get()), Scale::new(config.window_size.device_pixel_ratio.get()),
Box::new(LayoutFontMetricsProvider), Box::new(LayoutFontMetricsProvider),
ComputedValues::initial_values_with_font_override(font), ComputedValues::initial_values_with_font_override(font),
// TODO: obtain preferred color scheme from embedder // TODO: obtain preferred color scheme from embedder
@ -539,14 +521,15 @@ impl LayoutThread {
); );
LayoutThread { LayoutThread {
id, id: config.id,
url, webview_id: config.webview_id,
is_iframe, url: config.url,
script_chan, is_iframe: config.is_iframe,
time_profiler_chan, script_chan: config.script_chan,
time_profiler_chan: config.time_profiler_chan,
registered_painters: RegisteredPaintersImpl(Default::default()), registered_painters: RegisteredPaintersImpl(Default::default()),
image_cache, image_cache: config.image_cache,
font_context, font_context: config.font_context,
first_reflow: Cell::new(true), first_reflow: Cell::new(true),
parallel_flag: true, parallel_flag: true,
generation: Cell::new(0), generation: Cell::new(0),
@ -554,16 +537,16 @@ impl LayoutThread {
// Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR // Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR
epoch: Cell::new(Epoch(1)), epoch: Cell::new(Epoch(1)),
viewport_size: Size2D::new( viewport_size: Size2D::new(
Au::from_f32_px(window_size.initial_viewport.width), Au::from_f32_px(config.window_size.initial_viewport.width),
Au::from_f32_px(window_size.initial_viewport.height), Au::from_f32_px(config.window_size.initial_viewport.height),
), ),
compositor_api, compositor_api: config.compositor_api,
stylist: Stylist::new(device, QuirksMode::NoQuirks), stylist: Stylist::new(device, QuirksMode::NoQuirks),
display_list: Default::default(), display_list: Default::default(),
indexable_text: Default::default(), indexable_text: Default::default(),
scroll_offsets: Default::default(), scroll_offsets: Default::default(),
webrender_image_cache: Arc::new(RwLock::new(FnvHashMap::default())), webrender_image_cache: Arc::new(RwLock::new(FnvHashMap::default())),
paint_time_metrics, paint_time_metrics: config.paint_time_metrics,
last_iframe_sizes: Default::default(), last_iframe_sizes: Default::default(),
debug: opts::get().debug.clone(), debug: opts::get().debug.clone(),
nonincremental_layout: opts::get().nonincremental_layout, nonincremental_layout: opts::get().nonincremental_layout,
@ -640,6 +623,7 @@ impl LayoutThread {
}; };
self.font_context.add_all_web_fonts_from_stylesheet( self.font_context.add_all_web_fonts_from_stylesheet(
self.webview_id,
stylesheet, stylesheet,
guard, guard,
self.stylist.device(), self.stylist.device(),

View file

@ -16,7 +16,7 @@ use std::sync::{Arc, LazyLock};
use app_units::Au; use app_units::Au;
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::PipelineId; use base::id::{PipelineId, WebViewId};
use base::Epoch; use base::Epoch;
use embedder_traits::resources::{self, Resource}; use embedder_traits::resources::{self, Resource};
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D};
@ -105,6 +105,9 @@ pub struct LayoutThread {
/// The ID of the pipeline that we belong to. /// The ID of the pipeline that we belong to.
id: PipelineId, id: PipelineId,
/// The webview that contains the pipeline we belong to.
webview_id: WebViewId,
/// The URL of the pipeline that we belong to. /// The URL of the pipeline that we belong to.
url: ServoUrl, url: ServoUrl,
@ -169,18 +172,7 @@ pub struct LayoutFactoryImpl();
impl LayoutFactory for LayoutFactoryImpl { impl LayoutFactory for LayoutFactoryImpl {
fn create(&self, config: LayoutConfig) -> Box<dyn Layout> { fn create(&self, config: LayoutConfig) -> Box<dyn Layout> {
Box::new(LayoutThread::new( Box::new(LayoutThread::new(config))
config.id,
config.url,
config.is_iframe,
config.script_chan,
config.image_cache,
config.font_context,
config.time_profiler_chan,
config.compositor_api,
config.paint_time_metrics,
config.window_size,
))
} }
} }
@ -476,23 +468,12 @@ impl Layout for LayoutThread {
} }
} }
#[allow(clippy::too_many_arguments)]
impl LayoutThread { impl LayoutThread {
#[allow(clippy::too_many_arguments)] fn new(config: LayoutConfig) -> LayoutThread {
fn new(
id: PipelineId,
url: ServoUrl,
is_iframe: bool,
script_chan: IpcSender<ConstellationControlMsg>,
image_cache: Arc<dyn ImageCache>,
font_context: Arc<FontContext>,
time_profiler_chan: profile_time::ProfilerChan,
compositor_api: CrossProcessCompositorApi,
paint_time_metrics: PaintTimeMetrics,
window_size: WindowSizeData,
) -> LayoutThread {
// Let webrender know about this pipeline by sending an empty display list. // Let webrender know about this pipeline by sending an empty display list.
compositor_api.send_initial_transaction(id.into()); config
.compositor_api
.send_initial_transaction(config.id.into());
let mut font = Font::initial_values(); let mut font = Font::initial_values();
let default_font_size = pref!(fonts_default_size); let default_font_size = pref!(fonts_default_size);
@ -507,23 +488,24 @@ impl LayoutThread {
let device = Device::new( let device = Device::new(
MediaType::screen(), MediaType::screen(),
QuirksMode::NoQuirks, QuirksMode::NoQuirks,
window_size.initial_viewport, config.window_size.initial_viewport,
Scale::new(window_size.device_pixel_ratio.get()), Scale::new(config.window_size.device_pixel_ratio.get()),
Box::new(LayoutFontMetricsProvider(font_context.clone())), Box::new(LayoutFontMetricsProvider(config.font_context.clone())),
ComputedValues::initial_values_with_font_override(font), ComputedValues::initial_values_with_font_override(font),
// TODO: obtain preferred color scheme from embedder // TODO: obtain preferred color scheme from embedder
PrefersColorScheme::Light, PrefersColorScheme::Light,
); );
LayoutThread { LayoutThread {
id, id: config.id,
url, webview_id: config.webview_id,
is_iframe, url: config.url,
script_chan: script_chan.clone(), is_iframe: config.is_iframe,
time_profiler_chan, script_chan: config.script_chan.clone(),
time_profiler_chan: config.time_profiler_chan,
registered_painters: RegisteredPaintersImpl(Default::default()), registered_painters: RegisteredPaintersImpl(Default::default()),
image_cache, image_cache: config.image_cache,
font_context, font_context: config.font_context,
first_reflow: Cell::new(true), first_reflow: Cell::new(true),
generation: Cell::new(0), generation: Cell::new(0),
box_tree: Default::default(), box_tree: Default::default(),
@ -531,14 +513,14 @@ impl LayoutThread {
// Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR // Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR
epoch: Cell::new(Epoch(1)), epoch: Cell::new(Epoch(1)),
viewport_size: Size2D::new( viewport_size: Size2D::new(
Au::from_f32_px(window_size.initial_viewport.width), Au::from_f32_px(config.window_size.initial_viewport.width),
Au::from_f32_px(window_size.initial_viewport.height), Au::from_f32_px(config.window_size.initial_viewport.height),
), ),
compositor_api, compositor_api: config.compositor_api,
scroll_offsets: Default::default(), scroll_offsets: Default::default(),
stylist: Stylist::new(device, QuirksMode::NoQuirks), stylist: Stylist::new(device, QuirksMode::NoQuirks),
webrender_image_cache: Default::default(), webrender_image_cache: Default::default(),
paint_time_metrics, paint_time_metrics: config.paint_time_metrics,
debug: opts::get().debug.clone(), debug: opts::get().debug.clone(),
} }
} }
@ -619,6 +601,7 @@ impl LayoutThread {
}; };
self.font_context.add_all_web_fonts_from_stylesheet( self.font_context.add_all_web_fonts_from_stylesheet(
self.webview_id,
stylesheet, stylesheet,
guard, guard,
self.stylist.device(), self.stylist.device(),

View file

@ -195,18 +195,6 @@ pub fn should_request_be_blocked_by_csp(
.unwrap_or(csp::CheckResult::Allowed) .unwrap_or(csp::CheckResult::Allowed)
} }
pub fn maybe_intercept_request(
request: &mut Request,
context: &FetchContext,
response: &mut Option<Response>,
) {
context
.request_intercepter
.lock()
.unwrap()
.intercept_request(request, response, context);
}
/// [Main fetch](https://fetch.spec.whatwg.org/#concept-main-fetch) /// [Main fetch](https://fetch.spec.whatwg.org/#concept-main-fetch)
pub async fn main_fetch( pub async fn main_fetch(
fetch_params: &mut FetchParams, fetch_params: &mut FetchParams,
@ -314,7 +302,11 @@ pub async fn main_fetch(
let current_scheme = current_url.scheme(); let current_scheme = current_url.scheme();
// Intercept the request and maybe override the response. // Intercept the request and maybe override the response.
maybe_intercept_request(request, context, &mut response); context
.request_intercepter
.lock()
.unwrap()
.intercept_request(request, &mut response, context);
let mut response = match response { let mut response = match response {
Some(res) => res, Some(res) => res,

View file

@ -10,6 +10,7 @@ use std::path::{Path, PathBuf};
use std::sync::atomic::{self, AtomicBool, AtomicUsize, Ordering}; use std::sync::atomic::{self, AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, RwLock, Weak}; use std::sync::{Arc, Mutex, RwLock, Weak};
use base::id::WebViewId;
use embedder_traits::{EmbedderMsg, EmbedderProxy, FilterPattern}; use embedder_traits::{EmbedderMsg, EmbedderProxy, FilterPattern};
use headers::{ContentLength, ContentRange, ContentType, HeaderMap, HeaderMapExt, Range}; use headers::{ContentLength, ContentRange, ContentType, HeaderMap, HeaderMapExt, Range};
use http::header::{self, HeaderValue}; use http::header::{self, HeaderValue};
@ -153,14 +154,14 @@ impl FileManager {
/// Message handler /// Message handler
pub fn handle(&self, msg: FileManagerThreadMsg) { pub fn handle(&self, msg: FileManagerThreadMsg) {
match msg { match msg {
FileManagerThreadMsg::SelectFile(filter, sender, origin, opt_test_path) => { FileManagerThreadMsg::SelectFile(webview_id, filter, sender, origin, opt_test_path) => {
let store = self.store.clone(); let store = self.store.clone();
let embedder = self.embedder_proxy.clone(); let embedder = self.embedder_proxy.clone();
self.thread_pool self.thread_pool
.upgrade() .upgrade()
.map(|pool| { .map(|pool| {
pool.spawn(move || { pool.spawn(move || {
store.select_file(filter, sender, origin, opt_test_path, embedder); store.select_file(webview_id, filter, sender, origin, opt_test_path, embedder);
}); });
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
@ -169,14 +170,20 @@ impl FileManager {
); );
}); });
}, },
FileManagerThreadMsg::SelectFiles(filter, sender, origin, opt_test_paths) => { FileManagerThreadMsg::SelectFiles(
webview_id,
filter,
sender,
origin,
opt_test_paths,
) => {
let store = self.store.clone(); let store = self.store.clone();
let embedder = self.embedder_proxy.clone(); let embedder = self.embedder_proxy.clone();
self.thread_pool self.thread_pool
.upgrade() .upgrade()
.map(|pool| { .map(|pool| {
pool.spawn(move || { pool.spawn(move || {
store.select_files(filter, sender, origin, opt_test_paths, embedder); store.select_files(webview_id, filter, sender, origin, opt_test_paths, embedder);
}); });
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
@ -571,17 +578,18 @@ impl FileManagerStore {
fn query_files_from_embedder( fn query_files_from_embedder(
&self, &self,
webview_id: WebViewId,
patterns: Vec<FilterPattern>, patterns: Vec<FilterPattern>,
multiple_files: bool, multiple_files: bool,
embedder_proxy: EmbedderProxy, embedder_proxy: EmbedderProxy,
) -> Option<Vec<String>> { ) -> Option<Vec<String>> {
let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!"); let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!");
let msg = ( embedder_proxy.send(EmbedderMsg::SelectFiles(
None, webview_id,
EmbedderMsg::SelectFiles(patterns, multiple_files, ipc_sender), patterns,
); multiple_files,
ipc_sender,
embedder_proxy.send(msg); ));
match ipc_receiver.recv() { match ipc_receiver.recv() {
Ok(result) => result, Ok(result) => result,
Err(e) => { Err(e) => {
@ -593,6 +601,7 @@ impl FileManagerStore {
fn select_file( fn select_file(
&self, &self,
webview_id: WebViewId,
patterns: Vec<FilterPattern>, patterns: Vec<FilterPattern>,
sender: IpcSender<FileManagerResult<SelectedFile>>, sender: IpcSender<FileManagerResult<SelectedFile>>,
origin: FileOrigin, origin: FileOrigin,
@ -605,7 +614,7 @@ impl FileManagerStore {
let opt_s = if pref!(dom_testing_html_input_element_select_files_enabled) { let opt_s = if pref!(dom_testing_html_input_element_select_files_enabled) {
opt_test_path opt_test_path
} else { } else {
self.query_files_from_embedder(patterns, false, embedder_proxy) self.query_files_from_embedder(webview_id, patterns, false, embedder_proxy)
.and_then(|mut x| x.pop()) .and_then(|mut x| x.pop())
}; };
@ -623,6 +632,7 @@ impl FileManagerStore {
fn select_files( fn select_files(
&self, &self,
webview_id: WebViewId,
patterns: Vec<FilterPattern>, patterns: Vec<FilterPattern>,
sender: IpcSender<FileManagerResult<Vec<SelectedFile>>>, sender: IpcSender<FileManagerResult<Vec<SelectedFile>>>,
origin: FileOrigin, origin: FileOrigin,
@ -635,7 +645,7 @@ impl FileManagerStore {
let opt_v = if pref!(dom_testing_html_input_element_select_files_enabled) { let opt_v = if pref!(dom_testing_html_input_element_select_files_enabled) {
opt_test_paths opt_test_paths
} else { } else {
self.query_files_from_embedder(patterns, true, embedder_proxy) self.query_files_from_embedder(webview_id, patterns, true, embedder_proxy)
}; };
match opt_v { match opt_v {

View file

@ -9,7 +9,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
use async_recursion::async_recursion; use async_recursion::async_recursion;
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::{HistoryStateId, PipelineId, TopLevelBrowsingContextId}; use base::id::{HistoryStateId, PipelineId, WebViewId};
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use devtools_traits::{ use devtools_traits::{
ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest, ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest,
@ -1583,10 +1583,12 @@ async fn http_network_or_cache_fetch(
// Step 14.3 If requests use-URL-credentials flag is unset or isAuthenticationFetch is true, then: // Step 14.3 If requests use-URL-credentials flag is unset or isAuthenticationFetch is true, then:
if !http_request.use_url_credentials || authentication_fetch_flag { if !http_request.use_url_credentials || authentication_fetch_flag {
let Some(credentials) = prompt_user_for_credentials( let Some(webview_id) = http_request.target_webview_id else {
&context.state.embedder_proxy, return response;
http_request.target_browsing_context_id, };
) else { let Some(credentials) =
prompt_user_for_credentials(&context.state.embedder_proxy, webview_id)
else {
return response; return response;
}; };
let Some(username) = credentials.username else { let Some(username) = credentials.username else {
@ -1639,10 +1641,12 @@ async fn http_network_or_cache_fetch(
// Step 15.4 Prompt the end user as appropriate in requests window // Step 15.4 Prompt the end user as appropriate in requests window
// window and store the result as a proxy-authentication entry. // window and store the result as a proxy-authentication entry.
let Some(credentials) = prompt_user_for_credentials( let Some(webview_id) = http_request.target_webview_id else {
&context.state.embedder_proxy, return response;
http_request.target_browsing_context_id, };
) else { let Some(credentials) =
prompt_user_for_credentials(&context.state.embedder_proxy, webview_id)
else {
return response; return response;
}; };
let Some(user_name) = credentials.username else { let Some(user_name) = credentials.username else {
@ -1779,18 +1783,16 @@ impl Drop for ResponseEndTimer {
fn prompt_user_for_credentials( fn prompt_user_for_credentials(
embedder_proxy: &Mutex<EmbedderProxy>, embedder_proxy: &Mutex<EmbedderProxy>,
top_level_browsing_context_id: Option<TopLevelBrowsingContextId>, webview_id: WebViewId,
) -> Option<PromptCredentialsInput> { ) -> Option<PromptCredentialsInput> {
let proxy = embedder_proxy.lock().unwrap(); let proxy = embedder_proxy.lock().unwrap();
let (ipc_sender, ipc_receiver) = ipc::channel().unwrap(); let (ipc_sender, ipc_receiver) = ipc::channel().unwrap();
proxy.send(( proxy.send(EmbedderMsg::Prompt(
top_level_browsing_context_id, webview_id,
EmbedderMsg::Prompt(
PromptDefinition::Credentials(ipc_sender), PromptDefinition::Credentials(ipc_sender),
PromptOrigin::Trusted, PromptOrigin::Trusted,
),
)); ));
let Ok(credentials) = ipc_receiver.recv() else { let Ok(credentials) = ipc_receiver.recv() else {
@ -2100,7 +2102,11 @@ async fn cors_preflight_fetch(
context: &FetchContext, context: &FetchContext,
) -> Response { ) -> Response {
// Step 1 // Step 1
let mut preflight = RequestBuilder::new(request.current_url(), request.referrer.clone()) let mut preflight = RequestBuilder::new(
request.target_webview_id,
request.current_url(),
request.referrer.clone(),
)
.method(Method::OPTIONS) .method(Method::OPTIONS)
.origin(match &request.origin { .origin(match &request.origin {
Origin::Client => { Origin::Client => {

View file

@ -40,9 +40,10 @@ impl RequestIntercepter {
request.redirect_count > 0, request.redirect_count > 0,
); );
self.embedder_proxy.send(( self.embedder_proxy.send(EmbedderMsg::WebResourceRequested(
request.target_browsing_context_id, request.target_webview_id,
EmbedderMsg::WebResourceRequested(req, tx), req,
tx,
)); ));
let mut response_received = false; let mut response_received = false;

View file

@ -24,7 +24,7 @@ fn assert_parse(
use net_traits::request::RequestBuilder; use net_traits::request::RequestBuilder;
let url = ServoUrl::parse(url).unwrap(); let url = ServoUrl::parse(url).unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.pipeline_id(None) .pipeline_id(None)
.build(); .build();

View file

@ -65,7 +65,7 @@ fn test_fetch_response_is_not_network_error() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -79,7 +79,7 @@ fn test_fetch_response_is_not_network_error() {
#[test] #[test]
fn test_fetch_on_bad_port_is_network_error() { fn test_fetch_on_bad_port_is_network_error() {
let url = ServoUrl::parse("http://www.example.org:6667").unwrap(); let url = ServoUrl::parse("http://www.example.org:6667").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -101,7 +101,7 @@ fn test_fetch_response_body_matches_const_message() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -121,7 +121,7 @@ fn test_fetch_response_body_matches_const_message() {
#[test] #[test]
fn test_fetch_aboutblank() { fn test_fetch_aboutblank() {
let url = ServoUrl::parse("about:blank").unwrap(); let url = ServoUrl::parse("about:blank").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
@ -186,7 +186,7 @@ fn test_fetch_blob() {
); );
let url = ServoUrl::parse(&format!("blob:{}{}", origin.as_str(), id.simple())).unwrap(); let url = ServoUrl::parse(&format!("blob:{}{}", origin.as_str(), id.simple())).unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(origin.origin()) .origin(origin.origin())
.build(); .build();
@ -228,7 +228,7 @@ fn test_file() {
.unwrap(); .unwrap();
let url = ServoUrl::from_file_path(path.clone()).unwrap(); let url = ServoUrl::from_file_path(path.clone()).unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
@ -271,7 +271,7 @@ fn test_file() {
#[test] #[test]
fn test_fetch_ftp() { fn test_fetch_ftp() {
let url = ServoUrl::parse("ftp://not-supported").unwrap(); let url = ServoUrl::parse("ftp://not-supported").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -281,7 +281,7 @@ fn test_fetch_ftp() {
#[test] #[test]
fn test_fetch_bogus_scheme() { fn test_fetch_bogus_scheme() {
let url = ServoUrl::parse("bogus://whatever").unwrap(); let url = ServoUrl::parse("bogus://whatever").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -330,7 +330,7 @@ fn test_cors_preflight_fetch() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let target_url = url.clone().join("a.html").unwrap(); let target_url = url.clone().join("a.html").unwrap();
let mut request = RequestBuilder::new(url, Referrer::ReferrerUrl(target_url)).build(); let mut request = RequestBuilder::new(None, url, Referrer::ReferrerUrl(target_url)).build();
request.referrer_policy = ReferrerPolicy::Origin; request.referrer_policy = ReferrerPolicy::Origin;
request.use_cors_preflight = true; request.use_cors_preflight = true;
request.mode = RequestMode::CorsMode; request.mode = RequestMode::CorsMode;
@ -383,7 +383,7 @@ fn test_cors_preflight_cache_fetch() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let mut request = RequestBuilder::new(url, Referrer::NoReferrer).build(); let mut request = RequestBuilder::new(None, url, Referrer::NoReferrer).build();
request.use_cors_preflight = true; request.use_cors_preflight = true;
request.mode = RequestMode::CorsMode; request.mode = RequestMode::CorsMode;
let wrapped_request0 = request.clone(); let wrapped_request0 = request.clone();
@ -448,7 +448,7 @@ fn test_cors_preflight_fetch_network_error() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let mut request = RequestBuilder::new(url, Referrer::NoReferrer).build(); let mut request = RequestBuilder::new(None, url, Referrer::NoReferrer).build();
request.method = Method::from_bytes(b"CHICKEN").unwrap(); request.method = Method::from_bytes(b"CHICKEN").unwrap();
request.use_cors_preflight = true; request.use_cors_preflight = true;
request.mode = RequestMode::CorsMode; request.mode = RequestMode::CorsMode;
@ -477,7 +477,7 @@ fn test_fetch_response_is_basic_filtered() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -542,7 +542,7 @@ fn test_fetch_response_is_cors_filtered() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
// an origin mis-match will stop it from defaulting to a basic filtered response // an origin mis-match will stop it from defaulting to a basic filtered response
let mut request = RequestBuilder::new(url, Referrer::NoReferrer).build(); let mut request = RequestBuilder::new(None, url, Referrer::NoReferrer).build();
request.mode = RequestMode::CorsMode; request.mode = RequestMode::CorsMode;
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
let _ = server.close(); let _ = server.close();
@ -576,7 +576,7 @@ fn test_fetch_response_is_opaque_filtered() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
// an origin mis-match will fall through to an Opaque filtered response // an origin mis-match will fall through to an Opaque filtered response
let request = RequestBuilder::new(url, Referrer::NoReferrer).build(); let request = RequestBuilder::new(None, url, Referrer::NoReferrer).build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
let _ = server.close(); let _ = server.close();
@ -624,7 +624,7 @@ fn test_fetch_response_is_opaque_redirect_filtered() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let mut request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
request.redirect_mode = RedirectMode::Manual; request.redirect_mode = RedirectMode::Manual;
@ -660,7 +660,7 @@ fn test_fetch_with_local_urls_only() {
let (server, server_url) = make_server(handler); let (server, server_url) = make_server(handler);
let do_fetch = |url: ServoUrl| { let do_fetch = |url: ServoUrl| {
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let mut request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
@ -728,7 +728,7 @@ fn test_fetch_with_hsts() {
HstsEntry::new("localhost".to_owned(), IncludeSubdomains::NotIncluded, None).unwrap(), HstsEntry::new("localhost".to_owned(), IncludeSubdomains::NotIncluded, None).unwrap(),
); );
} }
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let mut request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
// Set the flag. // Set the flag.
@ -782,7 +782,7 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
context.state.override_manager.add_override(certificate); context.state.override_manager.add_override(certificate);
} }
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -838,7 +838,7 @@ fn test_fetch_self_signed() {
protocols: Arc::new(ProtocolRegistry::default()), protocols: Arc::new(ProtocolRegistry::default()),
}; };
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -859,7 +859,7 @@ fn test_fetch_self_signed() {
context.state.override_manager.add_override(certificate); context.state.override_manager.add_override(certificate);
} }
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -884,7 +884,7 @@ fn test_fetch_with_sri_network_error() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let mut request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
// To calulate hash use : // To calulate hash use :
@ -910,7 +910,7 @@ fn test_fetch_with_sri_sucess() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let mut request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
// To calulate hash use : // To calulate hash use :
@ -952,7 +952,7 @@ fn test_fetch_blocked_nosniff() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.destination(destination) .destination(destination)
.build(); .build();
@ -999,7 +999,7 @@ fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -1089,7 +1089,7 @@ fn test_fetch_redirect_updates_method_runner(
let (server, url) = crate::make_server(handler); let (server, url) = crate::make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.method(method) .method(method)
.build(); .build();
@ -1174,7 +1174,7 @@ fn test_fetch_async_returns_complete_response() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
@ -1194,7 +1194,7 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
// an origin mis-match will fall through to an Opaque filtered response // an origin mis-match will fall through to an Opaque filtered response
let request = RequestBuilder::new(url, Referrer::NoReferrer).build(); let request = RequestBuilder::new(None, url, Referrer::NoReferrer).build();
let fetch_response = fetch(request, None); let fetch_response = fetch(request, None);
let _ = server.close(); let _ = server.close();
@ -1228,7 +1228,7 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.redirect_mode(RedirectMode::Manual) .redirect_mode(RedirectMode::Manual)
.build(); .build();
@ -1253,7 +1253,7 @@ fn test_fetch_with_devtools() {
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.redirect_mode(RedirectMode::Manual) .redirect_mode(RedirectMode::Manual)
.pipeline_id(Some(TEST_PIPELINE_ID)) .pipeline_id(Some(TEST_PIPELINE_ID))
@ -1341,12 +1341,13 @@ fn test_fetch_request_intercepted() {
static HEADERVALUE: &str = "custom-value"; static HEADERVALUE: &str = "custom-value";
static STATUS_MESSAGE: &[u8] = b"custom status message"; static STATUS_MESSAGE: &[u8] = b"custom status message";
let (embedder_proxy, mut embedder_receiver) = create_embedder_proxy_and_receiver(); let (embedder_proxy, embedder_receiver) = create_embedder_proxy_and_receiver();
std::thread::spawn(move || { std::thread::spawn(move || {
let (_browser_context_id, embedder_msg) = embedder_receiver.recv_embedder_msg(); let embedder_msg = embedder_receiver.recv().unwrap();
match embedder_msg { match embedder_msg {
embedder_traits::EmbedderMsg::WebResourceRequested( embedder_traits::EmbedderMsg::WebResourceRequested(
_,
web_resource_request, web_resource_request,
response_sender, response_sender,
) => { ) => {
@ -1396,7 +1397,7 @@ fn test_fetch_request_intercepted() {
}; };
let url = ServoUrl::parse("http://www.example.org").unwrap(); let url = ServoUrl::parse("http://www.example.org").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.origin(url.origin()) .origin(url.origin())
.build(); .build();
let response = fetch_with_context(request, &mut context); let response = fetch_with_context(request, &mut context);

View file

@ -7,6 +7,7 @@ use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use base::id::TEST_WEBVIEW_ID;
use embedder_traits::FilterPattern; use embedder_traits::FilterPattern;
use ipc_channel::ipc; use ipc_channel::ipc;
use net::filemanager_thread::FileManager; use net::filemanager_thread::FileManager;
@ -44,6 +45,7 @@ fn test_filemanager() {
// Try to select a dummy file "components/net/tests/test.jpeg" // Try to select a dummy file "components/net/tests/test.jpeg"
let (tx, rx) = ipc::channel().unwrap(); let (tx, rx) = ipc::channel().unwrap();
filemanager.handle(FileManagerThreadMsg::SelectFile( filemanager.handle(FileManagerThreadMsg::SelectFile(
TEST_WEBVIEW_ID,
patterns.clone(), patterns.clone(),
tx, tx,
origin.clone(), origin.clone(),

View file

@ -20,7 +20,7 @@ fn test_refreshing_resource_sets_done_chan_the_appropriate_value() {
ResponseBody::Done(vec![]), ResponseBody::Done(vec![]),
]; ];
let url = ServoUrl::parse("https://servo.org").unwrap(); let url = ServoUrl::parse("https://servo.org").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.pipeline_id(Some(TEST_PIPELINE_ID)) .pipeline_id(Some(TEST_PIPELINE_ID))
.origin(url.origin()) .origin(url.origin())
.build(); .build();

View file

@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::time::Duration; use std::time::Duration;
use base::id::TEST_PIPELINE_ID; use base::id::{TEST_PIPELINE_ID, TEST_WEBVIEW_ID};
use cookie::Cookie as CookiePair; use cookie::Cookie as CookiePair;
use crossbeam_channel::{unbounded, Receiver}; use crossbeam_channel::{unbounded, Receiver};
use devtools_traits::{ use devtools_traits::{
@ -175,7 +175,7 @@ fn test_check_default_headers_loaded_in_every_request() {
*expected_headers.lock().unwrap() = Some(headers.clone()); *expected_headers.lock().unwrap() = Some(headers.clone());
// Testing for method.GET // Testing for method.GET
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(url.clone().origin()) .origin(url.clone().origin())
@ -201,7 +201,7 @@ fn test_check_default_headers_loaded_in_every_request() {
HeaderValue::from_str(&url_str[..url_str.len() - 1]).unwrap(), HeaderValue::from_str(&url_str[..url_str.len() - 1]).unwrap(),
); );
*expected_headers.lock().unwrap() = Some(post_headers); *expected_headers.lock().unwrap() = Some(post_headers);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::POST) .method(Method::POST)
.destination(Destination::Document) .destination(Destination::Document)
.origin(url.clone().origin()) .origin(url.clone().origin())
@ -231,7 +231,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::POST) .method(Method::POST)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -264,7 +264,7 @@ fn test_request_and_response_data_with_network_messages() {
let mut request_headers = HeaderMap::new(); let mut request_headers = HeaderMap::new();
request_headers.typed_insert(Host::from("bar.foo".parse::<Authority>().unwrap())); request_headers.typed_insert(Host::from("bar.foo".parse::<Authority>().unwrap()));
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.headers(request_headers) .headers(request_headers)
.body(None) .body(None)
@ -377,7 +377,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -417,7 +417,7 @@ fn test_redirected_request_to_devtools() {
}; };
let (pre_server, pre_url) = make_server(pre_handler); let (pre_server, pre_url) = make_server(pre_handler);
let request = RequestBuilder::new(pre_url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, pre_url.clone(), Referrer::NoReferrer)
.method(Method::POST) .method(Method::POST)
.destination(Destination::Document) .destination(Destination::Document)
.pipeline_id(Some(TEST_PIPELINE_ID)) .pipeline_id(Some(TEST_PIPELINE_ID))
@ -470,7 +470,7 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() {
}; };
let (pre_server, pre_url) = make_server(pre_handler); let (pre_server, pre_url) = make_server(pre_handler);
let request = RequestBuilder::new(pre_url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, pre_url.clone(), Referrer::NoReferrer)
.method(Method::POST) .method(Method::POST)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -502,7 +502,7 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -537,7 +537,7 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -584,7 +584,7 @@ fn test_load_doesnt_send_request_body_on_any_redirect() {
let content = b"Body on POST!"; let content = b"Body on POST!";
let request_body = create_request_body_with_content(content.to_vec()); let request_body = create_request_body_with_content(content.to_vec());
let request = RequestBuilder::new(pre_url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, pre_url.clone(), Referrer::NoReferrer)
.body(Some(request_body)) .body(Some(request_body))
.method(Method::POST) .method(Method::POST)
.destination(Destination::Document) .destination(Destination::Document)
@ -614,7 +614,7 @@ fn test_load_doesnt_add_host_to_hsts_list_when_url_is_http_even_if_hsts_headers_
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -661,7 +661,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -714,7 +714,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
cookie_jar.push(cookie, &url, CookieSource::HTTP); cookie_jar.push(cookie, &url, CookieSource::HTTP);
} }
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -761,7 +761,7 @@ fn test_load_sends_cookie_if_nonhttp() {
cookie_jar.push(cookie, &url, CookieSource::HTTP); cookie_jar.push(cookie, &url, CookieSource::HTTP);
} }
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -800,7 +800,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -849,7 +849,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -884,7 +884,7 @@ fn test_load_sets_content_length_to_length_of_request_body() {
let request_body = create_request_body_with_content(content.to_vec()); let request_body = create_request_body_with_content(content.to_vec());
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::POST) .method(Method::POST)
.body(Some(request_body)) .body(Some(request_body))
.destination(Destination::Document) .destination(Destination::Document)
@ -924,7 +924,7 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() {
let mut accept_headers = HeaderMap::new(); let mut accept_headers = HeaderMap::new();
accept_headers.insert(header::ACCEPT, HeaderValue::from_static("text/html")); accept_headers.insert(header::ACCEPT, HeaderValue::from_static("text/html"));
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.headers(accept_headers) .headers(accept_headers)
.destination(Destination::Document) .destination(Destination::Document)
@ -962,7 +962,7 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1001,7 +1001,7 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() {
let mut accept_encoding_headers = HeaderMap::new(); let mut accept_encoding_headers = HeaderMap::new();
accept_encoding_headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("chunked")); accept_encoding_headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("chunked"));
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.headers(accept_encoding_headers) .headers(accept_encoding_headers)
.destination(Destination::Document) .destination(Destination::Document)
@ -1039,7 +1039,7 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1095,7 +1095,7 @@ fn test_load_errors_when_there_a_redirect_loop() {
*url_b_for_a.lock().unwrap() = Some(url_b.clone()); *url_b_for_a.lock().unwrap() = Some(url_b.clone());
let request = RequestBuilder::new(url_a.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url_a.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1155,7 +1155,7 @@ fn test_load_succeeds_with_a_redirect_loop() {
*url_b_for_a.lock().unwrap() = Some(url_b.clone()); *url_b_for_a.lock().unwrap() = Some(url_b.clone());
let request = RequestBuilder::new(url_a.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url_a.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1198,7 +1198,7 @@ fn test_load_follows_a_redirect() {
}; };
let (pre_server, pre_url) = make_server(pre_handler); let (pre_server, pre_url) = make_server(pre_handler);
let request = RequestBuilder::new(pre_url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, pre_url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1283,7 +1283,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
cookie_jar.push(cookie_y, &url_y, CookieSource::HTTP); cookie_jar.push(cookie_y, &url_y, CookieSource::HTTP);
} }
let request = RequestBuilder::new(url_x.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url_x.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1334,7 +1334,7 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() {
let url = url.join("/initial/").unwrap(); let url = url.join("/initial/").unwrap();
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.destination(Destination::Document) .destination(Destination::Document)
.origin(mock_origin()) .origin(mock_origin())
@ -1367,7 +1367,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -1412,7 +1412,7 @@ fn test_auth_ui_needs_www_auth() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -1479,7 +1479,7 @@ fn test_fetch_compressed_response_update_count() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(None, url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -1565,7 +1565,7 @@ fn test_user_credentials_prompt_when_proxy_authentication_is_required() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(Some(TEST_WEBVIEW_ID), url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -1613,7 +1613,7 @@ fn test_prompt_credentials_when_client_receives_unauthorized_response() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(Some(TEST_WEBVIEW_ID), url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -1660,7 +1660,7 @@ fn test_prompt_credentials_user_cancels_dialog_input() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(Some(TEST_WEBVIEW_ID), url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)
@ -1703,7 +1703,7 @@ fn test_prompt_credentials_user_input_incorrect_credentials() {
}; };
let (server, url) = make_server(handler); let (server, url) = make_server(handler);
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer) let request = RequestBuilder::new(Some(TEST_WEBVIEW_ID), url.clone(), Referrer::NoReferrer)
.method(Method::GET) .method(Method::GET)
.body(None) .body(None)
.destination(Destination::Document) .destination(Destination::Document)

View file

@ -26,9 +26,9 @@ use std::net::TcpListener as StdTcpListener;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, Mutex, RwLock, Weak}; use std::sync::{Arc, LazyLock, Mutex, RwLock, Weak};
use crossbeam_channel::{unbounded, Sender}; use crossbeam_channel::{unbounded, Receiver, Sender};
use devtools_traits::DevtoolsControlMsg; use devtools_traits::DevtoolsControlMsg;
use embedder_traits::{EmbedderProxy, EmbedderReceiver, EventLoopWaker}; use embedder_traits::{EmbedderMsg, EmbedderProxy, EventLoopWaker};
use futures::future::ready; use futures::future::ready;
use http_body_util::combinators::BoxBody; use http_body_util::combinators::BoxBody;
use http_body_util::{BodyExt, Empty, Full}; use http_body_util::{BodyExt, Empty, Full};
@ -96,7 +96,7 @@ fn create_embedder_proxy() -> EmbedderProxy {
} }
} }
fn create_embedder_proxy_and_receiver() -> (EmbedderProxy, EmbedderReceiver) { fn create_embedder_proxy_and_receiver() -> (EmbedderProxy, Receiver<EmbedderMsg>) {
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
let event_loop_waker = || { let event_loop_waker = || {
struct DummyEventLoopWaker {} struct DummyEventLoopWaker {}
@ -120,19 +120,18 @@ fn create_embedder_proxy_and_receiver() -> (EmbedderProxy, EmbedderReceiver) {
event_loop_waker: event_loop_waker(), event_loop_waker: event_loop_waker(),
}; };
let embedder_receiver = EmbedderReceiver { receiver }; (embedder_proxy, receiver)
(embedder_proxy, embedder_receiver)
} }
fn receive_credential_prompt_msgs( fn receive_credential_prompt_msgs(
mut embedder_receiver: EmbedderReceiver, embedder_receiver: Receiver<EmbedderMsg>,
username: Option<String>, username: Option<String>,
password: Option<String>, password: Option<String>,
) -> std::thread::JoinHandle<()> { ) -> std::thread::JoinHandle<()> {
std::thread::spawn(move || loop { std::thread::spawn(move || loop {
let (_browser_context_id, embedder_msg) = embedder_receiver.recv_embedder_msg(); let embedder_msg = embedder_receiver.recv().unwrap();
match embedder_msg { match embedder_msg {
embedder_traits::EmbedderMsg::Prompt(prompt_definition, _prompt_origin) => { embedder_traits::EmbedderMsg::Prompt(_, prompt_definition, _prompt_origin) => {
match prompt_definition { match prompt_definition {
embedder_traits::PromptDefinition::Credentials(ipc_sender) => { embedder_traits::PromptDefinition::Credentials(ipc_sender) => {
ipc_sender ipc_sender
@ -143,7 +142,7 @@ fn receive_credential_prompt_msgs(
} }
break; break;
}, },
embedder_traits::EmbedderMsg::WebResourceRequested(_, _) => {}, embedder_traits::EmbedderMsg::WebResourceRequested(..) => {},
_ => unreachable!(), _ => unreachable!(),
} }
}) })

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use base::id::WebViewId;
use embedder_traits::EmbedderMsg; use embedder_traits::EmbedderMsg;
use ipc_channel::ipc::channel; use ipc_channel::ipc::channel;
use script_traits::{ScriptMsg, ScriptToConstellationChan}; use script_traits::{ScriptMsg, ScriptToConstellationChan};
@ -13,18 +14,25 @@ pub trait ClipboardProvider {
fn set_clipboard_contents(&mut self, _: String); fn set_clipboard_contents(&mut self, _: String);
} }
impl ClipboardProvider for ScriptToConstellationChan { pub(crate) struct EmbedderClipboardProvider {
pub constellation_sender: ScriptToConstellationChan,
pub webview_id: WebViewId,
}
impl ClipboardProvider for EmbedderClipboardProvider {
fn clipboard_contents(&mut self) -> String { fn clipboard_contents(&mut self) -> String {
let (tx, rx) = channel().unwrap(); let (tx, rx) = channel().unwrap();
self.send(ScriptMsg::ForwardToEmbedder( self.constellation_sender
EmbedderMsg::GetClipboardContents(tx), .send(ScriptMsg::ForwardToEmbedder(
EmbedderMsg::GetClipboardContents(self.webview_id, tx),
)) ))
.unwrap(); .unwrap();
rx.recv().unwrap() rx.recv().unwrap()
} }
fn set_clipboard_contents(&mut self, s: String) { fn set_clipboard_contents(&mut self, s: String) {
self.send(ScriptMsg::ForwardToEmbedder( self.constellation_sender
EmbedderMsg::SetClipboardContents(s), .send(ScriptMsg::ForwardToEmbedder(
EmbedderMsg::SetClipboardContents(self.webview_id, s),
)) ))
.unwrap(); .unwrap();
} }

View file

@ -220,6 +220,7 @@ impl Bluetooth {
} }
let option = RequestDeviceoptions::new( let option = RequestDeviceoptions::new(
self.global().as_window().webview_id(),
BluetoothScanfilterSequence::new(uuid_filters), BluetoothScanfilterSequence::new(uuid_filters),
ServiceUUIDSequence::new(optional_services_uuids), ServiceUUIDSequence::new(optional_services_uuids),
); );

View file

@ -6,7 +6,7 @@ use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use base::id::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId}; use base::id::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId, WebViewId};
use crossbeam_channel::{unbounded, Receiver, Sender}; use crossbeam_channel::{unbounded, Receiver, Sender};
use devtools_traits::DevtoolScriptControlMsg; use devtools_traits::DevtoolScriptControlMsg;
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -236,6 +236,10 @@ impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope {
} }
impl DedicatedWorkerGlobalScope { impl DedicatedWorkerGlobalScope {
pub(crate) fn webview_id(&self) -> Option<WebViewId> {
WebViewId::installed()
}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn new_inherited( fn new_inherited(
init: WorkerGlobalScopeInit, init: WorkerGlobalScopeInit,
@ -361,7 +365,11 @@ impl DedicatedWorkerGlobalScope {
let referrer = referrer_url.map(Referrer::ReferrerUrl).unwrap_or(referrer); let referrer = referrer_url.map(Referrer::ReferrerUrl).unwrap_or(referrer);
let request = RequestBuilder::new(worker_url.clone(), referrer) let request = RequestBuilder::new(
top_level_browsing_context_id,
worker_url.clone(),
referrer,
)
.destination(Destination::Worker) .destination(Destination::Worker)
.mode(RequestMode::SameOrigin) .mode(RequestMode::SameOrigin)
.credentials_mode(CredentialsMode::CredentialsSameOrigin) .credentials_mode(CredentialsMode::CredentialsSameOrigin)

View file

@ -15,6 +15,7 @@ use std::sync::{LazyLock, Mutex};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::WebViewId;
use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg}; use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg};
use chrono::Local; use chrono::Local;
use content_security_policy::{self as csp, CspList}; use content_security_policy::{self as csp, CspList};
@ -648,6 +649,10 @@ impl Document {
} }
} }
pub(crate) fn webview_id(&self) -> WebViewId {
self.window.webview_id()
}
#[inline] #[inline]
pub(crate) fn window(&self) -> &Window { pub(crate) fn window(&self) -> &Window {
&self.window &self.window
@ -1027,13 +1032,13 @@ impl Document {
match state { match state {
DocumentReadyState::Loading => { DocumentReadyState::Loading => {
if self.window().is_top_level() { if self.window().is_top_level() {
self.send_to_embedder(EmbedderMsg::LoadStart); self.send_to_embedder(EmbedderMsg::LoadStart(self.webview_id()));
self.send_to_embedder(EmbedderMsg::Status(None)); self.send_to_embedder(EmbedderMsg::Status(self.webview_id(), None));
} }
}, },
DocumentReadyState::Complete => { DocumentReadyState::Complete => {
if self.window().is_top_level() { if self.window().is_top_level() {
self.send_to_embedder(EmbedderMsg::LoadComplete); self.send_to_embedder(EmbedderMsg::LoadComplete(self.webview_id()));
} }
update_with_current_instant(&self.dom_complete); update_with_current_instant(&self.dom_complete);
}, },
@ -1121,7 +1126,7 @@ impl Document {
// Notify the embedder to hide the input method. // Notify the embedder to hide the input method.
if elem.input_method_type().is_some() { if elem.input_method_type().is_some() {
self.send_to_embedder(EmbedderMsg::HideIME); self.send_to_embedder(EmbedderMsg::HideIME(self.webview_id()));
} }
} }
@ -1165,6 +1170,7 @@ impl Document {
(None, false) (None, false)
}; };
self.send_to_embedder(EmbedderMsg::ShowIME( self.send_to_embedder(EmbedderMsg::ShowIME(
self.webview_id(),
kind, kind,
text, text,
multiline, multiline,
@ -1225,7 +1231,7 @@ impl Document {
let window = self.window(); let window = self.window();
if window.is_top_level() { if window.is_top_level() {
let title = self.title().map(String::from); let title = self.title().map(String::from);
self.send_to_embedder(EmbedderMsg::ChangePageTitle(title)); self.send_to_embedder(EmbedderMsg::ChangePageTitle(self.webview_id(), title));
} }
} }
@ -1621,7 +1627,7 @@ impl Document {
// Step 1 // Step 1
if drag_data_store.list_len() > 0 { if drag_data_store.list_len() > 0 {
// Step 1.1 Clear the clipboard. // Step 1.1 Clear the clipboard.
self.send_to_embedder(EmbedderMsg::ClearClipboardContents); self.send_to_embedder(EmbedderMsg::ClearClipboardContents(self.webview_id()));
// Step 1.2 // Step 1.2
for item in drag_data_store.iter_item_list() { for item in drag_data_store.iter_item_list() {
match item { match item {
@ -1629,7 +1635,10 @@ impl Document {
// Step 1.2.1.1 Ensure encoding is correct per OS and locale conventions // Step 1.2.1.1 Ensure encoding is correct per OS and locale conventions
// Step 1.2.1.2 Normalize line endings according to platform conventions // Step 1.2.1.2 Normalize line endings according to platform conventions
// Step 1.2.1.3 // Step 1.2.1.3
self.send_to_embedder(EmbedderMsg::SetClipboardContents(string.data())); self.send_to_embedder(EmbedderMsg::SetClipboardContents(
self.webview_id(),
string.data(),
));
}, },
Kind::File(_) => { Kind::File(_) => {
// Step 1.2.2 If data is of a type listed in the mandatory data types list, then // Step 1.2.2 If data is of a type listed in the mandatory data types list, then
@ -1642,7 +1651,7 @@ impl Document {
// Step 2.1 // Step 2.1
if drag_data_store.clear_was_called { if drag_data_store.clear_was_called {
// Step 2.1.1 If types-to-clear list is empty, clear the clipboard // Step 2.1.1 If types-to-clear list is empty, clear the clipboard
self.send_to_embedder(EmbedderMsg::ClearClipboardContents); self.send_to_embedder(EmbedderMsg::ClearClipboardContents(self.webview_id()));
// Step 2.1.2 Else remove the types in the list from the clipboard // Step 2.1.2 Else remove the types in the list from the clipboard
// As of now this can't be done with Arboard, and it's possible that will be removed from the spec // As of now this can't be done with Arboard, and it's possible that will be removed from the spec
} }
@ -2049,7 +2058,7 @@ impl Document {
} }
if cancel_state == EventDefault::Allowed { if cancel_state == EventDefault::Allowed {
let msg = EmbedderMsg::Keyboard(keyboard_event.clone()); let msg = EmbedderMsg::Keyboard(self.webview_id(), keyboard_event.clone());
self.send_to_embedder(msg); self.send_to_embedder(msg);
// This behavior is unspecced // This behavior is unspecced
@ -2455,7 +2464,7 @@ impl Document {
.is_empty(); .is_empty();
if default_prevented || return_value_not_empty { if default_prevented || return_value_not_empty {
let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); let (chan, port) = ipc::channel().expect("Failed to create IPC channel!");
let msg = EmbedderMsg::AllowUnload(chan); let msg = EmbedderMsg::AllowUnload(self.webview_id(), chan);
self.send_to_embedder(msg); self.send_to_embedder(msg);
can_unload = port.recv().unwrap(); can_unload = port.recv().unwrap();
} }
@ -4049,7 +4058,7 @@ impl Document {
let window = self.window(); let window = self.window();
// Step 6 // Step 6
if !error { if !error {
let event = EmbedderMsg::SetFullscreenState(true); let event = EmbedderMsg::SetFullscreenState(self.webview_id(), true);
self.send_to_embedder(event); self.send_to_embedder(event);
} }
@ -4091,7 +4100,7 @@ impl Document {
let window = self.window(); let window = self.window();
// Step 8 // Step 8
let event = EmbedderMsg::SetFullscreenState(false); let event = EmbedderMsg::SetFullscreenState(self.webview_id(), false);
self.send_to_embedder(event); self.send_to_embedder(event);
// Step 9 // Step 9

View file

@ -554,6 +554,7 @@ impl EventSourceMethods<crate::DomTypeHolder> for EventSource {
// Step 8 // Step 8
// TODO: Step 9 set request's client settings // TODO: Step 9 set request's client settings
let mut request = create_a_potential_cors_request( let mut request = create_a_potential_cors_request(
global.webview_id(),
url_record, url_record,
Destination::None, Destination::None,
Some(cors_attribute_state), Some(cors_attribute_state),

View file

@ -235,6 +235,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
weak_magnitude: *params.weakMagnitude, weak_magnitude: *params.weakMagnitude,
}; };
let event = EmbedderMsg::PlayGamepadHapticEffect( let event = EmbedderMsg::PlayGamepadHapticEffect(
document.webview_id(),
self.gamepad_index as usize, self.gamepad_index as usize,
embedder_traits::GamepadHapticEffectType::DualRumble(params), embedder_traits::GamepadHapticEffectType::DualRumble(params),
effect_complete_sender, effect_complete_sender,
@ -287,8 +288,11 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
}), }),
); );
let event = let event = EmbedderMsg::StopGamepadHapticEffect(
EmbedderMsg::StopGamepadHapticEffect(self.gamepad_index as usize, effect_stop_sender); document.webview_id(),
self.gamepad_index as usize,
effect_stop_sender,
);
self.global().as_window().send_to_embedder(event); self.global().as_window().send_to_embedder(event);
self.playing_effect_promise.borrow().clone().unwrap() self.playing_effect_promise.borrow().clone().unwrap()
@ -356,7 +360,12 @@ impl GamepadHapticActuator {
let (send, _rcv) = ipc::channel().expect("ipc channel failure"); let (send, _rcv) = ipc::channel().expect("ipc channel failure");
let event = EmbedderMsg::StopGamepadHapticEffect(self.gamepad_index as usize, send); let document = self.global().as_window().Document();
let event = EmbedderMsg::StopGamepadHapticEffect(
document.webview_id(),
self.gamepad_index as usize,
send,
);
self.global().as_window().send_to_embedder(event); self.global().as_window().send_to_embedder(event);
} }
} }

View file

@ -16,7 +16,7 @@ use std::{mem, ptr};
use base::id::{ use base::id::{
BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId, BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId,
ServiceWorkerId, ServiceWorkerRegistrationId, ServiceWorkerId, ServiceWorkerRegistrationId, WebViewId,
}; };
use content_security_policy::{CheckResult, CspList, PolicyDisposition}; use content_security_policy::{CheckResult, CspList, PolicyDisposition};
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
@ -691,6 +691,20 @@ impl FileListener {
} }
impl GlobalScope { impl GlobalScope {
/// A sender to the event loop of this global scope. This either sends to the Worker event loop
/// or the ScriptThread event loop in the case of a `Window`. This can be `None` for dedicated
/// workers that are not currently handling a message.
pub(crate) fn webview_id(&self) -> Option<WebViewId> {
if let Some(window) = self.downcast::<Window>() {
Some(window.webview_id())
} else if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() {
dedicated.webview_id()
} else {
// ServiceWorkerGlobalScope, PaintWorklet, or DissimilarOriginWindow
None
}
}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(crate) fn new_inherited( pub(crate) fn new_inherited(
pipeline_id: PipelineId, pipeline_id: PipelineId,

View file

@ -153,7 +153,7 @@ impl VirtualMethods for HTMLBodyElement {
let window = self.owner_window(); let window = self.owner_window();
window.prevent_layout_until_load_event(); window.prevent_layout_until_load_event();
if window.is_top_level() { if window.is_top_level() {
window.send_to_embedder(EmbedderMsg::HeadParsed); window.send_to_embedder(EmbedderMsg::HeadParsed(window.webview_id()));
} }
} }

View file

@ -10,7 +10,6 @@ use std::sync::Arc;
use std::{char, mem}; use std::{char, mem};
use app_units::{Au, AU_PER_PX}; use app_units::{Au, AU_PER_PX};
use base::id::PipelineId;
use cssparser::{Parser, ParserInput}; use cssparser::{Parser, ParserInput};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::Point2D; use euclid::Point2D;
@ -23,16 +22,14 @@ use net_traits::image_cache::{
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder, ImageResponse, ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder, ImageResponse,
PendingImageId, UsePlaceholder, PendingImageId, UsePlaceholder,
}; };
use net_traits::request::{ use net_traits::request::{Destination, Initiator, RequestId};
CorsSettings, Destination, Initiator, Referrer, RequestBuilder, RequestId,
};
use net_traits::{ use net_traits::{
FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ReferrerPolicy, FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ReferrerPolicy,
ResourceFetchTiming, ResourceTimingType, ResourceFetchTiming, ResourceTimingType,
}; };
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use pixels::{CorsStatus, Image, ImageMetadata}; use pixels::{CorsStatus, Image, ImageMetadata};
use servo_url::origin::{ImmutableOrigin, MutableOrigin}; use servo_url::origin::MutableOrigin;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use style::attr::{parse_integer, parse_length, AttrValue, LengthOrPercentageOrAuto}; use style::attr::{parse_integer, parse_length, AttrValue, LengthOrPercentageOrAuto};
use style::context::QuirksMode; use style::context::QuirksMode;
@ -318,34 +315,6 @@ impl PreInvoke for ImageContext {
} }
} }
#[derive(PartialEq)]
pub(crate) enum FromPictureOrSrcSet {
Yes,
No,
}
// https://html.spec.whatwg.org/multipage/#update-the-image-data steps 17-20
// This function is also used to prefetch an image in `script::dom::servoparser::prefetch`.
pub(crate) fn image_fetch_request(
img_url: ServoUrl,
origin: ImmutableOrigin,
referrer: Referrer,
pipeline_id: PipelineId,
cors_setting: Option<CorsSettings>,
referrer_policy: ReferrerPolicy,
from_picture_or_srcset: FromPictureOrSrcSet,
) -> RequestBuilder {
let mut request =
create_a_potential_cors_request(img_url, Destination::Image, cors_setting, None, referrer)
.origin(origin)
.pipeline_id(Some(pipeline_id))
.referrer_policy(referrer_policy);
if from_picture_or_srcset == FromPictureOrSrcSet::Yes {
request = request.initiator(Initiator::ImageSet);
}
request
}
#[allow(non_snake_case)] #[allow(non_snake_case)]
impl HTMLImageElement { impl HTMLImageElement {
/// Update the current image with a valid URL. /// Update the current image with a valid URL.
@ -445,19 +414,23 @@ impl HTMLImageElement {
url: img_url.clone(), url: img_url.clone(),
}; };
let request = image_fetch_request( // https://html.spec.whatwg.org/multipage/#update-the-image-data steps 17-20
// This function is also used to prefetch an image in `script::dom::servoparser::prefetch`.
let mut request = create_a_potential_cors_request(
Some(window.webview_id()),
img_url.clone(), img_url.clone(),
document.origin().immutable().clone(), Destination::Image,
document.global().get_referrer(),
document.global().pipeline_id(),
cors_setting_for_element(self.upcast()), cors_setting_for_element(self.upcast()),
referrer_policy_for_element(self.upcast()), None,
document.global().get_referrer(),
)
.origin(document.origin().immutable().clone())
.pipeline_id(Some(document.global().pipeline_id()))
.referrer_policy(referrer_policy_for_element(self.upcast()));
if Self::uses_srcset_or_picture(self.upcast()) { if Self::uses_srcset_or_picture(self.upcast()) {
FromPictureOrSrcSet::Yes request = request.initiator(Initiator::ImageSet);
} else { }
FromPictureOrSrcSet::No
},
);
// This is a background load because the load blocker already fulfills the // This is a background load because the load blocker already fulfills the
// purpose of delaying the document's load event. // purpose of delaying the document's load event.

View file

@ -24,7 +24,6 @@ use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::FileManagerThreadMsg; use net_traits::filemanager_thread::FileManagerThreadMsg;
use net_traits::{CoreResourceMsg, IpcSend}; use net_traits::{CoreResourceMsg, IpcSend};
use profile_traits::ipc; use profile_traits::ipc;
use script_traits::ScriptToConstellationChan;
use servo_atoms::Atom; use servo_atoms::Atom;
use style::attr::AttrValue; use style::attr::AttrValue;
use style::str::{split_commas, str_join}; use style::str::{split_commas, str_join};
@ -34,6 +33,7 @@ use unicode_bidi::{bidi_class, BidiClass};
use url::Url; use url::Url;
use super::bindings::str::{FromInputValueString, ToInputValueString}; use super::bindings::str::{FromInputValueString, ToInputValueString};
use crate::clipboard_provider::EmbedderClipboardProvider;
use crate::dom::activation::Activatable; use crate::dom::activation::Activatable;
use crate::dom::attr::Attr; use crate::dom::attr::Attr;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
@ -299,7 +299,7 @@ pub(crate) struct HTMLInputElement {
minlength: Cell<i32>, minlength: Cell<i32>,
#[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"] #[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"]
#[no_trace] #[no_trace]
textinput: DomRefCell<TextInput<ScriptToConstellationChan>>, textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
// https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag // https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag
value_dirty: Cell<bool>, value_dirty: Cell<bool>,
// not specified explicitly, but implied by the fact that sanitization can't // not specified explicitly, but implied by the fact that sanitization can't
@ -334,7 +334,7 @@ impl HTMLInputElement {
prefix: Option<Prefix>, prefix: Option<Prefix>,
document: &Document, document: &Document,
) -> HTMLInputElement { ) -> HTMLInputElement {
let chan = document let constellation_sender = document
.window() .window()
.as_global_scope() .as_global_scope()
.script_to_constellation_chan() .script_to_constellation_chan()
@ -355,7 +355,10 @@ impl HTMLInputElement {
textinput: DomRefCell::new(TextInput::new( textinput: DomRefCell::new(TextInput::new(
Single, Single,
DOMString::new(), DOMString::new(),
chan, EmbedderClipboardProvider {
constellation_sender,
webview_id: document.webview_id(),
},
None, None,
None, None,
SelectionDirection::None, SelectionDirection::None,
@ -1897,6 +1900,7 @@ impl HTMLInputElement {
let mut files: Vec<DomRoot<File>> = vec![]; let mut files: Vec<DomRoot<File>> = vec![];
let mut error = None; let mut error = None;
let webview_id = window.webview_id();
let filter = filter_from_accept(&self.Accept()); let filter = filter_from_accept(&self.Accept());
let target = self.upcast::<EventTarget>(); let target = self.upcast::<EventTarget>();
@ -1906,7 +1910,8 @@ impl HTMLInputElement {
let (chan, recv) = ipc::channel(self.global().time_profiler_chan().clone()) let (chan, recv) = ipc::channel(self.global().time_profiler_chan().clone())
.expect("Error initializing channel"); .expect("Error initializing channel");
let msg = FileManagerThreadMsg::SelectFiles(filter, chan, origin, opt_test_paths); let msg =
FileManagerThreadMsg::SelectFiles(webview_id, filter, chan, origin, opt_test_paths);
resource_threads resource_threads
.send(CoreResourceMsg::ToFileManager(msg)) .send(CoreResourceMsg::ToFileManager(msg))
.unwrap(); .unwrap();
@ -1933,7 +1938,8 @@ impl HTMLInputElement {
let (chan, recv) = ipc::channel(self.global().time_profiler_chan().clone()) let (chan, recv) = ipc::channel(self.global().time_profiler_chan().clone())
.expect("Error initializing channel"); .expect("Error initializing channel");
let msg = FileManagerThreadMsg::SelectFile(filter, chan, origin, opt_test_path); let msg =
FileManagerThreadMsg::SelectFile(webview_id, filter, chan, origin, opt_test_path);
resource_threads resource_threads
.send(CoreResourceMsg::ToFileManager(msg)) .send(CoreResourceMsg::ToFileManager(msg))
.unwrap(); .unwrap();

View file

@ -6,6 +6,7 @@ use std::borrow::{Borrow, ToOwned};
use std::cell::Cell; use std::cell::Cell;
use std::default::Default; use std::default::Default;
use base::id::WebViewId;
use cssparser::{Parser as CssParser, ParserInput}; use cssparser::{Parser as CssParser, ParserInput};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg; use embedder_traits::EmbedderMsg;
@ -366,7 +367,7 @@ impl HTMLLinkElement {
// Step 4. Let request be the result of creating a link request given options. // Step 4. Let request be the result of creating a link request given options.
let url = options.base_url.clone(); let url = options.base_url.clone();
let Some(request) = options.create_link_request() else { let Some(request) = options.create_link_request(self.owner_window().webview_id()) else {
// Step 5. If request is null, then return. // Step 5. If request is null, then return.
return; return;
}; };
@ -466,7 +467,7 @@ impl HTMLLinkElement {
Ok(url) => { Ok(url) => {
let window = document.window(); let window = document.window();
if window.is_top_level() { if window.is_top_level() {
let msg = EmbedderMsg::NewFavicon(url.clone()); let msg = EmbedderMsg::NewFavicon(document.webview_id(), url.clone());
window.send_to_embedder(msg); window.send_to_embedder(msg);
} }
}, },
@ -626,7 +627,7 @@ impl HTMLLinkElementMethods<crate::DomTypeHolder> for HTMLLinkElement {
impl LinkProcessingOptions { impl LinkProcessingOptions {
/// <https://html.spec.whatwg.org/multipage/#create-a-link-request> /// <https://html.spec.whatwg.org/multipage/#create-a-link-request>
fn create_link_request(self) -> Option<RequestBuilder> { fn create_link_request(self, webview_id: WebViewId) -> Option<RequestBuilder> {
// Step 1. Assert: options's href is not the empty string. // Step 1. Assert: options's href is not the empty string.
assert!(!self.href.is_empty()); assert!(!self.href.is_empty());
@ -651,6 +652,7 @@ impl LinkProcessingOptions {
// FIXME: Step 11. Set request's priority to options's fetch priority. // FIXME: Step 11. Set request's priority to options's fetch priority.
// FIXME: Use correct referrer // FIXME: Use correct referrer
let builder = create_a_potential_cors_request( let builder = create_a_potential_cors_request(
Some(webview_id),
url, url,
destination, destination,
self.cross_origin, self.cross_origin,

View file

@ -885,6 +885,7 @@ impl HTMLMediaElement {
let cors_setting = cors_setting_for_element(self.upcast()); let cors_setting = cors_setting_for_element(self.upcast());
let request = create_a_potential_cors_request( let request = create_a_potential_cors_request(
Some(document.webview_id()),
url.clone(), url.clone(),
destination, destination,
cors_setting, cors_setting,

View file

@ -11,7 +11,7 @@ use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use base::id::PipelineId; use base::id::{PipelineId, WebViewId};
use content_security_policy as csp; use content_security_policy as csp;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use encoding_rs::Encoding; use encoding_rs::Encoding;
@ -542,6 +542,7 @@ impl PreInvoke for ClassicContext {}
/// Steps 1-2 of <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script> /// Steps 1-2 of <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script>
// This function is also used to prefetch a script in `script::dom::servoparser::prefetch`. // This function is also used to prefetch a script in `script::dom::servoparser::prefetch`.
pub(crate) fn script_fetch_request( pub(crate) fn script_fetch_request(
webview_id: WebViewId,
url: ServoUrl, url: ServoUrl,
cors_setting: Option<CorsSettings>, cors_setting: Option<CorsSettings>,
origin: ImmutableOrigin, origin: ImmutableOrigin,
@ -551,6 +552,7 @@ pub(crate) fn script_fetch_request(
// We intentionally ignore options' credentials_mode member for classic scripts. // We intentionally ignore options' credentials_mode member for classic scripts.
// The mode is initialized by create_a_potential_cors_request. // The mode is initialized by create_a_potential_cors_request.
create_a_potential_cors_request( create_a_potential_cors_request(
Some(webview_id),
url, url,
Destination::Script, Destination::Script,
cors_setting, cors_setting,
@ -576,6 +578,7 @@ fn fetch_a_classic_script(
// Step 1, 2. // Step 1, 2.
let doc = script.owner_document(); let doc = script.owner_document();
let request = script_fetch_request( let request = script_fetch_request(
doc.webview_id(),
url.clone(), url.clone(),
cors_setting, cors_setting,
doc.origin().immutable().clone(), doc.origin().immutable().clone(),

View file

@ -9,10 +9,10 @@ use std::ops::Range;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix}; use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
use js::rust::HandleObject; use js::rust::HandleObject;
use script_traits::ScriptToConstellationChan;
use style::attr::AttrValue; use style::attr::AttrValue;
use style_dom::ElementState; use style_dom::ElementState;
use crate::clipboard_provider::EmbedderClipboardProvider;
use crate::dom::attr::Attr; use crate::dom::attr::Attr;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods; use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
@ -52,7 +52,7 @@ pub(crate) struct HTMLTextAreaElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
#[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"] #[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"]
#[no_trace] #[no_trace]
textinput: DomRefCell<TextInput<ScriptToConstellationChan>>, textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
placeholder: DomRefCell<DOMString>, placeholder: DomRefCell<DOMString>,
// https://html.spec.whatwg.org/multipage/#concept-textarea-dirty // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
value_dirty: Cell<bool>, value_dirty: Cell<bool>,
@ -142,7 +142,7 @@ impl HTMLTextAreaElement {
prefix: Option<Prefix>, prefix: Option<Prefix>,
document: &Document, document: &Document,
) -> HTMLTextAreaElement { ) -> HTMLTextAreaElement {
let chan = document let constellation_sender = document
.window() .window()
.as_global_scope() .as_global_scope()
.script_to_constellation_chan() .script_to_constellation_chan()
@ -158,7 +158,10 @@ impl HTMLTextAreaElement {
textinput: DomRefCell::new(TextInput::new( textinput: DomRefCell::new(TextInput::new(
Lines::Multiple, Lines::Multiple,
DOMString::new(), DOMString::new(),
chan, EmbedderClipboardProvider {
constellation_sender,
webview_id: document.webview_id(),
},
None, None,
None, None,
SelectionDirection::None, SelectionDirection::None,

View file

@ -223,7 +223,11 @@ impl HTMLVideoElement {
fn do_fetch_poster_frame(&self, poster_url: ServoUrl, id: PendingImageId, can_gc: CanGc) { fn do_fetch_poster_frame(&self, poster_url: ServoUrl, id: PendingImageId, can_gc: CanGc) {
// Continuation of step 4. // Continuation of step 4.
let document = self.owner_document(); let document = self.owner_document();
let request = RequestBuilder::new(poster_url.clone(), document.global().get_referrer()) let request = RequestBuilder::new(
Some(document.webview_id()),
poster_url.clone(),
document.global().get_referrer(),
)
.destination(Destination::Image) .destination(Destination::Image)
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.use_url_credentials(true) .use_url_credentials(true)

View file

@ -362,8 +362,12 @@ fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
} }
fn prompt_user_from_embedder(prompt: PermissionPrompt, gs: &GlobalScope) -> PermissionState { fn prompt_user_from_embedder(prompt: PermissionPrompt, gs: &GlobalScope) -> PermissionState {
let Some(webview_id) = gs.webview_id() else {
warn!("Requesting permissions from non-webview-associated global scope");
return PermissionState::Denied;
};
let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!"); let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!");
gs.send_to_embedder(EmbedderMsg::PromptPermission(prompt, sender)); gs.send_to_embedder(EmbedderMsg::PromptPermission(webview_id, prompt, sender));
match receiver.recv() { match receiver.recv() {
Ok(PermissionRequest::Granted) => PermissionState::Granted, Ok(PermissionRequest::Granted) => PermissionState::Granted,

View file

@ -108,7 +108,7 @@ impl Request {
} }
fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest { fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
RequestBuilder::new(url, global.get_referrer()) RequestBuilder::new(global.webview_id(), url, global.get_referrer())
.origin(global.get_url().origin()) .origin(global.get_url().origin())
.pipeline_id(Some(global.pipeline_id())) .pipeline_id(Some(global.pipeline_id()))
.https_state(global.get_https_state()) .https_state(global.get_https_state())

View file

@ -334,7 +334,7 @@ impl ServiceWorkerGlobalScope {
.map(Referrer::ReferrerUrl) .map(Referrer::ReferrerUrl)
.unwrap_or_else(|| global.upcast::<GlobalScope>().get_referrer()); .unwrap_or_else(|| global.upcast::<GlobalScope>().get_referrer());
let request = RequestBuilder::new(script_url, referrer) let request = RequestBuilder::new(None, script_url, referrer)
.destination(Destination::ServiceWorker) .destination(Destination::ServiceWorker)
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.parser_metadata(ParserMetadata::NotParserInserted) .parser_metadata(ParserMetadata::NotParserInserted)

View file

@ -4,7 +4,8 @@
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use base::id::PipelineId; use base::id::{PipelineId, WebViewId};
use content_security_policy::Destination;
use html5ever::buffer_queue::BufferQueue; use html5ever::buffer_queue::BufferQueue;
use html5ever::tokenizer::states::RawKind; use html5ever::tokenizer::states::RawKind;
use html5ever::tokenizer::{ use html5ever::tokenizer::{
@ -19,10 +20,9 @@ use servo_url::{ImmutableOrigin, ServoUrl};
use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::trace::{CustomTraceable, JSTraceable}; use crate::dom::bindings::trace::{CustomTraceable, JSTraceable};
use crate::dom::document::{determine_policy_for_token, Document}; use crate::dom::document::{determine_policy_for_token, Document};
use crate::dom::htmlimageelement::{image_fetch_request, FromPictureOrSrcSet};
use crate::dom::htmlscriptelement::script_fetch_request; use crate::dom::htmlscriptelement::script_fetch_request;
use crate::fetch::create_a_potential_cors_request;
use crate::script_module::ScriptFetchOptions; use crate::script_module::ScriptFetchOptions;
use crate::stylesheet_loader::stylesheet_fetch_request;
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
@ -43,6 +43,7 @@ impl Tokenizer {
let sink = PrefetchSink { let sink = PrefetchSink {
origin: document.origin().immutable().clone(), origin: document.origin().immutable().clone(),
pipeline_id: document.global().pipeline_id(), pipeline_id: document.global().pipeline_id(),
webview_id: document.webview_id(),
base_url: RefCell::new(None), base_url: RefCell::new(None),
document_url: document.url(), document_url: document.url(),
referrer: document.global().get_referrer(), referrer: document.global().get_referrer(),
@ -70,6 +71,8 @@ struct PrefetchSink {
#[no_trace] #[no_trace]
pipeline_id: PipelineId, pipeline_id: PipelineId,
#[no_trace] #[no_trace]
webview_id: WebViewId,
#[no_trace]
document_url: ServoUrl, document_url: ServoUrl,
#[no_trace] #[no_trace]
base_url: RefCell<Option<ServoUrl>>, base_url: RefCell<Option<ServoUrl>>,
@ -102,6 +105,7 @@ impl TokenSink for PrefetchSink {
.map(|attr| String::from(&attr.value)) .map(|attr| String::from(&attr.value))
.unwrap_or_default(); .unwrap_or_default();
let request = script_fetch_request( let request = script_fetch_request(
self.webview_id,
url, url,
cors_setting, cors_setting,
self.origin.clone(), self.origin.clone(),
@ -124,15 +128,18 @@ impl TokenSink for PrefetchSink {
(TagKind::StartTag, &local_name!("img")) if self.prefetching.get() => { (TagKind::StartTag, &local_name!("img")) if self.prefetching.get() => {
if let Some(url) = self.get_url(tag, local_name!("src")) { if let Some(url) = self.get_url(tag, local_name!("src")) {
debug!("Prefetch {} {}", tag.name, url); debug!("Prefetch {} {}", tag.name, url);
let request = image_fetch_request( let request = create_a_potential_cors_request(
Some(self.webview_id),
url, url,
self.origin.clone(), Destination::Image,
self.referrer.clone(),
self.pipeline_id,
self.get_cors_settings(tag, local_name!("crossorigin")), self.get_cors_settings(tag, local_name!("crossorigin")),
self.get_referrer_policy(tag, local_name!("referrerpolicy")), None,
FromPictureOrSrcSet::No, self.referrer.clone(),
); )
.origin(self.origin.clone())
.pipeline_id(Some(self.pipeline_id))
.referrer_policy(self.get_referrer_policy(tag, local_name!("referrerpolicy")));
let _ = self let _ = self
.resource_threads .resource_threads
.send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch));
@ -152,15 +159,21 @@ impl TokenSink for PrefetchSink {
.get_attr(tag, local_name!("integrity")) .get_attr(tag, local_name!("integrity"))
.map(|attr| String::from(&attr.value)) .map(|attr| String::from(&attr.value))
.unwrap_or_default(); .unwrap_or_default();
let request = stylesheet_fetch_request(
// https://html.spec.whatwg.org/multipage/#default-fetch-and-process-the-linked-resource
let request = create_a_potential_cors_request(
Some(self.webview_id),
url, url,
Destination::Style,
cors_setting, cors_setting,
self.origin.clone(), None,
self.pipeline_id,
self.referrer.clone(), self.referrer.clone(),
referrer_policy, )
integrity_metadata, .origin(self.origin.clone())
); .pipeline_id(Some(self.pipeline_id))
.referrer_policy(referrer_policy)
.integrity_metadata(integrity_metadata);
let _ = self let _ = self
.resource_threads .resource_threads
.send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch));

View file

@ -7,8 +7,7 @@
//! //!
//! <https://html.spec.whatwg.org/multipage/#textFieldSelection> //! <https://html.spec.whatwg.org/multipage/#textFieldSelection>
use script_traits::ScriptToConstellationChan; use crate::clipboard_provider::EmbedderClipboardProvider;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode; use crate::dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode;
use crate::dom::bindings::conversions::DerivedFrom; use crate::dom::bindings::conversions::DerivedFrom;
@ -27,13 +26,13 @@ pub(crate) trait TextControlElement: DerivedFrom<EventTarget> + DerivedFrom<Node
pub(crate) struct TextControlSelection<'a, E: TextControlElement> { pub(crate) struct TextControlSelection<'a, E: TextControlElement> {
element: &'a E, element: &'a E,
textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>, textinput: &'a DomRefCell<TextInput<EmbedderClipboardProvider>>,
} }
impl<'a, E: TextControlElement> TextControlSelection<'a, E> { impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
pub(crate) fn new( pub(crate) fn new(
element: &'a E, element: &'a E,
textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>, textinput: &'a DomRefCell<TextInput<EmbedderClipboardProvider>>,
) -> Self { ) -> Self {
TextControlSelection { element, textinput } TextControlSelection { element, textinput }
} }

View file

@ -255,7 +255,7 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
let ws = WebSocket::new(global, proto, url_record.clone(), dom_action_sender, can_gc); let ws = WebSocket::new(global, proto, url_record.clone(), dom_action_sender, can_gc);
let address = Trusted::new(&*ws); let address = Trusted::new(&*ws);
let request = RequestBuilder::new(url_record, Referrer::NoReferrer) let request = RequestBuilder::new(global.webview_id(), url_record, Referrer::NoReferrer)
.origin(global.origin().immutable().clone()) .origin(global.origin().immutable().clone())
.mode(RequestMode::WebSocket { protocols }); .mode(RequestMode::WebSocket { protocols });

View file

@ -17,7 +17,7 @@ use std::time::{Duration, Instant};
use app_units::Au; use app_units::Au;
use backtrace::Backtrace; use backtrace::Backtrace;
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::{BrowsingContextId, PipelineId}; use base::id::{BrowsingContextId, PipelineId, WebViewId};
use base64::Engine; use base64::Engine;
use bluetooth_traits::BluetoothRequest; use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLChan; use canvas_traits::webgl::WebGLChan;
@ -209,6 +209,11 @@ impl LayoutBlocker {
#[dom_struct] #[dom_struct]
pub(crate) struct Window { pub(crate) struct Window {
globalscope: GlobalScope, globalscope: GlobalScope,
/// The webview that contains this [`Window`].
///
/// This may not be the top-level [`Window`], in the case of frames.
#[no_trace]
webview_id: WebViewId,
script_chan: Sender<MainThreadScriptMsg>, script_chan: Sender<MainThreadScriptMsg>,
#[no_trace] #[no_trace]
#[ignore_malloc_size_of = "TODO: Add MallocSizeOf support to layout"] #[ignore_malloc_size_of = "TODO: Add MallocSizeOf support to layout"]
@ -391,6 +396,10 @@ pub(crate) struct Window {
} }
impl Window { impl Window {
pub(crate) fn webview_id(&self) -> WebViewId {
self.webview_id
}
pub(crate) fn as_global_scope(&self) -> &GlobalScope { pub(crate) fn as_global_scope(&self) -> &GlobalScope {
self.upcast::<GlobalScope>() self.upcast::<GlobalScope>()
} }
@ -726,7 +735,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
let (sender, receiver) = let (sender, receiver) =
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
let prompt = PromptDefinition::Alert(s.to_string(), sender); let prompt = PromptDefinition::Alert(s.to_string(), sender);
let msg = EmbedderMsg::Prompt(prompt, PromptOrigin::Untrusted); let msg = EmbedderMsg::Prompt(self.webview_id(), prompt, PromptOrigin::Untrusted);
self.send_to_embedder(msg); self.send_to_embedder(msg);
receiver.recv().unwrap(); receiver.recv().unwrap();
} }
@ -736,7 +745,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
let (sender, receiver) = let (sender, receiver) =
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
let prompt = PromptDefinition::OkCancel(s.to_string(), sender); let prompt = PromptDefinition::OkCancel(s.to_string(), sender);
let msg = EmbedderMsg::Prompt(prompt, PromptOrigin::Untrusted); let msg = EmbedderMsg::Prompt(self.webview_id(), prompt, PromptOrigin::Untrusted);
self.send_to_embedder(msg); self.send_to_embedder(msg);
receiver.recv().unwrap() == PromptResult::Primary receiver.recv().unwrap() == PromptResult::Primary
} }
@ -746,7 +755,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
let (sender, receiver) = let (sender, receiver) =
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
let prompt = PromptDefinition::Input(message.to_string(), default.to_string(), sender); let prompt = PromptDefinition::Input(message.to_string(), default.to_string(), sender);
let msg = EmbedderMsg::Prompt(prompt, PromptOrigin::Untrusted); let msg = EmbedderMsg::Prompt(self.webview_id(), prompt, PromptOrigin::Untrusted);
self.send_to_embedder(msg); self.send_to_embedder(msg);
receiver.recv().unwrap().map(|s| s.into()) receiver.recv().unwrap().map(|s| s.into())
} }
@ -1322,7 +1331,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
//TODO determine if this operation is allowed //TODO determine if this operation is allowed
let dpr = self.device_pixel_ratio(); let dpr = self.device_pixel_ratio();
let size = Size2D::new(width, height).to_f32() * dpr; let size = Size2D::new(width, height).to_f32() * dpr;
self.send_to_embedder(EmbedderMsg::ResizeTo(size.to_i32())); self.send_to_embedder(EmbedderMsg::ResizeTo(self.webview_id(), size.to_i32()));
} }
// https://drafts.csswg.org/cssom-view/#dom-window-resizeby // https://drafts.csswg.org/cssom-view/#dom-window-resizeby
@ -1341,7 +1350,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
//TODO determine if this operation is allowed //TODO determine if this operation is allowed
let dpr = self.device_pixel_ratio(); let dpr = self.device_pixel_ratio();
let point = Point2D::new(x, y).to_f32() * dpr; let point = Point2D::new(x, y).to_f32() * dpr;
let msg = EmbedderMsg::MoveTo(point.to_i32()); let msg = EmbedderMsg::MoveTo(self.webview_id(), point.to_i32());
self.send_to_embedder(msg); self.send_to_embedder(msg);
} }
@ -2738,6 +2747,7 @@ impl Window {
#[allow(unsafe_code)] #[allow(unsafe_code)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(crate) fn new( pub(crate) fn new(
webview_id: WebViewId,
runtime: Rc<Runtime>, runtime: Rc<Runtime>,
script_chan: Sender<MainThreadScriptMsg>, script_chan: Sender<MainThreadScriptMsg>,
layout: Box<dyn Layout>, layout: Box<dyn Layout>,
@ -2786,6 +2796,7 @@ impl Window {
)); ));
let win = Box::new(Self { let win = Box::new(Self {
webview_id,
globalscope: GlobalScope::new_inherited( globalscope: GlobalScope::new_inherited(
pipeline_id, pipeline_id,
devtools_chan, devtools_chan,

View file

@ -292,7 +292,7 @@ impl WindowProxy {
.and_then(ScriptThread::find_document) .and_then(ScriptThread::find_document)
.map(|doc| DomRoot::from_ref(doc.window())) .map(|doc| DomRoot::from_ref(doc.window()))
.unwrap(); .unwrap();
let msg = EmbedderMsg::AllowOpeningWebView(chan); let msg = EmbedderMsg::AllowOpeningWebView(window.webview_id(), chan);
window.send_to_embedder(msg); window.send_to_embedder(msg);
if let Some(new_top_level_browsing_context_id) = port.recv().unwrap() { if let Some(new_top_level_browsing_context_id) = port.recv().unwrap() {
let new_browsing_context_id = let new_browsing_context_id =

View file

@ -278,7 +278,11 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
rooted!(in(self.runtime.borrow().as_ref().unwrap().cx()) let mut rval = UndefinedValue()); rooted!(in(self.runtime.borrow().as_ref().unwrap().cx()) let mut rval = UndefinedValue());
for url in urls { for url in urls {
let global_scope = self.upcast::<GlobalScope>(); let global_scope = self.upcast::<GlobalScope>();
let request = NetRequestInit::new(url.clone(), global_scope.get_referrer()) let request = NetRequestInit::new(
global_scope.webview_id(),
url.clone(),
global_scope.get_referrer(),
)
.destination(Destination::Script) .destination(Destination::Script)
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.parser_metadata(ParserMetadata::NotParserInserted) .parser_metadata(ParserMetadata::NotParserInserted)

View file

@ -652,6 +652,7 @@ impl WorkletThread {
// TODO: Caching. // TODO: Caching.
let resource_fetcher = self.global_init.resource_threads.sender(); let resource_fetcher = self.global_init.resource_threads.sender();
let request = RequestBuilder::new( let request = RequestBuilder::new(
None,
script_url, script_url,
global_scope.upcast::<GlobalScope>().get_referrer(), global_scope.upcast::<GlobalScope>().get_referrer(),
) )

View file

@ -673,6 +673,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
}; };
let mut request = RequestBuilder::new( let mut request = RequestBuilder::new(
self.global().webview_id(),
self.request_url.borrow().clone().unwrap(), self.request_url.borrow().clone().unwrap(),
self.referrer.clone(), self.referrer.clone(),
) )

View file

@ -5,6 +5,7 @@
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use base::id::WebViewId;
use ipc_channel::ipc; use ipc_channel::ipc;
use net_traits::policy_container::RequestPolicyContainer; use net_traits::policy_container::RequestPolicyContainer;
use net_traits::request::{ use net_traits::request::{
@ -113,7 +114,7 @@ fn request_init_from_request(request: NetTraitsRequest) -> RequestBuilder {
referrer: request.referrer.clone(), referrer: request.referrer.clone(),
referrer_policy: request.referrer_policy, referrer_policy: request.referrer_policy,
pipeline_id: request.pipeline_id, pipeline_id: request.pipeline_id,
target_browsing_context_id: request.target_browsing_context_id, target_webview_id: request.target_webview_id,
redirect_mode: request.redirect_mode, redirect_mode: request.redirect_mode,
integrity_metadata: request.integrity_metadata.clone(), integrity_metadata: request.integrity_metadata.clone(),
url_list: vec![], url_list: vec![],
@ -366,13 +367,14 @@ pub(crate) fn load_whole_resource(
/// <https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request> /// <https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request>
pub(crate) fn create_a_potential_cors_request( pub(crate) fn create_a_potential_cors_request(
webview_id: Option<WebViewId>,
url: ServoUrl, url: ServoUrl,
destination: Destination, destination: Destination,
cors_setting: Option<CorsSettings>, cors_setting: Option<CorsSettings>,
same_origin_fallback: Option<bool>, same_origin_fallback: Option<bool>,
referrer: Referrer, referrer: Referrer,
) -> RequestBuilder { ) -> RequestBuilder {
RequestBuilder::new(url, referrer) RequestBuilder::new(webview_id, url, referrer)
// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
// Step 1 // Step 1
.mode(match cors_setting { .mode(match cors_setting {

View file

@ -106,7 +106,11 @@ pub(crate) fn fetch_image_for_layout(
url: url.clone(), url: url.clone(),
}; };
let request = FetchRequestInit::new(url, document.global().get_referrer()) let request = FetchRequestInit::new(
Some(document.webview_id()),
url,
document.global().get_referrer(),
)
.origin(document.origin().immutable().clone()) .origin(document.origin().immutable().clone())
.destination(Destination::Image) .destination(Destination::Image)
.pipeline_id(Some(document.global().pipeline_id())); .pipeline_id(Some(document.global().pipeline_id()));

View file

@ -192,15 +192,17 @@ impl InProgressLoad {
pub(crate) fn request_builder(&mut self) -> RequestBuilder { pub(crate) fn request_builder(&mut self) -> RequestBuilder {
let id = self.pipeline_id; let id = self.pipeline_id;
let top_level_browsing_context_id = self.top_level_browsing_context_id; let top_level_browsing_context_id = self.top_level_browsing_context_id;
let mut request_builder = let mut request_builder = RequestBuilder::new(
RequestBuilder::new(self.load_data.url.clone(), self.load_data.referrer.clone()) Some(top_level_browsing_context_id),
self.load_data.url.clone(),
self.load_data.referrer.clone(),
)
.method(self.load_data.method.clone()) .method(self.load_data.method.clone())
.destination(Destination::Document) .destination(Destination::Document)
.mode(RequestMode::Navigate) .mode(RequestMode::Navigate)
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.use_url_credentials(true) .use_url_credentials(true)
.pipeline_id(Some(id)) .pipeline_id(Some(id))
.target_browsing_context_id(Some(top_level_browsing_context_id))
.referrer_policy(self.load_data.referrer_policy) .referrer_policy(self.load_data.referrer_policy)
.headers(self.load_data.headers.clone()) .headers(self.load_data.headers.clone())
.body(self.load_data.data.clone()) .body(self.load_data.data.clone())

View file

@ -1745,9 +1745,10 @@ fn fetch_single_module_script(
ModuleOwner::Worker(_) | ModuleOwner::DynamicModule(_) => None, ModuleOwner::Worker(_) | ModuleOwner::DynamicModule(_) => None,
ModuleOwner::Window(script) => Some(script.root().owner_document()), ModuleOwner::Window(script) => Some(script.root().owner_document()),
}; };
let webview_id = document.as_ref().map(|document| document.webview_id());
// Step 7-8. // Step 7-8.
let request = RequestBuilder::new(url.clone(), global.get_referrer()) let request = RequestBuilder::new(webview_id, url.clone(), global.get_referrer())
.destination(destination) .destination(destination)
.origin(global.origin().immutable().clone()) .origin(global.origin().immutable().clone())
.parser_metadata(options.parser_metadata) .parser_metadata(options.parser_metadata)

View file

@ -1052,7 +1052,7 @@ impl ScriptThread {
let url = document.url(); let url = document.url();
url.join(&value).map(|url| url.to_string()).ok() url.join(&value).map(|url| url.to_string()).ok()
}); });
let event = EmbedderMsg::Status(status); let event = EmbedderMsg::Status(window.webview_id(), status);
window.send_to_embedder(event); window.send_to_embedder(event);
state_already_changed = true; state_already_changed = true;
@ -1069,7 +1069,7 @@ impl ScriptThread {
.next() .next()
.is_some() .is_some()
{ {
let event = EmbedderMsg::Status(None); let event = EmbedderMsg::Status(window.webview_id(), None);
window.send_to_embedder(event); window.send_to_embedder(event);
} }
} }
@ -3101,9 +3101,9 @@ impl ScriptThread {
let layout_config = LayoutConfig { let layout_config = LayoutConfig {
id: incomplete.pipeline_id, id: incomplete.pipeline_id,
webview_id: incomplete.top_level_browsing_context_id,
url: final_url.clone(), url: final_url.clone(),
is_iframe: incomplete.parent_info.is_some(), is_iframe: incomplete.parent_info.is_some(),
constellation_chan: self.senders.layout_to_constellation_ipc_sender.clone(),
script_chan: self.senders.constellation_sender.clone(), script_chan: self.senders.constellation_sender.clone(),
image_cache: self.image_cache.clone(), image_cache: self.image_cache.clone(),
font_context: font_context.clone(), font_context: font_context.clone(),
@ -3115,6 +3115,7 @@ impl ScriptThread {
// Create the window and document objects. // Create the window and document objects.
let window = Window::new( let window = Window::new(
incomplete.top_level_browsing_context_id,
self.js_runtime.clone(), self.js_runtime.clone(),
self.senders.self_sender.clone(), self.senders.self_sender.clone(),
self.layout_factory.create(layout_config), self.layout_factory.create(layout_config),

View file

@ -5,17 +5,16 @@
use std::io::{Read, Seek, Write}; use std::io::{Read, Seek, Write};
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use base::id::PipelineId;
use cssparser::SourceLocation; use cssparser::SourceLocation;
use encoding_rs::UTF_8; use encoding_rs::UTF_8;
use mime::{self, Mime}; use mime::{self, Mime};
use net_traits::request::{CorsSettings, Destination, Referrer, RequestBuilder, RequestId}; use net_traits::request::{CorsSettings, Destination, RequestId};
use net_traits::{ use net_traits::{
FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy,
ResourceFetchTiming, ResourceTimingType, ResourceFetchTiming, ResourceTimingType,
}; };
use servo_arc::Arc; use servo_arc::Arc;
use servo_url::{ImmutableOrigin, ServoUrl}; use servo_url::ServoUrl;
use style::media_queries::MediaList; use style::media_queries::MediaList;
use style::parser::ParserContext; use style::parser::ParserContext;
use style::shared_lock::{Locked, SharedRwLock}; use style::shared_lock::{Locked, SharedRwLock};
@ -343,39 +342,24 @@ impl StylesheetLoader<'_> {
document.increment_script_blocking_stylesheet_count(); document.increment_script_blocking_stylesheet_count();
} }
let request = stylesheet_fetch_request( // https://html.spec.whatwg.org/multipage/#default-fetch-and-process-the-linked-resource
let request = create_a_potential_cors_request(
Some(document.webview_id()),
url.clone(), url.clone(),
Destination::Style,
cors_setting, cors_setting,
document.origin().immutable().clone(), None,
self.elem.global().pipeline_id(),
self.elem.global().get_referrer(), self.elem.global().get_referrer(),
referrer_policy, )
integrity_metadata, .origin(document.origin().immutable().clone())
); .pipeline_id(Some(self.elem.global().pipeline_id()))
let request = document.prepare_request(request); .referrer_policy(referrer_policy)
.integrity_metadata(integrity_metadata);
document.fetch(LoadType::Stylesheet(url), request, context); document.fetch(LoadType::Stylesheet(url), request, context);
} }
} }
// This function is also used to prefetch a stylesheet in `script::dom::servoparser::prefetch`.
// https://html.spec.whatwg.org/multipage/#default-fetch-and-process-the-linked-resource
pub(crate) fn stylesheet_fetch_request(
url: ServoUrl,
cors_setting: Option<CorsSettings>,
origin: ImmutableOrigin,
pipeline_id: PipelineId,
referrer: Referrer,
referrer_policy: ReferrerPolicy,
integrity_metadata: String,
) -> RequestBuilder {
create_a_potential_cors_request(url, Destination::Style, cors_setting, None, referrer)
.origin(origin)
.pipeline_id(Some(pipeline_id))
.referrer_policy(referrer_policy)
.integrity_metadata(integrity_metadata)
}
impl StyleStylesheetLoader for StylesheetLoader<'_> { impl StyleStylesheetLoader for StylesheetLoader<'_> {
/// Request a stylesheet after parsing a given `@import` rule, and return /// Request a stylesheet after parsing a given `@import` rule, and return
/// the constructed `@import` rule. /// the constructed `@import` rule.

View file

@ -10,10 +10,9 @@ use std::default::Default;
use std::ops::{Add, AddAssign, Range}; use std::ops::{Add, AddAssign, Range};
use keyboard_types::{Key, KeyState, Modifiers, ShortcutMatcher}; use keyboard_types::{Key, KeyState, Modifiers, ShortcutMatcher};
use script_traits::ScriptToConstellationChan;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use crate::clipboard_provider::ClipboardProvider; use crate::clipboard_provider::{ClipboardProvider, EmbedderClipboardProvider};
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
@ -1150,7 +1149,7 @@ impl<T: ClipboardProvider> TextInput<T> {
/// <https://www.w3.org/TR/clipboard-apis/#clipboard-actions> step 3 /// <https://www.w3.org/TR/clipboard-apis/#clipboard-actions> step 3
pub(crate) fn handle_text_clipboard_action( pub(crate) fn handle_text_clipboard_action(
owning_node: &impl NodeTraits, owning_node: &impl NodeTraits,
textinput: &DomRefCell<TextInput<ScriptToConstellationChan>>, textinput: &DomRefCell<TextInput<EmbedderClipboardProvider>>,
event: &ClipboardEvent, event: &ClipboardEvent,
can_gc: CanGc, can_gc: CanGc,
) -> bool { ) -> bool {

View file

@ -128,7 +128,7 @@ impl ApplicationHandler<WakerEvent> for App {
webviews, webviews,
} = self } = self
{ {
for (_webview_id, message) in servo.get_events().collect::<Vec<_>>() { for message in servo.get_events().collect::<Vec<_>>() {
match message { match message {
// FIXME: rust-analyzer autocompletes this as top_level_browsing_context_id // FIXME: rust-analyzer autocompletes this as top_level_browsing_context_id
EmbedderMsg::WebViewOpened(webview_id) => { EmbedderMsg::WebViewOpened(webview_id) => {
@ -142,12 +142,12 @@ impl ApplicationHandler<WakerEvent> for App {
webview.raise_to_top(true); webview.raise_to_top(true);
} }
}, },
EmbedderMsg::AllowOpeningWebView(webview_id_sender) => { EmbedderMsg::AllowOpeningWebView(_, webview_id_sender) => {
let webview = servo.new_auxiliary_webview(); let webview = servo.new_auxiliary_webview();
let _ = webview_id_sender.send(Some(webview.id())); let _ = webview_id_sender.send(Some(webview.id()));
webviews.push(webview); webviews.push(webview);
}, },
EmbedderMsg::AllowNavigationRequest(pipeline_id, _) => { EmbedderMsg::AllowNavigationRequest(_, pipeline_id, _) => {
servo.handle_events([EmbedderEvent::AllowNavigationResponse( servo.handle_events([EmbedderEvent::AllowNavigationResponse(
pipeline_id, pipeline_id,
true, true,

View file

@ -53,7 +53,7 @@ use constellation::{
Constellation, FromCompositorLogger, FromScriptLogger, InitialConstellationState, Constellation, FromCompositorLogger, FromScriptLogger, InitialConstellationState,
UnprivilegedContent, UnprivilegedContent,
}; };
use crossbeam_channel::{unbounded, Sender}; use crossbeam_channel::{unbounded, Receiver, Sender};
pub use embedder_traits::*; pub use embedder_traits::*;
use env_logger::Builder as EnvLoggerBuilder; use env_logger::Builder as EnvLoggerBuilder;
use euclid::Scale; use euclid::Scale;
@ -187,8 +187,8 @@ mod media_platform {
pub struct Servo { pub struct Servo {
compositor: Rc<RefCell<IOCompositor>>, compositor: Rc<RefCell<IOCompositor>>,
constellation_proxy: ConstellationProxy, constellation_proxy: ConstellationProxy,
embedder_receiver: EmbedderReceiver, embedder_receiver: Receiver<EmbedderMsg>,
messages_for_embedder: Vec<(Option<TopLevelBrowsingContextId>, EmbedderMsg)>, messages_for_embedder: Vec<EmbedderMsg>,
/// For single-process Servo instances, this field controls the initialization /// For single-process Servo instances, this field controls the initialization
/// and deinitialization of the JS Engine. Multiprocess Servo instances have their /// and deinitialization of the JS Engine. Multiprocess Servo instances have their
/// own instance that exists in the content process instead. /// own instance that exists in the content process instead.
@ -738,20 +738,17 @@ impl Servo {
.on_pinch_zoom_window_event(zoom); .on_pinch_zoom_window_event(zoom);
}, },
EmbedderEvent::Navigation(top_level_browsing_context_id, direction) => { EmbedderEvent::Navigation(webview_id, direction) => {
let msg = let msg = ConstellationMsg::TraverseHistory(webview_id, direction);
ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction);
if let Err(e) = self.constellation_proxy.try_send(msg) { if let Err(e) = self.constellation_proxy.try_send(msg) {
warn!("Sending navigation to constellation failed ({:?}).", e); warn!("Sending navigation to constellation failed ({:?}).", e);
} }
self.messages_for_embedder.push(( self.messages_for_embedder
Some(top_level_browsing_context_id), .push(EmbedderMsg::Status(webview_id, None));
EmbedderMsg::Status(None),
));
}, },
EmbedderEvent::Keyboard(key_event) => { EmbedderEvent::Keyboard(webview_id, key_event) => {
let msg = ConstellationMsg::Keyboard(key_event); let msg = ConstellationMsg::Keyboard(webview_id, key_event);
if let Err(e) = self.constellation_proxy.try_send(msg) { if let Err(e) = self.constellation_proxy.try_send(msg) {
warn!("Sending keyboard event to constellation failed ({:?}).", e); warn!("Sending keyboard event to constellation failed ({:?}).", e);
} }
@ -930,10 +927,8 @@ impl Servo {
} }
fn receive_messages(&mut self) { fn receive_messages(&mut self) {
while let Some((top_level_browsing_context, msg)) = while let Ok(message) = self.embedder_receiver.try_recv() {
self.embedder_receiver.try_recv_embedder_msg() match (message, self.compositor.borrow().shutdown_state) {
{
match (msg, self.compositor.borrow().shutdown_state) {
(_, ShutdownState::FinishedShuttingDown) => { (_, ShutdownState::FinishedShuttingDown) => {
error!( error!(
"embedder shouldn't be handling messages after compositor has shut down" "embedder shouldn't be handling messages after compositor has shut down"
@ -942,20 +937,19 @@ impl Servo {
(_, ShutdownState::ShuttingDown) => {}, (_, ShutdownState::ShuttingDown) => {},
(EmbedderMsg::Keyboard(key_event), ShutdownState::NotShuttingDown) => { (EmbedderMsg::Keyboard(webview_id, key_event), ShutdownState::NotShuttingDown) => {
let event = (top_level_browsing_context, EmbedderMsg::Keyboard(key_event));
self.messages_for_embedder.push(event);
},
(msg, ShutdownState::NotShuttingDown) => {
self.messages_for_embedder self.messages_for_embedder
.push((top_level_browsing_context, msg)); .push(EmbedderMsg::Keyboard(webview_id, key_event));
},
(message, ShutdownState::NotShuttingDown) => {
self.messages_for_embedder.push(message);
}, },
} }
} }
} }
pub fn get_events(&mut self) -> Drain<'_, (Option<TopLevelBrowsingContextId>, EmbedderMsg)> { pub fn get_events(&mut self) -> Drain<'_, EmbedderMsg> {
self.messages_for_embedder.drain(..) self.messages_for_embedder.drain(..)
} }
@ -971,8 +965,7 @@ impl Servo {
if self.compositor.borrow().shutdown_state != ShutdownState::FinishedShuttingDown { if self.compositor.borrow().shutdown_state != ShutdownState::FinishedShuttingDown {
self.compositor.borrow_mut().perform_updates(); self.compositor.borrow_mut().perform_updates();
} else { } else {
self.messages_for_embedder self.messages_for_embedder.push(EmbedderMsg::Shutdown);
.push((None, EmbedderMsg::Shutdown));
} }
need_resize need_resize
} }
@ -1038,14 +1031,14 @@ impl Servo {
fn create_embedder_channel( fn create_embedder_channel(
event_loop_waker: Box<dyn EventLoopWaker>, event_loop_waker: Box<dyn EventLoopWaker>,
) -> (EmbedderProxy, EmbedderReceiver) { ) -> (EmbedderProxy, Receiver<EmbedderMsg>) {
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
( (
EmbedderProxy { EmbedderProxy {
sender, sender,
event_loop_waker, event_loop_waker,
}, },
EmbedderReceiver { receiver }, receiver,
) )
} }

View file

@ -202,7 +202,7 @@ impl WebView {
pub fn notify_keyboard_event(&self, event: KeyboardEvent) { pub fn notify_keyboard_event(&self, event: KeyboardEvent) {
self.0 self.0
.constellation_proxy .constellation_proxy
.send(ConstellationMsg::Keyboard(event)) .send(ConstellationMsg::Keyboard(self.id(), event))
} }
pub fn notify_ime_event(&self, event: CompositionEvent) { pub fn notify_ime_event(&self, event: CompositionEvent) {

View file

@ -443,3 +443,5 @@ pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId = BrowsingContextId {
namespace_id: TEST_NAMESPACE, namespace_id: TEST_NAMESPACE,
index: TEST_BROWSING_CONTEXT_INDEX, index: TEST_BROWSING_CONTEXT_INDEX,
}; };
pub const TEST_WEBVIEW_ID: WebViewId = TopLevelBrowsingContextId(TEST_BROWSING_CONTEXT_ID);

View file

@ -12,6 +12,7 @@ name = "bluetooth_traits"
path = "lib.rs" path = "lib.rs"
[dependencies] [dependencies]
base = { workspace = true }
embedder_traits = { workspace = true } embedder_traits = { workspace = true }
ipc-channel = { workspace = true } ipc-channel = { workspace = true }
regex = { workspace = true } regex = { workspace = true }

View file

@ -5,6 +5,7 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::slice::Iter; use std::slice::Iter;
use base::id::WebViewId;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// A device name can never be longer than 29 bytes. An adv packet is at most // A device name can never be longer than 29 bytes. An adv packet is at most
@ -114,21 +115,28 @@ impl BluetoothScanfilterSequence {
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct RequestDeviceoptions { pub struct RequestDeviceoptions {
webview_id: WebViewId,
filters: BluetoothScanfilterSequence, filters: BluetoothScanfilterSequence,
optional_services: ServiceUUIDSequence, optional_services: ServiceUUIDSequence,
} }
impl RequestDeviceoptions { impl RequestDeviceoptions {
pub fn new( pub fn new(
webview_id: WebViewId,
filters: BluetoothScanfilterSequence, filters: BluetoothScanfilterSequence,
services: ServiceUUIDSequence, services: ServiceUUIDSequence,
) -> RequestDeviceoptions { ) -> RequestDeviceoptions {
RequestDeviceoptions { RequestDeviceoptions {
webview_id,
filters, filters,
optional_services: services, optional_services: services,
} }
} }
pub fn webview_id(&self) -> WebViewId {
self.webview_id
}
pub fn get_filters(&self) -> &BluetoothScanfilterSequence { pub fn get_filters(&self) -> &BluetoothScanfilterSequence {
&self.filters &self.filters
} }

View file

@ -35,7 +35,7 @@ pub enum ConstellationMsg {
/// Query the constellation to see if the current compositor output is stable /// Query the constellation to see if the current compositor output is stable
IsReadyToSaveImage(HashMap<PipelineId, Epoch>), IsReadyToSaveImage(HashMap<PipelineId, Epoch>),
/// Inform the constellation of a key event. /// Inform the constellation of a key event.
Keyboard(KeyboardEvent), Keyboard(WebViewId, KeyboardEvent),
/// Inform the constellation of a composition event (IME). /// Inform the constellation of a composition event (IME).
IMECompositionEvent(CompositionEvent), IMECompositionEvent(CompositionEvent),
/// Whether to allow script to navigate. /// Whether to allow script to navigate.
@ -73,7 +73,7 @@ pub enum ConstellationMsg {
/// Forward an event to the script task of the given pipeline. /// Forward an event to the script task of the given pipeline.
ForwardEvent(PipelineId, CompositorEvent), ForwardEvent(PipelineId, CompositorEvent),
/// Requesting a change to the onscreen cursor. /// Requesting a change to the onscreen cursor.
SetCursor(Cursor), SetCursor(WebViewId, Cursor),
/// Enable the sampling profiler, with a given sampling rate and max total sampling duration. /// Enable the sampling profiler, with a given sampling rate and max total sampling duration.
ToggleProfiler(Duration, Duration), ToggleProfiler(Duration, Duration),
/// Request to exit from fullscreen mode /// Request to exit from fullscreen mode

View file

@ -6,8 +6,8 @@ pub mod resources;
use std::fmt::{Debug, Error, Formatter}; use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId}; use base::id::{PipelineId, WebViewId};
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::Sender;
use http::{HeaderMap, Method, StatusCode}; use http::{HeaderMap, Method, StatusCode};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use keyboard_types::KeyboardEvent; use keyboard_types::KeyboardEvent;
@ -77,14 +77,14 @@ impl Clone for Box<dyn EventLoopWaker> {
/// Sends messages to the embedder. /// Sends messages to the embedder.
pub struct EmbedderProxy { pub struct EmbedderProxy {
pub sender: Sender<(Option<TopLevelBrowsingContextId>, EmbedderMsg)>, pub sender: Sender<EmbedderMsg>,
pub event_loop_waker: Box<dyn EventLoopWaker>, pub event_loop_waker: Box<dyn EventLoopWaker>,
} }
impl EmbedderProxy { impl EmbedderProxy {
pub fn send(&self, msg: (Option<TopLevelBrowsingContextId>, EmbedderMsg)) { pub fn send(&self, message: EmbedderMsg) {
// Send a message and kick the OS event loop awake. // Send a message and kick the OS event loop awake.
if let Err(err) = self.sender.send(msg) { if let Err(err) = self.sender.send(message) {
warn!("Failed to send response ({:?}).", err); warn!("Failed to send response ({:?}).", err);
} }
self.event_loop_waker.wake(); self.event_loop_waker.wake();
@ -100,22 +100,6 @@ impl Clone for EmbedderProxy {
} }
} }
/// The port that the embedder receives messages on.
pub struct EmbedderReceiver {
pub receiver: Receiver<(Option<TopLevelBrowsingContextId>, EmbedderMsg)>,
}
impl EmbedderReceiver {
pub fn try_recv_embedder_msg(
&mut self,
) -> Option<(Option<TopLevelBrowsingContextId>, EmbedderMsg)> {
self.receiver.try_recv().ok()
}
pub fn recv_embedder_msg(&mut self) -> (Option<TopLevelBrowsingContextId>, EmbedderMsg) {
self.receiver.recv().unwrap()
}
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub enum ContextMenuResult { pub enum ContextMenuResult {
Dismissed, Dismissed,
@ -167,86 +151,108 @@ pub enum PromptResult {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub enum EmbedderMsg { pub enum EmbedderMsg {
/// A status message to be displayed by the browser chrome. /// A status message to be displayed by the browser chrome.
Status(Option<String>), Status(WebViewId, Option<String>),
/// Alerts the embedder that the current page has changed its title. /// Alerts the embedder that the current page has changed its title.
ChangePageTitle(Option<String>), ChangePageTitle(WebViewId, Option<String>),
/// Move the window to a point /// Move the window to a point
MoveTo(DeviceIntPoint), MoveTo(WebViewId, DeviceIntPoint),
/// Resize the window to size /// Resize the window to size
ResizeTo(DeviceIntSize), ResizeTo(WebViewId, DeviceIntSize),
/// Show dialog to user /// Show dialog to user
Prompt(PromptDefinition, PromptOrigin), Prompt(WebViewId, PromptDefinition, PromptOrigin),
/// Show a context menu to the user /// Show a context menu to the user
ShowContextMenu(IpcSender<ContextMenuResult>, Option<String>, Vec<String>), ShowContextMenu(
WebViewId,
IpcSender<ContextMenuResult>,
Option<String>,
Vec<String>,
),
/// Whether or not to allow a pipeline to load a url. /// Whether or not to allow a pipeline to load a url.
AllowNavigationRequest(PipelineId, ServoUrl), AllowNavigationRequest(WebViewId, PipelineId, ServoUrl),
/// Whether or not to allow script to open a new tab/browser /// Whether or not to allow script to open a new tab/browser
AllowOpeningWebView(IpcSender<Option<WebViewId>>), AllowOpeningWebView(WebViewId, IpcSender<Option<WebViewId>>),
/// A webview was created. /// A webview was created.
WebViewOpened(TopLevelBrowsingContextId), WebViewOpened(WebViewId),
/// A webview was destroyed. /// A webview was destroyed.
WebViewClosed(TopLevelBrowsingContextId), WebViewClosed(WebViewId),
/// A webview gained focus for keyboard events. /// A webview gained focus for keyboard events.
WebViewFocused(TopLevelBrowsingContextId), WebViewFocused(WebViewId),
/// All webviews lost focus for keyboard events. /// All webviews lost focus for keyboard events.
WebViewBlurred, WebViewBlurred,
/// Wether or not to unload a document /// Wether or not to unload a document
AllowUnload(IpcSender<bool>), AllowUnload(WebViewId, IpcSender<bool>),
/// Sends an unconsumed key event back to the embedder. /// Sends an unconsumed key event back to the embedder.
Keyboard(KeyboardEvent), Keyboard(WebViewId, KeyboardEvent),
/// Inform embedder to clear the clipboard /// Inform embedder to clear the clipboard
ClearClipboardContents, ClearClipboardContents(WebViewId),
/// Gets system clipboard contents /// Gets system clipboard contents
GetClipboardContents(IpcSender<String>), GetClipboardContents(WebViewId, IpcSender<String>),
/// Sets system clipboard contents /// Sets system clipboard contents
SetClipboardContents(String), SetClipboardContents(WebViewId, String),
/// Changes the cursor. /// Changes the cursor.
SetCursor(Cursor), SetCursor(WebViewId, Cursor),
/// A favicon was detected /// A favicon was detected
NewFavicon(ServoUrl), NewFavicon(WebViewId, ServoUrl),
/// `<head>` tag finished parsing /// `<head>` tag finished parsing
HeadParsed, HeadParsed(WebViewId),
/// The history state has changed. /// The history state has changed.
HistoryChanged(Vec<ServoUrl>, usize), HistoryChanged(WebViewId, Vec<ServoUrl>, usize),
/// Enter or exit fullscreen /// Enter or exit fullscreen
SetFullscreenState(bool), SetFullscreenState(WebViewId, bool),
/// The load of a page has begun /// The load of a page has begun
LoadStart, LoadStart(WebViewId),
/// The load of a page has completed /// The load of a page has completed
LoadComplete, LoadComplete(WebViewId),
WebResourceRequested(WebResourceRequest, IpcSender<WebResourceResponseMsg>), WebResourceRequested(
Option<WebViewId>,
WebResourceRequest,
IpcSender<WebResourceResponseMsg>,
),
/// A pipeline panicked. First string is the reason, second one is the backtrace. /// A pipeline panicked. First string is the reason, second one is the backtrace.
Panic(String, Option<String>), Panic(WebViewId, String, Option<String>),
/// Open dialog to select bluetooth device. /// Open dialog to select bluetooth device.
GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>), GetSelectedBluetoothDevice(WebViewId, Vec<String>, IpcSender<Option<String>>),
/// Open file dialog to select files. Set boolean flag to true allows to select multiple files. /// Open file dialog to select files. Set boolean flag to true allows to select multiple files.
SelectFiles(Vec<FilterPattern>, bool, IpcSender<Option<Vec<String>>>), SelectFiles(
WebViewId,
Vec<FilterPattern>,
bool,
IpcSender<Option<Vec<String>>>,
),
/// Open interface to request permission specified by prompt. /// Open interface to request permission specified by prompt.
PromptPermission(PermissionPrompt, IpcSender<PermissionRequest>), PromptPermission(WebViewId, PermissionPrompt, IpcSender<PermissionRequest>),
/// Request to present an IME to the user when an editable element is focused. /// Request to present an IME to the user when an editable element is focused.
/// If the input is text, the second parameter defines the pre-existing string /// If the input is text, the second parameter defines the pre-existing string
/// text content and the zero-based index into the string locating the insertion point. /// text content and the zero-based index into the string locating the insertion point.
/// bool is true for multi-line and false otherwise. /// bool is true for multi-line and false otherwise.
ShowIME(InputMethodType, Option<(String, i32)>, bool, DeviceIntRect), ShowIME(
WebViewId,
InputMethodType,
Option<(String, i32)>,
bool,
DeviceIntRect,
),
/// Request to hide the IME when the editable element is blurred. /// Request to hide the IME when the editable element is blurred.
HideIME, HideIME(WebViewId),
/// Servo has shut down /// Servo has shut down
Shutdown, Shutdown,
/// Report a complete sampled profile /// Report a complete sampled profile
ReportProfile(Vec<u8>), ReportProfile(Vec<u8>),
/// Notifies the embedder about media session events /// Notifies the embedder about media session events
/// (i.e. when there is metadata for the active media session, playback state changes...). /// (i.e. when there is metadata for the active media session, playback state changes...).
MediaSessionEvent(MediaSessionEvent), MediaSessionEvent(WebViewId, MediaSessionEvent),
/// Report the status of Devtools Server with a token that can be used to bypass the permission prompt. /// Report the status of Devtools Server with a token that can be used to bypass the permission prompt.
OnDevtoolsStarted(Result<u16, ()>, String), OnDevtoolsStarted(Result<u16, ()>, String),
/// Ask the user to allow a devtools client to connect.
RequestDevtoolsConnection(IpcSender<bool>),
/// Notify the embedder that it needs to present a new frame. /// Notify the embedder that it needs to present a new frame.
ReadyToPresent(Vec<WebViewId>), ReadyToPresent(Vec<WebViewId>),
/// The given event was delivered to a pipeline in the given browser. /// The given event was delivered to a pipeline in the given browser.
EventDelivered(CompositorEventVariant), EventDelivered(WebViewId, CompositorEventVariant),
/// Request to play a haptic effect on a connected gamepad. /// Request to play a haptic effect on a connected gamepad.
PlayGamepadHapticEffect(usize, GamepadHapticEffectType, IpcSender<bool>), PlayGamepadHapticEffect(WebViewId, usize, GamepadHapticEffectType, IpcSender<bool>),
/// Request to stop a haptic effect on a connected gamepad. /// Request to stop a haptic effect on a connected gamepad.
StopGamepadHapticEffect(usize, IpcSender<bool>), StopGamepadHapticEffect(WebViewId, usize, IpcSender<bool>),
} }
/// The variant of CompositorEvent that was delivered to a pipeline. /// The variant of CompositorEvent that was delivered to a pipeline.
@ -275,23 +281,23 @@ impl Debug for EmbedderMsg {
EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"), EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"),
EmbedderMsg::AllowNavigationRequest(..) => write!(f, "AllowNavigationRequest"), EmbedderMsg::AllowNavigationRequest(..) => write!(f, "AllowNavigationRequest"),
EmbedderMsg::Keyboard(..) => write!(f, "Keyboard"), EmbedderMsg::Keyboard(..) => write!(f, "Keyboard"),
EmbedderMsg::ClearClipboardContents => write!(f, "ClearClipboardContents"), EmbedderMsg::ClearClipboardContents(..) => write!(f, "ClearClipboardContents"),
EmbedderMsg::GetClipboardContents(..) => write!(f, "GetClipboardContents"), EmbedderMsg::GetClipboardContents(..) => write!(f, "GetClipboardContents"),
EmbedderMsg::SetClipboardContents(..) => write!(f, "SetClipboardContents"), EmbedderMsg::SetClipboardContents(..) => write!(f, "SetClipboardContents"),
EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"), EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"),
EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"), EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"),
EmbedderMsg::HeadParsed => write!(f, "HeadParsed"), EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"),
EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"), EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"),
EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"), EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
EmbedderMsg::LoadStart => write!(f, "LoadStart"), EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
EmbedderMsg::LoadComplete => write!(f, "LoadComplete"), EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
EmbedderMsg::WebResourceRequested(..) => write!(f, "WebResourceRequested"), EmbedderMsg::WebResourceRequested(..) => write!(f, "WebResourceRequested"),
EmbedderMsg::Panic(..) => write!(f, "Panic"), EmbedderMsg::Panic(..) => write!(f, "Panic"),
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"), EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"), EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
EmbedderMsg::PromptPermission(..) => write!(f, "PromptPermission"), EmbedderMsg::PromptPermission(..) => write!(f, "PromptPermission"),
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"), EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
EmbedderMsg::HideIME => write!(f, "HideIME"), EmbedderMsg::HideIME(..) => write!(f, "HideIME"),
EmbedderMsg::Shutdown => write!(f, "Shutdown"), EmbedderMsg::Shutdown => write!(f, "Shutdown"),
EmbedderMsg::AllowOpeningWebView(..) => write!(f, "AllowOpeningWebView"), EmbedderMsg::AllowOpeningWebView(..) => write!(f, "AllowOpeningWebView"),
EmbedderMsg::WebViewOpened(..) => write!(f, "WebViewOpened"), EmbedderMsg::WebViewOpened(..) => write!(f, "WebViewOpened"),
@ -301,6 +307,7 @@ impl Debug for EmbedderMsg {
EmbedderMsg::ReportProfile(..) => write!(f, "ReportProfile"), EmbedderMsg::ReportProfile(..) => write!(f, "ReportProfile"),
EmbedderMsg::MediaSessionEvent(..) => write!(f, "MediaSessionEvent"), EmbedderMsg::MediaSessionEvent(..) => write!(f, "MediaSessionEvent"),
EmbedderMsg::OnDevtoolsStarted(..) => write!(f, "OnDevtoolsStarted"), EmbedderMsg::OnDevtoolsStarted(..) => write!(f, "OnDevtoolsStarted"),
EmbedderMsg::RequestDevtoolsConnection(..) => write!(f, "RequestDevtoolsConnection"),
EmbedderMsg::ShowContextMenu(..) => write!(f, "ShowContextMenu"), EmbedderMsg::ShowContextMenu(..) => write!(f, "ShowContextMenu"),
EmbedderMsg::ReadyToPresent(..) => write!(f, "ReadyToPresent"), EmbedderMsg::ReadyToPresent(..) => write!(f, "ReadyToPresent"),
EmbedderMsg::EventDelivered(..) => write!(f, "HitTestedEvent"), EmbedderMsg::EventDelivered(..) => write!(f, "HitTestedEvent"),

View file

@ -7,6 +7,7 @@ use std::ops::Range;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::SystemTime; use std::time::SystemTime;
use base::id::WebViewId;
use embedder_traits::FilterPattern; use embedder_traits::FilterPattern;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
@ -136,6 +137,7 @@ pub struct SelectedFile {
pub enum FileManagerThreadMsg { pub enum FileManagerThreadMsg {
/// Select a single file. Last field is pre-selected file path for testing /// Select a single file. Last field is pre-selected file path for testing
SelectFile( SelectFile(
WebViewId,
Vec<FilterPattern>, Vec<FilterPattern>,
IpcSender<FileManagerResult<SelectedFile>>, IpcSender<FileManagerResult<SelectedFile>>,
FileOrigin, FileOrigin,
@ -144,6 +146,7 @@ pub enum FileManagerThreadMsg {
/// Select multiple files. Last field is pre-selected file paths for testing /// Select multiple files. Last field is pre-selected file paths for testing
SelectFiles( SelectFiles(
WebViewId,
Vec<FilterPattern>, Vec<FilterPattern>,
IpcSender<FileManagerResult<Vec<SelectedFile>>>, IpcSender<FileManagerResult<Vec<SelectedFile>>>,
FileOrigin, FileOrigin,

View file

@ -4,7 +4,7 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use base::id::{PipelineId, TopLevelBrowsingContextId}; use base::id::{PipelineId, WebViewId};
use content_security_policy::{self as csp}; use content_security_policy::{self as csp};
use http::header::{HeaderName, AUTHORIZATION}; use http::header::{HeaderName, AUTHORIZATION};
use http::{HeaderMap, Method}; use http::{HeaderMap, Method};
@ -266,7 +266,7 @@ pub struct RequestBuilder {
pub referrer: Referrer, pub referrer: Referrer,
pub referrer_policy: ReferrerPolicy, pub referrer_policy: ReferrerPolicy,
pub pipeline_id: Option<PipelineId>, pub pipeline_id: Option<PipelineId>,
pub target_browsing_context_id: Option<TopLevelBrowsingContextId>, pub target_webview_id: Option<WebViewId>,
pub redirect_mode: RedirectMode, pub redirect_mode: RedirectMode,
pub integrity_metadata: String, pub integrity_metadata: String,
// to keep track of redirects // to keep track of redirects
@ -280,7 +280,7 @@ pub struct RequestBuilder {
} }
impl RequestBuilder { impl RequestBuilder {
pub fn new(url: ServoUrl, referrer: Referrer) -> RequestBuilder { pub fn new(webview_id: Option<WebViewId>, url: ServoUrl, referrer: Referrer) -> RequestBuilder {
RequestBuilder { RequestBuilder {
id: RequestId::default(), id: RequestId::default(),
method: Method::GET, method: Method::GET,
@ -301,7 +301,7 @@ impl RequestBuilder {
referrer, referrer,
referrer_policy: ReferrerPolicy::EmptyString, referrer_policy: ReferrerPolicy::EmptyString,
pipeline_id: None, pipeline_id: None,
target_browsing_context_id: None, target_webview_id: webview_id,
redirect_mode: RedirectMode::Follow, redirect_mode: RedirectMode::Follow,
integrity_metadata: "".to_owned(), integrity_metadata: "".to_owned(),
url_list: vec![], url_list: vec![],
@ -383,14 +383,6 @@ impl RequestBuilder {
self self
} }
pub fn target_browsing_context_id(
mut self,
target_browsing_context_id: Option<TopLevelBrowsingContextId>,
) -> RequestBuilder {
self.target_browsing_context_id = target_browsing_context_id;
self
}
pub fn redirect_mode(mut self, redirect_mode: RedirectMode) -> RequestBuilder { pub fn redirect_mode(mut self, redirect_mode: RedirectMode) -> RequestBuilder {
self.redirect_mode = redirect_mode; self.redirect_mode = redirect_mode;
self self
@ -433,6 +425,7 @@ impl RequestBuilder {
Some(Origin::Origin(self.origin)), Some(Origin::Origin(self.origin)),
self.referrer, self.referrer,
self.pipeline_id, self.pipeline_id,
self.target_webview_id,
self.https_state, self.https_state,
); );
request.initiator = self.initiator; request.initiator = self.initiator;
@ -461,7 +454,6 @@ impl RequestBuilder {
request.response_tainting = self.response_tainting; request.response_tainting = self.response_tainting;
request.crash = self.crash; request.crash = self.crash;
request.policy_container = self.policy_container; request.policy_container = self.policy_container;
request.target_browsing_context_id = self.target_browsing_context_id;
request request
} }
} }
@ -488,7 +480,7 @@ pub struct Request {
pub body: Option<RequestBody>, pub body: Option<RequestBody>,
// TODO: client object // TODO: client object
pub window: Window, pub window: Window,
pub target_browsing_context_id: Option<TopLevelBrowsingContextId>, pub target_webview_id: Option<WebViewId>,
/// <https://fetch.spec.whatwg.org/#request-keepalive-flag> /// <https://fetch.spec.whatwg.org/#request-keepalive-flag>
pub keep_alive: bool, pub keep_alive: bool,
/// <https://fetch.spec.whatwg.org/#request-service-workers-mode> /// <https://fetch.spec.whatwg.org/#request-service-workers-mode>
@ -545,6 +537,7 @@ impl Request {
origin: Option<Origin>, origin: Option<Origin>,
referrer: Referrer, referrer: Referrer,
pipeline_id: Option<PipelineId>, pipeline_id: Option<PipelineId>,
webview_id: Option<WebViewId>,
https_state: HttpsState, https_state: HttpsState,
) -> Request { ) -> Request {
Request { Request {
@ -563,7 +556,7 @@ impl Request {
referrer, referrer,
referrer_policy: ReferrerPolicy::EmptyString, referrer_policy: ReferrerPolicy::EmptyString,
pipeline_id, pipeline_id,
target_browsing_context_id: None, target_webview_id: webview_id,
synchronous: false, synchronous: false,
mode: RequestMode::NoCors, mode: RequestMode::NoCors,
use_cors_preflight: false, use_cors_preflight: false,

View file

@ -23,7 +23,7 @@ use background_hang_monitor_api::BackgroundHangMonitorRegister;
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::{ use base::id::{
BlobId, BrowsingContextId, HistoryStateId, MessagePortId, PipelineId, PipelineNamespaceId, BlobId, BrowsingContextId, HistoryStateId, MessagePortId, PipelineId, PipelineNamespaceId,
TopLevelBrowsingContextId, TopLevelBrowsingContextId, WebViewId,
}; };
use base::Epoch; use base::Epoch;
use bitflags::bitflags; use bitflags::bitflags;
@ -732,7 +732,11 @@ pub enum WebDriverCommandMsg {
/// the provided channels to return the top level browsing context id /// the provided channels to return the top level browsing context id
/// associated with the new webview, and a notification when the initial /// associated with the new webview, and a notification when the initial
/// load is complete. /// load is complete.
NewWebView(IpcSender<TopLevelBrowsingContextId>, IpcSender<LoadStatus>), NewWebView(
WebViewId,
IpcSender<TopLevelBrowsingContextId>,
IpcSender<LoadStatus>,
),
/// Close the webview associated with the provided id. /// Close the webview associated with the provided id.
CloseWebView(TopLevelBrowsingContextId), CloseWebView(TopLevelBrowsingContextId),
/// Focus the webview associated with the provided id. /// Focus the webview associated with the provided id.

View file

@ -18,7 +18,7 @@ use std::sync::Arc;
use app_units::Au; use app_units::Au;
use atomic_refcell::AtomicRefCell; use atomic_refcell::AtomicRefCell;
use base::cross_process_instant::CrossProcessInstant; use base::cross_process_instant::CrossProcessInstant;
use base::id::{BrowsingContextId, PipelineId}; use base::id::{BrowsingContextId, PipelineId, WebViewId};
use base::Epoch; use base::Epoch;
use canvas_traits::canvas::{CanvasId, CanvasMsg}; use canvas_traits::canvas::{CanvasId, CanvasMsg};
use euclid::default::{Point2D, Rect}; use euclid::default::{Point2D, Rect};
@ -33,7 +33,7 @@ use net_traits::image_cache::{ImageCache, PendingImageId};
use profile_traits::mem::Report; use profile_traits::mem::Report;
use profile_traits::time; use profile_traits::time;
use script_traits::{ use script_traits::{
ConstellationControlMsg, InitialScriptState, LayoutMsg, LoadData, Painter, ScrollState, ConstellationControlMsg, InitialScriptState, LoadData, Painter, ScrollState,
UntrustedNodeAddress, WindowSizeData, UntrustedNodeAddress, WindowSizeData,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -182,9 +182,9 @@ pub struct HTMLMediaData {
pub struct LayoutConfig { pub struct LayoutConfig {
pub id: PipelineId, pub id: PipelineId,
pub webview_id: WebViewId,
pub url: ServoUrl, pub url: ServoUrl,
pub is_iframe: bool, pub is_iframe: bool,
pub constellation_chan: IpcSender<LayoutMsg>,
pub script_chan: IpcSender<ConstellationControlMsg>, pub script_chan: IpcSender<ConstellationControlMsg>,
pub image_cache: Arc<dyn ImageCache>, pub image_cache: Arc<dyn ImageCache>,
pub font_context: Arc<FontContext>, pub font_context: Arc<FontContext>,

View file

@ -947,7 +947,12 @@ impl Handler {
) -> WebDriverResult<WebDriverResponse> { ) -> WebDriverResult<WebDriverResponse> {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let cmd_msg = WebDriverCommandMsg::NewWebView(sender, self.load_status_sender.clone()); let session = self.session().unwrap();
let cmd_msg = WebDriverCommandMsg::NewWebView(
session.top_level_browsing_context_id,
sender,
self.load_status_sender.clone(),
);
self.constellation_chan self.constellation_chan
.send(ConstellationMsg::WebDriverCommand(cmd_msg)) .send(ConstellationMsg::WebDriverCommand(cmd_msg))
.unwrap(); .unwrap();

View file

@ -143,26 +143,27 @@ mod from_servo {
Self::WebResourceRequested(..) => target!("WebResourceRequested"), Self::WebResourceRequested(..) => target!("WebResourceRequested"),
Self::AllowUnload(..) => target!("AllowUnload"), Self::AllowUnload(..) => target!("AllowUnload"),
Self::Keyboard(..) => target!("Keyboard"), Self::Keyboard(..) => target!("Keyboard"),
Self::ClearClipboardContents => target!("ClearClipboardContents"), Self::ClearClipboardContents(..) => target!("ClearClipboardContents"),
Self::GetClipboardContents(..) => target!("GetClipboardContents"), Self::GetClipboardContents(..) => target!("GetClipboardContents"),
Self::SetClipboardContents(..) => target!("SetClipboardContents"), Self::SetClipboardContents(..) => target!("SetClipboardContents"),
Self::SetCursor(..) => target!("SetCursor"), Self::SetCursor(..) => target!("SetCursor"),
Self::NewFavicon(..) => target!("NewFavicon"), Self::NewFavicon(..) => target!("NewFavicon"),
Self::HeadParsed => target!("HeadParsed"), Self::HeadParsed(..) => target!("HeadParsed"),
Self::HistoryChanged(..) => target!("HistoryChanged"), Self::HistoryChanged(..) => target!("HistoryChanged"),
Self::SetFullscreenState(..) => target!("SetFullscreenState"), Self::SetFullscreenState(..) => target!("SetFullscreenState"),
Self::LoadStart => target!("LoadStart"), Self::LoadStart(..) => target!("LoadStart"),
Self::LoadComplete => target!("LoadComplete"), Self::LoadComplete(..) => target!("LoadComplete"),
Self::Panic(..) => target!("Panic"), Self::Panic(..) => target!("Panic"),
Self::GetSelectedBluetoothDevice(..) => target!("GetSelectedBluetoothDevice"), Self::GetSelectedBluetoothDevice(..) => target!("GetSelectedBluetoothDevice"),
Self::SelectFiles(..) => target!("SelectFiles"), Self::SelectFiles(..) => target!("SelectFiles"),
Self::PromptPermission(..) => target!("PromptPermission"), Self::PromptPermission(..) => target!("PromptPermission"),
Self::ShowIME(..) => target!("ShowIME"), Self::ShowIME(..) => target!("ShowIME"),
Self::HideIME => target!("HideIME"), Self::HideIME(..) => target!("HideIME"),
Self::Shutdown => target!("Shutdown"), Self::Shutdown => target!("Shutdown"),
Self::ReportProfile(..) => target!("ReportProfile"), Self::ReportProfile(..) => target!("ReportProfile"),
Self::MediaSessionEvent(..) => target!("MediaSessionEvent"), Self::MediaSessionEvent(..) => target!("MediaSessionEvent"),
Self::OnDevtoolsStarted(..) => target!("OnDevtoolsStarted"), Self::OnDevtoolsStarted(..) => target!("OnDevtoolsStarted"),
Self::RequestDevtoolsConnection(..) => target!("RequestDevtoolsConnection"),
Self::ReadyToPresent(..) => target!("ReadyToPresent"), Self::ReadyToPresent(..) => target!("ReadyToPresent"),
Self::EventDelivered(..) => target!("EventDelivered"), Self::EventDelivered(..) => target!("EventDelivered"),
Self::PlayGamepadHapticEffect(..) => target!("PlayGamepadHapticEffect"), Self::PlayGamepadHapticEffect(..) => target!("PlayGamepadHapticEffect"),

View file

@ -404,8 +404,8 @@ impl WebViewManager {
.position(|webview| webview.0 == focused_id) .position(|webview| webview.0 == focused_id)
} }
fn send_error(&self, webview_id: Option<WebViewId>, error: String) { fn send_error(&self, webview_id: WebViewId, error: String) {
let Some(webview) = webview_id.and_then(|id| self.get(id)) else { let Some(webview) = self.get(webview_id) else {
return warn!("{error}"); return warn!("{error}");
}; };
webview.servo_webview.send_error(error); webview.servo_webview.send_error(error);
@ -417,26 +417,21 @@ impl WebViewManager {
servo: &mut Servo, servo: &mut Servo,
clipboard: &mut Option<Clipboard>, clipboard: &mut Option<Clipboard>,
opts: &Opts, opts: &Opts,
events: Vec<(Option<WebViewId>, EmbedderMsg)>, messages: Vec<EmbedderMsg>,
) -> ServoEventResponse { ) -> ServoEventResponse {
let mut need_present = self.load_status() != LoadStatus::LoadComplete; let mut need_present = self.load_status() != LoadStatus::LoadComplete;
let mut need_update = false; let mut need_update = false;
for (webview_id, msg) in events { for message in messages {
if let Some(webview_id) = webview_id { trace_embedder_msg!(message, "{message:?}");
trace_embedder_msg!(msg, "{webview_id} {msg:?}");
} else {
trace_embedder_msg!(msg, "{msg:?}");
}
match msg { match message {
EmbedderMsg::Status(status) => { EmbedderMsg::Status(_, status) => {
self.status_text = status; self.status_text = status;
need_update = true; need_update = true;
}, },
EmbedderMsg::ChangePageTitle(title) => { EmbedderMsg::ChangePageTitle(webview_id, title) => {
// Set the title to the target webview, and update the OS window title // Set the title to the target webview, and update the OS window title
// if this is the currently focused one. // if this is the currently focused one.
if let Some(webview_id) = webview_id {
if let Some(webview) = self.get_mut(webview_id) { if let Some(webview) = self.get_mut(webview_id) {
webview.title = title.clone(); webview.title = title.clone();
if webview.focused { if webview.focused {
@ -447,13 +442,11 @@ impl WebViewManager {
} }
need_update = true; need_update = true;
} }
}
}, },
EmbedderMsg::MoveTo(point) => { EmbedderMsg::MoveTo(_, point) => {
self.window.set_position(point); self.window.set_position(point);
}, },
EmbedderMsg::ResizeTo(inner_size) => { EmbedderMsg::ResizeTo(webview_id, inner_size) => {
if let Some(webview_id) = webview_id {
if let Some(webview) = self.get_mut(webview_id) { if let Some(webview) = self.get_mut(webview_id) {
if webview.rect.size() != inner_size.to_f32() { if webview.rect.size() != inner_size.to_f32() {
webview.rect.set_size(inner_size.to_f32()); webview.rect.set_size(inner_size.to_f32());
@ -463,9 +456,8 @@ impl WebViewManager {
if let Some(webview) = self.get(webview_id) { if let Some(webview) = self.get(webview_id) {
self.window.request_resize(webview, inner_size); self.window.request_resize(webview, inner_size);
} }
}
}, },
EmbedderMsg::Prompt(definition, origin) => { EmbedderMsg::Prompt(webview_id, definition, origin) => {
let res = if opts.headless { let res = if opts.headless {
match definition { match definition {
PromptDefinition::Alert(_message, sender) => sender.send(()), PromptDefinition::Alert(_message, sender) => sender.send(()),
@ -553,7 +545,7 @@ impl WebViewManager {
self.send_error(webview_id, format!("Failed to send Prompt response: {e}")) self.send_error(webview_id, format!("Failed to send Prompt response: {e}"))
} }
}, },
EmbedderMsg::AllowUnload(sender) => { EmbedderMsg::AllowUnload(webview_id, sender) => {
// Always allow unload for now. // Always allow unload for now.
if let Err(e) = sender.send(true) { if let Err(e) = sender.send(true) {
self.send_error( self.send_error(
@ -562,12 +554,10 @@ impl WebViewManager {
) )
} }
}, },
EmbedderMsg::AllowNavigationRequest(pipeline_id, _url) => { EmbedderMsg::AllowNavigationRequest(_, pipeline_id, _url) => {
if let Some(_webview_id) = webview_id {
servo.allow_navigation_response(pipeline_id, true); servo.allow_navigation_response(pipeline_id, true);
}
}, },
EmbedderMsg::AllowOpeningWebView(response_chan) => { EmbedderMsg::AllowOpeningWebView(_, response_chan) => {
let webview = servo.new_auxiliary_webview(); let webview = servo.new_auxiliary_webview();
match response_chan.send(Some(webview.id())) { match response_chan.send(Some(webview.id())) {
Ok(()) => self.add(webview), Ok(()) => self.add(webview),
@ -614,15 +604,15 @@ impl WebViewManager {
} }
self.focused_webview_id = None; self.focused_webview_id = None;
}, },
EmbedderMsg::Keyboard(key_event) => { EmbedderMsg::Keyboard(webview_id, key_event) => {
self.handle_overridable_key_bindings(webview_id, key_event); self.handle_overridable_key_bindings(webview_id, key_event);
}, },
EmbedderMsg::ClearClipboardContents => { EmbedderMsg::ClearClipboardContents(_) => {
clipboard clipboard
.as_mut() .as_mut()
.and_then(|clipboard| clipboard.clear().ok()); .and_then(|clipboard| clipboard.clear().ok());
}, },
EmbedderMsg::GetClipboardContents(sender) => { EmbedderMsg::GetClipboardContents(_, sender) => {
let contents = clipboard let contents = clipboard
.as_mut() .as_mut()
.and_then(|clipboard| clipboard.get_text().ok()) .and_then(|clipboard| clipboard.get_text().ok())
@ -631,52 +621,52 @@ impl WebViewManager {
warn!("Failed to send clipboard ({})", e); warn!("Failed to send clipboard ({})", e);
} }
}, },
EmbedderMsg::SetClipboardContents(text) => { EmbedderMsg::SetClipboardContents(_, text) => {
if let Some(clipboard) = clipboard.as_mut() { if let Some(clipboard) = clipboard.as_mut() {
if let Err(e) = clipboard.set_text(text) { if let Err(e) = clipboard.set_text(text) {
warn!("Error setting clipboard contents ({})", e); warn!("Error setting clipboard contents ({})", e);
} }
} }
}, },
EmbedderMsg::SetCursor(cursor) => { EmbedderMsg::SetCursor(_, cursor) => {
self.window.set_cursor(cursor); self.window.set_cursor(cursor);
}, },
EmbedderMsg::NewFavicon(_url) => { EmbedderMsg::NewFavicon(_, _url) => {
// FIXME: show favicons in the UI somehow // FIXME: show favicons in the UI somehow
}, },
EmbedderMsg::HeadParsed => { EmbedderMsg::HeadParsed(webview_id) => {
if let Some(webview) = webview_id.and_then(|id| self.get_mut(id)) { if let Some(webview) = self.get_mut(webview_id) {
webview.load_status = LoadStatus::HeadParsed; webview.load_status = LoadStatus::HeadParsed;
need_update = true; need_update = true;
}; };
}, },
EmbedderMsg::HistoryChanged(urls, current) => { EmbedderMsg::HistoryChanged(webview_id, urls, current) => {
if let Some(webview) = webview_id.and_then(|id| self.get_mut(id)) { if let Some(webview) = self.get_mut(webview_id) {
webview.url = Some(urls[current].clone()); webview.url = Some(urls[current].clone());
need_update = true; need_update = true;
}; };
}, },
EmbedderMsg::SetFullscreenState(state) => { EmbedderMsg::SetFullscreenState(_, state) => {
self.window.set_fullscreen(state); self.window.set_fullscreen(state);
}, },
EmbedderMsg::LoadStart => { EmbedderMsg::LoadStart(webview_id) => {
if let Some(webview) = webview_id.and_then(|id| self.get_mut(id)) { if let Some(webview) = self.get_mut(webview_id) {
webview.load_status = LoadStatus::LoadStart; webview.load_status = LoadStatus::LoadStart;
need_update = true; need_update = true;
}; };
}, },
EmbedderMsg::LoadComplete => { EmbedderMsg::LoadComplete(webview_id) => {
if let Some(webview) = webview_id.and_then(|id| self.get_mut(id)) { if let Some(webview) = self.get_mut(webview_id) {
webview.load_status = LoadStatus::LoadComplete; webview.load_status = LoadStatus::LoadComplete;
need_update = true; need_update = true;
}; };
}, },
EmbedderMsg::WebResourceRequested(_web_resource_request, _response_sender) => {}, EmbedderMsg::WebResourceRequested(_, _web_resource_request, _response_sender) => {},
EmbedderMsg::Shutdown => { EmbedderMsg::Shutdown => {
self.shutdown_requested = true; self.shutdown_requested = true;
}, },
EmbedderMsg::Panic(_reason, _backtrace) => {}, EmbedderMsg::Panic(_, _reason, _backtrace) => {},
EmbedderMsg::GetSelectedBluetoothDevice(devices, sender) => { EmbedderMsg::GetSelectedBluetoothDevice(webview_id, devices, sender) => {
let selected = platform_get_selected_devices(devices); let selected = platform_get_selected_devices(devices);
if let Err(e) = sender.send(selected) { if let Err(e) = sender.send(selected) {
self.send_error( self.send_error(
@ -685,7 +675,7 @@ impl WebViewManager {
); );
}; };
}, },
EmbedderMsg::SelectFiles(patterns, multiple_files, sender) => { EmbedderMsg::SelectFiles(webview_id, patterns, multiple_files, sender) => {
let result = match (opts.headless, get_selected_files(patterns, multiple_files)) let result = match (opts.headless, get_selected_files(patterns, multiple_files))
{ {
(true, _) | (false, None) => sender.send(None), (true, _) | (false, None) => sender.send(None),
@ -698,16 +688,16 @@ impl WebViewManager {
); );
}; };
}, },
EmbedderMsg::PromptPermission(prompt, sender) => { EmbedderMsg::PromptPermission(_, prompt, sender) => {
let _ = sender.send(match opts.headless { let _ = sender.send(match opts.headless {
true => PermissionRequest::Denied, true => PermissionRequest::Denied,
false => prompt_user(prompt), false => prompt_user(prompt),
}); });
}, },
EmbedderMsg::ShowIME(_kind, _text, _multiline, _rect) => { EmbedderMsg::ShowIME(_webview_id, _kind, _text, _multiline, _rect) => {
debug!("ShowIME received"); debug!("ShowIME received");
}, },
EmbedderMsg::HideIME => { EmbedderMsg::HideIME(_webview_id) => {
debug!("HideIME received"); debug!("HideIME received");
}, },
EmbedderMsg::ReportProfile(bytes) => { EmbedderMsg::ReportProfile(bytes) => {
@ -717,7 +707,7 @@ impl WebViewManager {
error!("Failed to store profile: {}", e); error!("Failed to store profile: {}", e);
} }
}, },
EmbedderMsg::MediaSessionEvent(_) => { EmbedderMsg::MediaSessionEvent(..) => {
debug!("MediaSessionEvent received"); debug!("MediaSessionEvent received");
// TODO(ferjm): MediaSession support for winit based browsers. // TODO(ferjm): MediaSession support for winit based browsers.
}, },
@ -725,28 +715,31 @@ impl WebViewManager {
Ok(p) => info!("Devtools Server running on port {}", p), Ok(p) => info!("Devtools Server running on port {}", p),
Err(()) => error!("Error running devtools server"), Err(()) => error!("Error running devtools server"),
}, },
EmbedderMsg::ShowContextMenu(sender, ..) => { EmbedderMsg::RequestDevtoolsConnection(response_sender) => {
let _ = response_sender.send(true);
},
EmbedderMsg::ShowContextMenu(_, sender, ..) => {
let _ = sender.send(ContextMenuResult::Ignored); let _ = sender.send(ContextMenuResult::Ignored);
}, },
EmbedderMsg::ReadyToPresent(_webview_ids) => { EmbedderMsg::ReadyToPresent(_webview_ids) => {
need_present = true; need_present = true;
}, },
EmbedderMsg::EventDelivered(event) => { EmbedderMsg::EventDelivered(webview_id, event) => {
if let Some(webview) = webview_id.and_then(|id| self.get_mut(id)) { if let Some(webview) = self.get_mut(webview_id) {
if let CompositorEventVariant::MouseButtonEvent = event { if let CompositorEventVariant::MouseButtonEvent = event {
webview.servo_webview.raise_to_top(true); webview.servo_webview.raise_to_top(true);
webview.servo_webview.focus(); webview.servo_webview.focus();
} }
}; };
}, },
EmbedderMsg::PlayGamepadHapticEffect(index, effect, effect_complete_sender) => { EmbedderMsg::PlayGamepadHapticEffect(_, index, effect, effect_complete_sender) => {
match effect { match effect {
GamepadHapticEffectType::DualRumble(params) => { GamepadHapticEffectType::DualRumble(params) => {
self.play_haptic_effect(index, params, effect_complete_sender); self.play_haptic_effect(index, params, effect_complete_sender);
}, },
} }
}, },
EmbedderMsg::StopGamepadHapticEffect(index, haptic_stop_sender) => { EmbedderMsg::StopGamepadHapticEffect(_, index, haptic_stop_sender) => {
let stopped_successfully = self.stop_haptic_effect(index); let stopped_successfully = self.stop_haptic_effect(index);
haptic_stop_sender haptic_stop_sender
.send(stopped_successfully) .send(stopped_successfully)
@ -762,12 +755,8 @@ impl WebViewManager {
} }
/// Handle servoshell key bindings that may have been prevented by the page in the focused webview. /// Handle servoshell key bindings that may have been prevented by the page in the focused webview.
fn handle_overridable_key_bindings( fn handle_overridable_key_bindings(&mut self, webview_id: WebViewId, event: KeyboardEvent) {
&mut self, let Some(webview) = self.get(webview_id) else {
webview_id: Option<WebViewId>,
event: KeyboardEvent,
) {
let Some(webview) = webview_id.and_then(|id| self.get(id)) else {
return; return;
}; };

View file

@ -455,23 +455,21 @@ impl ServoGlue {
fn handle_servo_events(&mut self) -> Result<(), &'static str> { fn handle_servo_events(&mut self) -> Result<(), &'static str> {
let mut need_update = false; let mut need_update = false;
let events: Vec<_> = self.servo.get_events().collect(); let messages: Vec<_> = self.servo.get_events().collect();
for (browser_id, event) in events { for message in messages {
match event { match message {
EmbedderMsg::ChangePageTitle(title) => { EmbedderMsg::ChangePageTitle(_, title) => {
self.callbacks.host_callbacks.on_title_changed(title); self.callbacks.host_callbacks.on_title_changed(title);
}, },
EmbedderMsg::AllowNavigationRequest(pipeline_id, url) => { EmbedderMsg::AllowNavigationRequest(_, pipeline_id, url) => {
if let Some(_browser_id) = browser_id {
let data: bool = self let data: bool = self
.callbacks .callbacks
.host_callbacks .host_callbacks
.on_allow_navigation(url.to_string()); .on_allow_navigation(url.to_string());
self.servo.allow_navigation_response(pipeline_id, data); self.servo.allow_navigation_response(pipeline_id, data);
need_update = true; need_update = true;
}
}, },
EmbedderMsg::HistoryChanged(entries, current) => { EmbedderMsg::HistoryChanged(_, entries, current) => {
let can_go_back = current > 0; let can_go_back = current > 0;
let can_go_forward = current < entries.len() - 1; let can_go_forward = current < entries.len() - 1;
self.callbacks self.callbacks
@ -481,19 +479,19 @@ impl ServoGlue {
.host_callbacks .host_callbacks
.on_url_changed(entries[current].clone().to_string()); .on_url_changed(entries[current].clone().to_string());
}, },
EmbedderMsg::LoadStart => { EmbedderMsg::LoadStart(_) => {
self.callbacks.host_callbacks.on_load_started(); self.callbacks.host_callbacks.on_load_started();
}, },
EmbedderMsg::LoadComplete => { EmbedderMsg::LoadComplete(_) => {
self.callbacks.host_callbacks.on_load_ended(); self.callbacks.host_callbacks.on_load_ended();
}, },
EmbedderMsg::GetSelectedBluetoothDevice(_, sender) => { EmbedderMsg::GetSelectedBluetoothDevice(_, _, sender) => {
let _ = sender.send(None); let _ = sender.send(None);
}, },
EmbedderMsg::AllowUnload(sender) => { EmbedderMsg::AllowUnload(_, sender) => {
let _ = sender.send(true); let _ = sender.send(true);
}, },
EmbedderMsg::ShowContextMenu(sender, title, items) => { EmbedderMsg::ShowContextMenu(_, sender, title, items) => {
if self.context_menu_sender.is_some() { if self.context_menu_sender.is_some() {
warn!( warn!(
"Trying to show a context menu when a context menu is already active" "Trying to show a context menu when a context menu is already active"
@ -506,7 +504,7 @@ impl ServoGlue {
.show_context_menu(title, items); .show_context_menu(title, items);
} }
}, },
EmbedderMsg::Prompt(definition, origin) => { EmbedderMsg::Prompt(_, definition, origin) => {
let cb = &self.callbacks.host_callbacks; let cb = &self.callbacks.host_callbacks;
let trusted = origin == PromptOrigin::Trusted; let trusted = origin == PromptOrigin::Trusted;
let res = match definition { let res = match definition {
@ -533,7 +531,7 @@ impl ServoGlue {
.send_error(format!("Failed to send Prompt response: {e}")); .send_error(format!("Failed to send Prompt response: {e}"));
} }
}, },
EmbedderMsg::AllowOpeningWebView(response_chan) => { EmbedderMsg::AllowOpeningWebView(_, response_chan) => {
let new_webview = self.servo.new_auxiliary_webview(); let new_webview = self.servo.new_auxiliary_webview();
let new_webview_id = new_webview.id(); let new_webview_id = new_webview.id();
self.webviews.insert(new_webview_id, new_webview); self.webviews.insert(new_webview_id, new_webview);
@ -568,17 +566,17 @@ impl ServoGlue {
EmbedderMsg::WebViewBlurred => { EmbedderMsg::WebViewBlurred => {
self.focused_webview_id = None; self.focused_webview_id = None;
}, },
EmbedderMsg::GetClipboardContents(sender) => { EmbedderMsg::GetClipboardContents(_, sender) => {
let contents = self.callbacks.host_callbacks.get_clipboard_contents(); let contents = self.callbacks.host_callbacks.get_clipboard_contents();
let _ = sender.send(contents.unwrap_or("".to_owned())); let _ = sender.send(contents.unwrap_or("".to_owned()));
}, },
EmbedderMsg::SetClipboardContents(text) => { EmbedderMsg::SetClipboardContents(_, text) => {
self.callbacks.host_callbacks.set_clipboard_contents(text); self.callbacks.host_callbacks.set_clipboard_contents(text);
}, },
EmbedderMsg::Shutdown => { EmbedderMsg::Shutdown => {
self.callbacks.host_callbacks.on_shutdown_complete(); self.callbacks.host_callbacks.on_shutdown_complete();
}, },
EmbedderMsg::PromptPermission(prompt, sender) => { EmbedderMsg::PromptPermission(_, prompt, sender) => {
let message = match prompt { let message = match prompt {
PermissionPrompt::Request(permission_name) => { PermissionPrompt::Request(permission_name) => {
format!("Do you want to grant permission for {:?}?", permission_name) format!("Do you want to grant permission for {:?}?", permission_name)
@ -601,15 +599,15 @@ impl ServoGlue {
let _ = sender.send(result); let _ = sender.send(result);
}, },
EmbedderMsg::ShowIME(kind, text, multiline, bounds) => { EmbedderMsg::ShowIME(_, kind, text, multiline, bounds) => {
self.callbacks self.callbacks
.host_callbacks .host_callbacks
.on_ime_show(kind, text, multiline, bounds); .on_ime_show(kind, text, multiline, bounds);
}, },
EmbedderMsg::HideIME => { EmbedderMsg::HideIME(_) => {
self.callbacks.host_callbacks.on_ime_hide(); self.callbacks.host_callbacks.on_ime_hide();
}, },
EmbedderMsg::MediaSessionEvent(event) => { EmbedderMsg::MediaSessionEvent(_, event) => {
match event { match event {
MediaSessionEvent::SetMetadata(metadata) => { MediaSessionEvent::SetMetadata(metadata) => {
self.callbacks.host_callbacks.on_media_session_metadata( self.callbacks.host_callbacks.on_media_session_metadata(
@ -637,30 +635,31 @@ impl ServoGlue {
.host_callbacks .host_callbacks
.on_devtools_started(port, token); .on_devtools_started(port, token);
}, },
EmbedderMsg::Panic(reason, backtrace) => { EmbedderMsg::RequestDevtoolsConnection(result_sender) => {
result_sender.send(true);
},
EmbedderMsg::Panic(_, reason, backtrace) => {
self.callbacks.host_callbacks.on_panic(reason, backtrace); self.callbacks.host_callbacks.on_panic(reason, backtrace);
}, },
EmbedderMsg::ReadyToPresent(_webview_ids) => { EmbedderMsg::ReadyToPresent(_webview_ids) => {
self.need_present = true; self.need_present = true;
}, },
EmbedderMsg::Keyboard(..) => { EmbedderMsg::ResizeTo(_, size) => {
error!("Received unexpected keyboard event"); warn!("Received resize event (to {size:?}). Currently only the user can resize windows");
},
EmbedderMsg::ResizeTo(size) => {
error!("Received resize event (to {size:?}). Currently only the user can resize windows");
}, },
EmbedderMsg::Keyboard(..) |
EmbedderMsg::Status(..) | EmbedderMsg::Status(..) |
EmbedderMsg::SelectFiles(..) | EmbedderMsg::SelectFiles(..) |
EmbedderMsg::MoveTo(..) | EmbedderMsg::MoveTo(..) |
EmbedderMsg::SetCursor(..) | EmbedderMsg::SetCursor(..) |
EmbedderMsg::NewFavicon(..) | EmbedderMsg::NewFavicon(..) |
EmbedderMsg::HeadParsed | EmbedderMsg::HeadParsed(..) |
EmbedderMsg::SetFullscreenState(..) | EmbedderMsg::SetFullscreenState(..) |
EmbedderMsg::ReportProfile(..) | EmbedderMsg::ReportProfile(..) |
EmbedderMsg::EventDelivered(..) | EmbedderMsg::EventDelivered(..) |
EmbedderMsg::PlayGamepadHapticEffect(..) | EmbedderMsg::PlayGamepadHapticEffect(..) |
EmbedderMsg::StopGamepadHapticEffect(..) | EmbedderMsg::StopGamepadHapticEffect(..) |
EmbedderMsg::ClearClipboardContents | EmbedderMsg::ClearClipboardContents(..) |
EmbedderMsg::WebResourceRequested(..) => {}, EmbedderMsg::WebResourceRequested(..) => {},
} }
} }