mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Auto merge of #16506 - cbrewster:about_chaos, r=asajeffrey
Make non-initial about:blank loads async <!-- Please describe your changes on the following line: --> --- <!-- 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 #14856 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- 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/16506) <!-- Reviewable:end -->
This commit is contained in:
commit
dc8cf694ed
20 changed files with 336 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,7 +599,11 @@ 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) {
|
||||
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)
|
||||
|
@ -610,6 +614,16 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
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 {
|
||||
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,
|
||||
}, WindowSizeType::Initial);
|
||||
|
||||
pipeline.event_loop.send(msg)
|
||||
};
|
||||
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,7 +1467,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
is_private);
|
||||
}
|
||||
|
||||
fn handle_script_loaded_about_blank_in_iframe_msg(&mut self,
|
||||
fn handle_script_new_iframe(&mut self,
|
||||
load_info: IFrameLoadInfo,
|
||||
layout_sender: IpcSender<LayoutControlMsg>) {
|
||||
let IFrameLoadInfo {
|
||||
|
@ -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,12 +159,13 @@ impl HTMLIFrameElement {
|
|||
replace: replace,
|
||||
};
|
||||
|
||||
if load_data.as_ref().map_or(false, |d| d.url.as_str() == "about:blank") {
|
||||
match nav_type {
|
||||
NavigationType::InitialAboutBlank => {
|
||||
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
|
||||
|
||||
global_scope
|
||||
.constellation_chan()
|
||||
.send(ConstellationMsg::ScriptLoadedAboutBlankInIFrame(load_info, pipeline_sender))
|
||||
.send(ConstellationMsg::ScriptNewIFrame(load_info, pipeline_sender))
|
||||
.unwrap();
|
||||
|
||||
let new_layout_info = NewLayoutInfo {
|
||||
|
@ -168,8 +179,10 @@ impl HTMLIFrameElement {
|
|||
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
|
||||
};
|
||||
|
||||
self.pipeline_id.set(Some(new_pipeline_id));
|
||||
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
|
||||
} else {
|
||||
},
|
||||
NavigationType::Regular => {
|
||||
let load_info = IFrameLoadInfoWithData {
|
||||
info: load_info,
|
||||
load_data: load_data,
|
||||
|
@ -181,6 +194,7 @@ impl HTMLIFrameElement {
|
|||
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if PREFS.is_mozbrowser_enabled() {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
||||
|
@ -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, reason: UpdatePipelineIdReason) {
|
||||
if self.pending_pipeline_id.get() != Some(new_pipeline_id) && reason == UpdatePipelineIdReason::Navigation {
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId) {
|
||||
self.pipeline_id.set(Some(new_pipeline_id));
|
||||
|
||||
// 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();
|
||||
|
||||
|
|
|
@ -331418,6 +331418,12 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html": [
|
||||
[
|
||||
"/html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html",
|
||||
{}
|
||||
]
|
||||
],
|
||||
"html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html": [
|
||||
[
|
||||
"/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html",
|
||||
|
@ -570683,6 +570689,10 @@
|
|||
"56df0cb79a1af927a0209c0bbbb5edb25ccaee5f",
|
||||
"testharness"
|
||||
],
|
||||
"html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html": [
|
||||
"46708fc218e559fba7049a36888a7c8a24c22672",
|
||||
"testharness"
|
||||
],
|
||||
"html/semantics/embedded-content/the-iframe-element/cross_origin_child.html": [
|
||||
"a42082bb612b280eda5aa598ed750cfce3edd537",
|
||||
"support"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[matchMedia.html]
|
||||
disabled: true
|
||||
type: testharness
|
||||
[window.matchMedia exists]
|
||||
expected: FAIL
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Iframe's contentDocument should only change after its pending load has matured.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
iframe.onload = t.step_func(function() {
|
||||
assert_true(iframe.contentDocument.location.toString().includes("support/blank.htm"));
|
||||
t.done();
|
||||
});
|
||||
|
||||
assert_equals(iframe.contentDocument.location.toString(), "about:blank");
|
||||
iframe.src = "support/blank.htm?pipe=trickle(d2)";
|
||||
// The location of the contentDocument should not change until the new document has matured.
|
||||
assert_equals(iframe.contentDocument.location.toString(), "about:blank");
|
||||
}, "contentDocument should only change after a load matures.");
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue