Rewild Your Web
web browser dweb
at main 167 lines 7.2 kB view raw
1--- original 2+++ modified 3@@ -38,7 +38,7 @@ 4 use embedder_traits::{ 5 AlertResponse, ConfirmResponse, EmbedderMsg, JavaScriptEvaluationError, PromptResponse, 6 ScriptToEmbedderChan, SimpleDialogRequest, Theme, UntrustedNodeAddress, ViewportDetails, 7- WebDriverJSResult, WebDriverLoadStatus, 8+ WebDriverJSResult, WebDriverLoadStatus, WebViewPoint, 9 }; 10 use euclid::default::Rect as UntypedRect; 11 use euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; 12@@ -1139,12 +1139,22 @@ 13 14 let (sender, receiver) = 15 ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap(); 16+ 17 let dialog = SimpleDialogRequest::Alert { 18 id: self.Document().embedder_controls().next_control_id(), 19 message: message.to_string(), 20 response_sender: sender, 21 }; 22- self.send_to_embedder(EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog)); 23+ 24+ // For embedded webviews, route through constellation to parent shell 25+ if self.as_global_scope().is_embedded_webview() { 26+ self.Document() 27+ .embedder_controls() 28+ .show_simple_dialog_for_embedded_webview(dialog); 29+ } else { 30+ self.send_to_embedder(EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog)); 31+ } 32+ 33 receiver.recv().unwrap_or_else(|_| { 34 // If the receiver is closed, we assume the dialog was cancelled. 35 debug!("Alert dialog was cancelled or failed to show."); 36@@ -1172,13 +1182,22 @@ 37 // the user to respond with a positive or negative response. 38 let (sender, receiver) = 39 ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap(); 40+ 41 let dialog = SimpleDialogRequest::Confirm { 42 id: self.Document().embedder_controls().next_control_id(), 43 message: message.to_string(), 44 response_sender: sender, 45 }; 46- self.send_to_embedder(EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog)); 47 48+ // For embedded webviews, route through constellation to parent shell 49+ if self.as_global_scope().is_embedded_webview() { 50+ self.Document() 51+ .embedder_controls() 52+ .show_simple_dialog_for_embedded_webview(dialog); 53+ } else { 54+ self.send_to_embedder(EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog)); 55+ } 56+ 57 // Step 5: Let userPromptHandler be WebDriver BiDi user prompt opened with this, 58 // "confirm", and message. 59 // 60@@ -1223,6 +1242,7 @@ 61 // defaulted to the value given by default. 62 let (sender, receiver) = 63 ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap(); 64+ 65 let dialog = SimpleDialogRequest::Prompt { 66 id: self.Document().embedder_controls().next_control_id(), 67 message: message.to_string(), 68@@ -1229,8 +1249,16 @@ 69 default: default.to_string(), 70 response_sender: sender, 71 }; 72- self.send_to_embedder(EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog)); 73 74+ // For embedded webviews, route through constellation to parent shell 75+ if self.as_global_scope().is_embedded_webview() { 76+ self.Document() 77+ .embedder_controls() 78+ .show_simple_dialog_for_embedded_webview(dialog); 79+ } else { 80+ self.send_to_embedder(EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog)); 81+ } 82+ 83 // Step 6: Let userPromptHandler be WebDriver BiDi user prompt opened with this, 84 // "prompt", and message. 85 // TODO: Add support for WebDriver BiDi. 86@@ -3053,9 +3081,33 @@ 87 &self, 88 input_event: &ConstellationInputEvent, 89 ) -> Option<HitTestResult> { 90- self.hit_test_from_point_in_viewport( 91- input_event.hit_test_result.as_ref()?.point_in_viewport, 92- ) 93+ // For pointer events with coordinates, prefer the original event point over the 94+ // WebRender hit test result's point_in_viewport. This is because the WebRender 95+ // hit test might have computed coordinates relative to an embedded iframe's 96+ // viewport, not the parent document's viewport. 97+ // 98+ // For events without coordinates or when the original point is unavailable, 99+ // fall back to the WebRender hit test result's point. 100+ let point_in_viewport = input_event 101+ .event 102+ .event 103+ .point() 104+ .map(|point| match point { 105+ WebViewPoint::Page(css_point) => css_point, 106+ WebViewPoint::Device(device_point) => { 107+ let scale = self.device_pixel_ratio(); 108+ Point2D::new(device_point.x / scale.get(), device_point.y / scale.get()) 109+ }, 110+ }) 111+ .or_else(|| { 112+ // Fall back to the WebRender hit test result's point if the original 113+ // event point is not available. 114+ input_event 115+ .hit_test_result 116+ .as_ref() 117+ .map(|r| r.point_in_viewport) 118+ })?; 119+ self.hit_test_from_point_in_viewport(point_in_viewport) 120 } 121 122 #[expect(unsafe_code)] 123@@ -3074,8 +3126,25 @@ 124 // SAFETY: This is safe because `Window::query_elements_from_point` has ensured that 125 // layout has run and any OpaqueNodes that no longer refer to real nodes are gone. 126 let address = UntrustedNodeAddress(result.node.0 as *const c_void); 127+ let node = unsafe { from_untrusted_node_address(address) }; 128+ 129+ // Verify the node belongs to this window's document 130+ let node_doc = node.owner_doc(); 131+ let our_doc = self.Document(); 132+ if &*node_doc != &*our_doc { 133+ warn!( 134+ "hit_test_from_point_in_viewport: node {:?} belongs to different document! \ 135+ Node doc URL: {:?}, Our doc URL: {:?}", 136+ node.debug_str(), 137+ node_doc.url(), 138+ our_doc.url() 139+ ); 140+ // Return None to indicate hit test failed for this document 141+ return None; 142+ } 143+ 144 Some(HitTestResult { 145- node: unsafe { from_untrusted_node_address(address) }, 146+ node, 147 cursor: result.cursor, 148 point_in_node: result.point_in_target, 149 point_in_frame, 150@@ -3755,6 +3824,8 @@ 151 player_context: WindowGLContext, 152 #[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>, 153 inherited_secure_context: Option<bool>, 154+ is_embedded_webview: bool, 155+ hide_focus: bool, 156 theme: Theme, 157 weak_script_thread: Weak<ScriptThread>, 158 ) -> DomRoot<Self> { 159@@ -3781,6 +3852,8 @@ 160 gpu_id_hub, 161 inherited_secure_context, 162 unminify_js, 163+ is_embedded_webview, 164+ hide_focus, 165 Some(font_context.clone()), 166 ), 167 ongoing_navigation: Default::default(),