Rewild Your Web
web browser dweb
at main 198 lines 8.2 kB view raw
1--- original 2+++ modified 3@@ -41,9 +41,9 @@ 4 use canvas_traits::webgl::WebGLPipeline; 5 use chrono::{DateTime, Local}; 6 use constellation_traits::{ 7- JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, ScreenshotReadinessResponse, 8- ScriptToConstellationChan, ScriptToConstellationMessage, StructuredSerializedData, 9- WindowSizeType, 10+ EmbeddedWebViewEventType, JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, 11+ ScreenshotReadinessResponse, ScriptToConstellationChan, ScriptToConstellationMessage, 12+ StructuredSerializedData, WindowSizeType, 13 }; 14 use crossbeam_channel::unbounded; 15 use data_url::mime::Mime; 16@@ -54,8 +54,8 @@ 17 use embedder_traits::user_contents::{UserContentManagerId, UserContents, UserScript}; 18 use embedder_traits::{ 19 EmbedderControlId, EmbedderControlResponse, EmbedderMsg, FocusSequenceNumber, 20- JavaScriptEvaluationError, JavaScriptEvaluationId, MediaSessionActionType, Theme, 21- ViewportDetails, WebDriverScriptCommand, 22+ JavaScriptEvaluationError, JavaScriptEvaluationId, MediaSessionActionType, ServoErrorType, 23+ Theme, ViewportDetails, WebDriverScriptCommand, 24 }; 25 use encoding_rs::Encoding; 26 use fonts::{FontContext, SystemFontServiceProxy}; 27@@ -92,6 +92,7 @@ 28 UpdatePipelineIdReason, 29 }; 30 use servo_arc::Arc as ServoArc; 31+use servo_config::pref_util::PrefValue; 32 use servo_config::{opts, prefs}; 33 use servo_url::{ImmutableOrigin, MutableOrigin, OriginSnapshot, ServoUrl}; 34 use storage_traits::StorageThreads; 35@@ -1940,11 +1941,22 @@ 36 self.handle_refresh_cursor(pipeline_id); 37 }, 38 ScriptThreadMessage::PreferencesUpdated(updates) => { 39- let mut current_preferences = prefs::get().clone(); 40- for (name, value) in updates { 41- current_preferences.set_value(&name, value); 42+ // Only update core preferences (those without namespace separator) 43+ // Embedder preferences are already stored in the embedder prefs registry 44+ let core_updates: Vec<_> = updates 45+ .iter() 46+ .filter(|(name, _)| !name.contains('.')) 47+ .collect(); 48+ if !core_updates.is_empty() { 49+ let mut current_preferences = prefs::get().clone(); 50+ for (name, value) in core_updates { 51+ current_preferences.set_value(name, value.clone()); 52+ } 53+ prefs::set(current_preferences); 54 } 55- prefs::set(current_preferences); 56+ 57+ // Dispatch preferencechanged events to all Embedder instances 58+ self.dispatch_preference_changed_to_embedders(&updates, CanGc::from_cx(cx)); 59 }, 60 ScriptThreadMessage::ForwardKeyboardScroll(pipeline_id, scroll) => { 61 if let Some(document) = self.documents.borrow().find_document(pipeline_id) { 62@@ -1979,6 +1991,16 @@ 63 ScriptThreadMessage::UpdatePinchZoomInfos(id, pinch_zoom_infos) => { 64 self.handle_update_pinch_zoom_infos(id, pinch_zoom_infos, CanGc::from_cx(cx)); 65 }, 66+ ScriptThreadMessage::DispatchEmbeddedWebViewEvent { 67+ target, 68+ parent, 69+ event, 70+ } => { 71+ self.handle_embedded_webview_event(parent, target, event, CanGc::from_cx(cx)); 72+ }, 73+ ScriptThreadMessage::DispatchServoError(error_type, message) => { 74+ self.handle_dispatch_servo_error(error_type, message, CanGc::from_cx(cx)); 75+ }, 76 } 77 } 78 79@@ -2925,6 +2947,9 @@ 80 .documents 81 .borrow() 82 .find_iframe(parent_pipeline_id, browsing_context_id); 83+ let is_embedded_webview = frame_element 84+ .as_ref() 85+ .is_some_and(|iframe| iframe.is_embedded_webview()); 86 if let Some(frame_element) = frame_element { 87 frame_element.update_pipeline_id(new_pipeline_id, reason, can_gc); 88 } 89@@ -2943,6 +2968,7 @@ 90 // is no need to pass along existing opener information that 91 // will be discarded. 92 None, 93+ is_embedded_webview, 94 ); 95 } 96 } 97@@ -3222,6 +3248,44 @@ 98 } 99 } 100 101+ /// Handle an embedded webview event that should be dispatched on an iframe element. 102+ fn handle_embedded_webview_event( 103+ &self, 104+ parent_id: PipelineId, 105+ browsing_context_id: BrowsingContextId, 106+ event: EmbeddedWebViewEventType, 107+ can_gc: CanGc, 108+ ) { 109+ let iframe = self 110+ .documents 111+ .borrow() 112+ .find_iframe(parent_id, browsing_context_id); 113+ match iframe { 114+ Some(iframe) => iframe.dispatch_embedded_webview_event(event, can_gc), 115+ None => warn!( 116+ "Embedded webview event sent to closed pipeline {}.", 117+ parent_id 118+ ), 119+ } 120+ } 121+ 122+ /// Handle a servo error by dispatching servoerror events to all navigator.embedder instances. 123+ fn handle_dispatch_servo_error( 124+ &self, 125+ error_type: ServoErrorType, 126+ message: String, 127+ can_gc: CanGc, 128+ ) { 129+ // Dispatch servoerror event to windows that already have an Embedder created 130+ for (_, document) in self.documents.borrow().iter() { 131+ if let Some(embedder) = document.window().Navigator().get_embedder() { 132+ // Enter the realm of the embedder's global before dispatching JS events 133+ let _ac = enter_realm(&*embedder); 134+ embedder.dispatch_servo_error(&error_type, &message, can_gc); 135+ } 136+ } 137+ } 138+ 139 fn ask_constellation_for_top_level_info( 140 &self, 141 sender_webview_id: WebViewId, 142@@ -3334,7 +3398,13 @@ 143 self.senders.pipeline_to_embedder_sender.clone(), 144 self.senders.constellation_sender.clone(), 145 incomplete.pipeline_id, 146- incomplete.parent_info, 147+ // For embedded webviews, don't pass parent_info to Window so that 148+ // is_top_level() returns true (they are top-level browsing contexts). 149+ if incomplete.is_embedded_webview { 150+ None 151+ } else { 152+ incomplete.parent_info 153+ }, 154 incomplete.viewport_details, 155 origin.clone(), 156 final_url.clone(), 157@@ -3356,6 +3426,8 @@ 158 #[cfg(feature = "webgpu")] 159 self.gpu_id_hub.clone(), 160 incomplete.load_data.inherited_secure_context, 161+ incomplete.is_embedded_webview, 162+ incomplete.hide_focus, 163 incomplete.theme, 164 self.this.clone(), 165 ); 166@@ -3377,6 +3449,7 @@ 167 incomplete.webview_id, 168 incomplete.parent_info, 169 incomplete.opener, 170+ incomplete.is_embedded_webview, 171 ); 172 if window_proxy.parent().is_some() { 173 // https://html.spec.whatwg.org/multipage/#navigating-across-documents:delaying-load-events-mode-2 174@@ -4084,6 +4157,24 @@ 175 document.event_handler().handle_refresh_cursor(); 176 } 177 178+ /// Dispatch preferencechanged events to all Embedder instances in this script thread. 179+ fn dispatch_preference_changed_to_embedders( 180+ &self, 181+ changes: &[(String, PrefValue)], 182+ can_gc: CanGc, 183+ ) { 184+ // Dispatch preferencechanged event to windows that already have an Embedder created 185+ for (_, document) in self.documents.borrow().iter() { 186+ if let Some(embedder) = document.window().Navigator().get_embedder() { 187+ // Enter the realm of the embedder's global before dispatching JS events 188+ let _ac = enter_realm(&*embedder); 189+ for (name, value) in changes { 190+ embedder.dispatch_preference_changed(name, value, can_gc); 191+ } 192+ } 193+ } 194+ } 195+ 196 pub(crate) fn is_servo_privileged(url: ServoUrl) -> bool { 197 with_script_thread(|script_thread| script_thread.privileged_urls.contains(&url)) 198 }