···11--- original
22+++ modified
33-@@ -2,8 +2,9 @@
44- * License, v. 2.0. If a copy of the MPL was not distributed with this
55- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
33+@@ -4,8 +4,9 @@
44+55+ //! Preferences are the global configuration options that can be changed at runtime.
6677+use std::collections::HashMap;
88 use std::env::consts::ARCH;
···1111 use std::time::Duration;
12121313 use serde::{Deserialize, Serialize};
1414-@@ -13,11 +14,16 @@
1414+@@ -15,6 +16,11 @@
15151616 static PREFERENCES: RwLock<Preferences> = RwLock::new(Preferences::const_default());
1717···2020+static EMBEDDER_PREFS: LazyLock<RwLock<HashMap<String, PrefValue>>> =
2121+ LazyLock::new(|| RwLock::new(HashMap::new()));
2222+
2323+ /// A trait to be implemented by components that wish to be notified about runtime changes to the
2424+ /// global preferences for the current process.
2325 pub trait PreferencesObserver: Send + Sync {
2626+@@ -24,7 +30,7 @@
2427 fn prefs_changed(&self, _changes: &[(&'static str, PrefValue)]) {}
2528 }
2629···29323033 #[inline]
3134 /// Get the current set of global preferences for Servo.
3232-@@ -63,6 +69,21 @@
3535+@@ -73,6 +79,21 @@
3336 }
3437 }
3538
···3030 /// dependencies, which is why we store a `dyn WebViewTrait` here instead of the `WebView` itself.
3131@@ -116,6 +128,10 @@
3232 /// and initial values for zoom derived from the `viewport` meta tag in web content.
3333- viewport_description: Option<ViewportDescription>,
3333+ viewport_description: ViewportDescription,
34343535+ /// Whether this is an embedded webview. Embedded webviews have different zoom behavior:
3636+ /// page zoom is applied inside the display list rather than as an external transform.
···4242@@ -154,6 +170,7 @@
4343 hidden: false,
4444 animating: false,
4545- viewport_description: None,
4545+ viewport_description: Default::default(),
4646+ is_embedded_webview: false,
4747 embedder_to_constellation_sender,
4848 refresh_driver,
···206206 }
207207208208 // Batch up all scroll events and changes to pinch zoom into a single change, or
209209-@@ -807,15 +921,24 @@
209209+@@ -810,15 +924,24 @@
210210 }
211211 }
212212···237237238238 let scroll_result = combined_scroll_event.and_then(|combined_event| {
239239 self.scroll_node_at_device_point(
240240-@@ -824,6 +947,21 @@
240240+@@ -827,6 +950,21 @@
241241 combined_event.scroll,
242242 )
243243 });
···259259 if let Some(ref scroll_result) = scroll_result {
260260 self.send_scroll_positions_to_layout_for_pipeline(
261261 scroll_result.hit_test_result.pipeline_id,
262262-@@ -839,7 +977,11 @@
262262+@@ -842,7 +980,11 @@
263263 self.send_pinch_zoom_infos_to_script();
264264 }
265265···272272 }
273273274274 /// Perform a hit test at the given [`DevicePoint`] and apply the [`Scroll`]
275275-@@ -846,7 +988,7 @@
275275+@@ -849,7 +991,7 @@
276276 /// scrolling to the applicable scroll node under that point. If a scroll was
277277 /// performed, returns the hit test result contains [`PipelineId`] of the node
278278 /// scrolled, the id, and the final scroll delta.
···281281 &mut self,
282282 render_api: &RenderApi,
283283 cursor: DevicePoint,
284284-@@ -874,7 +1016,10 @@
284284+@@ -877,7 +1019,10 @@
285285 // its ancestor pipelines.
286286 let mut previous_pipeline_id = None;
287287 for hit_test_result in hit_test_results {
···293293 if previous_pipeline_id.replace(hit_test_result.pipeline_id) !=
294294 Some(hit_test_result.pipeline_id)
295295 {
296296-@@ -901,7 +1046,11 @@
296296+@@ -904,7 +1049,11 @@
297297 }
298298 }
299299 }
···306306 }
307307308308 /// Scroll the viewport (root pipeline, root scroll node) of this WebView, but first
309309-@@ -1040,20 +1189,45 @@
309309+@@ -1043,20 +1192,45 @@
310310 }
311311312312 fn send_window_size_message(&self) {
···364364 }
365365366366 /// Set the `hidpi_scale_factor` for this renderer, returning `true` if the value actually changed.
367367-@@ -1117,8 +1291,21 @@
367367+@@ -1120,8 +1294,21 @@
368368 if let Some(wheel_event) = self.pending_wheel_events.remove(&id) {
369369 if !result.contains(InputEventResult::DefaultPrevented) {
370370 // A scroll delta for a wheel event is the inverse of the wheel delta.
···11--- original
22+++ modified
33-@@ -1056,9 +1056,10 @@
33+@@ -1064,9 +1064,10 @@
44 // Return the result of loading an XML document given navigationParams and type.
55 MediaType::Xml => self.load_xml_document(parser),
66 // Return the result of loading a text document given navigationParams and type.
···1212 // Return the result of loading a media document given navigationParams and type.
1313 MediaType::Image | MediaType::AudioVideo => {
1414 self.load_media_document(parser, media_type, &mime_type, cx);
1515-@@ -1126,6 +1127,17 @@
1515+@@ -1134,6 +1135,17 @@
1616 self.process_link_headers_in_media_phase_with_task(&parser.document);
1717 }
1818
+10-10
patches/components/script/dom/window.rs.patch
···1818 use crate::script_runtime::{CanGc, JSContext as SafeJSContext, Runtime};
1919 use crate::script_thread::ScriptThread;
2020 use crate::script_window_proxies::ScriptWindowProxies;
2121-@@ -1145,12 +1145,22 @@
2121+@@ -1144,12 +1144,22 @@
22222323 let (sender, receiver) =
2424 ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap();
···4242 receiver.recv().unwrap_or_else(|_| {
4343 // If the receiver is closed, we assume the dialog was cancelled.
4444 debug!("Alert dialog was cancelled or failed to show.");
4545-@@ -1178,13 +1188,22 @@
4545+@@ -1177,13 +1187,22 @@
4646 // the user to respond with a positive or negative response.
4747 let (sender, receiver) =
4848 ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap();
···6666 // Step 5: Let userPromptHandler be WebDriver BiDi user prompt opened with this,
6767 // "confirm", and message.
6868 //
6969-@@ -1229,6 +1248,7 @@
6969+@@ -1228,6 +1247,7 @@
7070 // defaulted to the value given by default.
7171 let (sender, receiver) =
7272 ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap();
···7474 let dialog = SimpleDialogRequest::Prompt {
7575 id: self.Document().embedder_controls().next_control_id(),
7676 message: message.to_string(),
7777-@@ -1235,8 +1255,16 @@
7777+@@ -1234,8 +1254,16 @@
7878 default: default.to_string(),
7979 response_sender: sender,
8080 };
···9292 // Step 6: Let userPromptHandler be WebDriver BiDi user prompt opened with this,
9393 // "prompt", and message.
9494 // TODO: Add support for WebDriver BiDi.
9595-@@ -1669,6 +1697,26 @@
9595+@@ -1668,6 +1696,26 @@
9696 // https://html.spec.whatwg.org/multipage/#windoweventhandlers
9797 window_event_handlers!();
9898···119119 /// <https://developer.mozilla.org/en-US/docs/Web/API/Window/screen>
120120 fn Screen(&self, can_gc: CanGc) -> DomRoot<Screen> {
121121 self.screen.or_init(|| Screen::new(self, can_gc))
122122-@@ -3040,9 +3088,33 @@
122122+@@ -3039,9 +3087,33 @@
123123 &self,
124124 input_event: &ConstellationInputEvent,
125125 ) -> Option<HitTestResult> {
···156156 }
157157158158 #[expect(unsafe_code)]
159159-@@ -3061,8 +3133,25 @@
159159+@@ -3060,8 +3132,25 @@
160160 // SAFETY: This is safe because `Window::query_elements_from_point` has ensured that
161161 // layout has run and any OpaqueNodes that no longer refer to real nodes are gone.
162162 let address = UntrustedNodeAddress(result.node.0 as *const c_void);
···183183 cursor: result.cursor,
184184 point_in_node: result.point_in_target,
185185 point_in_frame,
186186-@@ -3605,6 +3694,8 @@
186186+@@ -3604,6 +3693,8 @@
187187 player_context: WindowGLContext,
188188 #[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>,
189189 inherited_secure_context: Option<bool>,
···192192 theme: Theme,
193193 weak_script_thread: Weak<ScriptThread>,
194194 ) -> DomRoot<Self> {
195195-@@ -3631,6 +3722,8 @@
195195+@@ -3630,6 +3721,8 @@
196196 gpu_id_hub,
197197 inherited_secure_context,
198198 unminify_js,
···201201 Some(font_context),
202202 ),
203203 ongoing_navigation: Default::default(),
204204-@@ -3906,3 +3999,120 @@
204204+@@ -3905,3 +3998,120 @@
205205 Self::create_named_properties_object(cx, proto, object)
206206 }
207207 }
···11--- original
22+++ modified
33-@@ -299,6 +299,7 @@
33+@@ -300,6 +300,7 @@
44 &self,
55 name: DOMString,
66 noopener: bool,
···88 ) -> Option<DomRoot<WindowProxy>> {
99 let (response_sender, response_receiver) = generic_channel::channel().unwrap();
1010 let window = self
1111-@@ -334,6 +335,7 @@
1111+@@ -351,6 +352,7 @@
1212 opener_webview_id: window.webview_id(),
1313 opener_pipeline_id: self.currently_active.get().unwrap(),
1414 response_sender,
···1616 };
1717 let constellation_msg = ScriptToConstellationMessage::CreateAuxiliaryWebView(load_info);
1818 window.send_to_constellation(constellation_msg);
1919-@@ -352,6 +354,8 @@
2020- // Use the current `WebView`'s theme initially, but the embedder may
2121- // change this later.
2222- theme: window.theme(),
1919+@@ -373,6 +375,8 @@
2020+ sandboxing_flags: sandboxing_flag_set,
2121+ iframe_element_referrer_policy: ReferrerPolicy::EmptyString,
2222+ },
2323+ is_embedded_webview: false,
2424+ hide_focus: false,
2525 };
26262727 with_script_thread(|script_thread| {
2828-@@ -504,14 +508,32 @@
2828+@@ -525,14 +529,32 @@
2929 // (TODO) Step 11. Let referrerPolicy be the empty string.
3030 // (TODO) Step 12. If noreferrer is true, then set referrerPolicy to "no-referrer".
3131···6262 // TODO Step 15.2, Set up browsing context features for targetNavigable's
6363 // active browsing context given tokenizedFeatures.
6464 let target_document = match chosen.document() {
6565-@@ -526,16 +548,12 @@
6565+@@ -547,16 +569,12 @@
6666 let target_window = target_document.window();
6767 // Step 15.3 and 15.4 will have happened elsewhere,
6868 // since we've created a new browsing context and loaded it with about:blank.
···8080 let referrer = if noreferrer {
8181 Referrer::NoReferrer
8282 } else {
8383-@@ -599,6 +617,7 @@
8383+@@ -620,6 +638,7 @@
8484 &self,
8585 name: DOMString,
8686 noopener: bool,
···8888 ) -> (Option<DomRoot<WindowProxy>>, bool) {
8989 match name.to_lowercase().as_ref() {
9090 "" | "_self" => {
9191-@@ -616,7 +635,10 @@
9191+@@ -637,7 +656,10 @@
9292 // Step 5
9393 (Some(DomRoot::from_ref(self.top())), false)
9494 },
···100100 _ => {
101101 // Step 6.
102102 // TODO: expand the search to all 'familiar' bc,
103103-@@ -624,7 +646,10 @@
103103+@@ -645,7 +667,10 @@
104104 // See https://html.spec.whatwg.org/multipage/#familiar-with
105105 match ScriptThread::find_window_proxy_by_name(&name) {
106106 Some(proxy) => (Some(proxy), false),
+5-5
patches/components/script/navigation.rs.patch
···11--- original
22+++ modified
33-@@ -175,6 +175,10 @@
44- /// The [`Theme`] to use for this page, once it loads.
33+@@ -185,6 +185,10 @@
44+ /// The [`TargetSnapshotParams`] to use when creating this document.
55 #[no_trace]
66- pub(crate) theme: Theme,
66+ pub(crate) target_snapshot_params: TargetSnapshotParams,
77+ /// Whether this is an embedded webview (has parent_info but should have no WindowProxy parent).
88+ pub(crate) is_embedded_webview: bool,
99+ /// Whether this document should never receive focus (hidefocus attribute on the iframe).
···1111 }
12121313 impl InProgressLoad {
1414-@@ -196,6 +200,8 @@
1515- url_list: vec![url],
1414+@@ -207,6 +211,8 @@
1615 user_content_manager_id: new_pipeline_info.user_content_manager_id,
1716 theme: new_pipeline_info.theme,
1717+ target_snapshot_params: new_pipeline_info.target_snapshot_params,
1818+ is_embedded_webview: new_pipeline_info.is_embedded_webview,
1919+ hide_focus: new_pipeline_info.hide_focus,
2020 }
···11--- original
22+++ modified
33-@@ -18,7 +18,7 @@
33+@@ -16,7 +16,7 @@
44 };
55 use paint_api::rendering_context::RenderingContext;
66 use servo_base::generic_channel::{GenericSender, SendError};
···99 use servo_constellation_traits::EmbedderToConstellationMessage;
1010 use tokio::sync::mpsc::UnboundedSender as TokioSender;
1111 use tokio::sync::oneshot::Sender;
1212-@@ -963,6 +963,14 @@
1212+@@ -962,6 +962,14 @@
1313 ///
1414 /// [`window.open`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/open
1515 fn request_create_new(&self, _parent_webview: WebView, _: CreateNewWebViewRequest) {}
···2424 /// Content in a [`WebView`] is requesting permission to access a feature requiring
2525 /// permission from the user. The embedder should allow or deny the request, either by
2626 /// reading a cached value or querying the user for permission via the user interface.
2727-@@ -1034,6 +1042,25 @@
2727+@@ -1015,6 +1023,25 @@
2828 _tree_update: accesskit::TreeUpdate,
2929 ) {
3030 }
···8686 /// Specifies the information required to load an iframe.
8787 #[derive(Debug, Deserialize, Serialize)]
8888 pub struct IFrameLoadInfo {
8989-@@ -535,6 +573,90 @@
8989+@@ -538,6 +576,90 @@
9090 NoLongerActive,
9191 }
9292···177177 /// Messages from the script to the constellation.
178178 #[derive(Deserialize, IntoStaticStr, Serialize)]
179179 pub enum ScriptToConstellationMessage {
180180-@@ -579,6 +701,10 @@
180180+@@ -582,6 +704,10 @@
181181 NewBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin),
182182 /// A global stopped managing broadcast channels for a given channel-name.
183183 RemoveBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin),
···188188 /// Broadcast a message to all same-origin broadcast channels,
189189 /// excluding the source of the broadcast.
190190 ScheduleBroadcast(BroadcastChannelRouterId, BroadcastChannelMsg),
191191-@@ -591,6 +717,9 @@
191191+@@ -594,6 +720,9 @@
192192 Option<String>,
193193 Option<String>,
194194 ),
···198198 /// Indicates whether this pipeline is currently running animations.
199199 ChangeRunningAnimationsState(AnimationState),
200200 /// Requests that a new 2D canvas thread be created. (This is done in the constellation because
201201-@@ -673,6 +802,10 @@
201201+@@ -676,6 +805,10 @@
202202 ScriptNewIFrame(IFrameLoadInfoWithData),
203203 /// Script has opened a new auxiliary browsing context.
204204 CreateAuxiliaryWebView(AuxiliaryWebViewCreationRequest),
···209209 /// Mark a new document as active
210210 ActivateDocument,
211211 /// Set the document state for a pipeline (used by screenshot / reftests)
212212-@@ -722,6 +855,109 @@
212212+@@ -725,6 +858,109 @@
213213 RespondToScreenshotReadinessRequest(ScreenshotReadinessResponse),
214214 /// Request the constellation to force garbage collection in all `ScriptThread`'s.
215215 TriggerGarbageCollection,
···11--- original
22+++ modified
33-@@ -109,6 +109,10 @@
33+@@ -136,6 +136,10 @@
44 DirectoryListingHTML,
55 /// A HTML page that is used for the about:memory url.
66 AboutMemoryHTML,
···1111 /// RPC script for the Debugger API on behalf of devtools.
1212 DebuggerJS,
1313 }
1414-@@ -125,6 +129,7 @@
1414+@@ -152,6 +156,7 @@
1515 Resource::CrashHTML => "crash.html",
1616 Resource::DirectoryListingHTML => "directory-listing.html",
1717 Resource::AboutMemoryHTML => "about-memory.html",
+2-2
patches/components/shared/net/lib.rs.patch
···2626 }
27272828 /// A loading context, for context-specific sniffing, as defined in
2929-@@ -634,6 +639,64 @@
2929+@@ -632,6 +637,64 @@
3030 Prefetch,
3131 }
3232···9191 #[derive(Debug, Deserialize, Serialize)]
9292 pub enum CoreResourceMsg {
9393 Fetch(RequestBuilder, FetchChannels),
9494-@@ -705,6 +768,10 @@
9494+@@ -703,6 +766,10 @@
9595 /// and exit
9696 Exit(GenericOneshotSender<()>),
9797 CollectMemoryReport(ReportsChan),
+9-8
patches/components/shared/script/lib.rs.patch
···99 };
1010 use euclid::{Scale, Size2D};
1111 use fonts_traits::SystemFontServiceProxySender;
1212-@@ -41,8 +41,8 @@
1212+@@ -41,8 +41,9 @@
1313 use servo_canvas_traits::webgl::WebGLPipeline;
1414 use servo_config::prefs::PrefValue;
1515 use servo_constellation_traits::{
1616- KeyboardScroll, LoadData, NavigationHistoryBehavior, ScriptToConstellationSender,
1717-- ScrollStateUpdate, StructuredSerializedData, WindowSizeType,
1717+- ScrollStateUpdate, StructuredSerializedData, TargetSnapshotParams, WindowSizeType,
1818+ EmbeddedWebViewEventType, KeyboardScroll, LoadData, NavigationHistoryBehavior, PairingEvent,
1919-+ ScriptToConstellationSender, ScrollStateUpdate, StructuredSerializedData, WindowSizeType,
1919++ ScriptToConstellationSender, ScrollStateUpdate, StructuredSerializedData, TargetSnapshotParams,
2020++ WindowSizeType,
2021 };
2122 use servo_url::{ImmutableOrigin, ServoUrl};
2223 use storage_traits::StorageThreads;
2323-@@ -77,6 +77,14 @@
2424- pub user_content_manager_id: Option<UserContentManagerId>,
2525- /// The [`Theme`] of the new layout.
2424+@@ -79,6 +80,14 @@
2625 pub theme: Theme,
2626+ /// A snapshot of the navigation parameters of the target of this navigation.
2727+ pub target_snapshot_params: TargetSnapshotParams,
2728+ /// Whether this pipeline is for an embedded webview (created via `<iframe embed>`).
2829+ /// Embedded webviews have `parent_info` set for rendering hierarchy, but their
2930+ /// WindowProxy should have no parent (so `window.parent === window.self`).
···3536 }
36373738 /// When a pipeline is closed, should its browsing context be discarded too?
3838-@@ -286,6 +294,15 @@
3939+@@ -289,6 +298,15 @@
3940 SendImageKeysBatch(PipelineId, Vec<ImageKey>),
4041 /// Preferences were updated in the parent process.
4142 PreferencesUpdated(Vec<(String, PrefValue)>),
···5152 /// Notify the `ScriptThread` that the Servo renderer is no longer waiting on
5253 /// asynchronous image uploads for the given `Pipeline`. These are mainly used
5354 /// by canvas to perform uploads while the display list is being built.
5454-@@ -322,6 +339,24 @@
5555+@@ -325,6 +343,24 @@
5556 SetAccessibilityActive(PipelineId, bool),
5657 /// Force a garbage collection in this script thread.
5758 TriggerGarbageCollection,