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

View file

@ -443,3 +443,5 @@ pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId = BrowsingContextId {
namespace_id: TEST_NAMESPACE,
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"
[dependencies]
base = { workspace = true }
embedder_traits = { workspace = true }
ipc-channel = { workspace = true }
regex = { workspace = true }

View file

@ -5,6 +5,7 @@
use std::collections::{HashMap, HashSet};
use std::slice::Iter;
use base::id::WebViewId;
use serde::{Deserialize, Serialize};
// 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)]
pub struct RequestDeviceoptions {
webview_id: WebViewId,
filters: BluetoothScanfilterSequence,
optional_services: ServiceUUIDSequence,
}
impl RequestDeviceoptions {
pub fn new(
webview_id: WebViewId,
filters: BluetoothScanfilterSequence,
services: ServiceUUIDSequence,
) -> RequestDeviceoptions {
RequestDeviceoptions {
webview_id,
filters,
optional_services: services,
}
}
pub fn webview_id(&self) -> WebViewId {
self.webview_id
}
pub fn get_filters(&self) -> &BluetoothScanfilterSequence {
&self.filters
}

View file

@ -35,7 +35,7 @@ pub enum ConstellationMsg {
/// Query the constellation to see if the current compositor output is stable
IsReadyToSaveImage(HashMap<PipelineId, Epoch>),
/// Inform the constellation of a key event.
Keyboard(KeyboardEvent),
Keyboard(WebViewId, KeyboardEvent),
/// Inform the constellation of a composition event (IME).
IMECompositionEvent(CompositionEvent),
/// Whether to allow script to navigate.
@ -73,7 +73,7 @@ pub enum ConstellationMsg {
/// Forward an event to the script task of the given pipeline.
ForwardEvent(PipelineId, CompositorEvent),
/// 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.
ToggleProfiler(Duration, Duration),
/// Request to exit from fullscreen mode

View file

@ -6,8 +6,8 @@ pub mod resources;
use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId};
use crossbeam_channel::{Receiver, Sender};
use base::id::{PipelineId, WebViewId};
use crossbeam_channel::Sender;
use http::{HeaderMap, Method, StatusCode};
use ipc_channel::ipc::IpcSender;
use keyboard_types::KeyboardEvent;
@ -77,14 +77,14 @@ impl Clone for Box<dyn EventLoopWaker> {
/// Sends messages to the embedder.
pub struct EmbedderProxy {
pub sender: Sender<(Option<TopLevelBrowsingContextId>, EmbedderMsg)>,
pub sender: Sender<EmbedderMsg>,
pub event_loop_waker: Box<dyn EventLoopWaker>,
}
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.
if let Err(err) = self.sender.send(msg) {
if let Err(err) = self.sender.send(message) {
warn!("Failed to send response ({:?}).", err);
}
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)]
pub enum ContextMenuResult {
Dismissed,
@ -167,86 +151,108 @@ pub enum PromptResult {
#[derive(Deserialize, Serialize)]
pub enum EmbedderMsg {
/// 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.
ChangePageTitle(Option<String>),
ChangePageTitle(WebViewId, Option<String>),
/// Move the window to a point
MoveTo(DeviceIntPoint),
MoveTo(WebViewId, DeviceIntPoint),
/// Resize the window to size
ResizeTo(DeviceIntSize),
ResizeTo(WebViewId, DeviceIntSize),
/// Show dialog to user
Prompt(PromptDefinition, PromptOrigin),
Prompt(WebViewId, PromptDefinition, PromptOrigin),
/// 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.
AllowNavigationRequest(PipelineId, ServoUrl),
AllowNavigationRequest(WebViewId, PipelineId, ServoUrl),
/// 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.
WebViewOpened(TopLevelBrowsingContextId),
WebViewOpened(WebViewId),
/// A webview was destroyed.
WebViewClosed(TopLevelBrowsingContextId),
WebViewClosed(WebViewId),
/// A webview gained focus for keyboard events.
WebViewFocused(TopLevelBrowsingContextId),
WebViewFocused(WebViewId),
/// All webviews lost focus for keyboard events.
WebViewBlurred,
/// Wether or not to unload a document
AllowUnload(IpcSender<bool>),
AllowUnload(WebViewId, IpcSender<bool>),
/// Sends an unconsumed key event back to the embedder.
Keyboard(KeyboardEvent),
Keyboard(WebViewId, KeyboardEvent),
/// Inform embedder to clear the clipboard
ClearClipboardContents,
ClearClipboardContents(WebViewId),
/// Gets system clipboard contents
GetClipboardContents(IpcSender<String>),
GetClipboardContents(WebViewId, IpcSender<String>),
/// Sets system clipboard contents
SetClipboardContents(String),
SetClipboardContents(WebViewId, String),
/// Changes the cursor.
SetCursor(Cursor),
SetCursor(WebViewId, Cursor),
/// A favicon was detected
NewFavicon(ServoUrl),
NewFavicon(WebViewId, ServoUrl),
/// `<head>` tag finished parsing
HeadParsed,
HeadParsed(WebViewId),
/// The history state has changed.
HistoryChanged(Vec<ServoUrl>, usize),
HistoryChanged(WebViewId, Vec<ServoUrl>, usize),
/// Enter or exit fullscreen
SetFullscreenState(bool),
SetFullscreenState(WebViewId, bool),
/// The load of a page has begun
LoadStart,
LoadStart(WebViewId),
/// The load of a page has completed
LoadComplete,
WebResourceRequested(WebResourceRequest, IpcSender<WebResourceResponseMsg>),
LoadComplete(WebViewId),
WebResourceRequested(
Option<WebViewId>,
WebResourceRequest,
IpcSender<WebResourceResponseMsg>,
),
/// 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.
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.
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.
PromptPermission(PermissionPrompt, IpcSender<PermissionRequest>),
PromptPermission(WebViewId, PermissionPrompt, IpcSender<PermissionRequest>),
/// 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
/// text content and the zero-based index into the string locating the insertion point.
/// 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.
HideIME,
HideIME(WebViewId),
/// Servo has shut down
Shutdown,
/// Report a complete sampled profile
ReportProfile(Vec<u8>),
/// Notifies the embedder about media session events
/// (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.
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.
ReadyToPresent(Vec<WebViewId>),
/// 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.
PlayGamepadHapticEffect(usize, GamepadHapticEffectType, IpcSender<bool>),
PlayGamepadHapticEffect(WebViewId, usize, GamepadHapticEffectType, IpcSender<bool>),
/// 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.
@ -275,23 +281,23 @@ impl Debug for EmbedderMsg {
EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"),
EmbedderMsg::AllowNavigationRequest(..) => write!(f, "AllowNavigationRequest"),
EmbedderMsg::Keyboard(..) => write!(f, "Keyboard"),
EmbedderMsg::ClearClipboardContents => write!(f, "ClearClipboardContents"),
EmbedderMsg::ClearClipboardContents(..) => write!(f, "ClearClipboardContents"),
EmbedderMsg::GetClipboardContents(..) => write!(f, "GetClipboardContents"),
EmbedderMsg::SetClipboardContents(..) => write!(f, "SetClipboardContents"),
EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"),
EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"),
EmbedderMsg::HeadParsed => write!(f, "HeadParsed"),
EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"),
EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"),
EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
EmbedderMsg::LoadStart => write!(f, "LoadStart"),
EmbedderMsg::LoadComplete => write!(f, "LoadComplete"),
EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"),
EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
EmbedderMsg::WebResourceRequested(..) => write!(f, "WebResourceRequested"),
EmbedderMsg::Panic(..) => write!(f, "Panic"),
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
EmbedderMsg::PromptPermission(..) => write!(f, "PromptPermission"),
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
EmbedderMsg::HideIME => write!(f, "HideIME"),
EmbedderMsg::HideIME(..) => write!(f, "HideIME"),
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
EmbedderMsg::AllowOpeningWebView(..) => write!(f, "AllowOpeningWebView"),
EmbedderMsg::WebViewOpened(..) => write!(f, "WebViewOpened"),
@ -301,6 +307,7 @@ impl Debug for EmbedderMsg {
EmbedderMsg::ReportProfile(..) => write!(f, "ReportProfile"),
EmbedderMsg::MediaSessionEvent(..) => write!(f, "MediaSessionEvent"),
EmbedderMsg::OnDevtoolsStarted(..) => write!(f, "OnDevtoolsStarted"),
EmbedderMsg::RequestDevtoolsConnection(..) => write!(f, "RequestDevtoolsConnection"),
EmbedderMsg::ShowContextMenu(..) => write!(f, "ShowContextMenu"),
EmbedderMsg::ReadyToPresent(..) => write!(f, "ReadyToPresent"),
EmbedderMsg::EventDelivered(..) => write!(f, "HitTestedEvent"),

View file

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

View file

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

View file

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

View file

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