aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorDelan Azabani <dazabani@igalia.com>2025-01-30 19:15:35 +0800
committerGitHub <noreply@github.com>2025-01-30 11:15:35 +0000
commit5e9de2cb61fbfd82b27343bf03439838458b9848 (patch)
tree64574624cda94237bbfc443a29b792229fde0ee2 /components/script/dom
parent9eeb602f7afca502753bb8211ab646c952951761 (diff)
downloadservo-5e9de2cb61fbfd82b27343bf03439838458b9848.tar.gz
servo-5e9de2cb61fbfd82b27343bf03439838458b9848.zip
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>
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bluetooth.rs1
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs28
-rw-r--r--components/script/dom/document.rs33
-rw-r--r--components/script/dom/eventsource.rs1
-rw-r--r--components/script/dom/gamepadhapticactuator.rs15
-rw-r--r--components/script/dom/globalscope.rs16
-rw-r--r--components/script/dom/htmlbodyelement.rs2
-rw-r--r--components/script/dom/htmlimageelement.rs61
-rw-r--r--components/script/dom/htmlinputelement.rs18
-rw-r--r--components/script/dom/htmllinkelement.rs8
-rw-r--r--components/script/dom/htmlmediaelement.rs1
-rw-r--r--components/script/dom/htmlscriptelement.rs5
-rw-r--r--components/script/dom/htmltextareaelement.rs11
-rw-r--r--components/script/dom/htmlvideoelement.rs16
-rw-r--r--components/script/dom/permissions.rs6
-rw-r--r--components/script/dom/request.rs2
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs2
-rw-r--r--components/script/dom/servoparser/prefetch.rs45
-rw-r--r--components/script/dom/textcontrol.rs7
-rw-r--r--components/script/dom/websocket.rs2
-rw-r--r--components/script/dom/window.rs23
-rw-r--r--components/script/dom/windowproxy.rs2
-rw-r--r--components/script/dom/workerglobalscope.rs18
-rw-r--r--components/script/dom/worklet.rs1
-rw-r--r--components/script/dom/xmlhttprequest.rs1
25 files changed, 196 insertions, 129 deletions
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index 42b18974b5f..9141ee17450 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -220,6 +220,7 @@ impl Bluetooth {
}
let option = RequestDeviceoptions::new(
+ self.global().as_window().webview_id(),
BluetoothScanfilterSequence::new(uuid_filters),
ServiceUUIDSequence::new(optional_services_uuids),
);
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 745b5dd9aeb..ba4ac308ad0 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -6,7 +6,7 @@ use std::sync::atomic::AtomicBool;
use std::sync::Arc;
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 devtools_traits::DevtoolScriptControlMsg;
use dom_struct::dom_struct;
@@ -236,6 +236,10 @@ impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope {
}
impl DedicatedWorkerGlobalScope {
+ pub(crate) fn webview_id(&self) -> Option<WebViewId> {
+ WebViewId::installed()
+ }
+
#[allow(clippy::too_many_arguments)]
fn new_inherited(
init: WorkerGlobalScopeInit,
@@ -361,15 +365,19 @@ impl DedicatedWorkerGlobalScope {
let referrer = referrer_url.map(Referrer::ReferrerUrl).unwrap_or(referrer);
- let request = RequestBuilder::new(worker_url.clone(), referrer)
- .destination(Destination::Worker)
- .mode(RequestMode::SameOrigin)
- .credentials_mode(CredentialsMode::CredentialsSameOrigin)
- .parser_metadata(ParserMetadata::NotParserInserted)
- .use_url_credentials(true)
- .pipeline_id(Some(pipeline_id))
- .referrer_policy(referrer_policy)
- .origin(origin);
+ let request = RequestBuilder::new(
+ top_level_browsing_context_id,
+ worker_url.clone(),
+ referrer,
+ )
+ .destination(Destination::Worker)
+ .mode(RequestMode::SameOrigin)
+ .credentials_mode(CredentialsMode::CredentialsSameOrigin)
+ .parser_metadata(ParserMetadata::NotParserInserted)
+ .use_url_credentials(true)
+ .pipeline_id(Some(pipeline_id))
+ .referrer_policy(referrer_policy)
+ .origin(origin);
let runtime = unsafe {
let task_source = SendableTaskSource {
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 689a848caed..f7bfc88de82 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -15,6 +15,7 @@ use std::sync::{LazyLock, Mutex};
use std::time::{Duration, Instant};
use base::cross_process_instant::CrossProcessInstant;
+use base::id::WebViewId;
use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg};
use chrono::Local;
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]
pub(crate) fn window(&self) -> &Window {
&self.window
@@ -1027,13 +1032,13 @@ impl Document {
match state {
DocumentReadyState::Loading => {
if self.window().is_top_level() {
- self.send_to_embedder(EmbedderMsg::LoadStart);
- self.send_to_embedder(EmbedderMsg::Status(None));
+ self.send_to_embedder(EmbedderMsg::LoadStart(self.webview_id()));
+ self.send_to_embedder(EmbedderMsg::Status(self.webview_id(), None));
}
},
DocumentReadyState::Complete => {
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);
},
@@ -1121,7 +1126,7 @@ impl Document {
// Notify the embedder to hide the input method.
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)
};
self.send_to_embedder(EmbedderMsg::ShowIME(
+ self.webview_id(),
kind,
text,
multiline,
@@ -1225,7 +1231,7 @@ impl Document {
let window = self.window();
if window.is_top_level() {
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
if drag_data_store.list_len() > 0 {
// Step 1.1 Clear the clipboard.
- self.send_to_embedder(EmbedderMsg::ClearClipboardContents);
+ self.send_to_embedder(EmbedderMsg::ClearClipboardContents(self.webview_id()));
// Step 1.2
for item in drag_data_store.iter_item_list() {
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.2 Normalize line endings according to platform conventions
// 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(_) => {
// 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
if drag_data_store.clear_was_called {
// 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
// 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 {
- let msg = EmbedderMsg::Keyboard(keyboard_event.clone());
+ let msg = EmbedderMsg::Keyboard(self.webview_id(), keyboard_event.clone());
self.send_to_embedder(msg);
// This behavior is unspecced
@@ -2455,7 +2464,7 @@ impl Document {
.is_empty();
if default_prevented || return_value_not_empty {
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);
can_unload = port.recv().unwrap();
}
@@ -4049,7 +4058,7 @@ impl Document {
let window = self.window();
// Step 6
if !error {
- let event = EmbedderMsg::SetFullscreenState(true);
+ let event = EmbedderMsg::SetFullscreenState(self.webview_id(), true);
self.send_to_embedder(event);
}
@@ -4091,7 +4100,7 @@ impl Document {
let window = self.window();
// Step 8
- let event = EmbedderMsg::SetFullscreenState(false);
+ let event = EmbedderMsg::SetFullscreenState(self.webview_id(), false);
self.send_to_embedder(event);
// Step 9
diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs
index 1d68817ace5..b75289497b8 100644
--- a/components/script/dom/eventsource.rs
+++ b/components/script/dom/eventsource.rs
@@ -554,6 +554,7 @@ impl EventSourceMethods<crate::DomTypeHolder> for EventSource {
// Step 8
// TODO: Step 9 set request's client settings
let mut request = create_a_potential_cors_request(
+ global.webview_id(),
url_record,
Destination::None,
Some(cors_attribute_state),
diff --git a/components/script/dom/gamepadhapticactuator.rs b/components/script/dom/gamepadhapticactuator.rs
index d152f633c02..cd93f3421bc 100644
--- a/components/script/dom/gamepadhapticactuator.rs
+++ b/components/script/dom/gamepadhapticactuator.rs
@@ -235,6 +235,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
weak_magnitude: *params.weakMagnitude,
};
let event = EmbedderMsg::PlayGamepadHapticEffect(
+ document.webview_id(),
self.gamepad_index as usize,
embedder_traits::GamepadHapticEffectType::DualRumble(params),
effect_complete_sender,
@@ -287,8 +288,11 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
}),
);
- let event =
- EmbedderMsg::StopGamepadHapticEffect(self.gamepad_index as usize, effect_stop_sender);
+ let event = EmbedderMsg::StopGamepadHapticEffect(
+ document.webview_id(),
+ self.gamepad_index as usize,
+ effect_stop_sender,
+ );
self.global().as_window().send_to_embedder(event);
self.playing_effect_promise.borrow().clone().unwrap()
@@ -356,7 +360,12 @@ impl GamepadHapticActuator {
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);
}
}
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index 62d9fee32bd..2a510c25668 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -16,7 +16,7 @@ use std::{mem, ptr};
use base::id::{
BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId,
- ServiceWorkerId, ServiceWorkerRegistrationId,
+ ServiceWorkerId, ServiceWorkerRegistrationId, WebViewId,
};
use content_security_policy::{CheckResult, CspList, PolicyDisposition};
use crossbeam_channel::Sender;
@@ -691,6 +691,20 @@ impl FileListener {
}
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)]
pub(crate) fn new_inherited(
pipeline_id: PipelineId,
diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs
index d3e540f562f..228e1490200 100644
--- a/components/script/dom/htmlbodyelement.rs
+++ b/components/script/dom/htmlbodyelement.rs
@@ -153,7 +153,7 @@ impl VirtualMethods for HTMLBodyElement {
let window = self.owner_window();
window.prevent_layout_until_load_event();
if window.is_top_level() {
- window.send_to_embedder(EmbedderMsg::HeadParsed);
+ window.send_to_embedder(EmbedderMsg::HeadParsed(window.webview_id()));
}
}
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 36fa7b9ee67..8e563c16e54 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -10,7 +10,6 @@ use std::sync::Arc;
use std::{char, mem};
use app_units::{Au, AU_PER_PX};
-use base::id::PipelineId;
use cssparser::{Parser, ParserInput};
use dom_struct::dom_struct;
use euclid::Point2D;
@@ -23,16 +22,14 @@ use net_traits::image_cache::{
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder, ImageResponse,
PendingImageId, UsePlaceholder,
};
-use net_traits::request::{
- CorsSettings, Destination, Initiator, Referrer, RequestBuilder, RequestId,
-};
+use net_traits::request::{Destination, Initiator, RequestId};
use net_traits::{
FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ReferrerPolicy,
ResourceFetchTiming, ResourceTimingType,
};
use num_traits::ToPrimitive;
use pixels::{CorsStatus, Image, ImageMetadata};
-use servo_url::origin::{ImmutableOrigin, MutableOrigin};
+use servo_url::origin::MutableOrigin;
use servo_url::ServoUrl;
use style::attr::{parse_integer, parse_length, AttrValue, LengthOrPercentageOrAuto};
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)]
impl HTMLImageElement {
/// Update the current image with a valid URL.
@@ -445,19 +414,23 @@ impl HTMLImageElement {
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(),
- document.origin().immutable().clone(),
- document.global().get_referrer(),
- document.global().pipeline_id(),
+ Destination::Image,
cors_setting_for_element(self.upcast()),
- referrer_policy_for_element(self.upcast()),
- if Self::uses_srcset_or_picture(self.upcast()) {
- FromPictureOrSrcSet::Yes
- } else {
- FromPictureOrSrcSet::No
- },
- );
+ 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()) {
+ request = request.initiator(Initiator::ImageSet);
+ }
// This is a background load because the load blocker already fulfills the
// purpose of delaying the document's load event.
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index e8844084c68..e5c3270f27e 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -24,7 +24,6 @@ use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::FileManagerThreadMsg;
use net_traits::{CoreResourceMsg, IpcSend};
use profile_traits::ipc;
-use script_traits::ScriptToConstellationChan;
use servo_atoms::Atom;
use style::attr::AttrValue;
use style::str::{split_commas, str_join};
@@ -34,6 +33,7 @@ use unicode_bidi::{bidi_class, BidiClass};
use url::Url;
use super::bindings::str::{FromInputValueString, ToInputValueString};
+use crate::clipboard_provider::EmbedderClipboardProvider;
use crate::dom::activation::Activatable;
use crate::dom::attr::Attr;
use crate::dom::bindings::cell::DomRefCell;
@@ -299,7 +299,7 @@ pub(crate) struct HTMLInputElement {
minlength: Cell<i32>,
#[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"]
#[no_trace]
- textinput: DomRefCell<TextInput<ScriptToConstellationChan>>,
+ textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
// https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag
value_dirty: Cell<bool>,
// not specified explicitly, but implied by the fact that sanitization can't
@@ -334,7 +334,7 @@ impl HTMLInputElement {
prefix: Option<Prefix>,
document: &Document,
) -> HTMLInputElement {
- let chan = document
+ let constellation_sender = document
.window()
.as_global_scope()
.script_to_constellation_chan()
@@ -355,7 +355,10 @@ impl HTMLInputElement {
textinput: DomRefCell::new(TextInput::new(
Single,
DOMString::new(),
- chan,
+ EmbedderClipboardProvider {
+ constellation_sender,
+ webview_id: document.webview_id(),
+ },
None,
None,
SelectionDirection::None,
@@ -1897,6 +1900,7 @@ impl HTMLInputElement {
let mut files: Vec<DomRoot<File>> = vec![];
let mut error = None;
+ let webview_id = window.webview_id();
let filter = filter_from_accept(&self.Accept());
let target = self.upcast::<EventTarget>();
@@ -1906,7 +1910,8 @@ impl HTMLInputElement {
let (chan, recv) = ipc::channel(self.global().time_profiler_chan().clone())
.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
.send(CoreResourceMsg::ToFileManager(msg))
.unwrap();
@@ -1933,7 +1938,8 @@ impl HTMLInputElement {
let (chan, recv) = ipc::channel(self.global().time_profiler_chan().clone())
.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
.send(CoreResourceMsg::ToFileManager(msg))
.unwrap();
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 50d5e274c85..299be2d2156 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -6,6 +6,7 @@ use std::borrow::{Borrow, ToOwned};
use std::cell::Cell;
use std::default::Default;
+use base::id::WebViewId;
use cssparser::{Parser as CssParser, ParserInput};
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
@@ -366,7 +367,7 @@ impl HTMLLinkElement {
// Step 4. Let request be the result of creating a link request given options.
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.
return;
};
@@ -466,7 +467,7 @@ impl HTMLLinkElement {
Ok(url) => {
let window = document.window();
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);
}
},
@@ -626,7 +627,7 @@ impl HTMLLinkElementMethods<crate::DomTypeHolder> for HTMLLinkElement {
impl LinkProcessingOptions {
/// <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.
assert!(!self.href.is_empty());
@@ -651,6 +652,7 @@ impl LinkProcessingOptions {
// FIXME: Step 11. Set request's priority to options's fetch priority.
// FIXME: Use correct referrer
let builder = create_a_potential_cors_request(
+ Some(webview_id),
url,
destination,
self.cross_origin,
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index c7fd9462b21..b859f06007c 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -885,6 +885,7 @@ impl HTMLMediaElement {
let cors_setting = cors_setting_for_element(self.upcast());
let request = create_a_potential_cors_request(
+ Some(document.webview_id()),
url.clone(),
destination,
cors_setting,
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 1aaa0119760..ab00b5356f6 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -11,7 +11,7 @@ use std::ptr;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
-use base::id::PipelineId;
+use base::id::{PipelineId, WebViewId};
use content_security_policy as csp;
use dom_struct::dom_struct;
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>
// This function is also used to prefetch a script in `script::dom::servoparser::prefetch`.
pub(crate) fn script_fetch_request(
+ webview_id: WebViewId,
url: ServoUrl,
cors_setting: Option<CorsSettings>,
origin: ImmutableOrigin,
@@ -551,6 +552,7 @@ pub(crate) fn script_fetch_request(
// We intentionally ignore options' credentials_mode member for classic scripts.
// The mode is initialized by create_a_potential_cors_request.
create_a_potential_cors_request(
+ Some(webview_id),
url,
Destination::Script,
cors_setting,
@@ -576,6 +578,7 @@ fn fetch_a_classic_script(
// Step 1, 2.
let doc = script.owner_document();
let request = script_fetch_request(
+ doc.webview_id(),
url.clone(),
cors_setting,
doc.origin().immutable().clone(),
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index e660e3e4d93..c18f245eb87 100644
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -9,10 +9,10 @@ use std::ops::Range;
use dom_struct::dom_struct;
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
use js::rust::HandleObject;
-use script_traits::ScriptToConstellationChan;
use style::attr::AttrValue;
use style_dom::ElementState;
+use crate::clipboard_provider::EmbedderClipboardProvider;
use crate::dom::attr::Attr;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
@@ -52,7 +52,7 @@ pub(crate) struct HTMLTextAreaElement {
htmlelement: HTMLElement,
#[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"]
#[no_trace]
- textinput: DomRefCell<TextInput<ScriptToConstellationChan>>,
+ textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
placeholder: DomRefCell<DOMString>,
// https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
value_dirty: Cell<bool>,
@@ -142,7 +142,7 @@ impl HTMLTextAreaElement {
prefix: Option<Prefix>,
document: &Document,
) -> HTMLTextAreaElement {
- let chan = document
+ let constellation_sender = document
.window()
.as_global_scope()
.script_to_constellation_chan()
@@ -158,7 +158,10 @@ impl HTMLTextAreaElement {
textinput: DomRefCell::new(TextInput::new(
Lines::Multiple,
DOMString::new(),
- chan,
+ EmbedderClipboardProvider {
+ constellation_sender,
+ webview_id: document.webview_id(),
+ },
None,
None,
SelectionDirection::None,
diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs
index 974b50a3949..d21a317bd47 100644
--- a/components/script/dom/htmlvideoelement.rs
+++ b/components/script/dom/htmlvideoelement.rs
@@ -223,12 +223,16 @@ impl HTMLVideoElement {
fn do_fetch_poster_frame(&self, poster_url: ServoUrl, id: PendingImageId, can_gc: CanGc) {
// Continuation of step 4.
let document = self.owner_document();
- let request = RequestBuilder::new(poster_url.clone(), document.global().get_referrer())
- .destination(Destination::Image)
- .credentials_mode(CredentialsMode::Include)
- .use_url_credentials(true)
- .origin(document.origin().immutable().clone())
- .pipeline_id(Some(document.global().pipeline_id()));
+ let request = RequestBuilder::new(
+ Some(document.webview_id()),
+ poster_url.clone(),
+ document.global().get_referrer(),
+ )
+ .destination(Destination::Image)
+ .credentials_mode(CredentialsMode::Include)
+ .use_url_credentials(true)
+ .origin(document.origin().immutable().clone())
+ .pipeline_id(Some(document.global().pipeline_id()));
// Step 5.
// This delay must be independent from the ones created by HTMLMediaElement during
diff --git a/components/script/dom/permissions.rs b/components/script/dom/permissions.rs
index 1d7c8e63698..bcdf42ac63e 100644
--- a/components/script/dom/permissions.rs
+++ b/components/script/dom/permissions.rs
@@ -362,8 +362,12 @@ fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
}
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!");
- gs.send_to_embedder(EmbedderMsg::PromptPermission(prompt, sender));
+ gs.send_to_embedder(EmbedderMsg::PromptPermission(webview_id, prompt, sender));
match receiver.recv() {
Ok(PermissionRequest::Granted) => PermissionState::Granted,
diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs
index 6f672660db5..70fa7b212e5 100644
--- a/components/script/dom/request.rs
+++ b/components/script/dom/request.rs
@@ -108,7 +108,7 @@ impl Request {
}
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())
.pipeline_id(Some(global.pipeline_id()))
.https_state(global.get_https_state())
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index aa9184a3dc9..07c44cd11f7 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -334,7 +334,7 @@ impl ServiceWorkerGlobalScope {
.map(Referrer::ReferrerUrl)
.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)
.credentials_mode(CredentialsMode::Include)
.parser_metadata(ParserMetadata::NotParserInserted)
diff --git a/components/script/dom/servoparser/prefetch.rs b/components/script/dom/servoparser/prefetch.rs
index 5e394816f44..c67a90372dc 100644
--- a/components/script/dom/servoparser/prefetch.rs
+++ b/components/script/dom/servoparser/prefetch.rs
@@ -4,7 +4,8 @@
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::tokenizer::states::RawKind;
use html5ever::tokenizer::{
@@ -19,10 +20,9 @@ use servo_url::{ImmutableOrigin, ServoUrl};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::trace::{CustomTraceable, JSTraceable};
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::fetch::create_a_potential_cors_request;
use crate::script_module::ScriptFetchOptions;
-use crate::stylesheet_loader::stylesheet_fetch_request;
#[derive(JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
@@ -43,6 +43,7 @@ impl Tokenizer {
let sink = PrefetchSink {
origin: document.origin().immutable().clone(),
pipeline_id: document.global().pipeline_id(),
+ webview_id: document.webview_id(),
base_url: RefCell::new(None),
document_url: document.url(),
referrer: document.global().get_referrer(),
@@ -70,6 +71,8 @@ struct PrefetchSink {
#[no_trace]
pipeline_id: PipelineId,
#[no_trace]
+ webview_id: WebViewId,
+ #[no_trace]
document_url: ServoUrl,
#[no_trace]
base_url: RefCell<Option<ServoUrl>>,
@@ -102,6 +105,7 @@ impl TokenSink for PrefetchSink {
.map(|attr| String::from(&attr.value))
.unwrap_or_default();
let request = script_fetch_request(
+ self.webview_id,
url,
cors_setting,
self.origin.clone(),
@@ -124,15 +128,18 @@ impl TokenSink for PrefetchSink {
(TagKind::StartTag, &local_name!("img")) if self.prefetching.get() => {
if let Some(url) = self.get_url(tag, local_name!("src")) {
debug!("Prefetch {} {}", tag.name, url);
- let request = image_fetch_request(
+ let request = create_a_potential_cors_request(
+ Some(self.webview_id),
url,
- self.origin.clone(),
- self.referrer.clone(),
- self.pipeline_id,
+ Destination::Image,
self.get_cors_settings(tag, local_name!("crossorigin")),
- self.get_referrer_policy(tag, local_name!("referrerpolicy")),
- FromPictureOrSrcSet::No,
- );
+ None,
+ 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
.resource_threads
.send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch));
@@ -152,15 +159,21 @@ impl TokenSink for PrefetchSink {
.get_attr(tag, local_name!("integrity"))
.map(|attr| String::from(&attr.value))
.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,
+ Destination::Style,
cors_setting,
- self.origin.clone(),
- self.pipeline_id,
+ None,
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
.resource_threads
.send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch));
diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs
index 184138ab3c0..09f0365fed2 100644
--- a/components/script/dom/textcontrol.rs
+++ b/components/script/dom/textcontrol.rs
@@ -7,8 +7,7 @@
//!
//! <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::codegen::Bindings::HTMLFormElementBinding::SelectionMode;
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> {
element: &'a E,
- textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>,
+ textinput: &'a DomRefCell<TextInput<EmbedderClipboardProvider>>,
}
impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
pub(crate) fn new(
element: &'a E,
- textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>,
+ textinput: &'a DomRefCell<TextInput<EmbedderClipboardProvider>>,
) -> Self {
TextControlSelection { element, textinput }
}
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index ab4303bf863..ad54f06d84d 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -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 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())
.mode(RequestMode::WebSocket { protocols });
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index e8487f24b95..73ce02a40ab 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -17,7 +17,7 @@ use std::time::{Duration, Instant};
use app_units::Au;
use backtrace::Backtrace;
use base::cross_process_instant::CrossProcessInstant;
-use base::id::{BrowsingContextId, PipelineId};
+use base::id::{BrowsingContextId, PipelineId, WebViewId};
use base64::Engine;
use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLChan;
@@ -209,6 +209,11 @@ impl LayoutBlocker {
#[dom_struct]
pub(crate) struct Window {
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>,
#[no_trace]
#[ignore_malloc_size_of = "TODO: Add MallocSizeOf support to layout"]
@@ -391,6 +396,10 @@ pub(crate) struct Window {
}
impl Window {
+ pub(crate) fn webview_id(&self) -> WebViewId {
+ self.webview_id
+ }
+
pub(crate) fn as_global_scope(&self) -> &GlobalScope {
self.upcast::<GlobalScope>()
}
@@ -726,7 +735,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
let (sender, receiver) =
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
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);
receiver.recv().unwrap();
}
@@ -736,7 +745,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
let (sender, receiver) =
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
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);
receiver.recv().unwrap() == PromptResult::Primary
}
@@ -746,7 +755,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
let (sender, receiver) =
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
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);
receiver.recv().unwrap().map(|s| s.into())
}
@@ -1322,7 +1331,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
//TODO determine if this operation is allowed
let dpr = self.device_pixel_ratio();
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
@@ -1341,7 +1350,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
//TODO determine if this operation is allowed
let dpr = self.device_pixel_ratio();
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);
}
@@ -2738,6 +2747,7 @@ impl Window {
#[allow(unsafe_code)]
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
+ webview_id: WebViewId,
runtime: Rc<Runtime>,
script_chan: Sender<MainThreadScriptMsg>,
layout: Box<dyn Layout>,
@@ -2786,6 +2796,7 @@ impl Window {
));
let win = Box::new(Self {
+ webview_id,
globalscope: GlobalScope::new_inherited(
pipeline_id,
devtools_chan,
diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs
index 5f113b5f068..f26180bfc66 100644
--- a/components/script/dom/windowproxy.rs
+++ b/components/script/dom/windowproxy.rs
@@ -292,7 +292,7 @@ impl WindowProxy {
.and_then(ScriptThread::find_document)
.map(|doc| DomRoot::from_ref(doc.window()))
.unwrap();
- let msg = EmbedderMsg::AllowOpeningWebView(chan);
+ let msg = EmbedderMsg::AllowOpeningWebView(window.webview_id(), chan);
window.send_to_embedder(msg);
if let Some(new_top_level_browsing_context_id) = port.recv().unwrap() {
let new_browsing_context_id =
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 7db2123e36e..94b709a4fa6 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -278,13 +278,17 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
rooted!(in(self.runtime.borrow().as_ref().unwrap().cx()) let mut rval = UndefinedValue());
for url in urls {
let global_scope = self.upcast::<GlobalScope>();
- let request = NetRequestInit::new(url.clone(), global_scope.get_referrer())
- .destination(Destination::Script)
- .credentials_mode(CredentialsMode::Include)
- .parser_metadata(ParserMetadata::NotParserInserted)
- .use_url_credentials(true)
- .origin(global_scope.origin().immutable().clone())
- .pipeline_id(Some(self.upcast::<GlobalScope>().pipeline_id()));
+ let request = NetRequestInit::new(
+ global_scope.webview_id(),
+ url.clone(),
+ global_scope.get_referrer(),
+ )
+ .destination(Destination::Script)
+ .credentials_mode(CredentialsMode::Include)
+ .parser_metadata(ParserMetadata::NotParserInserted)
+ .use_url_credentials(true)
+ .origin(global_scope.origin().immutable().clone())
+ .pipeline_id(Some(self.upcast::<GlobalScope>().pipeline_id()));
let (url, source) = match fetch::load_whole_resource(
request,
diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs
index 752aa4e5e9e..527fc47f3ad 100644
--- a/components/script/dom/worklet.rs
+++ b/components/script/dom/worklet.rs
@@ -652,6 +652,7 @@ impl WorkletThread {
// TODO: Caching.
let resource_fetcher = self.global_init.resource_threads.sender();
let request = RequestBuilder::new(
+ None,
script_url,
global_scope.upcast::<GlobalScope>().get_referrer(),
)
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index e0eca131d65..5e2bb5abc27 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -673,6 +673,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
};
let mut request = RequestBuilder::new(
+ self.global().webview_id(),
self.request_url.borrow().clone().unwrap(),
self.referrer.clone(),
)