mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Make non-initial about:blank loads asynchronous
Don't update iframe pipeline until load completes To preserve the previous functionality of delaying load events when a new navigation is triggered, pending pipeline id represents the current pending load. The load event is only fired if the load message's pipeline id matches the pending pipeline id. Track frame size on Frame instead of Pipeline Disabled matchMedia test Track creator pipeline id
This commit is contained in:
parent
f579405510
commit
d004db95cf
18 changed files with 305 additions and 200 deletions
|
@ -903,7 +903,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
match ServoUrl::parse(&url_string) {
|
||||
Ok(url) => {
|
||||
let msg = match self.root_pipeline {
|
||||
Some(ref pipeline) => ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, None, None)),
|
||||
Some(ref pipeline) =>
|
||||
ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, Some(pipeline.id), None, None)),
|
||||
None => ConstellationMsg::InitLoadUrl(url)
|
||||
};
|
||||
if let Err(e) = self.constellation_chan.send(msg) {
|
||||
|
|
|
@ -101,7 +101,7 @@ use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState,
|
|||
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
|
||||
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
|
||||
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
|
||||
use script_traits::{SWManagerMsg, ScopeThings, WindowSizeType};
|
||||
use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WindowSizeType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use servo_config::opts;
|
||||
use servo_config::prefs::PREFS;
|
||||
|
@ -599,17 +599,31 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
|
||||
let (event_loop, host) = match sandbox {
|
||||
IFrameSandboxState::IFrameSandboxed => (None, None),
|
||||
IFrameSandboxState::IFrameUnsandboxed => match reg_host(&load_data.url) {
|
||||
None => (None, None),
|
||||
Some(host) => {
|
||||
let event_loop = self.event_loops.get(&top_level_frame_id)
|
||||
.and_then(|map| map.get(&host))
|
||||
.and_then(|weak| weak.upgrade());
|
||||
match event_loop {
|
||||
None => (None, Some(host)),
|
||||
Some(event_loop) => (Some(event_loop.clone()), None),
|
||||
IFrameSandboxState::IFrameUnsandboxed => {
|
||||
// If this is an about:blank load, it must share the creator's event loop.
|
||||
// This must match the logic in the script thread when determining the proper origin.
|
||||
if load_data.url.as_str() != "about:blank" {
|
||||
match reg_host(&load_data.url) {
|
||||
None => (None, None),
|
||||
Some(host) => {
|
||||
let event_loop = self.event_loops.get(&top_level_frame_id)
|
||||
.and_then(|map| map.get(&host))
|
||||
.and_then(|weak| weak.upgrade());
|
||||
match event_loop {
|
||||
None => (None, Some(host)),
|
||||
Some(event_loop) => (Some(event_loop.clone()), None),
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
} else if let Some(parent) = parent_info
|
||||
.and_then(|(pipeline_id, _)| self.pipelines.get(&pipeline_id)) {
|
||||
(Some(parent.event_loop.clone()), None)
|
||||
} else if let Some(creator) = load_data.creator_pipeline_id
|
||||
.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) {
|
||||
(Some(creator.event_loop.clone()), None)
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -735,7 +749,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
}
|
||||
|
||||
/// Create a new frame and update the internal bookkeeping.
|
||||
fn new_frame(&mut self, frame_id: FrameId, pipeline_id: PipelineId, load_data: LoadData) {
|
||||
fn new_frame(&mut self,
|
||||
frame_id: FrameId,
|
||||
pipeline_id: PipelineId,
|
||||
load_data: LoadData) {
|
||||
let frame = Frame::new(frame_id, pipeline_id, load_data);
|
||||
self.frames.insert(frame_id, frame);
|
||||
|
||||
|
@ -915,11 +932,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
load_info.info.new_pipeline_id);
|
||||
self.handle_script_loaded_url_in_iframe_msg(load_info);
|
||||
}
|
||||
FromScriptMsg::ScriptLoadedAboutBlankInIFrame(load_info, lc) => {
|
||||
FromScriptMsg::ScriptNewIFrame(load_info, layout_sender) => {
|
||||
debug!("constellation got loaded `about:blank` in iframe message {:?} {:?}",
|
||||
load_info.parent_pipeline_id,
|
||||
load_info.new_pipeline_id);
|
||||
self.handle_script_loaded_about_blank_in_iframe_msg(load_info, lc);
|
||||
self.handle_script_new_iframe(load_info, layout_sender);
|
||||
}
|
||||
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
|
||||
self.handle_change_running_animations_state(pipeline_id, animation_state)
|
||||
|
@ -1277,10 +1294,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
// Notify the browser chrome that the pipeline has failed
|
||||
self.trigger_mozbrowsererror(top_level_frame_id, reason, backtrace);
|
||||
|
||||
let pipeline_id = self.frames.get(&top_level_frame_id).map(|frame| frame.pipeline_id);
|
||||
let pipeline_url = pipeline_id.and_then(|id| self.pipelines.get(&id).map(|pipeline| pipeline.url.clone()));
|
||||
let parent_info = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.parent_info));
|
||||
let window_size = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.size));
|
||||
let (window_size, pipeline_id) = {
|
||||
let frame = self.frames.get(&top_level_frame_id);
|
||||
let window_size = frame.and_then(|frame| frame.size);
|
||||
let pipeline_id = frame.map(|frame| frame.pipeline_id);
|
||||
(window_size, pipeline_id)
|
||||
};
|
||||
|
||||
let (pipeline_url, parent_info) = {
|
||||
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);
|
||||
(pipeline_url, parent_info)
|
||||
};
|
||||
|
||||
self.close_frame_children(top_level_frame_id, DiscardBrowsingContext::No, ExitPipelineMode::Force);
|
||||
|
||||
|
@ -1295,7 +1321,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
warn!("creating replacement pipeline for about:failure");
|
||||
|
||||
let new_pipeline_id = PipelineId::new();
|
||||
let load_data = LoadData::new(failure_url, None, None);
|
||||
let load_data = LoadData::new(failure_url, None, None, None);
|
||||
let sandbox = IFrameSandboxState::IFrameSandboxed;
|
||||
self.new_pipeline(new_pipeline_id, top_level_frame_id, parent_info,
|
||||
window_size, load_data.clone(), sandbox, false);
|
||||
|
@ -1340,7 +1366,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
let window_size = self.window_size.initial_viewport;
|
||||
let root_pipeline_id = PipelineId::new();
|
||||
let root_frame_id = self.root_frame_id;
|
||||
let load_data = LoadData::new(url.clone(), None, None);
|
||||
let load_data = LoadData::new(url.clone(), None, None, None);
|
||||
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
||||
self.new_pipeline(root_pipeline_id, root_frame_id, None, Some(window_size), load_data.clone(), sandbox, false);
|
||||
self.handle_load_start_msg(root_pipeline_id);
|
||||
|
@ -1353,29 +1379,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
}
|
||||
|
||||
fn handle_frame_size_msg(&mut self,
|
||||
iframe_sizes: Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>) {
|
||||
for (pipeline_id, size) in iframe_sizes {
|
||||
let result = {
|
||||
let pipeline = match self.pipelines.get_mut(&pipeline_id) {
|
||||
Some(pipeline) => pipeline,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
if pipeline.size == Some(size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pipeline.size = Some(size);
|
||||
let msg = ConstellationControlMsg::Resize(pipeline_id, WindowSizeData {
|
||||
initial_viewport: size,
|
||||
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
||||
}, WindowSizeType::Initial);
|
||||
|
||||
pipeline.event_loop.send(msg)
|
||||
iframe_sizes: Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>) {
|
||||
for (frame_id, size) in iframe_sizes {
|
||||
let window_size = WindowSizeData {
|
||||
initial_viewport: size,
|
||||
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
||||
};
|
||||
if let Err(e) = result {
|
||||
self.handle_send_error(pipeline_id, e);
|
||||
}
|
||||
|
||||
self.resize_frame(window_size, WindowSizeType::Initial, frame_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1423,12 +1434,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
};
|
||||
|
||||
// TODO - loaddata here should have referrer info (not None, None)
|
||||
LoadData::new(url, None, None)
|
||||
LoadData::new(url, Some(source_pipeline.id), None, None)
|
||||
});
|
||||
|
||||
let is_private = load_info.info.is_private || source_pipeline.is_private;
|
||||
|
||||
let window_size = old_pipeline.and_then(|old_pipeline| old_pipeline.size);
|
||||
let window_size = self.frames.get(&load_info.info.frame_id).and_then(|frame| frame.size);
|
||||
|
||||
(load_data, window_size, is_private)
|
||||
};
|
||||
|
@ -1456,9 +1467,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
is_private);
|
||||
}
|
||||
|
||||
fn handle_script_loaded_about_blank_in_iframe_msg(&mut self,
|
||||
load_info: IFrameLoadInfo,
|
||||
layout_sender: IpcSender<LayoutControlMsg>) {
|
||||
fn handle_script_new_iframe(&mut self,
|
||||
load_info: IFrameLoadInfo,
|
||||
layout_sender: IpcSender<LayoutControlMsg>) {
|
||||
let IFrameLoadInfo {
|
||||
parent_pipeline_id,
|
||||
new_pipeline_id,
|
||||
|
@ -1486,12 +1497,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
self.compositor_proxy.clone_compositor_proxy(),
|
||||
is_private || parent_pipeline.is_private,
|
||||
url.clone(),
|
||||
None,
|
||||
parent_pipeline.visible)
|
||||
};
|
||||
|
||||
// TODO: Referrer?
|
||||
let load_data = LoadData::new(url, None, None);
|
||||
let load_data = LoadData::new(url, Some(parent_pipeline_id), None, None);
|
||||
|
||||
let replace_instant = if replace {
|
||||
self.frames.get(&frame_id).map(|frame| frame.instant)
|
||||
|
@ -1641,7 +1651,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
// changes would be overridden by changing the subframe associated with source_id.
|
||||
|
||||
// Create the new pipeline
|
||||
let window_size = self.pipelines.get(&source_id).and_then(|source| source.size);
|
||||
let window_size = self.frames.get(&root_frame_id).and_then(|frame| frame.size);
|
||||
let new_pipeline_id = PipelineId::new();
|
||||
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
||||
let replace_instant = if replace {
|
||||
|
@ -1959,7 +1969,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
},
|
||||
WebDriverCommandMsg::Refresh(pipeline_id, reply) => {
|
||||
let load_data = match self.pipelines.get(&pipeline_id) {
|
||||
Some(pipeline) => LoadData::new(pipeline.url.clone(), None, None),
|
||||
Some(pipeline) => LoadData::new(pipeline.url.clone(), None, None, None),
|
||||
None => return warn!("Pipeline {:?} Refresh after closure.", pipeline_id),
|
||||
};
|
||||
self.load_url_for_webdriver(pipeline_id, load_data, reply, true);
|
||||
|
@ -2019,8 +2029,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
let load_data = entry.load_data;
|
||||
let (parent_info, window_size, is_private) = match self.frames.get(&frame_id) {
|
||||
Some(frame) => match self.pipelines.get(&frame.pipeline_id) {
|
||||
Some(pipeline) => (pipeline.parent_info, pipeline.size, pipeline.is_private),
|
||||
None => (None, None, false),
|
||||
Some(pipeline) => (pipeline.parent_info, frame.size, pipeline.is_private),
|
||||
None => (None, frame.size, false),
|
||||
},
|
||||
None => return warn!("no frame to traverse"),
|
||||
};
|
||||
|
@ -2101,7 +2111,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
// Update the owning iframe to point to the new pipeline id.
|
||||
// This makes things like contentDocument work correctly.
|
||||
if let Some((parent_pipeline_id, _)) = parent_info {
|
||||
let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, frame_id, pipeline_id);
|
||||
let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
||||
frame_id, pipeline_id, UpdatePipelineIdReason::Traversal);
|
||||
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
|
||||
Some(pipeline) => pipeline.event_loop.send(msg),
|
||||
|
@ -2245,7 +2256,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
}
|
||||
|
||||
if new_frame {
|
||||
self.new_frame(frame_change.frame_id, frame_change.new_pipeline_id, frame_change.load_data);
|
||||
self.new_frame(frame_change.frame_id,
|
||||
frame_change.new_pipeline_id,
|
||||
frame_change.load_data);
|
||||
self.update_activity(frame_change.new_pipeline_id);
|
||||
self.notify_history_changed(frame_change.new_pipeline_id);
|
||||
};
|
||||
|
@ -2275,7 +2288,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
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::FramedContentChanged(parent_pipeline_id, pipeline.frame_id);
|
||||
let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
||||
pipeline.frame_id, pipeline_id, UpdatePipelineIdReason::Navigation);
|
||||
let _ = parent_pipeline.event_loop.send(msg);
|
||||
}
|
||||
}
|
||||
|
@ -2298,45 +2312,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
fn handle_window_size_msg(&mut self, new_size: WindowSizeData, size_type: WindowSizeType) {
|
||||
debug!("handle_window_size_msg: {:?}", new_size.initial_viewport.to_untyped());
|
||||
|
||||
if let Some(frame) = self.frames.get(&self.root_frame_id) {
|
||||
// Send Resize (or ResizeInactive) messages to each
|
||||
// pipeline in the frame tree.
|
||||
let pipeline_id = frame.pipeline_id;
|
||||
let pipeline = match self.pipelines.get(&pipeline_id) {
|
||||
None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
|
||||
Some(pipeline) => pipeline,
|
||||
};
|
||||
let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
|
||||
pipeline.id,
|
||||
new_size,
|
||||
size_type
|
||||
));
|
||||
let pipelines = frame.prev.iter().chain(frame.next.iter())
|
||||
.filter_map(|entry| entry.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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Send resize message to any pending pipelines that aren't loaded yet.
|
||||
for pending_frame in &self.pending_frames {
|
||||
let pipeline_id = pending_frame.new_pipeline_id;
|
||||
let pipeline = match self.pipelines.get(&pipeline_id) {
|
||||
None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; }
|
||||
Some(pipeline) => pipeline,
|
||||
};
|
||||
if pipeline.parent_info.is_none() {
|
||||
let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
|
||||
pipeline.id,
|
||||
new_size,
|
||||
size_type
|
||||
));
|
||||
}
|
||||
}
|
||||
let frame_id = self.root_frame_id;
|
||||
self.resize_frame(new_size, size_type, frame_id);
|
||||
|
||||
if let Some(resize_channel) = self.webdriver.resize_channel.take() {
|
||||
let _ = resize_channel.send(new_size);
|
||||
|
@ -2422,7 +2399,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
// size for the pipeline, then its painting should be up to date. If the constellation
|
||||
// *hasn't* received a size, it could be that the layer was hidden by script before the
|
||||
// compositor discovered it, so we just don't check the layer.
|
||||
if let Some(size) = pipeline.size {
|
||||
if let Some(size) = frame.size {
|
||||
// If the rectangle for this pipeline is zero sized, it will
|
||||
// never be painted. In this case, don't query the layout
|
||||
// thread as it won't contribute to the final output image.
|
||||
|
@ -2509,6 +2486,54 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
self.set_activity(pipeline_id, self.get_activity(pipeline_id));
|
||||
}
|
||||
|
||||
/// Handle updating the size of a frame. This notifies every pipeline in the frame of the new
|
||||
/// size.
|
||||
fn resize_frame(&mut self, new_size: WindowSizeData, size_type: WindowSizeType, frame_id: FrameId) {
|
||||
if let Some(frame) = self.frames.get_mut(&frame_id) {
|
||||
frame.size = Some(new_size.initial_viewport);
|
||||
}
|
||||
|
||||
if let Some(frame) = self.frames.get(&frame_id) {
|
||||
// Send Resize (or ResizeInactive) messages to each
|
||||
// pipeline in the frame tree.
|
||||
let pipeline_id = frame.pipeline_id;
|
||||
let pipeline = match self.pipelines.get(&pipeline_id) {
|
||||
None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
|
||||
Some(pipeline) => pipeline,
|
||||
};
|
||||
let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
|
||||
pipeline.id,
|
||||
new_size,
|
||||
size_type
|
||||
));
|
||||
let pipelines = frame.prev.iter().chain(frame.next.iter())
|
||||
.filter_map(|entry| entry.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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Send resize message to any pending pipelines that aren't loaded yet.
|
||||
for pending_frame in &self.pending_frames {
|
||||
let pipeline_id = pending_frame.new_pipeline_id;
|
||||
let pipeline = match self.pipelines.get(&pipeline_id) {
|
||||
None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; }
|
||||
Some(pipeline) => pipeline,
|
||||
};
|
||||
if pipeline.frame_id == frame_id {
|
||||
let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
|
||||
pipeline.id,
|
||||
new_size,
|
||||
size_type
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_joint_session_future(&mut self, frame_id: FrameId) {
|
||||
let frame_ids: Vec<FrameId> = self.full_frame_tree_iter(frame_id)
|
||||
.map(|frame| frame.id)
|
||||
|
@ -2652,7 +2677,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
self.pipelines.get(&frame.pipeline_id).map(|pipeline: &Pipeline| {
|
||||
let mut frame_tree = SendableFrameTree {
|
||||
pipeline: pipeline.to_sendable(),
|
||||
size: pipeline.size,
|
||||
size: frame.size,
|
||||
children: vec!(),
|
||||
};
|
||||
|
||||
|
|
|
@ -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 euclid::size::TypedSize2D;
|
||||
use msg::constellation_msg::{FrameId, PipelineId};
|
||||
use pipeline::Pipeline;
|
||||
use script_traits::LoadData;
|
||||
|
@ -9,6 +10,7 @@ use std::collections::HashMap;
|
|||
use std::iter::once;
|
||||
use std::mem::replace;
|
||||
use std::time::Instant;
|
||||
use style_traits::CSSPixel;
|
||||
|
||||
/// A frame in the frame tree.
|
||||
/// Each frame is the constellation's view of a browsing context.
|
||||
|
@ -22,13 +24,16 @@ pub struct Frame {
|
|||
/// The frame id.
|
||||
pub id: FrameId,
|
||||
|
||||
/// The timestamp for the current session history entry
|
||||
/// The size of the frame.
|
||||
pub size: Option<TypedSize2D<f32, CSSPixel>>,
|
||||
|
||||
/// The timestamp for the current session history entry.
|
||||
pub instant: Instant,
|
||||
|
||||
/// The pipeline for the current session history entry
|
||||
/// The pipeline for the current session history entry.
|
||||
pub pipeline_id: PipelineId,
|
||||
|
||||
/// The load data for the current session history entry
|
||||
/// The load data for the current session history entry.
|
||||
pub load_data: LoadData,
|
||||
|
||||
/// The past session history, ordered chronologically.
|
||||
|
@ -44,6 +49,7 @@ impl Frame {
|
|||
pub fn new(id: FrameId, pipeline_id: PipelineId, load_data: LoadData) -> Frame {
|
||||
Frame {
|
||||
id: id,
|
||||
size: None,
|
||||
pipeline_id: pipeline_id,
|
||||
instant: Instant::now(),
|
||||
load_data: load_data,
|
||||
|
|
|
@ -76,10 +76,6 @@ pub struct Pipeline {
|
|||
/// The title of the most recently-loaded page.
|
||||
pub title: Option<String>,
|
||||
|
||||
/// The size of the frame.
|
||||
/// TODO: move this field to `Frame`.
|
||||
pub size: Option<TypedSize2D<f32, CSSPixel>>,
|
||||
|
||||
/// Whether this pipeline is currently running animations. Pipelines that are running
|
||||
/// animations cause composites to be continually scheduled.
|
||||
pub running_animations: bool,
|
||||
|
@ -291,7 +287,6 @@ impl Pipeline {
|
|||
state.compositor_proxy,
|
||||
state.is_private,
|
||||
url,
|
||||
state.window_size,
|
||||
state.prev_visibility.unwrap_or(true)))
|
||||
}
|
||||
|
||||
|
@ -305,7 +300,6 @@ impl Pipeline {
|
|||
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
||||
is_private: bool,
|
||||
url: ServoUrl,
|
||||
size: Option<TypedSize2D<f32, CSSPixel>>,
|
||||
visible: bool)
|
||||
-> Pipeline {
|
||||
let pipeline = Pipeline {
|
||||
|
@ -318,7 +312,6 @@ impl Pipeline {
|
|||
url: url,
|
||||
title: None,
|
||||
children: vec!(),
|
||||
size: size,
|
||||
running_animations: false,
|
||||
visible: visible,
|
||||
is_private: is_private,
|
||||
|
|
|
@ -34,7 +34,7 @@ use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
|||
use ipc_channel::ipc;
|
||||
use list_item::ListItemFlow;
|
||||
use model::{self, MaybeAuto, specified};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::FrameId;
|
||||
use net_traits::image::base::PixelFormat;
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
use range::Range;
|
||||
|
@ -173,7 +173,7 @@ pub struct DisplayListBuildState<'a> {
|
|||
|
||||
/// Vector containing iframe sizes, used to inform the constellation about
|
||||
/// new iframe sizes
|
||||
pub iframe_sizes: Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>,
|
||||
pub iframe_sizes: Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>,
|
||||
|
||||
/// A stack of clips used to cull display list entries that are outside the
|
||||
/// rendered region.
|
||||
|
@ -1809,7 +1809,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
|
||||
let size = Size2D::new(item.bounds().size.width.to_f32_px(),
|
||||
item.bounds().size.height.to_f32_px());
|
||||
state.iframe_sizes.push((fragment_info.pipeline_id, TypedSize2D::from_untyped(&size)));
|
||||
state.iframe_sizes.push((fragment_info.frame_id, TypedSize2D::from_untyped(&size)));
|
||||
|
||||
state.add_display_item(item);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ use ipc_channel::ipc::IpcSender;
|
|||
use layout_debug;
|
||||
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, SizeConstraint};
|
||||
use model::{style_length, ToGfxMatrix};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::{FrameId, PipelineId};
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
use range::*;
|
||||
|
@ -467,19 +467,23 @@ impl ImageFragmentInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// A fragment that represents an inline frame (iframe). This stores the pipeline ID so that the
|
||||
/// A fragment that represents an inline frame (iframe). This stores the frame ID so that the
|
||||
/// size of this iframe can be communicated via the constellation to the iframe's own layout thread.
|
||||
#[derive(Clone)]
|
||||
pub struct IframeFragmentInfo {
|
||||
/// The pipeline ID of this iframe.
|
||||
/// The frame ID of this iframe.
|
||||
pub frame_id: FrameId,
|
||||
/// The pipelineID of this iframe.
|
||||
pub pipeline_id: PipelineId,
|
||||
}
|
||||
|
||||
impl IframeFragmentInfo {
|
||||
/// Creates the information specific to an iframe fragment.
|
||||
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> IframeFragmentInfo {
|
||||
let frame_id = node.iframe_frame_id();
|
||||
let pipeline_id = node.iframe_pipeline_id();
|
||||
IframeFragmentInfo {
|
||||
frame_id: frame_id,
|
||||
pipeline_id: pipeline_id,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -310,3 +310,4 @@ pub enum FrameType {
|
|||
IFrame,
|
||||
MozBrowserIFrame,
|
||||
}
|
||||
|
||||
|
|
|
@ -345,7 +345,7 @@ impl HTMLFormElement {
|
|||
let _target = submitter.target();
|
||||
// TODO: Handle browsing contexts, partially loaded documents (step 16-17)
|
||||
|
||||
let mut load_data = LoadData::new(action_components, doc.get_referrer_policy(), Some(doc.url()));
|
||||
let mut load_data = LoadData::new(action_components, None, doc.get_referrer_policy(), Some(doc.url()));
|
||||
|
||||
// Step 18
|
||||
match (&*scheme, method) {
|
||||
|
|
|
@ -44,7 +44,7 @@ use msg::constellation_msg::{FrameType, FrameId, PipelineId, TraversalDirection}
|
|||
use net_traits::response::HttpsState;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use script_thread::{ScriptThread, Runnable};
|
||||
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData};
|
||||
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData, UpdatePipelineIdReason};
|
||||
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg as ConstellationMsg};
|
||||
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||
use servo_atoms::Atom;
|
||||
|
@ -69,6 +69,12 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum NavigationType {
|
||||
InitialAboutBlank,
|
||||
Regular,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum ProcessingMode {
|
||||
FirstTime,
|
||||
|
@ -80,6 +86,7 @@ pub struct HTMLIFrameElement {
|
|||
htmlelement: HTMLElement,
|
||||
frame_id: FrameId,
|
||||
pipeline_id: Cell<Option<PipelineId>>,
|
||||
pending_pipeline_id: Cell<Option<PipelineId>>,
|
||||
sandbox: MutNullableJS<DOMTokenList>,
|
||||
sandbox_allowance: Cell<Option<SandboxAllowance>>,
|
||||
load_blocker: DOMRefCell<Option<LoadBlocker>>,
|
||||
|
@ -108,12 +115,14 @@ impl HTMLIFrameElement {
|
|||
pub fn generate_new_pipeline_id(&self) -> (Option<PipelineId>, PipelineId) {
|
||||
let old_pipeline_id = self.pipeline_id.get();
|
||||
let new_pipeline_id = PipelineId::new();
|
||||
self.pipeline_id.set(Some(new_pipeline_id));
|
||||
debug!("Frame {} created pipeline {}.", self.frame_id, new_pipeline_id);
|
||||
(old_pipeline_id, new_pipeline_id)
|
||||
}
|
||||
|
||||
pub fn navigate_or_reload_child_browsing_context(&self, load_data: Option<LoadData>, replace: bool) {
|
||||
pub fn navigate_or_reload_child_browsing_context(&self,
|
||||
load_data: Option<LoadData>,
|
||||
nav_type: NavigationType,
|
||||
replace: bool) {
|
||||
let sandboxed = if self.is_sandboxed() {
|
||||
IFrameSandboxed
|
||||
} else {
|
||||
|
@ -136,6 +145,7 @@ impl HTMLIFrameElement {
|
|||
|
||||
let window = window_from_node(self);
|
||||
let (old_pipeline_id, new_pipeline_id) = self.generate_new_pipeline_id();
|
||||
self.pending_pipeline_id.set(Some(new_pipeline_id));
|
||||
let private_iframe = self.privatebrowsing();
|
||||
let frame_type = if self.Mozbrowser() { FrameType::MozBrowserIFrame } else { FrameType::IFrame };
|
||||
|
||||
|
@ -149,37 +159,41 @@ impl HTMLIFrameElement {
|
|||
replace: replace,
|
||||
};
|
||||
|
||||
if load_data.as_ref().map_or(false, |d| d.url.as_str() == "about:blank") {
|
||||
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
|
||||
match nav_type {
|
||||
NavigationType::InitialAboutBlank => {
|
||||
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
|
||||
|
||||
global_scope
|
||||
.constellation_chan()
|
||||
.send(ConstellationMsg::ScriptLoadedAboutBlankInIFrame(load_info, pipeline_sender))
|
||||
.unwrap();
|
||||
global_scope
|
||||
.constellation_chan()
|
||||
.send(ConstellationMsg::ScriptNewIFrame(load_info, pipeline_sender))
|
||||
.unwrap();
|
||||
|
||||
let new_layout_info = NewLayoutInfo {
|
||||
parent_info: Some((global_scope.pipeline_id(), frame_type)),
|
||||
new_pipeline_id: new_pipeline_id,
|
||||
frame_id: self.frame_id,
|
||||
load_data: load_data.unwrap(),
|
||||
pipeline_port: pipeline_receiver,
|
||||
content_process_shutdown_chan: None,
|
||||
window_size: None,
|
||||
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
|
||||
};
|
||||
let new_layout_info = NewLayoutInfo {
|
||||
parent_info: Some((global_scope.pipeline_id(), frame_type)),
|
||||
new_pipeline_id: new_pipeline_id,
|
||||
frame_id: self.frame_id,
|
||||
load_data: load_data.unwrap(),
|
||||
pipeline_port: pipeline_receiver,
|
||||
content_process_shutdown_chan: None,
|
||||
window_size: None,
|
||||
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
|
||||
};
|
||||
|
||||
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
|
||||
} else {
|
||||
let load_info = IFrameLoadInfoWithData {
|
||||
info: load_info,
|
||||
load_data: load_data,
|
||||
old_pipeline_id: old_pipeline_id,
|
||||
sandbox: sandboxed,
|
||||
};
|
||||
global_scope
|
||||
self.pipeline_id.set(Some(new_pipeline_id));
|
||||
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
|
||||
},
|
||||
NavigationType::Regular => {
|
||||
let load_info = IFrameLoadInfoWithData {
|
||||
info: load_info,
|
||||
load_data: load_data,
|
||||
old_pipeline_id: old_pipeline_id,
|
||||
sandbox: sandboxed,
|
||||
};
|
||||
global_scope
|
||||
.constellation_chan()
|
||||
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if PREFS.is_mozbrowser_enabled() {
|
||||
|
@ -192,9 +206,10 @@ impl HTMLIFrameElement {
|
|||
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
|
||||
// TODO: srcdoc
|
||||
|
||||
let window = window_from_node(self);
|
||||
|
||||
// https://github.com/whatwg/html/issues/490
|
||||
if mode == ProcessingMode::FirstTime && !self.upcast::<Element>().has_attribute(&local_name!("src")) {
|
||||
let window = window_from_node(self);
|
||||
let event_loop = window.dom_manipulation_task_source();
|
||||
let _ = event_loop.queue(box IFrameLoadEventSteps::new(self),
|
||||
window.upcast());
|
||||
|
@ -205,9 +220,15 @@ impl HTMLIFrameElement {
|
|||
|
||||
// TODO: check ancestor browsing contexts for same URL
|
||||
|
||||
let creator_pipeline_id = if url.as_str() == "about:blank" {
|
||||
Some(window.upcast::<GlobalScope>().pipeline_id())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let document = document_from_node(self);
|
||||
self.navigate_or_reload_child_browsing_context(
|
||||
Some(LoadData::new(url, document.get_referrer_policy(), Some(document.url()))), false);
|
||||
let load_data = LoadData::new(url, creator_pipeline_id, document.get_referrer_policy(), Some(document.url()));
|
||||
self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::Regular, false);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -225,19 +246,30 @@ impl HTMLIFrameElement {
|
|||
// Synchronously create a new context and navigate it to about:blank.
|
||||
let url = ServoUrl::parse("about:blank").unwrap();
|
||||
let document = document_from_node(self);
|
||||
let load_data = LoadData::new(url,
|
||||
document.get_referrer_policy(),
|
||||
Some(document.url().clone()));
|
||||
self.navigate_or_reload_child_browsing_context(Some(load_data), false);
|
||||
let pipeline_id = Some(window_from_node(self).upcast::<GlobalScope>().pipeline_id());
|
||||
let load_data = LoadData::new(url, pipeline_id, document.get_referrer_policy(), Some(document.url().clone()));
|
||||
self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::InitialAboutBlank, false);
|
||||
}
|
||||
|
||||
pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId) {
|
||||
pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId, reason: UpdatePipelineIdReason) {
|
||||
if self.pending_pipeline_id.get() != Some(new_pipeline_id) && reason == UpdatePipelineIdReason::Navigation {
|
||||
return;
|
||||
}
|
||||
|
||||
self.pipeline_id.set(Some(new_pipeline_id));
|
||||
|
||||
let mut blocker = self.load_blocker.borrow_mut();
|
||||
LoadBlocker::terminate(&mut blocker);
|
||||
// Only terminate the load blocker if the pipeline id was updated due to a traversal.
|
||||
// The load blocker will be terminated for a navigation in iframe_load_event_steps.
|
||||
if reason == UpdatePipelineIdReason::Traversal {
|
||||
let mut blocker = self.load_blocker.borrow_mut();
|
||||
LoadBlocker::terminate(&mut blocker);
|
||||
}
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
let window = window_from_node(self);
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::FramedContentChanged);
|
||||
}
|
||||
|
||||
fn new_inherited(local_name: LocalName,
|
||||
|
@ -247,6 +279,7 @@ impl HTMLIFrameElement {
|
|||
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
||||
frame_id: FrameId::new(),
|
||||
pipeline_id: Cell::new(None),
|
||||
pending_pipeline_id: Cell::new(None),
|
||||
sandbox: Default::default(),
|
||||
sandbox_allowance: Cell::new(None),
|
||||
load_blocker: DOMRefCell::new(None),
|
||||
|
@ -296,7 +329,7 @@ impl HTMLIFrameElement {
|
|||
pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) {
|
||||
// TODO(#9592): assert that the load blocker is present at all times when we
|
||||
// can guarantee that it's created for the case of iframe.reload().
|
||||
if Some(loaded_pipeline) != self.pipeline_id() { return; }
|
||||
if Some(loaded_pipeline) != self.pending_pipeline_id.get() { return; }
|
||||
|
||||
// TODO A cross-origin child document would not be easily accessible
|
||||
// from this script thread. It's unclear how to implement
|
||||
|
@ -330,7 +363,8 @@ impl HTMLIFrameElement {
|
|||
}
|
||||
|
||||
pub trait HTMLIFrameElementLayoutMethods {
|
||||
fn pipeline_id(self) -> Option<PipelineId>;
|
||||
fn pipeline_id(&self) -> Option<PipelineId>;
|
||||
fn frame_id(&self) -> FrameId;
|
||||
fn get_width(&self) -> LengthOrPercentageOrAuto;
|
||||
fn get_height(&self) -> LengthOrPercentageOrAuto;
|
||||
}
|
||||
|
@ -338,12 +372,21 @@ pub trait HTMLIFrameElementLayoutMethods {
|
|||
impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
fn pipeline_id(self) -> Option<PipelineId> {
|
||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||
unsafe {
|
||||
(*self.unsafe_get()).pipeline_id.get()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
fn frame_id(&self) -> FrameId {
|
||||
unsafe {
|
||||
(*self.unsafe_get()).frame_id
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn get_width(&self) -> LengthOrPercentageOrAuto {
|
||||
unsafe {
|
||||
|
@ -563,7 +606,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
|||
fn Reload(&self, _hard_reload: bool) -> ErrorResult {
|
||||
if self.Mozbrowser() {
|
||||
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
|
||||
self.navigate_or_reload_child_browsing_context(None, true);
|
||||
self.navigate_or_reload_child_browsing_context(None, NavigationType::Regular, true);
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -739,6 +782,7 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
// a new iframe. Without this, the constellation gets very
|
||||
// confused.
|
||||
self.pipeline_id.set(None);
|
||||
self.pending_pipeline_id.set(None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ use heapsize::{HeapSizeOf, heap_size_of};
|
|||
use html5ever::{Prefix, Namespace, QualName};
|
||||
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
||||
use libc::{self, c_void, uintptr_t};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::{FrameId, PipelineId};
|
||||
use ref_slice::ref_slice;
|
||||
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
|
||||
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
|
||||
|
@ -970,6 +970,7 @@ pub trait LayoutNodeHelpers {
|
|||
fn image_url(&self) -> Option<ServoUrl>;
|
||||
fn canvas_data(&self) -> Option<HTMLCanvasData>;
|
||||
fn svg_data(&self) -> Option<SVGSVGData>;
|
||||
fn iframe_frame_id(&self) -> FrameId;
|
||||
fn iframe_pipeline_id(&self) -> PipelineId;
|
||||
fn opaque(&self) -> OpaqueNode;
|
||||
}
|
||||
|
@ -1120,6 +1121,12 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
|
|||
.map(|svg| svg.data())
|
||||
}
|
||||
|
||||
fn iframe_frame_id(&self) -> FrameId {
|
||||
let iframe_element = self.downcast::<HTMLIFrameElement>()
|
||||
.expect("not an iframe element!");
|
||||
iframe_element.frame_id()
|
||||
}
|
||||
|
||||
fn iframe_pipeline_id(&self) -> PipelineId {
|
||||
let iframe_element = self.downcast::<HTMLIFrameElement>()
|
||||
.expect("not an iframe element!");
|
||||
|
|
|
@ -1537,10 +1537,10 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
|
||||
self.main_thread_script_chan().send(
|
||||
MainThreadScriptMsg::Navigate(self.upcast::<GlobalScope>().pipeline_id(),
|
||||
LoadData::new(url, referrer_policy, Some(doc.url())),
|
||||
replace)).unwrap();
|
||||
MainThreadScriptMsg::Navigate(pipeline_id,
|
||||
LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), replace)).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_fire_timer(&self, timer_id: TimerEventId) {
|
||||
|
|
|
@ -44,7 +44,7 @@ use dom::node::{LayoutNodeHelpers, Node};
|
|||
use dom::text::Text;
|
||||
use gfx_traits::ByteIndex;
|
||||
use html5ever::{LocalName, Namespace};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::{FrameId, PipelineId};
|
||||
use range::Range;
|
||||
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress};
|
||||
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
|
||||
|
@ -908,6 +908,11 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
|||
this.svg_data()
|
||||
}
|
||||
|
||||
fn iframe_frame_id(&self) -> FrameId {
|
||||
let this = unsafe { self.get_jsmanaged() };
|
||||
this.iframe_frame_id()
|
||||
}
|
||||
|
||||
fn iframe_pipeline_id(&self) -> PipelineId {
|
||||
let this = unsafe { self.get_jsmanaged() };
|
||||
this.iframe_pipeline_id()
|
||||
|
|
|
@ -46,7 +46,7 @@ use dom::element::Element;
|
|||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||
use dom::htmliframeelement::HTMLIFrameElement;
|
||||
use dom::htmliframeelement::{HTMLIFrameElement, NavigationType};
|
||||
use dom::mutationobserver::MutationObserver;
|
||||
use dom::node::{Node, NodeDamage, window_from_node};
|
||||
use dom::serviceworker::TrustedServiceWorkerAddress;
|
||||
|
@ -87,7 +87,7 @@ use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
|
|||
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
||||
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
|
||||
use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
|
||||
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
|
||||
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg, UpdatePipelineIdReason};
|
||||
use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource};
|
||||
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
||||
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
|
||||
|
@ -555,8 +555,8 @@ impl ScriptThreadFactory for ScriptThread {
|
|||
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread);
|
||||
|
||||
let origin = MutableOrigin::new(load_data.url.origin());
|
||||
let new_load = InProgressLoad::new(id, frame_id, parent_info, layout_chan, window_size,
|
||||
load_data.url.clone(), origin);
|
||||
let new_load = InProgressLoad::new(id, frame_id, parent_info,
|
||||
layout_chan, window_size, load_data.url.clone(), origin);
|
||||
script_thread.start_page_load(new_load, load_data);
|
||||
|
||||
let reporter_name = format!("script-reporter-{}", id);
|
||||
|
@ -827,7 +827,22 @@ impl ScriptThread {
|
|||
FromConstellation(ConstellationControlMsg::AttachLayout(
|
||||
new_layout_info)) => {
|
||||
self.profile_event(ScriptThreadEventCategory::AttachLayout, || {
|
||||
let origin = MutableOrigin::new(new_layout_info.load_data.url.origin());
|
||||
// If this is an about:blank load, it must share the creator's origin.
|
||||
// This must match the logic in the constellation when creating a new pipeline
|
||||
let origin = if new_layout_info.load_data.url.as_str() != "about:blank" {
|
||||
MutableOrigin::new(new_layout_info.load_data.url.origin())
|
||||
} else if let Some(parent) = new_layout_info.parent_info
|
||||
.and_then(|(pipeline_id, _)| self.documents.borrow()
|
||||
.find_document(pipeline_id)) {
|
||||
parent.origin().clone()
|
||||
} else if let Some(creator) = new_layout_info.load_data.creator_pipeline_id
|
||||
.and_then(|pipeline_id| self.documents.borrow()
|
||||
.find_document(pipeline_id)) {
|
||||
creator.origin().clone()
|
||||
} else {
|
||||
MutableOrigin::new(ImmutableOrigin::new_opaque())
|
||||
};
|
||||
|
||||
self.handle_new_layout(new_layout_info, origin);
|
||||
})
|
||||
}
|
||||
|
@ -1043,10 +1058,12 @@ impl ScriptThread {
|
|||
event),
|
||||
ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
||||
frame_id,
|
||||
new_pipeline_id) =>
|
||||
new_pipeline_id,
|
||||
reason) =>
|
||||
self.handle_update_pipeline_id(parent_pipeline_id,
|
||||
frame_id,
|
||||
new_pipeline_id),
|
||||
new_pipeline_id,
|
||||
reason),
|
||||
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
|
||||
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id),
|
||||
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
|
||||
|
@ -1062,8 +1079,6 @@ impl ScriptThread {
|
|||
self.handle_frame_load_event(parent_id, frame_id, child_id),
|
||||
ConstellationControlMsg::DispatchStorageEvent(pipeline_id, storage, url, key, old_value, new_value) =>
|
||||
self.handle_storage_event(pipeline_id, storage, url, key, old_value, new_value),
|
||||
ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, frame_id) =>
|
||||
self.handle_framed_content_changed(parent_pipeline_id, frame_id),
|
||||
ConstellationControlMsg::ReportCSSError(pipeline_id, filename, line, column, msg) =>
|
||||
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
||||
ConstellationControlMsg::Reload(pipeline_id) =>
|
||||
|
@ -1399,20 +1414,6 @@ impl ScriptThread {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_framed_content_changed(&self,
|
||||
parent_pipeline_id: PipelineId,
|
||||
frame_id: FrameId) {
|
||||
let doc = self.documents.borrow().find_document(parent_pipeline_id).unwrap();
|
||||
let frame_element = doc.find_iframe(frame_id);
|
||||
if let Some(ref frame_element) = frame_element {
|
||||
frame_element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
let window = doc.window();
|
||||
window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::FramedContentChanged);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_post_message_msg(&self, pipeline_id: PipelineId, origin: Option<ImmutableOrigin>, data: Vec<u8>) {
|
||||
match { self.documents.borrow().find_window(pipeline_id) } {
|
||||
None => return warn!("postMessage after pipeline {} closed.", pipeline_id),
|
||||
|
@ -1443,10 +1444,11 @@ impl ScriptThread {
|
|||
fn handle_update_pipeline_id(&self,
|
||||
parent_pipeline_id: PipelineId,
|
||||
frame_id: FrameId,
|
||||
new_pipeline_id: PipelineId) {
|
||||
new_pipeline_id: PipelineId,
|
||||
reason: UpdatePipelineIdReason) {
|
||||
let frame_element = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
|
||||
if let Some(frame_element) = frame_element {
|
||||
frame_element.update_pipeline_id(new_pipeline_id);
|
||||
frame_element.update_pipeline_id(new_pipeline_id, reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2065,7 +2067,7 @@ impl ScriptThread {
|
|||
Some(frame_id) => {
|
||||
let iframe = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
|
||||
if let Some(iframe) = iframe {
|
||||
iframe.navigate_or_reload_child_browsing_context(Some(load_data), replace);
|
||||
iframe.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::Regular, replace);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
|
|
@ -11,7 +11,7 @@ use SVGSVGData;
|
|||
use atomic_refcell::AtomicRefCell;
|
||||
use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type};
|
||||
use html5ever::{Namespace, LocalName};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::{FrameId, PipelineId};
|
||||
use range::Range;
|
||||
use servo_url::ServoUrl;
|
||||
use std::fmt::Debug;
|
||||
|
@ -271,6 +271,10 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
|
|||
|
||||
fn svg_data(&self) -> Option<SVGSVGData>;
|
||||
|
||||
/// If this node is an iframe element, returns its frame ID. If this node is
|
||||
/// not an iframe element, fails.
|
||||
fn iframe_frame_id(&self) -> FrameId;
|
||||
|
||||
/// If this node is an iframe element, returns its pipeline ID. If this node is
|
||||
/// not an iframe element, fails.
|
||||
fn iframe_pipeline_id(&self) -> PipelineId;
|
||||
|
|
|
@ -134,6 +134,8 @@ pub enum LayoutControlMsg {
|
|||
pub struct LoadData {
|
||||
/// The URL.
|
||||
pub url: ServoUrl,
|
||||
/// The creator pipeline id if this is an about:blank load.
|
||||
pub creator_pipeline_id: Option<PipelineId>,
|
||||
/// The method.
|
||||
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
||||
serialize_with = "::hyper_serde::serialize")]
|
||||
|
@ -152,9 +154,14 @@ pub struct LoadData {
|
|||
|
||||
impl LoadData {
|
||||
/// Create a new `LoadData` object.
|
||||
pub fn new(url: ServoUrl, referrer_policy: Option<ReferrerPolicy>, referrer_url: Option<ServoUrl>) -> LoadData {
|
||||
pub fn new(url: ServoUrl,
|
||||
creator_pipeline_id: Option<PipelineId>,
|
||||
referrer_policy: Option<ReferrerPolicy>,
|
||||
referrer_url: Option<ServoUrl>)
|
||||
-> LoadData {
|
||||
LoadData {
|
||||
url: url,
|
||||
creator_pipeline_id: creator_pipeline_id,
|
||||
method: Method::Get,
|
||||
headers: Headers::new(),
|
||||
data: None,
|
||||
|
@ -211,6 +218,15 @@ pub enum DocumentActivity {
|
|||
FullyActive,
|
||||
}
|
||||
|
||||
/// The reason why the pipeline id of an iframe is being updated.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HeapSizeOf, Debug, Deserialize, Serialize)]
|
||||
pub enum UpdatePipelineIdReason {
|
||||
/// The pipeline id is being updated due to a navigation.
|
||||
Navigation,
|
||||
/// The pipeline id is being updated due to a history traversal.
|
||||
Traversal,
|
||||
}
|
||||
|
||||
/// Messages sent from the constellation or layout to the script thread.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum ConstellationControlMsg {
|
||||
|
@ -249,7 +265,7 @@ pub enum ConstellationControlMsg {
|
|||
MozBrowserEvent(PipelineId, Option<FrameId>, MozBrowserEvent),
|
||||
/// Updates the current pipeline ID of a given iframe.
|
||||
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
||||
UpdatePipelineId(PipelineId, FrameId, PipelineId),
|
||||
UpdatePipelineId(PipelineId, FrameId, PipelineId, UpdatePipelineIdReason),
|
||||
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
|
||||
/// PipelineId is for the parent, FrameId is for the actual frame.
|
||||
FocusIFrame(PipelineId, FrameId),
|
||||
|
@ -274,9 +290,6 @@ pub enum ConstellationControlMsg {
|
|||
/// Cause a `storage` event to be dispatched at the appropriate window.
|
||||
/// The strings are key, old value and new value.
|
||||
DispatchStorageEvent(PipelineId, StorageType, ServoUrl, Option<String>, Option<String>, Option<String>),
|
||||
/// Notifies a parent pipeline that one of its child frames is now active.
|
||||
/// PipelineId is for the parent, FrameId is the child frame.
|
||||
FramedContentChanged(PipelineId, FrameId),
|
||||
/// Report an error from a CSS parser for the given pipeline
|
||||
ReportCSSError(PipelineId, String, usize, usize, String),
|
||||
/// Reload the given page.
|
||||
|
@ -312,7 +325,6 @@ impl fmt::Debug for ConstellationControlMsg {
|
|||
WebFontLoaded(..) => "WebFontLoaded",
|
||||
DispatchFrameLoadEvent { .. } => "DispatchFrameLoadEvent",
|
||||
DispatchStorageEvent(..) => "DispatchStorageEvent",
|
||||
FramedContentChanged(..) => "FramedContentChanged",
|
||||
ReportCSSError(..) => "ReportCSSError",
|
||||
Reload(..) => "Reload",
|
||||
WebVREvents(..) => "WebVREvents",
|
||||
|
|
|
@ -34,8 +34,8 @@ use webrender_traits::ClipId;
|
|||
pub enum LayoutMsg {
|
||||
/// Indicates whether this pipeline is currently running animations.
|
||||
ChangeRunningAnimationsState(PipelineId, AnimationState),
|
||||
/// Inform the constellation of the size of the pipeline's viewport.
|
||||
FrameSizes(Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>),
|
||||
/// Inform the constellation of the size of the frame's viewport.
|
||||
FrameSizes(Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>),
|
||||
/// Requests that the constellation inform the compositor of the a cursor change.
|
||||
SetCursor(Cursor),
|
||||
/// Notifies the constellation that the viewport has been constrained in some manner
|
||||
|
@ -120,8 +120,8 @@ pub enum ScriptMsg {
|
|||
VisibilityChangeComplete(PipelineId, bool),
|
||||
/// A load has been requested in an IFrame.
|
||||
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
|
||||
/// A load of `about:blank` has been completed in an IFrame.
|
||||
ScriptLoadedAboutBlankInIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
|
||||
/// A load of the initial `about:blank` has been completed in an IFrame.
|
||||
ScriptNewIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
|
||||
/// Requests that the constellation set the contents of the clipboard
|
||||
SetClipboardContents(String),
|
||||
/// Mark a new document as active
|
||||
|
|
|
@ -357,7 +357,7 @@ impl Handler {
|
|||
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
|
||||
let load_data = LoadData::new(url, None, None);
|
||||
let load_data = LoadData::new(url, Some(pipeline_id), None, None);
|
||||
let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone());
|
||||
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[matchMedia.html]
|
||||
disabled: true
|
||||
type: testharness
|
||||
[window.matchMedia exists]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue