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

@ -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),
);

View file

@ -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 {

View file

@ -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

View file

@ -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),

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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()));
}
}

View file

@ -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.

View file

@ -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();

View file

@ -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,

View file

@ -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,

View file

@ -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(),

View file

@ -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,

View file

@ -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

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 {
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,

View file

@ -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())

View file

@ -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)

View file

@ -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));

View file

@ -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 }
}

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 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 });

View file

@ -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,

View file

@ -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 =

View file

@ -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,

View file

@ -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(),
)

View file

@ -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(),
)