diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index bbdf1863857..9500e783e08 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -544,6 +544,13 @@ impl IOCompositor { self.window.load_end(back, forward, root); } + (Msg::AllowNavigation(url, response_chan), ShutdownState::NotShuttingDown) => { + let allow = self.window.allow_navigation(url); + if let Err(e) = response_chan.send(allow) { + warn!("Failed to send allow_navigation result ({}).", e); + } + } + (Msg::DelayedCompositionTimeout(timestamp), ShutdownState::NotShuttingDown) => { if let CompositionRequest::DelayedComposite(this_timestamp) = self.composition_request { diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs index 8a78a7e8882..e475bba0514 100644 --- a/components/compositing/compositor_thread.rs +++ b/components/compositing/compositor_thread.rs @@ -86,6 +86,8 @@ pub enum Msg { LoadStart(bool, bool), /// The load of a page has completed: (can go back, can go forward, is root frame). LoadComplete(bool, bool, bool), + /// Wether or not to follow a link + AllowNavigation(ServoUrl, IpcSender), /// We hit the delayed composition timeout. (See `delayed_composition.rs`.) DelayedCompositionTimeout(u64), /// Composite. @@ -144,6 +146,7 @@ impl Debug for Msg { Msg::ChangePageUrl(..) => write!(f, "ChangePageUrl"), Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), Msg::LoadComplete(..) => write!(f, "LoadComplete"), + Msg::AllowNavigation(..) => write!(f, "AllowNavigation"), Msg::LoadStart(..) => write!(f, "LoadStart"), Msg::DelayedCompositionTimeout(..) => write!(f, "DelayedCompositionTimeout"), Msg::Recomposite(..) => write!(f, "Recomposite"), diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 84a1365af0d..8c0c3b922eb 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -137,6 +137,8 @@ pub trait WindowMethods { fn load_end(&self, back: bool, forward: bool, root: bool); /// Called when the browser encounters an error while loading a URL fn load_error(&self, code: NetError, url: String); + /// Wether or not to follow a link + fn allow_navigation(&self, url: ServoUrl) -> bool; /// Called when the tag has finished parsing fn head_parsed(&self); diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 9e182194eef..391fa1a679d 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -1575,6 +1575,13 @@ impl Constellation } fn load_url(&mut self, source_id: PipelineId, load_data: LoadData, replace: bool) -> Option { + // Allow the embedder to handle the url itself + let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); + self.compositor_proxy.send(ToCompositorMsg::AllowNavigation(load_data.url.clone(), chan)); + if let Ok(false) = port.recv() { + return None; + } + debug!("Loading {} in pipeline {}.", load_data.url, source_id); // If this load targets an iframe, its framing element may exist // in a separate script thread than the framed document that initiated diff --git a/ports/cef/window.rs b/ports/cef/window.rs index ecf8a1f2984..1e96b828c24 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -484,6 +484,10 @@ impl WindowMethods for Window { } } + fn allow_navigation(&self, _: ServoUrl) -> bool { + true + } + fn supports_clipboard(&self) -> bool { false } diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 04cc8fbe2b0..5f48abef1cd 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -1107,6 +1107,10 @@ impl WindowMethods for Window { } } + fn allow_navigation(&self, _: ServoUrl) -> bool { + true + } + fn supports_clipboard(&self) -> bool { false }