diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-09-13 10:28:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-13 10:28:45 -0400 |
commit | 7b3feb7ffe176907233c85e0fc1c4300ee64ea8c (patch) | |
tree | b62142fe4156f51a4958c3daf3503bd338571044 /components/constellation | |
parent | efa2c7334eef4e2d4e905b5d187deb1fd54ae577 (diff) | |
parent | b051df76ef3f5d9764c37607105b8a31956aaec0 (diff) | |
download | servo-7b3feb7ffe176907233c85e0fc1c4300ee64ea8c.tar.gz servo-7b3feb7ffe176907233c85e0fc1c4300ee64ea8c.zip |
Auto merge of #21559 - mandreyel:pipeline-fields-to-browsingcontext, r=cbrewster
Frame should store some of the data that is currently in Pipeline #14692
<!-- Please describe your changes on the following line: -->
Apologies, meant to land it sooner but deadline at work got hectic.
So I moved the `Pipeline::{visible, is_private, parent_info}` fields (`size` was moved earlier) to `BrowsingContext`, and renamed them where appropriate (and did some minor refactoring on the side, hope that's alright).
This introduced some complications, because when a pipeline is spawned for a browsing context that does not yet exist, the browsing context won't be constructed until after pipeline has made its document active. Thus, values for the fields that used to be in `Pipeline` and are now in `BrowsingContext` could not be easily retrieved when constructing the `BrowsingContext` (since in most cases they were only available when spawning a pipeline).
For this reason, I've put these fields in `SessionHistoryChange` since one is always created and added to `Constellation::pending_changes` when a new pipeline is created, so it provides an easy way to forward the necessary values to new `BrowsingContext`s.
Though frankly I'm not sure I like expanding `SessionHistoryChange`'s purpose to serve as a crutch to construct browsing contexts, so a way to uncouple purposes would be to separately store the values for a to-be-created `BrowsingContext` in a collection of structs in `Constellation` and consume them when a new `BrowsingContext` is created. Here's a PoC: https://github.com/mandreyel/servo/commit/6fa2160bcc14db7ab020a65eba1473d7c36bc44d.
I didn't include this by default because it introduces a little overhead. Perhaps `PendingBrowsingContextInfo` could be stored as an `Option<>` next to a `SessionHistoryChange` in `Constellation::pending_changes`? That'd uncouple the two structs but not incur any overhead.
I don't think it's finished, so I've marked some areas where I need input on small matters with `TODO(mandreyel)`, but the general idea is done. I'll be sure to squash commits when no further changes need be done!
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #14692.
<!-- Either: -->
- [x] These changes do not require tests because no new features or behaviour were introduced.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21559)
<!-- Reviewable:end -->
Diffstat (limited to 'components/constellation')
-rw-r--r-- | components/constellation/browsingcontext.rs | 51 | ||||
-rw-r--r-- | components/constellation/constellation.rs | 662 | ||||
-rw-r--r-- | components/constellation/pipeline.rs | 62 | ||||
-rw-r--r-- | components/constellation/session_history.rs | 5 |
4 files changed, 454 insertions, 326 deletions
diff --git a/components/constellation/browsingcontext.rs b/components/constellation/browsingcontext.rs index 329a3ef20a0..c4415ff169c 100644 --- a/components/constellation/browsingcontext.rs +++ b/components/constellation/browsingcontext.rs @@ -8,13 +8,31 @@ use pipeline::Pipeline; use std::collections::{HashMap, HashSet}; use style_traits::CSSPixel; +/// Because a browsing context is only constructed once the document that's +/// going to be in it becomes active (i.e. not when a pipeline is spawned), some +/// values needed in browsing context are not easily available at the point of +/// constructing it. Thus, every time a pipeline is created for a browsing +/// context which doesn't exist yet, these values needed for the new browsing +/// context are stored here so that they may be available later. +pub struct NewBrowsingContextInfo { + /// The parent pipeline that contains this browsing context. `None` if this + /// is a top level browsing context. + pub parent_pipeline_id: Option<PipelineId>, + + /// Whether this browsing context is in private browsing mode. + pub is_private: bool, + + /// Whether this browsing context should be treated as visible for the + /// purposes of scheduling and resource management. + pub is_visible: bool, +} + /// The constellation's view of a browsing context. -/// Each browsing context has a session history, caused by -/// navigation and traversing the history. Each browsing context has its -/// current entry, plus past and future entries. The past is sorted -/// chronologically, the future is sorted reverse chronologically: -/// in particular prev.pop() is the latest past entry, and -/// next.pop() is the earliest future entry. +/// Each browsing context has a session history, caused by navigation and +/// traversing the history. Each browsing context has its current entry, plus +/// past and future entries. The past is sorted chronologically, the future is +/// sorted reverse chronologically: in particular prev.pop() is the latest +/// past entry, and next.pop() is the earliest future entry. pub struct BrowsingContext { /// The browsing context id. pub id: BrowsingContextId, @@ -25,9 +43,22 @@ pub struct BrowsingContext { /// The size of the frame. pub size: Option<TypedSize2D<f32, CSSPixel>>, + /// Whether this browsing context is in private browsing mode. + pub is_private: bool, + + /// Whether this browsing context should be treated as visible for the + /// purposes of scheduling and resource management. + pub is_visible: bool, + /// The pipeline for the current session history entry. pub pipeline_id: PipelineId, + /// The parent pipeline that contains this browsing context. `None` if this + /// is a top level browsing context. + pub parent_pipeline_id: Option<PipelineId>, + + /// All the pipelines that have been presented or will be presented in + /// this browsing context. pub pipelines: HashSet<PipelineId>, } @@ -38,6 +69,9 @@ impl BrowsingContext { id: BrowsingContextId, top_level_id: TopLevelBrowsingContextId, pipeline_id: PipelineId, + parent_pipeline_id: Option<PipelineId>, + is_private: bool, + is_visible: bool, ) -> BrowsingContext { let mut pipelines = HashSet::new(); pipelines.insert(pipeline_id); @@ -45,8 +79,11 @@ impl BrowsingContext { id: id, top_level_id: top_level_id, size: None, + is_private: is_private, + is_visible: is_visible, pipeline_id: pipeline_id, - pipelines, + parent_pipeline_id: parent_pipeline_id, + pipelines: pipelines, } } diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index a9c757cc2ba..58b3bdefe89 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -92,6 +92,7 @@ use backtrace::Backtrace; use bluetooth_traits::BluetoothRequest; use browsingcontext::{AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator}; +use browsingcontext::NewBrowsingContextInfo; use canvas::canvas_paint_thread::CanvasPaintThread; use canvas::webgl_thread::WebGLThreads; use canvas_traits::canvas::CanvasId; @@ -602,9 +603,8 @@ where pipelines: HashMap::new(), browsing_contexts: HashMap::new(), pending_changes: vec![], - // We initialize the namespace at 2, - // since we reserved namespace 0 for the embedder, - // and 0 for the constellation + // We initialize the namespace at 2, since we reserved + // namespace 0 for the embedder, and 0 for the constellation next_pipeline_namespace_id: PipelineNamespaceId(2), focus_pipeline_id: None, time_profiler_chan: state.time_profiler_chan, @@ -679,7 +679,7 @@ where pipeline_id: PipelineId, browsing_context_id: BrowsingContextId, top_level_browsing_context_id: TopLevelBrowsingContextId, - parent_info: Option<PipelineId>, + parent_pipeline_id: Option<PipelineId>, opener: Option<BrowsingContextId>, initial_window_size: Option<TypedSize2D<f32, CSSPixel>>, // TODO: we have to provide ownership of the LoadData @@ -689,6 +689,7 @@ where load_data: LoadData, sandbox: IFrameSandboxState, is_private: bool, + is_visible: bool, ) { if self.shutting_down { return; @@ -717,7 +718,7 @@ where }, } } else if let Some(parent) = - parent_info.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) + parent_pipeline_id.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) { (Some(parent.event_loop.clone()), None) } else if let Some(creator) = load_data @@ -737,22 +738,11 @@ where self.public_resource_threads.clone() }; - let parent_visibility = parent_info - .and_then(|parent_pipeline_id| self.pipelines.get(&parent_pipeline_id)) - .map(|pipeline| pipeline.visible); - - let prev_visibility = self - .browsing_contexts - .get(&browsing_context_id) - .and_then(|browsing_context| self.pipelines.get(&browsing_context.pipeline_id)) - .map(|pipeline| pipeline.visible) - .or(parent_visibility); - let result = Pipeline::spawn::<Message, LTF, STF>(InitialPipelineState { id: pipeline_id, browsing_context_id, top_level_browsing_context_id, - parent_info, + parent_pipeline_id, opener, script_to_constellation_chan: ScriptToConstellationChan { sender: self.script_sender.clone(), @@ -773,10 +763,9 @@ where load_data, device_pixel_ratio: self.window_size.device_pixel_ratio, pipeline_namespace_id: self.next_pipeline_namespace_id(), - prev_visibility, + prev_visibility: is_visible, webrender_api_sender: self.webrender_api_sender.clone(), webrender_document: self.webrender_document, - is_private, webgl_chan: self .webgl_threads .as_ref() @@ -843,26 +832,31 @@ where browsing_context_id: BrowsingContextId, top_level_id: TopLevelBrowsingContextId, pipeline_id: PipelineId, + parent_pipeline_id: Option<PipelineId>, + is_private: bool, + is_visible: bool, ) { debug!("Creating new browsing context {}", browsing_context_id); - let browsing_context = BrowsingContext::new(browsing_context_id, top_level_id, pipeline_id); - self.browsing_contexts - .insert(browsing_context_id, browsing_context); + let browsing_context = BrowsingContext::new( + browsing_context_id, + top_level_id, + pipeline_id, + parent_pipeline_id, + is_private, + is_visible, + ); + self.browsing_contexts.insert(browsing_context_id, browsing_context); - // If a child browsing_context, add it to the parent pipeline. - let parent_info = self - .pipelines - .get(&pipeline_id) - .and_then(|pipeline| pipeline.parent_info); - if let Some(parent_id) = parent_info { - if let Some(parent) = self.pipelines.get_mut(&parent_id) { + // If this context is a nested container, attach it to parent pipeline. + if let Some(parent_pipeline_id) = parent_pipeline_id { + if let Some(parent) = self.pipelines.get_mut(&parent_pipeline_id) { parent.add_child(browsing_context_id); } } } fn add_pending_change(&mut self, change: SessionHistoryChange) { - self.handle_load_start_msg(change.top_level_browsing_context_id, change.new_pipeline_id); + self.handle_load_start_msg(change.top_level_browsing_context_id, change.browsing_context_id); self.pending_changes.push(change); } @@ -1188,11 +1182,11 @@ where } } }, - FromScriptMsg::SetVisible(visible) => { - self.handle_set_visible_msg(source_pipeline_id, visible); + FromScriptMsg::SetVisible(is_visible) => { + self.handle_set_visible_msg(source_pipeline_id, is_visible); }, - FromScriptMsg::VisibilityChangeComplete(visible) => { - self.handle_visibility_change_complete(source_pipeline_id, visible); + FromScriptMsg::VisibilityChangeComplete(is_visible) => { + self.handle_visibility_change_complete(source_pipeline_id, is_visible); }, FromScriptMsg::RemoveIFrame(browsing_context_id, sender) => { let removed_pipeline_ids = self.handle_remove_iframe_msg(browsing_context_id); @@ -1233,13 +1227,19 @@ where warn!("Sending reply to get browsing context failed ({:?}).", e); } }, + // TODO(mandreyel): maybe change semantics of this message to + // reflect moving parent_info into BrowsingContext, i.e. message + // could be: GetParentInfo(BrowsingContextId, Sender) FromScriptMsg::GetParentInfo(pipeline_id, sender) => { - let result = self - .pipelines + let browsing_context = self.pipelines .get(&pipeline_id) - .and_then(|pipeline| pipeline.parent_info); - if let Err(e) = sender.send(result) { - warn!("Sending reply to get parent info failed ({:?}).", e); + .and_then(|pipeline| self.browsing_contexts.get(&pipeline.browsing_context_id)); + if let Some(browsing_context) = browsing_context { + if let Err(e) = sender.send(browsing_context.parent_pipeline_id) { + warn!("Sending reply to get parent info failed ({:?}).", e); + } + } else { + warn!("GetParentInfo for pipeline {} with no browsing context.", pipeline_id) } }, FromScriptMsg::GetTopForBrowsingContext(browsing_context_id, sender) => { @@ -1533,19 +1533,19 @@ where EmbedderMsg::Panic(reason, backtrace), )); - let (window_size, pipeline_id) = { + let (window_size, pipeline_id, is_visible) = { let browsing_context = self.browsing_contexts.get(&browsing_context_id); - let window_size = browsing_context.and_then(|browsing_context| browsing_context.size); - let pipeline_id = browsing_context.map(|browsing_context| browsing_context.pipeline_id); - (window_size, pipeline_id) + let window_size = browsing_context.and_then(|ctx| ctx.size); + let pipeline_id = browsing_context.map(|ctx| ctx.pipeline_id); + let is_visible = browsing_context.map(|ctx| ctx.is_visible); + (window_size, pipeline_id, is_visible) }; - let (pipeline_url, parent_info, opener) = { + let (pipeline_url, opener) = { let pipeline = pipeline_id.and_then(|id| self.pipelines.get(&id)); let pipeline_url = pipeline.map(|pipeline| pipeline.url.clone()); - let parent_info = pipeline.and_then(|pipeline| pipeline.parent_info); let opener = pipeline.and_then(|pipeline| pipeline.opener); - (pipeline_url, parent_info, opener) + (pipeline_url, opener) }; self.close_browsing_context_children( @@ -1567,22 +1567,25 @@ where let new_pipeline_id = PipelineId::new(); let load_data = LoadData::new(failure_url, None, None, None); let sandbox = IFrameSandboxState::IFrameSandboxed; + let is_private = false; self.new_pipeline( new_pipeline_id, browsing_context_id, top_level_browsing_context_id, - parent_info, + None, opener, window_size, load_data.clone(), sandbox, - false, + is_private, + is_visible.unwrap_or(true), ); self.add_pending_change(SessionHistoryChange { top_level_browsing_context_id: top_level_browsing_context_id, browsing_context_id: browsing_context_id, new_pipeline_id: new_pipeline_id, replace: None, + new_browsing_context_info: None, }); } @@ -1652,6 +1655,9 @@ where let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); let load_data = LoadData::new(url.clone(), None, None, None); let sandbox = IFrameSandboxState::IFrameUnsandboxed; + let is_private = false; + let is_visible = true; + if self.focus_pipeline_id.is_none() { self.focus_pipeline_id = Some(pipeline_id); } @@ -1666,13 +1672,19 @@ where Some(window_size), load_data.clone(), sandbox, - false, + is_private, + is_visible, ); self.add_pending_change(SessionHistoryChange { top_level_browsing_context_id: top_level_browsing_context_id, browsing_context_id: browsing_context_id, new_pipeline_id: pipeline_id, replace: None, + new_browsing_context_info: Some(NewBrowsingContextInfo { + parent_pipeline_id: None, + is_private: is_private, + is_visible: is_visible, + }), }); } @@ -1699,29 +1711,38 @@ where } fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) { - let (browsing_context_id, parent_id) = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => match pipeline.parent_info { - Some(parent_id) => (pipeline.browsing_context_id, parent_id), - None => return debug!("Pipeline {} has no parent.", pipeline_id), - }, - None => return warn!("Pipeline {} loaded after closure.", pipeline_id), + let browsing_context_id = match self.pipelines.get(&pipeline_id) { + Some(pipeline) => pipeline.browsing_context_id, + None => return warn!("Subframe {} loaded after closure.", pipeline_id), + }; + let parent_pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(browsing_context) => browsing_context.parent_pipeline_id, + None => return warn!( + "Subframe {} loaded in closed browsing context {}.", + pipeline_id, + browsing_context_id, + ), + }; + let parent_pipeline_id = match parent_pipeline_id { + Some(parent_pipeline_id) => parent_pipeline_id, + None => return warn!("Subframe {} has no parent.", pipeline_id), }; let msg = ConstellationControlMsg::DispatchIFrameLoadEvent { target: browsing_context_id, - parent: parent_id, + parent: parent_pipeline_id, child: pipeline_id, }; - let result = match self.pipelines.get(&parent_id) { + let result = match self.pipelines.get(&parent_pipeline_id) { Some(parent) => parent.event_loop.send(msg), None => { return warn!( "Parent {} browsing context loaded after closure.", - parent_id + parent_pipeline_id ) }, }; if let Err(e) = result { - self.handle_send_error(parent_id, e); + self.handle_send_error(parent_pipeline_id, e); } } @@ -1741,27 +1762,24 @@ where listener.initiate_fetch(Some(cancel_chan)); } - // The script thread associated with pipeline_id has loaded a URL in an iframe via script. This - // will result in a new pipeline being spawned and a child being added to - // the parent pipeline. This message is never the result of a - // page navigation. + // The script thread associated with pipeline_id has loaded a URL in an + // iframe via script. This will result in a new pipeline being spawned and + // a child being added to the parent browsing context. This message is never + // the result of a page navigation. fn handle_script_loaded_url_in_iframe_msg(&mut self, load_info: IFrameLoadInfoWithData) { - let (load_data, window_size, is_private) = { - let old_pipeline = load_info - .old_pipeline_id - .and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id)); - - let source_pipeline = match self.pipelines.get(&load_info.info.parent_pipeline_id) { - Some(source_pipeline) => source_pipeline, - None => { - return warn!( - "Script loaded url in closed iframe {}.", - load_info.info.parent_pipeline_id - ) - }, - }; + let IFrameLoadInfo { + parent_pipeline_id, + browsing_context_id, + top_level_browsing_context_id, + new_pipeline_id, + is_private, + replace, + } = load_info.info; + let (load_data, is_private) = { // If no url is specified, reload. + let old_pipeline = load_info.old_pipeline_id + .and_then(|id| self.pipelines.get(&id)); let load_data = load_info.load_data.unwrap_or_else(|| { let url = match old_pipeline { Some(old_pipeline) => old_pipeline.url.clone(), @@ -1769,44 +1787,71 @@ where }; // TODO - loaddata here should have referrer info (not None, None) - LoadData::new(url, Some(source_pipeline.id), None, None) + LoadData::new(url, Some(parent_pipeline_id), None, None) }); - let is_private = load_info.info.is_private || source_pipeline.is_private; - - let window_size = self - .browsing_contexts - .get(&load_info.info.browsing_context_id) - .and_then(|browsing_context| browsing_context.size); + let is_parent_private = { + let parent_browsing_context_id = + match self.pipelines.get(&parent_pipeline_id) { + Some(pipeline) => pipeline.browsing_context_id, + None => return warn!( + "Script loaded url in iframe {} in closed parent pipeline {}.", + browsing_context_id, + parent_pipeline_id, + ), + }; + let is_parent_private = + match self.browsing_contexts.get(&parent_browsing_context_id) { + Some(ctx) => ctx.is_private, + None => return warn!( + "Script loaded url in iframe {} in closed parent browsing context {}.", + browsing_context_id, + parent_browsing_context_id, + ), + }; + is_parent_private + }; + let is_private = is_private || is_parent_private; - (load_data, window_size, is_private) + (load_data, is_private) }; - let replace = if load_info.info.replace { - self.browsing_contexts - .get(&load_info.info.browsing_context_id) - .map(|browsing_context| NeedsToReload::No(browsing_context.pipeline_id)) - } else { - None + let (replace, window_size, is_visible) = { + let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { + Some(ctx) => ctx, + None => return warn!( + "Script loaded url in iframe with closed browsing context {}.", + browsing_context_id, + ), + }; + let replace = if replace { + Some(NeedsToReload::No(browsing_context.pipeline_id)) + } else { + None + }; + (replace, browsing_context.size, browsing_context.is_visible) }; // Create the new pipeline, attached to the parent and push to pending changes self.new_pipeline( - load_info.info.new_pipeline_id, - load_info.info.browsing_context_id, - load_info.info.top_level_browsing_context_id, - Some(load_info.info.parent_pipeline_id), + new_pipeline_id, + browsing_context_id, + top_level_browsing_context_id, + Some(parent_pipeline_id), None, window_size, load_data.clone(), load_info.sandbox, is_private, + is_visible, ); self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: load_info.info.top_level_browsing_context_id, - browsing_context_id: load_info.info.browsing_context_id, - new_pipeline_id: load_info.info.new_pipeline_id, - replace, + top_level_browsing_context_id: top_level_browsing_context_id, + browsing_context_id: browsing_context_id, + new_pipeline_id: new_pipeline_id, + replace: replace, + // Browsing context for iframe already exists. + new_browsing_context_info: None, }); } @@ -1829,38 +1874,51 @@ where // TODO: Referrer? let load_data = LoadData::new(url.clone(), Some(parent_pipeline_id), None, None); - let pipeline = { - let parent_pipeline = match self.pipelines.get(&parent_pipeline_id) { - Some(parent_pipeline) => parent_pipeline, - None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id), - }; - - let script_sender = parent_pipeline.event_loop.clone(); - - Pipeline::new( + let (pipeline, is_private, is_visible) = { + let (script_sender, parent_browsing_context_id) = + match self.pipelines.get(&parent_pipeline_id) { + Some(pipeline) => (pipeline.event_loop.clone(), pipeline.browsing_context_id), + None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id), + }; + let (is_parent_private, is_parent_visible) = + match self.browsing_contexts.get(&parent_browsing_context_id) { + Some(ctx) => (ctx.is_private, ctx.is_visible), + None => return warn!( + "New iframe {} loaded in closed parent browsing context {}.", + browsing_context_id, + parent_browsing_context_id, + ), + }; + let is_private = is_private || is_parent_private; + let pipeline = Pipeline::new( new_pipeline_id, browsing_context_id, top_level_browsing_context_id, - Some(parent_pipeline_id), None, script_sender, layout_sender, self.compositor_proxy.clone(), - is_private || parent_pipeline.is_private, url, - parent_pipeline.visible, + is_parent_visible, load_data, - ) + ); + + (pipeline, is_private, is_parent_visible) }; assert!(!self.pipelines.contains_key(&new_pipeline_id)); self.pipelines.insert(new_pipeline_id, pipeline); - self.add_pending_change(SessionHistoryChange { top_level_browsing_context_id: top_level_browsing_context_id, browsing_context_id: browsing_context_id, new_pipeline_id: new_pipeline_id, replace: None, + // Browsing context for iframe doesn't exist yet. + new_browsing_context_info: Some(NewBrowsingContextInfo { + parent_pipeline_id: Some(parent_pipeline_id), + is_private: is_private, + is_visible: is_visible, + }), }); } @@ -1879,24 +1937,38 @@ where // TODO: Referrer? let load_data = LoadData::new(url.clone(), None, None, None); - let pipeline = { - let (opener_pipeline, opener_id) = match self.pipelines.get(&opener_pipeline_id) { - Some(opener_pipeline) => (opener_pipeline, opener_pipeline.browsing_context_id), - None => return warn!("Auxiliary loaded url in closed pipeline {}.", opener_pipeline_id), - }; - let script_sender = opener_pipeline.event_loop.clone(); - Pipeline::new(new_pipeline_id, - new_browsing_context_id, - new_top_level_browsing_context_id, - None, - Some(opener_id), - script_sender, - layout_sender, - self.compositor_proxy.clone(), - opener_pipeline.is_private, - url, - opener_pipeline.visible, - load_data) + let (pipeline, is_private, is_visible) = { + let (script_sender, opener_browsing_context_id) = + match self.pipelines.get(&opener_pipeline_id) { + Some(pipeline) => (pipeline.event_loop.clone(), pipeline.browsing_context_id), + None => return warn!( + "Auxiliary loaded url in closed iframe {}.", + opener_pipeline_id + ), + }; + let (is_opener_private, is_opener_visible) = + match self.browsing_contexts.get(&opener_browsing_context_id) { + Some(ctx) => (ctx.is_private, ctx.is_visible), + None => return warn!( + "New auxiliary {} loaded in closed opener browsing context {}.", + new_browsing_context_id, + opener_browsing_context_id, + ), + }; + let pipeline = Pipeline::new( + new_pipeline_id, + new_browsing_context_id, + new_top_level_browsing_context_id, + Some(opener_browsing_context_id), + script_sender, + layout_sender, + self.compositor_proxy.clone(), + url, + is_opener_visible, + load_data + ); + + (pipeline, is_opener_private, is_opener_visible) }; assert!(!self.pipelines.contains_key(&new_pipeline_id)); @@ -1907,6 +1979,12 @@ where browsing_context_id: new_browsing_context_id, new_pipeline_id: new_pipeline_id, replace: None, + new_browsing_context_info: Some(NewBrowsingContextInfo { + // Auxiliary browsing contexts are always top-level. + parent_pipeline_id: None, + is_private: is_private, + is_visible: is_visible, + }), }); } @@ -1993,14 +2071,36 @@ where // requested change so it can update its internal state. // // If replace is true, the current entry is replaced instead of a new entry being added. - let (browsing_context_id, parent_info, opener) = match self.pipelines.get(&source_id) { - Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info, pipeline.opener), + let (browsing_context_id, opener) = match self.pipelines.get(&source_id) { + Some(pipeline) => (pipeline.browsing_context_id, pipeline.opener), None => { warn!("Pipeline {} loaded after closure.", source_id); return None; }, }; - match parent_info { + let (window_size, pipeline_id, parent_pipeline_id, is_visible) = + match self.browsing_contexts.get(&browsing_context_id) { + Some(ctx) => ( + ctx.size, + ctx.pipeline_id, + ctx.parent_pipeline_id, + ctx.is_visible, + ), + None => { + // This should technically never happen (since `load_url` is + // only called on existing browsing contexts), but we prefer to + // avoid `expect`s or `unwrap`s in `Constellation` to ward + // against future changes that might break things. + warn!( + "Pipeline {} loaded url in closed browsing context {}.", + source_id, + browsing_context_id, + ); + return None; + }, + }; + + match parent_pipeline_id { Some(parent_pipeline_id) => { // Find the script thread for the pipeline containing the iframe // and issue an iframe load through there. @@ -2046,17 +2146,6 @@ where // changes would be overridden by changing the subframe associated with source_id. // Create the new pipeline - let (top_level_id, window_size, pipeline_id) = - match self.browsing_contexts.get(&browsing_context_id) { - Some(context) => (context.top_level_id, context.size, context.pipeline_id), - None => { - warn!( - "Browsing context {} loaded after closure.", - browsing_context_id - ); - return None; - }, - }; let replace = if replace { Some(NeedsToReload::No(pipeline_id)) @@ -2066,22 +2155,28 @@ where let new_pipeline_id = PipelineId::new(); let sandbox = IFrameSandboxState::IFrameUnsandboxed; + // TODO(mandreyel): why is this false? Should we not inherit the + // privacy of the (existing) browsing context? + let is_private = false; self.new_pipeline( new_pipeline_id, browsing_context_id, - top_level_id, + top_level_browsing_context_id, None, opener, window_size, load_data.clone(), sandbox, - false, + is_private, + is_visible, ); self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: top_level_id, + top_level_browsing_context_id: top_level_browsing_context_id, browsing_context_id: browsing_context_id, new_pipeline_id: new_pipeline_id, replace, + // `load_url` is always invoked on an existing browsing context. + new_browsing_context_info: None, }); Some(new_pipeline_id) }, @@ -2108,14 +2203,9 @@ where fn handle_load_start_msg( &mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, - pipeline_id: PipelineId, + browsing_context_id: BrowsingContextId, ) { - if self - .pipelines - .get(&pipeline_id) - .and_then(|p| p.parent_info) - .is_none() - { + if browsing_context_id == top_level_browsing_context_id { // Notify embedder top level document started loading. self.embedder_proxy .send((Some(top_level_browsing_context_id), EmbedderMsg::LoadStart)); @@ -2164,8 +2254,9 @@ where EmbedderMsg::LoadComplete, )); } + } else { + self.handle_subframe_loaded(pipeline_id); } - self.handle_subframe_loaded(pipeline_id); } fn handle_navigated_to_fragment( @@ -2355,73 +2446,71 @@ where // TODO: Save the sandbox state so it can be restored here. let sandbox = IFrameSandboxState::IFrameUnsandboxed; + let (top_level_id, + old_pipeline_id, + parent_pipeline_id, + window_size, + is_private, + is_visible + ) = match self.browsing_contexts.get(&browsing_context_id) { + Some(ctx) => ( + ctx.top_level_id, + ctx.pipeline_id, + ctx.parent_pipeline_id, + ctx.size, + ctx.is_private, + ctx.is_visible, + ), + None => return warn!("No browsing context to traverse!"), + }; + let opener = match self.pipelines.get(&old_pipeline_id) { + Some(pipeline) => pipeline.opener, + None => None, + }; let new_pipeline_id = PipelineId::new(); - let (top_level_id, parent_info, opener, window_size, is_private) = - match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => { - match self.pipelines.get(&browsing_context.pipeline_id) { - Some(pipeline) => ( - browsing_context.top_level_id, - pipeline.parent_info, - pipeline.opener, - browsing_context.size, - pipeline.is_private, - ), - None => ( - browsing_context.top_level_id, - None, - None, - browsing_context.size, - false, - ), - } - }, - None => return warn!("No browsing context to traverse!"), - }; self.new_pipeline( new_pipeline_id, browsing_context_id, top_level_id, - parent_info, + parent_pipeline_id, opener, window_size, load_data.clone(), sandbox, is_private, + is_visible, ); self.add_pending_change(SessionHistoryChange { top_level_browsing_context_id: top_level_id, browsing_context_id: browsing_context_id, new_pipeline_id: new_pipeline_id, replace: Some(NeedsToReload::Yes(pipeline_id, load_data.clone())), + // Browsing context must exist at this point. + new_browsing_context_info: None, }); return; }, }; - let old_pipeline_id = match self.browsing_contexts.get_mut(&browsing_context_id) { - Some(browsing_context) => { - let old_pipeline_id = browsing_context.pipeline_id; - browsing_context.update_current_entry(new_pipeline_id); - old_pipeline_id - }, - None => { - return warn!( - "Browsing context {} was closed during traversal", - browsing_context_id - ); - }, - }; - - let parent_info = self - .pipelines - .get(&old_pipeline_id) - .and_then(|pipeline| pipeline.parent_info); + let (old_pipeline_id, parent_pipeline_id) = + match self.browsing_contexts.get_mut(&browsing_context_id) { + Some(browsing_context) => { + let old_pipeline_id = browsing_context.pipeline_id; + browsing_context.update_current_entry(new_pipeline_id); + (old_pipeline_id, browsing_context.parent_pipeline_id) + }, + None => { + return warn!( + "Browsing context {} was closed during traversal", + browsing_context_id + ); + }, + }; self.update_activity(old_pipeline_id); self.update_activity(new_pipeline_id); - if let Some(parent_pipeline_id) = parent_info { + if let Some(parent_pipeline_id) = parent_pipeline_id { let msg = ConstellationControlMsg::UpdatePipelineId( parent_pipeline_id, browsing_context_id, @@ -2602,7 +2691,7 @@ where let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { None => { return warn!( - "postMessage to closed browsing_context {}.", + "PostMessage to closed browsing_context {}.", browsing_context_id ) }, @@ -2653,12 +2742,23 @@ where } } + fn handle_focus_msg(&mut self, pipeline_id: PipelineId) { + self.focus_pipeline_id = Some(pipeline_id); + + // Focus parent iframes recursively + self.focus_parent_pipeline(pipeline_id); + } + fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) { - let (browsing_context_id, parent_info) = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info), + let browsing_context_id = match self.pipelines.get(&pipeline_id) { + Some(pipeline) => pipeline.browsing_context_id, None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id), }; - let parent_pipeline_id = match parent_info { + let parent_pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(ctx) => ctx.parent_pipeline_id, + None => return warn!("Browsing context {:?} focus parent after closure.", browsing_context_id), + }; + let parent_pipeline_id = match parent_pipeline_id { Some(info) => info, None => return debug!("Pipeline {:?} focus has no parent.", pipeline_id), }; @@ -2676,13 +2776,6 @@ where self.focus_parent_pipeline(parent_pipeline_id); } - fn handle_focus_msg(&mut self, pipeline_id: PipelineId) { - self.focus_pipeline_id = Some(pipeline_id); - - // Focus parent iframes recursively - self.focus_parent_pipeline(pipeline_id); - } - fn handle_remove_iframe_msg( &mut self, browsing_context_id: BrowsingContextId, @@ -2695,7 +2788,7 @@ where result } - fn handle_set_visible_msg(&mut self, pipeline_id: PipelineId, visible: bool) { + fn handle_set_visible_msg(&mut self, pipeline_id: PipelineId, is_visible: bool) { let browsing_context_id = match self.pipelines.get(&pipeline_id) { Some(pipeline) => pipeline.browsing_context_id, None => { @@ -2706,24 +2799,38 @@ where }, }; - let child_pipeline_ids: Vec<PipelineId> = self + // TODO(mandreyel): can we make a mutable version of + // AllBrowsingContextsIterator to directly modify a browsing context + // without the need for this indirection? + let nested_ctx_ids: Vec<BrowsingContextId> = self .all_descendant_browsing_contexts_iter(browsing_context_id) - .flat_map(|browsing_context| browsing_context.pipelines.iter().cloned()) + .filter(|ctx| ctx.is_visible != is_visible) + .map(|ctx| ctx.id) .collect(); - for id in child_pipeline_ids { - if let Some(pipeline) = self.pipelines.get_mut(&id) { - pipeline.change_visibility(visible); + for ctx_id in nested_ctx_ids { + if let Some(browsing_context) = self.browsing_contexts.get_mut(&ctx_id) { + browsing_context.is_visible = is_visible; + for pipeline_id in browsing_context.pipelines.iter() { + if let Some(pipeline) = self.pipelines.get_mut(&pipeline_id) { + pipeline.notify_visibility(is_visible); + } + } } } } fn handle_visibility_change_complete(&mut self, pipeline_id: PipelineId, visibility: bool) { - let (browsing_context_id, parent_pipeline_info) = match self.pipelines.get(&pipeline_id) { + let browsing_context_id = match self.pipelines.get(&pipeline_id) { + Some(pipeline) => pipeline.browsing_context_id, None => return warn!("Visibity change for closed pipeline {:?}.", pipeline_id), - Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info), }; - if let Some(parent_pipeline_id) = parent_pipeline_info { + let parent_pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(ctx) => ctx.parent_pipeline_id, + None => return warn!("Visibility change for closed browsing context {:?}.", pipeline_id), + }; + + if let Some(parent_pipeline_id) = parent_pipeline_id { let visibility_msg = ConstellationControlMsg::NotifyVisibilityChange( parent_pipeline_id, browsing_context_id, @@ -2786,18 +2893,8 @@ where }, WebDriverCommandMsg::Refresh(top_level_browsing_context_id, reply) => { let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - let load_data = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => { - match self.pipelines.get(&browsing_context.pipeline_id) { - Some(pipeline) => pipeline.load_data.clone(), - None => { - return warn!( - "Pipeline {} refresh after closure.", - browsing_context.pipeline_id - ) - }, - } - }, + let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(browsing_context) => browsing_context.pipeline_id, None => { return warn!( "Browsing context {} Refresh after closure.", @@ -2805,6 +2902,10 @@ where ) }, }; + let load_data = match self.pipelines.get(&pipeline_id) { + Some(pipeline) => pipeline.load_data.clone(), + None => return warn!("Pipeline {} refresh after closure.", pipeline_id), + }; self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, true); }, WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd) => { @@ -2856,10 +2957,11 @@ where } fn notify_history_changed(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - // Send a flat projection of the history. - // The final vector is a concatenation of the LoadData of the past entries, - // the current entry and the future entries. - // LoadData of inner frames are ignored and replaced with the LoadData of the parent. + // Send a flat projection of the history to embedder. + // The final vector is a concatenation of the LoadData of the past + // entries, the current entry and the future entries. + // LoadData of inner frames are ignored and replaced with the LoadData + // of the parent. let session_history = match self .joint_session_histories @@ -3033,10 +3135,22 @@ where match old_pipeline_id { None => { + let new_context_info = match change.new_browsing_context_info { + Some(info) => info, + None => { + return warn!( + "No NewBrowsingContextInfo for browsing context {}", + change.browsing_context_id, + ) + }, + }; self.new_browsing_context( change.browsing_context_id, change.top_level_browsing_context_id, change.new_pipeline_id, + new_context_info.parent_pipeline_id, + new_context_info.is_private, + new_context_info.is_visible, ); self.update_activity(change.new_pipeline_id); self.notify_history_changed(change.top_level_browsing_context_id); @@ -3210,21 +3324,6 @@ where fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) { debug!("Document ready to activate {}", pipeline_id); - // Notify the parent (if there is one). - if let Some(pipeline) = self.pipelines.get(&pipeline_id) { - if let Some(parent_pipeline_id) = pipeline.parent_info { - if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) { - let msg = ConstellationControlMsg::UpdatePipelineId( - parent_pipeline_id, - pipeline.browsing_context_id, - pipeline_id, - UpdatePipelineIdReason::Navigation, - ); - let _ = parent_pipeline.event_loop.send(msg); - } - } - } - // Find the pending change whose new pipeline id is pipeline_id. let pending_index = self .pending_changes @@ -3235,6 +3334,31 @@ where // the active document of its frame. if let Some(pending_index) = pending_index { let change = self.pending_changes.swap_remove(pending_index); + // Notify the parent (if there is one). + let parent_pipeline_id = match change.new_browsing_context_info { + // This will be a new browsing context. + Some(ref info) => info.parent_pipeline_id, + // This is an existing browsing context. + None => match self.browsing_contexts.get(&change.browsing_context_id) { + Some(ctx) => ctx.parent_pipeline_id, + None => return warn!( + "Activated document {} after browsing context {} closure.", + change.new_pipeline_id, + change.browsing_context_id, + ), + }, + }; + if let Some(parent_pipeline_id) = parent_pipeline_id { + if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) { + let msg = ConstellationControlMsg::UpdatePipelineId( + parent_pipeline_id, + change.browsing_context_id, + pipeline_id, + UpdatePipelineIdReason::Navigation, + ); + let _ = parent_pipeline.event_loop.send(msg); + } + } self.change_session_history(change); } } @@ -3409,8 +3533,8 @@ where self.browsing_contexts.get(&ancestor.browsing_context_id) { if browsing_context.pipeline_id == ancestor_id { - if let Some(parent_id) = ancestor.parent_info { - ancestor_id = parent_id; + if let Some(parent_pipeline_id) = browsing_context.parent_pipeline_id { + ancestor_id = parent_pipeline_id; continue; } else { return DocumentActivity::FullyActive; @@ -3459,11 +3583,7 @@ where ) { if let Some(browsing_context) = self.browsing_contexts.get_mut(&browsing_context_id) { browsing_context.size = Some(new_size.initial_viewport); - } - - if let Some(browsing_context) = self.browsing_contexts.get(&browsing_context_id) { - // Send Resize (or ResizeInactive) messages to each - // pipeline in the frame tree. + // Send Resize (or ResizeInactive) messages to each pipeline in the frame tree. let pipeline_id = browsing_context.pipeline_id; let pipeline = match self.pipelines.get(&pipeline_id) { None => return warn!("Pipeline {:?} resized after closing.", pipeline_id), @@ -3474,18 +3594,17 @@ where new_size, size_type, )); - let pipelines = browsing_context - .pipelines + let pipeline_ids = browsing_context.pipelines .iter() - .filter(|pipeline_id| **pipeline_id != pipeline.id) - .filter_map(|pipeline_id| self.pipelines.get(&pipeline_id)); - for pipeline in pipelines { - let _ = pipeline - .event_loop - .send(ConstellationControlMsg::ResizeInactive( - pipeline.id, - new_size, - )); + .filter(|pipeline_id| **pipeline_id != pipeline.id); + for id in pipeline_ids { + if let Some(pipeline) = self.pipelines.get(&id) { + let _ = pipeline.event_loop + .send(ConstellationControlMsg::ResizeInactive( + pipeline.id, + new_size, + )); + } } } @@ -3524,8 +3643,8 @@ where ); let browsing_context = match self.browsing_contexts.remove(&browsing_context_id) { + Some(ctx) => ctx, None => return warn!("Closing browsing context {:?} twice.", browsing_context_id), - Some(browsing_context) => browsing_context, }; { @@ -3533,12 +3652,7 @@ where session_history.remove_entries_for_browsing_context(browsing_context_id); } - let parent_info = self - .pipelines - .get(&browsing_context.pipeline_id) - .and_then(|pipeline| pipeline.parent_info); - - if let Some(parent_pipeline_id) = parent_info { + if let Some(parent_pipeline_id) = browsing_context.parent_pipeline_id { match self.pipelines.get_mut(&parent_pipeline_id) { None => { return warn!( diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index d45129db3c0..d110bbfcdce 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -58,10 +58,6 @@ pub struct Pipeline { /// The ID of the top-level browsing context that contains this Pipeline. pub top_level_browsing_context_id: TopLevelBrowsingContextId, - /// The parent pipeline of this one. `None` if this is a root pipeline. - /// TODO: move this field to `BrowsingContext`. - pub parent_info: Option<PipelineId>, - pub opener: Option<BrowsingContextId>, /// The event loop handling this pipeline. @@ -85,14 +81,6 @@ pub struct Pipeline { /// The child browsing contexts of this pipeline (these are iframes in the document). pub children: Vec<BrowsingContextId>, - /// Whether this pipeline is in private browsing mode. - /// TODO: move this field to `BrowsingContext`. - pub is_private: bool, - - /// Whether this pipeline should be treated as visible for the purposes of scheduling and - /// resource management. - pub visible: bool, - /// The Load Data used to create this pipeline. pub load_data: LoadData, @@ -119,7 +107,7 @@ pub struct InitialPipelineState { /// The ID of the parent pipeline and frame type, if any. /// If `None`, this is the root. - pub parent_info: Option<PipelineId>, + pub parent_pipeline_id: Option<PipelineId>, pub opener: Option<BrowsingContextId>, @@ -171,8 +159,11 @@ pub struct InitialPipelineState { /// The ID of the pipeline namespace for this script thread. pub pipeline_namespace_id: PipelineNamespaceId, - /// Pipeline visibility to be inherited - pub prev_visibility: Option<bool>, + /// Whether the browsing context in which pipeline is embedded is visible + /// for the purposes of scheduling and resource management. This field is + /// only used to notify script and compositor threads after spawning + /// a pipeline. + pub prev_visibility: bool, /// Webrender api. pub webrender_api_sender: webrender_api::RenderApiSender, @@ -180,9 +171,6 @@ pub struct InitialPipelineState { /// The ID of the document processed by this script thread. pub webrender_document: webrender_api::DocumentId, - /// Whether this pipeline is considered private. - pub is_private: bool, - /// A channel to the WebGL thread. pub webgl_chan: Option<WebGLPipeline>, @@ -216,7 +204,7 @@ impl Pipeline { let script_chan = match state.event_loop { Some(script_chan) => { let new_layout_info = NewLayoutInfo { - parent_info: state.parent_info, + parent_info: state.parent_pipeline_id, new_pipeline_id: state.id, browsing_context_id: state.browsing_context_id, top_level_browsing_context_id: state.top_level_browsing_context_id, @@ -270,7 +258,7 @@ impl Pipeline { id: state.id, browsing_context_id: state.browsing_context_id, top_level_browsing_context_id: state.top_level_browsing_context_id, - parent_info: state.parent_info, + parent_pipeline_id: state.parent_pipeline_id, opener: state.opener, script_to_constellation_chan: state.script_to_constellation_chan.clone(), scheduler_chan: state.scheduler_chan, @@ -317,14 +305,12 @@ impl Pipeline { state.id, state.browsing_context_id, state.top_level_browsing_context_id, - state.parent_info, state.opener, script_chan, pipeline_chan, state.compositor_proxy, - state.is_private, url, - state.prev_visibility.unwrap_or(true), + state.prev_visibility, state.load_data, )) } @@ -335,21 +321,18 @@ impl Pipeline { id: PipelineId, browsing_context_id: BrowsingContextId, top_level_browsing_context_id: TopLevelBrowsingContextId, - parent_info: Option<PipelineId>, opener: Option<BrowsingContextId>, event_loop: Rc<EventLoop>, layout_chan: IpcSender<LayoutControlMsg>, compositor_proxy: CompositorProxy, - is_private: bool, url: ServoUrl, - visible: bool, + is_visible: bool, load_data: LoadData, ) -> Pipeline { let pipeline = Pipeline { id: id, browsing_context_id: browsing_context_id, top_level_browsing_context_id: top_level_browsing_context_id, - parent_info: parent_info, opener: opener, event_loop: event_loop, layout_chan: layout_chan, @@ -357,14 +340,12 @@ impl Pipeline { url: url, children: vec![], running_animations: false, - visible: visible, - is_private: is_private, load_data: load_data, history_state_id: None, history_states: HashSet::new(), }; - pipeline.notify_visibility(); + pipeline.notify_visibility(is_visible); pipeline } @@ -448,25 +429,16 @@ impl Pipeline { } /// Notify the script thread that this pipeline is visible. - fn notify_visibility(&self) { + pub fn notify_visibility(&self, is_visible: bool) { let script_msg = - ConstellationControlMsg::ChangeFrameVisibilityStatus(self.id, self.visible); - let compositor_msg = CompositorMsg::PipelineVisibilityChanged(self.id, self.visible); + ConstellationControlMsg::ChangeFrameVisibilityStatus(self.id, is_visible); + let compositor_msg = CompositorMsg::PipelineVisibilityChanged(self.id, is_visible); let err = self.event_loop.send(script_msg); if let Err(e) = err { warn!("Sending visibility change failed ({}).", e); } self.compositor_proxy.send(compositor_msg); } - - /// Change the visibility of this pipeline. - pub fn change_visibility(&mut self, visible: bool) { - if visible == self.visible { - return; - } - self.visible = visible; - self.notify_visibility(); - } } /// Creating a new pipeline may require creating a new event loop. @@ -477,7 +449,7 @@ pub struct UnprivilegedPipelineContent { id: PipelineId, top_level_browsing_context_id: TopLevelBrowsingContextId, browsing_context_id: BrowsingContextId, - parent_info: Option<PipelineId>, + parent_pipeline_id: Option<PipelineId>, opener: Option<BrowsingContextId>, script_to_constellation_chan: ScriptToConstellationChan, layout_to_constellation_chan: IpcSender<LayoutMsg>, @@ -526,7 +498,7 @@ impl UnprivilegedPipelineContent { id: self.id, browsing_context_id: self.browsing_context_id, top_level_browsing_context_id: self.top_level_browsing_context_id, - parent_info: self.parent_info, + parent_info: self.parent_pipeline_id, opener: self.opener, control_chan: self.script_chan.clone(), control_port: self.script_port, @@ -553,7 +525,7 @@ impl UnprivilegedPipelineContent { self.id, self.top_level_browsing_context_id, self.load_data.url, - self.parent_info.is_some(), + self.parent_pipeline_id.is_some(), layout_pair, self.pipeline_port, self.layout_to_constellation_chan, diff --git a/components/constellation/session_history.rs b/components/constellation/session_history.rs index aa550fac0fb..8faa09e7555 100644 --- a/components/constellation/session_history.rs +++ b/components/constellation/session_history.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use browsingcontext::NewBrowsingContextInfo; use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId}; use script_traits::LoadData; use servo_url::ServoUrl; @@ -113,6 +114,10 @@ pub struct SessionHistoryChange { /// The old pipeline that the new pipeline should replace. pub replace: Option<NeedsToReload>, + + /// Holds data for not-yet constructed browsing contexts that are not + /// easily available when they need to be constructed. + pub new_browsing_context_info: Option<NewBrowsingContextInfo>, } /// Represents a pipeline or discarded pipeline in a history entry. |