mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
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:
parent
9eeb602f7a
commit
5e9de2cb61
70 changed files with 809 additions and 753 deletions
|
@ -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),
|
||||
);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue