mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
auto merge of #3951 : mrobinson/servo/iframes, r=jdm
This is the first step to allowing incremental iframe creation and destruction. This should eliminate task failures when an iframe is added to the frame tree lazily via script.
This commit is contained in:
commit
ccdd2910a2
6 changed files with 185 additions and 78 deletions
|
@ -4,12 +4,13 @@
|
||||||
|
|
||||||
use compositor_layer::{CompositorData, CompositorLayer, DoesntWantScrollEvents};
|
use compositor_layer::{CompositorData, CompositorLayer, DoesntWantScrollEvents};
|
||||||
use compositor_layer::{ScrollPositionChanged, WantsScrollEvents};
|
use compositor_layer::{ScrollPositionChanged, WantsScrollEvents};
|
||||||
use compositor_task::{Msg, CompositorTask, Exit, ChangeReadyState, SetIds, LayerProperties};
|
use compositor_task::{ChangeReadyState, ChangeRenderState, CompositorEventListener};
|
||||||
use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpdateDescendantLayer};
|
use compositor_task::{CompositorProxy, CompositorReceiver, CompositorTask};
|
||||||
use compositor_task::{SetLayerOrigin, Paint, ScrollFragmentPoint, LoadComplete};
|
use compositor_task::{CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer, Exit};
|
||||||
use compositor_task::{ShutdownComplete, ChangeRenderState, RenderMsgDiscarded, ScrollTimeout};
|
use compositor_task::{FrameTreeUpdateMsg, GetGraphicsMetadata, LayerProperties};
|
||||||
use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver};
|
use compositor_task::{LoadComplete, Msg, Paint, RenderMsgDiscarded, ScrollFragmentPoint};
|
||||||
use constellation::SendableFrameTree;
|
use compositor_task::{ScrollTimeout, SetIds, SetLayerOrigin, ShutdownComplete};
|
||||||
|
use constellation::{SendableFrameTree, FrameTreeDiff};
|
||||||
use pipeline::CompositionPipeline;
|
use pipeline::CompositionPipeline;
|
||||||
use scrolling::ScrollingTimerProxy;
|
use scrolling::ScrollingTimerProxy;
|
||||||
use windowing;
|
use windowing;
|
||||||
|
@ -267,6 +268,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
new_constellation_chan);
|
new_constellation_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(FrameTreeUpdateMsg(frame_tree_diff, response_channel), NotShuttingDown) => {
|
||||||
|
self.update_frame_tree(&frame_tree_diff);
|
||||||
|
response_channel.send(());
|
||||||
|
}
|
||||||
|
|
||||||
(CreateOrUpdateRootLayer(layer_properties), NotShuttingDown) => {
|
(CreateOrUpdateRootLayer(layer_properties), NotShuttingDown) => {
|
||||||
self.create_or_update_root_layer(layer_properties);
|
self.create_or_update_root_layer(layer_properties);
|
||||||
}
|
}
|
||||||
|
@ -446,6 +452,34 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
return root_layer;
|
return root_layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_frame_tree(&mut self, frame_tree_diff: &FrameTreeDiff) {
|
||||||
|
let layer_properties = LayerProperties {
|
||||||
|
pipeline_id: frame_tree_diff.pipeline.id,
|
||||||
|
epoch: Epoch(0),
|
||||||
|
id: LayerId::null(),
|
||||||
|
rect: Rect::zero(),
|
||||||
|
background_color: azure_hl::Color::new(0., 0., 0., 0.),
|
||||||
|
scroll_policy: Scrollable,
|
||||||
|
};
|
||||||
|
let root_layer = CompositorData::new_layer(frame_tree_diff.pipeline.clone(),
|
||||||
|
layer_properties,
|
||||||
|
WantsScrollEvents,
|
||||||
|
opts::get().tile_size);
|
||||||
|
|
||||||
|
match frame_tree_diff.rect {
|
||||||
|
Some(ref frame_rect) => {
|
||||||
|
*root_layer.masks_to_bounds.borrow_mut() = true;
|
||||||
|
|
||||||
|
let frame_rect = frame_rect.to_untyped();
|
||||||
|
*root_layer.bounds.borrow_mut() = Rect::from_untyped(&frame_rect);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent_layer = self.find_pipeline_root_layer(frame_tree_diff.parent_pipeline.id);
|
||||||
|
parent_layer.add_child(root_layer);
|
||||||
|
}
|
||||||
|
|
||||||
fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Rc<Layer<CompositorData>> {
|
fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Rc<Layer<CompositorData>> {
|
||||||
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null()) {
|
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null()) {
|
||||||
Some(ref layer) => layer.clone(),
|
Some(ref layer) => layer.clone(),
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! Communication with the compositor task.
|
//! Communication with the compositor task.
|
||||||
|
|
||||||
pub use windowing;
|
pub use windowing;
|
||||||
pub use constellation::SendableFrameTree;
|
pub use constellation::{SendableFrameTree, FrameTreeDiff};
|
||||||
|
|
||||||
use compositor;
|
use compositor;
|
||||||
use headless;
|
use headless;
|
||||||
|
@ -189,6 +189,8 @@ pub enum Msg {
|
||||||
RenderMsgDiscarded,
|
RenderMsgDiscarded,
|
||||||
/// Sets the channel to the current layout and render tasks, along with their id
|
/// Sets the channel to the current layout and render tasks, along with their id
|
||||||
SetIds(SendableFrameTree, Sender<()>, ConstellationChan),
|
SetIds(SendableFrameTree, Sender<()>, ConstellationChan),
|
||||||
|
/// Sends an updated version of the frame tree.
|
||||||
|
FrameTreeUpdateMsg(FrameTreeDiff, Sender<()>),
|
||||||
/// The load of a page for a given URL has completed.
|
/// The load of a page for a given URL has completed.
|
||||||
LoadComplete(PipelineId, Url),
|
LoadComplete(PipelineId, Url),
|
||||||
/// Indicates that the scrolling timeout with the given starting timestamp has happened and a
|
/// Indicates that the scrolling timeout with the given starting timestamp has happened and a
|
||||||
|
@ -211,6 +213,7 @@ impl Show for Msg {
|
||||||
ChangeRenderState(..) => write!(f, "ChangeRenderState"),
|
ChangeRenderState(..) => write!(f, "ChangeRenderState"),
|
||||||
RenderMsgDiscarded(..) => write!(f, "RenderMsgDiscarded"),
|
RenderMsgDiscarded(..) => write!(f, "RenderMsgDiscarded"),
|
||||||
SetIds(..) => write!(f, "SetIds"),
|
SetIds(..) => write!(f, "SetIds"),
|
||||||
|
FrameTreeUpdateMsg(..) => write!(f, "FrameTreeUpdateMsg"),
|
||||||
LoadComplete(..) => write!(f, "LoadComplete"),
|
LoadComplete(..) => write!(f, "LoadComplete"),
|
||||||
ScrollTimeout(..) => write!(f, "ScrollTimeout"),
|
ScrollTimeout(..) => write!(f, "ScrollTimeout"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use pipeline::{Pipeline, CompositionPipeline};
|
use pipeline::{Pipeline, CompositionPipeline};
|
||||||
|
|
||||||
use compositor_task::{CompositorProxy, LoadComplete, ShutdownComplete, SetLayerOrigin, SetIds};
|
use compositor_task::{CompositorProxy, FrameTreeUpdateMsg, LoadComplete, ShutdownComplete, SetLayerOrigin, SetIds};
|
||||||
use devtools_traits::DevtoolsControlChan;
|
use devtools_traits::DevtoolsControlChan;
|
||||||
use geom::rect::{Rect, TypedRect};
|
use geom::rect::{Rect, TypedRect};
|
||||||
use geom::scale_factor::ScaleFactor;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
@ -18,9 +18,9 @@ use script_traits::{ScriptControlChan, ScriptTaskFactory};
|
||||||
use servo_msg::compositor_msg::LayerId;
|
use servo_msg::compositor_msg::LayerId;
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, Failure, FrameRectMsg};
|
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, Failure, FrameRectMsg};
|
||||||
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
||||||
use servo_msg::constellation_msg::{LoadCompleteMsg, LoadIframeUrlMsg, LoadUrlMsg, Msg};
|
use servo_msg::constellation_msg::{LoadCompleteMsg, LoadUrlMsg, LoadData, Msg, NavigateMsg};
|
||||||
use servo_msg::constellation_msg::{LoadData, NavigateMsg, NavigationType, PipelineId};
|
use servo_msg::constellation_msg::{NavigationType, PipelineId, RendererReadyMsg, ResizedWindowMsg};
|
||||||
use servo_msg::constellation_msg::{RendererReadyMsg, ResizedWindowMsg, SubpageId, WindowSizeData};
|
use servo_msg::constellation_msg::{ScriptLoadedURLInIFrameMsg, SubpageId, WindowSizeData};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
|
@ -29,7 +29,7 @@ use servo_util::geometry::{PagePx, ViewportPx};
|
||||||
use servo_util::opts;
|
use servo_util::opts;
|
||||||
use servo_util::task::spawn_named;
|
use servo_util::task::spawn_named;
|
||||||
use servo_util::time::TimeProfilerChan;
|
use servo_util::time::TimeProfilerChan;
|
||||||
use std::cell::RefCell;
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::hashmap::{HashMap, HashSet};
|
use std::collections::hashmap::{HashMap, HashSet};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
@ -83,6 +83,21 @@ struct FrameTree {
|
||||||
pub pipeline: Rc<Pipeline>,
|
pub pipeline: Rc<Pipeline>,
|
||||||
pub parent: RefCell<Option<Rc<Pipeline>>>,
|
pub parent: RefCell<Option<Rc<Pipeline>>>,
|
||||||
pub children: RefCell<Vec<ChildFrameTree>>,
|
pub children: RefCell<Vec<ChildFrameTree>>,
|
||||||
|
pub has_compositor_layer: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FrameTree {
|
||||||
|
fn new(pipeline: Rc<Pipeline>, parent_pipeline: Option<Rc<Pipeline>>) -> FrameTree {
|
||||||
|
FrameTree {
|
||||||
|
pipeline: pipeline.clone(),
|
||||||
|
parent: match parent_pipeline {
|
||||||
|
Some(ref pipeline) => RefCell::new(Some(pipeline.clone())),
|
||||||
|
None => RefCell::new(None),
|
||||||
|
},
|
||||||
|
children: RefCell::new(vec!()),
|
||||||
|
has_compositor_layer: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
|
@ -93,6 +108,15 @@ struct ChildFrameTree {
|
||||||
pub rect: Option<TypedRect<PagePx, f32>>,
|
pub rect: Option<TypedRect<PagePx, f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ChildFrameTree {
|
||||||
|
fn new(frame_tree: Rc<FrameTree>, rect: Option<TypedRect<PagePx, f32>>) -> ChildFrameTree {
|
||||||
|
ChildFrameTree {
|
||||||
|
frame_tree: frame_tree,
|
||||||
|
rect: rect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SendableFrameTree {
|
pub struct SendableFrameTree {
|
||||||
pub pipeline: CompositionPipeline,
|
pub pipeline: CompositionPipeline,
|
||||||
pub children: Vec<SendableChildFrameTree>,
|
pub children: Vec<SendableChildFrameTree>,
|
||||||
|
@ -108,6 +132,16 @@ enum ReplaceResult {
|
||||||
OriginalNode(Rc<FrameTree>),
|
OriginalNode(Rc<FrameTree>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A struct that triggers the addition of a new frame to a previously existing frame tree.
|
||||||
|
pub struct FrameTreeDiff {
|
||||||
|
/// The parent pipeline of the new frame.
|
||||||
|
pub parent_pipeline: CompositionPipeline,
|
||||||
|
/// The pipeline of the new frame itself.
|
||||||
|
pub pipeline: CompositionPipeline,
|
||||||
|
/// The frame rect of the new frame used for positioning its compositor layer.
|
||||||
|
pub rect: Option<TypedRect<PagePx, f32>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl FrameTree {
|
impl FrameTree {
|
||||||
fn to_sendable(&self) -> SendableFrameTree {
|
fn to_sendable(&self) -> SendableFrameTree {
|
||||||
let sendable_frame_tree = SendableFrameTree {
|
let sendable_frame_tree = SendableFrameTree {
|
||||||
|
@ -382,9 +416,12 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
debug!("constellation got frame rect message");
|
debug!("constellation got frame rect message");
|
||||||
self.handle_frame_rect_msg(pipeline_id, subpage_id, Rect::from_untyped(&rect));
|
self.handle_frame_rect_msg(pipeline_id, subpage_id, Rect::from_untyped(&rect));
|
||||||
}
|
}
|
||||||
LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, sandbox) => {
|
ScriptLoadedURLInIFrameMsg(url, source_pipeline_id, subpage_id, sandbox) => {
|
||||||
debug!("constellation got iframe URL load message");
|
debug!("constellation got iframe URL load message");
|
||||||
self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, sandbox);
|
self.handle_script_loaded_url_in_iframe_msg(url,
|
||||||
|
source_pipeline_id,
|
||||||
|
subpage_id,
|
||||||
|
sandbox);
|
||||||
}
|
}
|
||||||
// Load a new page, usually -- but not always -- from a mouse click or typed url
|
// Load a new page, usually -- but not always -- from a mouse click or typed url
|
||||||
// If there is already a pending page (self.pending_frames), it will not be overridden;
|
// If there is already a pending page (self.pending_frames), it will not be overridden;
|
||||||
|
@ -478,11 +515,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
self.pending_frames.push(FrameChange{
|
self.pending_frames.push(FrameChange{
|
||||||
before: Some(pipeline_id),
|
before: Some(pipeline_id),
|
||||||
after: Rc::new(FrameTree {
|
after: Rc::new(FrameTree::new(pipeline.clone(), None)),
|
||||||
pipeline: pipeline.clone(),
|
|
||||||
parent: RefCell::new(None),
|
|
||||||
children: RefCell::new(vec!()),
|
|
||||||
}),
|
|
||||||
navigation_type: constellation_msg::Load,
|
navigation_type: constellation_msg::Load,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -495,11 +528,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
self.pending_frames.push(FrameChange {
|
self.pending_frames.push(FrameChange {
|
||||||
before: None,
|
before: None,
|
||||||
after: Rc::new(FrameTree {
|
after: Rc::new(FrameTree::new(pipeline.clone(), None)),
|
||||||
pipeline: pipeline.clone(),
|
|
||||||
parent: RefCell::new(None),
|
|
||||||
children: RefCell::new(vec!()),
|
|
||||||
}),
|
|
||||||
navigation_type: constellation_msg::Load,
|
navigation_type: constellation_msg::Load,
|
||||||
});
|
});
|
||||||
self.pipelines.insert(pipeline.id, pipeline);
|
self.pipelines.insert(pipeline.id, pipeline);
|
||||||
|
@ -593,21 +622,20 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn handle_load_iframe_url_msg(&mut self,
|
// The script task associated with pipeline_id has loaded a URL in an iframe via script. This
|
||||||
|
// will result in a new pipeline being spawned and a frame tree being added to
|
||||||
|
// source_pipeline_id's frame tree's children. This message is never the result of a page
|
||||||
|
// navigation.
|
||||||
|
fn handle_script_loaded_url_in_iframe_msg(&mut self,
|
||||||
url: Url,
|
url: Url,
|
||||||
source_pipeline_id: PipelineId,
|
source_pipeline_id: PipelineId,
|
||||||
subpage_id: SubpageId,
|
subpage_id: SubpageId,
|
||||||
sandbox: IFrameSandboxState) {
|
sandbox: IFrameSandboxState) {
|
||||||
// A message from the script associated with pipeline_id that it has
|
|
||||||
// parsed an iframe during html parsing. This iframe will result in a
|
|
||||||
// new pipeline being spawned and a frame tree being added to pipeline_id's
|
|
||||||
// frame tree's children. This message is never the result of a link clicked
|
|
||||||
// or a new url entered.
|
|
||||||
// Start by finding the frame trees matching the pipeline id,
|
// Start by finding the frame trees matching the pipeline id,
|
||||||
// and add the new pipeline to their sub frames.
|
// and add the new pipeline to their sub frames.
|
||||||
let frame_trees = self.find_all(source_pipeline_id);
|
let frame_trees = self.find_all(source_pipeline_id);
|
||||||
if frame_trees.is_empty() {
|
if frame_trees.is_empty() {
|
||||||
fail!("Constellation: source pipeline id of LoadIframeUrlMsg is not in
|
fail!("Constellation: source pipeline id of ScriptLoadedURLInIFrameMsg is not in
|
||||||
navigation context, nor is it in a pending frame. This should be
|
navigation context, nor is it in a pending frame. This should be
|
||||||
impossible.");
|
impossible.");
|
||||||
}
|
}
|
||||||
|
@ -617,7 +645,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
// Compare the pipeline's url to the new url. If the origin is the same,
|
// Compare the pipeline's url to the new url. If the origin is the same,
|
||||||
// then reuse the script task in creating the new pipeline
|
// then reuse the script task in creating the new pipeline
|
||||||
let source_pipeline = self.pipelines.find(&source_pipeline_id).expect("Constellation:
|
let source_pipeline = self.pipelines.find(&source_pipeline_id).expect("Constellation:
|
||||||
source Id of LoadIframeUrlMsg does have an associated pipeline in
|
source Id of ScriptLoadedURLInIFrameMsg does have an associated pipeline in
|
||||||
constellation. This should be impossible.").clone();
|
constellation. This should be impossible.").clone();
|
||||||
|
|
||||||
let source_url = source_pipeline.load_data.url.clone();
|
let source_url = source_pipeline.load_data.url.clone();
|
||||||
|
@ -626,7 +654,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
source_url.port() == url.port()) && sandbox == IFrameUnsandboxed;
|
source_url.port() == url.port()) && sandbox == IFrameUnsandboxed;
|
||||||
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
|
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
|
||||||
// Reuse the script task if the URL is same-origin
|
// Reuse the script task if the URL is same-origin
|
||||||
let new_pipeline = if same_script {
|
let script_pipeline = if same_script {
|
||||||
debug!("Constellation: loading same-origin iframe at {:?}", url);
|
debug!("Constellation: loading same-origin iframe at {:?}", url);
|
||||||
Some(source_pipeline.clone())
|
Some(source_pipeline.clone())
|
||||||
} else {
|
} else {
|
||||||
|
@ -637,20 +665,15 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
let pipeline = self.new_pipeline(
|
let pipeline = self.new_pipeline(
|
||||||
next_pipeline_id,
|
next_pipeline_id,
|
||||||
Some(subpage_id),
|
Some(subpage_id),
|
||||||
new_pipeline,
|
script_pipeline,
|
||||||
LoadData::new(url)
|
LoadData::new(url)
|
||||||
);
|
);
|
||||||
|
|
||||||
let rect = self.pending_sizes.pop(&(source_pipeline_id, subpage_id));
|
let rect = self.pending_sizes.pop(&(source_pipeline_id, subpage_id));
|
||||||
for frame_tree in frame_trees.iter() {
|
for frame_tree in frame_trees.iter() {
|
||||||
frame_tree.children.borrow_mut().push(ChildFrameTree {
|
frame_tree.children.borrow_mut().push(ChildFrameTree::new(
|
||||||
frame_tree: Rc::new(FrameTree {
|
Rc::new(FrameTree::new(pipeline.clone(), Some(source_pipeline.clone()))),
|
||||||
pipeline: pipeline.clone(),
|
rect));
|
||||||
parent: RefCell::new(Some(source_pipeline.clone())),
|
|
||||||
children: RefCell::new(vec!()),
|
|
||||||
}),
|
|
||||||
rect: rect,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
self.pipelines.insert(pipeline.id, pipeline);
|
self.pipelines.insert(pipeline.id, pipeline);
|
||||||
}
|
}
|
||||||
|
@ -684,13 +707,9 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
let pipeline = self.new_pipeline(next_pipeline_id, subpage_id, None, load_data);
|
let pipeline = self.new_pipeline(next_pipeline_id, subpage_id, None, load_data);
|
||||||
|
|
||||||
self.pending_frames.push(FrameChange{
|
self.pending_frames.push(FrameChange {
|
||||||
before: Some(source_id),
|
before: Some(source_id),
|
||||||
after: Rc::new(FrameTree {
|
after: Rc::new(FrameTree::new(pipeline.clone(), parent.borrow().clone())),
|
||||||
pipeline: pipeline.clone(),
|
|
||||||
parent: parent,
|
|
||||||
children: RefCell::new(vec!()),
|
|
||||||
}),
|
|
||||||
navigation_type: constellation_msg::Load,
|
navigation_type: constellation_msg::Load,
|
||||||
});
|
});
|
||||||
self.pipelines.insert(pipeline.id, pipeline);
|
self.pipelines.insert(pipeline.id, pipeline);
|
||||||
|
@ -737,22 +756,23 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pipeline_is_in_current_frame(&self, pipeline_id: PipelineId) -> bool {
|
||||||
|
self.current_frame().iter()
|
||||||
|
.any(|current_frame| current_frame.contains(pipeline_id))
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_renderer_ready_msg(&mut self, pipeline_id: PipelineId) {
|
fn handle_renderer_ready_msg(&mut self, pipeline_id: PipelineId) {
|
||||||
debug!("Renderer {:?} ready to send paint msg", pipeline_id);
|
debug!("Renderer {:?} ready to send paint msg", pipeline_id);
|
||||||
// This message could originate from a pipeline in the navigation context or
|
// This message could originate from a pipeline in the navigation context or
|
||||||
// from a pending frame. The only time that we will grant paint permission is
|
// from a pending frame. The only time that we will grant paint permission is
|
||||||
// when the message originates from a pending frame or the current frame.
|
// when the message originates from a pending frame or the current frame.
|
||||||
|
|
||||||
for current_frame in self.current_frame().iter() {
|
|
||||||
// Messages originating in the current frame are not navigations;
|
// Messages originating in the current frame are not navigations;
|
||||||
// they may come from a page load in a subframe.
|
// they may come from a page load in a subframe.
|
||||||
if current_frame.contains(pipeline_id) {
|
if self.pipeline_is_in_current_frame(pipeline_id) {
|
||||||
for frame in current_frame.iter() {
|
self.create_compositor_layer_for_iframe_if_necessary(pipeline_id);
|
||||||
frame.pipeline.grant_paint_permission();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Find the pending frame change whose new pipeline id is pipeline_id.
|
// Find the pending frame change whose new pipeline id is pipeline_id.
|
||||||
// If it is not found, it simply means that this pipeline will not receive
|
// If it is not found, it simply means that this pipeline will not receive
|
||||||
|
@ -814,10 +834,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
let parent = next_frame_tree.find(parent.id).expect(
|
let parent = next_frame_tree.find(parent.id).expect(
|
||||||
"Constellation: pending frame has a parent frame that is not
|
"Constellation: pending frame has a parent frame that is not
|
||||||
active. This is a bug.");
|
active. This is a bug.");
|
||||||
parent.children.borrow_mut().push(ChildFrameTree {
|
parent.children.borrow_mut().push(ChildFrameTree::new(to_add.clone(),
|
||||||
frame_tree: to_add.clone(),
|
rect));
|
||||||
rect: rect,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -911,11 +929,65 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
let mut iter = frame_tree.iter();
|
let mut iter = frame_tree.iter();
|
||||||
for frame in iter {
|
for frame in iter {
|
||||||
|
frame.has_compositor_layer.set(true);
|
||||||
frame.pipeline.grant_paint_permission();
|
frame.pipeline.grant_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(()) => {} // message has been discarded, probably shutting down
|
Err(()) => {} // message has been discarded, probably shutting down
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_child_parent_pair_in_frame_tree(&self,
|
||||||
|
frame_tree: Rc<FrameTree>,
|
||||||
|
child_pipeline_id: PipelineId)
|
||||||
|
-> Option<(ChildFrameTree, Rc<FrameTree>)> {
|
||||||
|
for child in frame_tree.children.borrow().iter() {
|
||||||
|
let child_frame_tree = child.frame_tree.clone();
|
||||||
|
if child.frame_tree.pipeline.id == child_pipeline_id {
|
||||||
|
return Some((ChildFrameTree::new(child_frame_tree, child.rect),
|
||||||
|
frame_tree.clone()));
|
||||||
|
}
|
||||||
|
let result = self.find_child_parent_pair_in_frame_tree(child_frame_tree,
|
||||||
|
child_pipeline_id);
|
||||||
|
if result.is_some() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_compositor_layer_for_iframe_if_necessary(&mut self, pipeline_id: PipelineId) {
|
||||||
|
let current_frame_tree = match self.current_frame() {
|
||||||
|
&Some(ref tree) => tree.clone(),
|
||||||
|
&None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (child, parent) =
|
||||||
|
match self.find_child_parent_pair_in_frame_tree(current_frame_tree, pipeline_id) {
|
||||||
|
Some(pair) => pair,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if child.frame_tree.has_compositor_layer.get() {
|
||||||
|
child.frame_tree.pipeline.grant_paint_permission();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sendable_frame_tree_diff = FrameTreeDiff {
|
||||||
|
parent_pipeline: parent.pipeline.to_sendable(),
|
||||||
|
pipeline: child.frame_tree.pipeline.to_sendable(),
|
||||||
|
rect: child.rect,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (chan, port) = channel();
|
||||||
|
self.compositor_proxy.send(FrameTreeUpdateMsg(sendable_frame_tree_diff, chan));
|
||||||
|
match port.recv_opt() {
|
||||||
|
Ok(()) => {
|
||||||
|
child.frame_tree.has_compositor_layer.set(true);
|
||||||
|
child.frame_tree.pipeline.grant_paint_permission();
|
||||||
|
}
|
||||||
|
Err(()) => {} // The message has been discarded, we are probably shutting down.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpdateDescendantLayer};
|
use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpdateDescendantLayer};
|
||||||
use compositor_task::{Exit, ChangeReadyState, LoadComplete, Paint, ScrollFragmentPoint, SetIds};
|
use compositor_task::{Exit, ChangeReadyState, LoadComplete, Paint, ScrollFragmentPoint, SetIds};
|
||||||
use compositor_task::{SetLayerOrigin, ShutdownComplete, ChangeRenderState, RenderMsgDiscarded};
|
use compositor_task::{SetLayerOrigin, ShutdownComplete, ChangeRenderState, RenderMsgDiscarded};
|
||||||
use compositor_task::{CompositorEventListener, CompositorReceiver, ScrollTimeout};
|
use compositor_task::{CompositorEventListener, CompositorReceiver, ScrollTimeout, FrameTreeUpdateMsg};
|
||||||
use windowing::WindowEvent;
|
use windowing::WindowEvent;
|
||||||
|
|
||||||
use geom::scale_factor::ScaleFactor;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
@ -92,6 +92,10 @@ impl CompositorEventListener for NullCompositor {
|
||||||
response_chan.send(());
|
response_chan.send(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameTreeUpdateMsg(_, response_channel) => {
|
||||||
|
response_channel.send(());
|
||||||
|
}
|
||||||
|
|
||||||
// Explicitly list ignored messages so that when we add a new one,
|
// Explicitly list ignored messages so that when we add a new one,
|
||||||
// we'll notice and think about whether it needs a response, like
|
// we'll notice and think about whether it needs a response, like
|
||||||
// SetIds.
|
// SetIds.
|
||||||
|
|
|
@ -58,7 +58,7 @@ pub enum Msg {
|
||||||
LoadCompleteMsg(PipelineId, Url),
|
LoadCompleteMsg(PipelineId, Url),
|
||||||
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
|
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
|
||||||
LoadUrlMsg(PipelineId, LoadData),
|
LoadUrlMsg(PipelineId, LoadData),
|
||||||
LoadIframeUrlMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
|
ScriptLoadedURLInIFrameMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
|
||||||
NavigateMsg(NavigationDirection),
|
NavigateMsg(NavigationDirection),
|
||||||
RendererReadyMsg(PipelineId),
|
RendererReadyMsg(PipelineId),
|
||||||
ResizedWindowMsg(WindowSizeData),
|
ResizedWindowMsg(WindowSizeData),
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyStateValues};
|
|
||||||
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
|
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
|
||||||
|
@ -16,14 +15,14 @@ use dom::element::{HTMLIFrameElementTypeId, Element};
|
||||||
use dom::element::AttributeHandlers;
|
use dom::element::AttributeHandlers;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node, document_from_node};
|
use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use page::IterablePage;
|
use page::IterablePage;
|
||||||
|
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
||||||
use servo_msg::constellation_msg::{IFrameSandboxed, IFrameUnsandboxed};
|
use servo_msg::constellation_msg::{IFrameSandboxed, IFrameUnsandboxed};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, LoadIframeUrlMsg};
|
use servo_msg::constellation_msg::{ConstellationChan, ScriptLoadedURLInIFrameMsg};
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
|
@ -120,13 +119,8 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
||||||
subpage_id: subpage_id,
|
subpage_id: subpage_id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let doc = document_from_node(self).root();
|
|
||||||
if doc.ReadyState() == DocumentReadyStateValues::Loading {
|
|
||||||
// https://github.com/servo/servo/issues/3738
|
|
||||||
// We can't handle dynamic frame tree changes in the compositor right now.
|
|
||||||
let ConstellationChan(ref chan) = page.constellation_chan;
|
let ConstellationChan(ref chan) = page.constellation_chan;
|
||||||
chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
|
chan.send(ScriptLoadedURLInIFrameMsg(url, page.id, subpage_id, sandboxed));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue