diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 228211e3ef87..45dd597b4137 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -606,6 +606,10 @@ impl Constellation { script_chan.send(ConstellationControlMsg::UpdateSubpageId(parent_pipeline_id, subpage_id, new_subpage_id)).unwrap(); + + // If this is an iframe, send a mozbrowser location change event. + // This is the result of a back/forward navigation. + self.trigger_mozbrowserlocationchange(next_pipeline_id); } } @@ -637,7 +641,7 @@ impl Constellation { } fn handle_mozbrowser_event_msg(&mut self, - pipeline_id: PipelineId, + containing_pipeline_id: PipelineId, subpage_id: SubpageId, event_name: String, event_detail: Option) { @@ -645,13 +649,8 @@ impl Constellation { // Find the script channel for the given parent pipeline, // and pass the event to that script task. - let pipeline = self.pipeline(pipeline_id); - let ScriptControlChan(ref script_channel) = pipeline.script_chan; - let event = ConstellationControlMsg::MozBrowserEvent(pipeline_id, - subpage_id, - event_name, - event_detail); - script_channel.send(event).unwrap(); + let pipeline = self.pipeline(containing_pipeline_id); + pipeline.trigger_mozbrowser_event(subpage_id, event_name, event_detail); } fn add_or_replace_pipeline_in_frame_tree(&mut self, frame_change: FrameChange) { @@ -692,6 +691,10 @@ impl Constellation { // Build frame tree and send permission self.send_frame_tree_and_grant_paint_permission(); + // If this is an iframe, send a mozbrowser location change event. + // This is the result of a link being clicked and a navigation completing. + self.trigger_mozbrowserlocationchange(frame_change.new_pipeline_id); + // Remove any evicted frames if let Some(evicted_frames) = evicted_frames { for pipeline_id in &evicted_frames { @@ -862,6 +865,28 @@ impl Constellation { } } + // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange + fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) { + if opts::experimental_enabled() { + // Work around borrow checker + let event_info = { + let pipeline = self.pipeline(pipeline_id); + + pipeline.parent_info.map(|(containing_pipeline_id, subpage_id)| { + (containing_pipeline_id, subpage_id, pipeline.url.serialize()) + }) + }; + + // If this is an iframe, then send the event with new url + if let Some((containing_pipeline_id, subpage_id, url)) = event_info { + let parent_pipeline = self.pipeline(containing_pipeline_id); + parent_pipeline.trigger_mozbrowser_event(subpage_id, + "mozbrowserlocationchange".to_owned(), + Some(url)); + } + } + } + fn pipeline_is_in_current_frame(&self, pipeline_id: PipelineId) -> bool { self.current_frame_tree_iter(self.root_frame_id) .any(|current_frame| current_frame.current == pipeline_id) diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index 0d8e6261d25d..b5fcebb578ae 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -24,6 +24,7 @@ use profile::time::TimeProfilerChan; use std::sync::mpsc::{Receiver, channel}; use url::Url; use util::geometry::{PagePx, ViewportPx}; +use util::opts; /// A uniquely-identifiable pipeline of script task, layout task, and paint task. pub struct Pipeline { @@ -244,4 +245,18 @@ impl Pipeline { pub fn add_child(&mut self, frame_id: FrameId) { self.children.push(frame_id); } + + pub fn trigger_mozbrowser_event(&self, + subpage_id: SubpageId, + event_name: String, + event_detail: Option) { + assert!(opts::experimental_enabled()); + + let ScriptControlChan(ref script_channel) = self.script_chan; + let event = ConstellationControlMsg::MozBrowserEvent(self.id, + subpage_id, + event_name, + event_detail); + script_channel.send(event).unwrap(); + } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 999d759df791..a153d462772b 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -213,6 +213,7 @@ pub trait DocumentHelpers<'a> { fn begin_focus_transaction(self); fn request_focus(self, elem: JSRef); fn commit_focus_transaction(self); + fn title_changed(self); fn send_title_to_compositor(self); fn dirty_all_nodes(self); fn handle_click_event(self, js_runtime: *mut JSRuntime, _button: uint, point: Point2D); @@ -222,6 +223,7 @@ pub trait DocumentHelpers<'a> { fn handle_mouse_move_event(self, js_runtime: *mut JSRuntime, point: Point2D, prev_mouse_over_targets: &mut Vec>) -> bool; fn set_current_script(self, script: Option>); + fn trigger_mozbrowser_event(self, event_name: String, event_detail: Option); } impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { @@ -453,6 +455,14 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { self.focused.assign(self.possibly_focused.get()); } + /// Handles any updates when the document's title has changed. + fn title_changed(self) { + // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsertitlechange + self.trigger_mozbrowser_event("mozbrowsertitlechange".to_owned(), Some(self.Title())); + + self.send_title_to_compositor(); + } + /// Sends this document's title to the compositor. fn send_title_to_compositor(self) { let window = self.window().root(); @@ -672,6 +682,21 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { fn set_current_script(self, script: Option>) { self.current_script.assign(script); } + + fn trigger_mozbrowser_event(self, event_name: String, event_detail: Option) { + if opts::experimental_enabled() { + let window = self.window.root(); + + if let Some((containing_pipeline_id, subpage_id)) = window.r().parent_info() { + let ConstellationChan(ref chan) = window.r().constellation_chan(); + let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id, + subpage_id, + event_name, + event_detail); + chan.send(event).unwrap(); + } + } + } } #[derive(PartialEq)] @@ -1438,19 +1463,8 @@ impl DocumentProgressHandler { event.r().fire(target); }); - if opts::experimental_enabled() { - // If this is a child frame, and experimental mode is enabled, - // send the mozbrowserloadend event. For details, see - // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadend - if let Some((containing_pipeline_id, subpage_id)) = window_ref.parent_info() { - let ConstellationChan(ref chan) = window_ref.constellation_chan(); - let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id, - subpage_id, - "mozbrowserloadend".to_owned(), - None); - chan.send(event).unwrap(); - } - } + // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadend + document.r().trigger_mozbrowser_event("mozbrowserloadend".to_owned(), None); window_ref.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs index 71352d742dbc..85a1390bffab 100644 --- a/components/script/dom/htmltitleelement.rs +++ b/components/script/dom/htmltitleelement.rs @@ -78,7 +78,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTitleElement> { let node: JSRef = NodeCast::from_ref(*self); if node.is_in_doc() { let document = node.owner_doc().root(); - document.r().send_title_to_compositor(); + document.r().title_changed(); } } @@ -86,7 +86,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTitleElement> { let node: JSRef = NodeCast::from_ref(*self); if is_in_doc { let document = node.owner_doc().root(); - document.r().send_title_to_compositor() + document.r().title_changed(); } } } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 8a915cbc9988..bb7a5563d0f6 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -761,6 +761,11 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { fn thaw(self) { self.timers.resume(); + + // Push the document title to the compositor since we are + // activating this document due to a navigation. + let document = self.Document().root(); + document.r().title_changed(); } fn freeze(self) { diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 70af85346d37..fbc725407888 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -381,6 +381,7 @@ impl Window { VirtualKeyCode::Semicolon => Ok(Key::Semicolon), VirtualKeyCode::Slash => Ok(Key::Slash), VirtualKeyCode::Tab => Ok(Key::Tab), + VirtualKeyCode::Subtract => Ok(Key::Minus), _ => Err(()), }