diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index ba5a4353d129..a57bc38dfd6c 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -548,6 +548,7 @@ impl Constellation fn new_pipeline(&mut self, pipeline_id: PipelineId, parent_info: Option<(PipelineId, FrameType)>, + old_pipeline_id: Option, initial_window_size: Option>, script_channel: Option>, load_data: LoadData, @@ -560,7 +561,9 @@ impl Constellation self.public_resource_threads.clone() }; - let parent_visibility = if let Some((parent_pipeline_id, _)) = parent_info { + let prev_visibility = if let Some(id) = old_pipeline_id { + self.pipelines.get(&id).map(|pipeline| pipeline.visible) + } else if let Some((parent_pipeline_id, _)) = parent_info { self.pipelines.get(&parent_pipeline_id).map(|pipeline| pipeline.visible) } else { None @@ -586,7 +589,7 @@ impl Constellation load_data: load_data, device_pixel_ratio: self.window_size.device_pixel_ratio, pipeline_namespace_id: self.next_pipeline_namespace_id(), - parent_visibility: parent_visibility, + prev_visibility: prev_visibility, webrender_api_sender: self.webrender_api_sender.clone(), is_private: is_private, }); @@ -1146,7 +1149,7 @@ impl Constellation let new_pipeline_id = PipelineId::new(); let load_data = LoadData::new(failure_url, None, None); - self.new_pipeline(new_pipeline_id, parent_info, window_size, None, load_data, false); + self.new_pipeline(new_pipeline_id, parent_info, Some(pipeline_id), window_size, None, load_data, false); self.push_pending_frame(new_pipeline_id, Some(pipeline_id)); @@ -1171,7 +1174,7 @@ impl Constellation let window_size = self.window_size.visible_viewport; let root_pipeline_id = PipelineId::new(); debug_assert!(PipelineId::fake_root_pipeline_id() == root_pipeline_id); - self.new_pipeline(root_pipeline_id, None, Some(window_size), None, + self.new_pipeline(root_pipeline_id, None, None, Some(window_size), None, LoadData::new(url.clone(), None, None), false); self.handle_load_start_msg(root_pipeline_id); self.push_pending_frame(root_pipeline_id, None); @@ -1290,6 +1293,7 @@ impl Constellation // Create the new pipeline, attached to the parent and push to pending frames self.new_pipeline(load_info.new_pipeline_id, Some((load_info.parent_pipeline_id, load_info.frame_type)), + load_info.old_pipeline_id, window_size, script_chan, load_data, @@ -1424,7 +1428,7 @@ impl Constellation // Create the new pipeline let window_size = self.pipelines.get(&source_id).and_then(|source| source.size); let new_pipeline_id = PipelineId::new(); - self.new_pipeline(new_pipeline_id, None, window_size, None, load_data, false); + self.new_pipeline(new_pipeline_id, None, None, window_size, None, load_data, false); self.push_pending_frame(new_pipeline_id, Some(source_id)); // Send message to ScriptThread that will suspend all timers @@ -1668,9 +1672,16 @@ impl Constellation } fn handle_set_visible_msg(&mut self, pipeline_id: PipelineId, visible: bool) { - let frame_id = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.frame); - let child_pipeline_ids: Vec = self.current_frame_tree_iter(frame_id) - .map(|frame| frame.current.pipeline_id) + let frame_id = match self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.frame) { + Some(id) => id, + None => return warn!("No frame associated with pipeline {:?}", pipeline_id), + }; + + let child_pipeline_ids: Vec = self.full_frame_tree_iter(frame_id) + .flat_map(|frame| frame.next.iter() + .chain(frame.prev.iter()) + .chain(once(&frame.current))) + .map(|state| state.pipeline_id) .collect(); for id in child_pipeline_ids { if let Some(pipeline) = self.pipelines.get_mut(&id) { diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 7ed977b89adc..300aada74300 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -121,8 +121,8 @@ pub struct InitialPipelineState { pub load_data: LoadData, /// The ID of the pipeline namespace for this script thread. pub pipeline_namespace_id: PipelineNamespaceId, - /// Pipeline visibility is inherited from parent - pub parent_visibility: Option, + /// Pipeline visibility to be inherited + pub prev_visibility: Option, /// Optional webrender api (if enabled). pub webrender_api_sender: Option, /// Whether this pipeline is considered private. @@ -263,7 +263,7 @@ impl Pipeline { state.is_private, state.load_data.url, state.window_size, - state.parent_visibility.unwrap_or(true)); + state.prev_visibility.unwrap_or(true)); pipeline.notify_visibility(); diff --git a/tests/wpt/mozilla/tests/mozilla/mozbrowser/iframe_visibility.html b/tests/wpt/mozilla/tests/mozilla/mozbrowser/iframe_visibility.html index 4681f5db25ae..8987998993cd 100644 --- a/tests/wpt/mozilla/tests/mozilla/mozbrowser/iframe_visibility.html +++ b/tests/wpt/mozilla/tests/mozilla/mozbrowser/iframe_visibility.html @@ -88,5 +88,28 @@ }); document.body.appendChild(iframe); }, 'Minimum setTimeout of 1s when pipeline is invisible'); + + async_test(function(t) { + var iframe = document.createElement("iframe"); + var destination = "helper.html"; + iframe.src = "http://web-platform.test:8000/common/blank.html"; + iframe.mozbrowser = true; + iframe.onload = t.step_func(function() { + iframe.addEventListener("mozbrowservisibilitychange", t.step_func(function() { + iframe.src = destination; + })); + if (iframe.src !== destination) { + iframe.setVisible(false); + } else { + var startTime = Date.now(); + iframe.contentWindow.setTimeout(t.step_func(function() { + assert_true(Date.now() - startTime >= 1000); + t.done(); + }), 1); + } + }); + document.body.appendChild(iframe); + }, 'Minimum setTimeout of 1s persists after new page is loaded'); +