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) {
|
match ServoUrl::parse(&url_string) {
|
||||||
Ok(url) => {
|
Ok(url) => {
|
||||||
let msg = match self.root_pipeline {
|
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)
|
None => ConstellationMsg::InitLoadUrl(url)
|
||||||
};
|
};
|
||||||
if let Err(e) = self.constellation_chan.send(msg) {
|
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::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
|
||||||
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
|
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
|
||||||
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
|
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 serde::{Deserialize, Serialize};
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_config::prefs::PREFS;
|
use servo_config::prefs::PREFS;
|
||||||
|
@ -599,7 +599,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
let (event_loop, host) = match sandbox {
|
let (event_loop, host) = match sandbox {
|
||||||
IFrameSandboxState::IFrameSandboxed => (None, None),
|
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),
|
None => (None, None),
|
||||||
Some(host) => {
|
Some(host) => {
|
||||||
let event_loop = self.event_loops.get(&top_level_frame_id)
|
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),
|
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.
|
/// 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);
|
let frame = Frame::new(frame_id, pipeline_id, load_data);
|
||||||
self.frames.insert(frame_id, frame);
|
self.frames.insert(frame_id, frame);
|
||||||
|
|
||||||
|
@ -915,11 +932,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
load_info.info.new_pipeline_id);
|
load_info.info.new_pipeline_id);
|
||||||
self.handle_script_loaded_url_in_iframe_msg(load_info);
|
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 {:?} {:?}",
|
debug!("constellation got loaded `about:blank` in iframe message {:?} {:?}",
|
||||||
load_info.parent_pipeline_id,
|
load_info.parent_pipeline_id,
|
||||||
load_info.new_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) => {
|
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
|
||||||
self.handle_change_running_animations_state(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
|
// Notify the browser chrome that the pipeline has failed
|
||||||
self.trigger_mozbrowsererror(top_level_frame_id, reason, backtrace);
|
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 (window_size, pipeline_id) = {
|
||||||
let pipeline_url = pipeline_id.and_then(|id| self.pipelines.get(&id).map(|pipeline| pipeline.url.clone()));
|
let frame = self.frames.get(&top_level_frame_id);
|
||||||
let parent_info = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.parent_info));
|
let window_size = frame.and_then(|frame| frame.size);
|
||||||
let window_size = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.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);
|
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");
|
warn!("creating replacement pipeline for about:failure");
|
||||||
|
|
||||||
let new_pipeline_id = PipelineId::new();
|
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;
|
let sandbox = IFrameSandboxState::IFrameSandboxed;
|
||||||
self.new_pipeline(new_pipeline_id, top_level_frame_id, parent_info,
|
self.new_pipeline(new_pipeline_id, top_level_frame_id, parent_info,
|
||||||
window_size, load_data.clone(), sandbox, false);
|
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 window_size = self.window_size.initial_viewport;
|
||||||
let root_pipeline_id = PipelineId::new();
|
let root_pipeline_id = PipelineId::new();
|
||||||
let root_frame_id = self.root_frame_id;
|
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;
|
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
||||||
self.new_pipeline(root_pipeline_id, root_frame_id, None, Some(window_size), load_data.clone(), sandbox, false);
|
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);
|
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,
|
fn handle_frame_size_msg(&mut self,
|
||||||
iframe_sizes: Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>) {
|
iframe_sizes: Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>) {
|
||||||
for (pipeline_id, size) in iframe_sizes {
|
for (frame_id, size) in iframe_sizes {
|
||||||
let result = {
|
let window_size = WindowSizeData {
|
||||||
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,
|
initial_viewport: size,
|
||||||
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
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)
|
// 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 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)
|
(load_data, window_size, is_private)
|
||||||
};
|
};
|
||||||
|
@ -1456,7 +1467,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
is_private);
|
is_private);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_script_loaded_about_blank_in_iframe_msg(&mut self,
|
fn handle_script_new_iframe(&mut self,
|
||||||
load_info: IFrameLoadInfo,
|
load_info: IFrameLoadInfo,
|
||||||
layout_sender: IpcSender<LayoutControlMsg>) {
|
layout_sender: IpcSender<LayoutControlMsg>) {
|
||||||
let IFrameLoadInfo {
|
let IFrameLoadInfo {
|
||||||
|
@ -1486,12 +1497,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.compositor_proxy.clone_compositor_proxy(),
|
self.compositor_proxy.clone_compositor_proxy(),
|
||||||
is_private || parent_pipeline.is_private,
|
is_private || parent_pipeline.is_private,
|
||||||
url.clone(),
|
url.clone(),
|
||||||
None,
|
|
||||||
parent_pipeline.visible)
|
parent_pipeline.visible)
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Referrer?
|
// 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 {
|
let replace_instant = if replace {
|
||||||
self.frames.get(&frame_id).map(|frame| frame.instant)
|
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.
|
// changes would be overridden by changing the subframe associated with source_id.
|
||||||
|
|
||||||
// Create the new pipeline
|
// 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 new_pipeline_id = PipelineId::new();
|
||||||
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
||||||
let replace_instant = if replace {
|
let replace_instant = if replace {
|
||||||
|
@ -1959,7 +1969,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::Refresh(pipeline_id, reply) => {
|
WebDriverCommandMsg::Refresh(pipeline_id, reply) => {
|
||||||
let load_data = match self.pipelines.get(&pipeline_id) {
|
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),
|
None => return warn!("Pipeline {:?} Refresh after closure.", pipeline_id),
|
||||||
};
|
};
|
||||||
self.load_url_for_webdriver(pipeline_id, load_data, reply, true);
|
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 load_data = entry.load_data;
|
||||||
let (parent_info, window_size, is_private) = match self.frames.get(&frame_id) {
|
let (parent_info, window_size, is_private) = match self.frames.get(&frame_id) {
|
||||||
Some(frame) => match self.pipelines.get(&frame.pipeline_id) {
|
Some(frame) => match self.pipelines.get(&frame.pipeline_id) {
|
||||||
Some(pipeline) => (pipeline.parent_info, pipeline.size, pipeline.is_private),
|
Some(pipeline) => (pipeline.parent_info, frame.size, pipeline.is_private),
|
||||||
None => (None, None, false),
|
None => (None, frame.size, false),
|
||||||
},
|
},
|
||||||
None => return warn!("no frame to traverse"),
|
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.
|
// Update the owning iframe to point to the new pipeline id.
|
||||||
// This makes things like contentDocument work correctly.
|
// This makes things like contentDocument work correctly.
|
||||||
if let Some((parent_pipeline_id, _)) = parent_info {
|
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) {
|
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||||
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
|
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
|
||||||
Some(pipeline) => pipeline.event_loop.send(msg),
|
Some(pipeline) => pipeline.event_loop.send(msg),
|
||||||
|
@ -2245,7 +2256,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_frame {
|
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.update_activity(frame_change.new_pipeline_id);
|
||||||
self.notify_history_changed(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(pipeline) = self.pipelines.get(&pipeline_id) {
|
||||||
if let Some((parent_pipeline_id, _)) = pipeline.parent_info {
|
if let Some((parent_pipeline_id, _)) = pipeline.parent_info {
|
||||||
if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) {
|
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);
|
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) {
|
fn handle_window_size_msg(&mut self, new_size: WindowSizeData, size_type: WindowSizeType) {
|
||||||
debug!("handle_window_size_msg: {:?}", new_size.initial_viewport.to_untyped());
|
debug!("handle_window_size_msg: {:?}", new_size.initial_viewport.to_untyped());
|
||||||
|
|
||||||
if let Some(frame) = self.frames.get(&self.root_frame_id) {
|
let frame_id = self.root_frame_id;
|
||||||
// Send Resize (or ResizeInactive) messages to each
|
self.resize_frame(new_size, size_type, frame_id);
|
||||||
// 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
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(resize_channel) = self.webdriver.resize_channel.take() {
|
if let Some(resize_channel) = self.webdriver.resize_channel.take() {
|
||||||
let _ = resize_channel.send(new_size);
|
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
|
// 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
|
// *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.
|
// 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
|
// If the rectangle for this pipeline is zero sized, it will
|
||||||
// never be painted. In this case, don't query the layout
|
// never be painted. In this case, don't query the layout
|
||||||
// thread as it won't contribute to the final output image.
|
// 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));
|
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) {
|
fn clear_joint_session_future(&mut self, frame_id: FrameId) {
|
||||||
let frame_ids: Vec<FrameId> = self.full_frame_tree_iter(frame_id)
|
let frame_ids: Vec<FrameId> = self.full_frame_tree_iter(frame_id)
|
||||||
.map(|frame| 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| {
|
self.pipelines.get(&frame.pipeline_id).map(|pipeline: &Pipeline| {
|
||||||
let mut frame_tree = SendableFrameTree {
|
let mut frame_tree = SendableFrameTree {
|
||||||
pipeline: pipeline.to_sendable(),
|
pipeline: pipeline.to_sendable(),
|
||||||
size: pipeline.size,
|
size: frame.size,
|
||||||
children: vec!(),
|
children: vec!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use euclid::size::TypedSize2D;
|
||||||
use msg::constellation_msg::{FrameId, PipelineId};
|
use msg::constellation_msg::{FrameId, PipelineId};
|
||||||
use pipeline::Pipeline;
|
use pipeline::Pipeline;
|
||||||
use script_traits::LoadData;
|
use script_traits::LoadData;
|
||||||
|
@ -9,6 +10,7 @@ use std::collections::HashMap;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use style_traits::CSSPixel;
|
||||||
|
|
||||||
/// A frame in the frame tree.
|
/// A frame in the frame tree.
|
||||||
/// Each frame is the constellation's view of a browsing context.
|
/// Each frame is the constellation's view of a browsing context.
|
||||||
|
@ -22,13 +24,16 @@ pub struct Frame {
|
||||||
/// The frame id.
|
/// The frame id.
|
||||||
pub id: FrameId,
|
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,
|
pub instant: Instant,
|
||||||
|
|
||||||
/// The pipeline for the current session history entry
|
/// The pipeline for the current session history entry.
|
||||||
pub pipeline_id: PipelineId,
|
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,
|
pub load_data: LoadData,
|
||||||
|
|
||||||
/// The past session history, ordered chronologically.
|
/// The past session history, ordered chronologically.
|
||||||
|
@ -44,6 +49,7 @@ impl Frame {
|
||||||
pub fn new(id: FrameId, pipeline_id: PipelineId, load_data: LoadData) -> Frame {
|
pub fn new(id: FrameId, pipeline_id: PipelineId, load_data: LoadData) -> Frame {
|
||||||
Frame {
|
Frame {
|
||||||
id: id,
|
id: id,
|
||||||
|
size: None,
|
||||||
pipeline_id: pipeline_id,
|
pipeline_id: pipeline_id,
|
||||||
instant: Instant::now(),
|
instant: Instant::now(),
|
||||||
load_data: load_data,
|
load_data: load_data,
|
||||||
|
|
|
@ -76,10 +76,6 @@ pub struct Pipeline {
|
||||||
/// The title of the most recently-loaded page.
|
/// The title of the most recently-loaded page.
|
||||||
pub title: Option<String>,
|
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
|
/// Whether this pipeline is currently running animations. Pipelines that are running
|
||||||
/// animations cause composites to be continually scheduled.
|
/// animations cause composites to be continually scheduled.
|
||||||
pub running_animations: bool,
|
pub running_animations: bool,
|
||||||
|
@ -291,7 +287,6 @@ impl Pipeline {
|
||||||
state.compositor_proxy,
|
state.compositor_proxy,
|
||||||
state.is_private,
|
state.is_private,
|
||||||
url,
|
url,
|
||||||
state.window_size,
|
|
||||||
state.prev_visibility.unwrap_or(true)))
|
state.prev_visibility.unwrap_or(true)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +300,6 @@ impl Pipeline {
|
||||||
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
||||||
is_private: bool,
|
is_private: bool,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
size: Option<TypedSize2D<f32, CSSPixel>>,
|
|
||||||
visible: bool)
|
visible: bool)
|
||||||
-> Pipeline {
|
-> Pipeline {
|
||||||
let pipeline = Pipeline {
|
let pipeline = Pipeline {
|
||||||
|
@ -318,7 +312,6 @@ impl Pipeline {
|
||||||
url: url,
|
url: url,
|
||||||
title: None,
|
title: None,
|
||||||
children: vec!(),
|
children: vec!(),
|
||||||
size: size,
|
|
||||||
running_animations: false,
|
running_animations: false,
|
||||||
visible: visible,
|
visible: visible,
|
||||||
is_private: is_private,
|
is_private: is_private,
|
||||||
|
|
|
@ -34,7 +34,7 @@ use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use list_item::ListItemFlow;
|
use list_item::ListItemFlow;
|
||||||
use model::{self, MaybeAuto, specified};
|
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::base::PixelFormat;
|
||||||
use net_traits::image_cache::UsePlaceholder;
|
use net_traits::image_cache::UsePlaceholder;
|
||||||
use range::Range;
|
use range::Range;
|
||||||
|
@ -173,7 +173,7 @@ pub struct DisplayListBuildState<'a> {
|
||||||
|
|
||||||
/// Vector containing iframe sizes, used to inform the constellation about
|
/// Vector containing iframe sizes, used to inform the constellation about
|
||||||
/// new iframe sizes
|
/// 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
|
/// A stack of clips used to cull display list entries that are outside the
|
||||||
/// rendered region.
|
/// rendered region.
|
||||||
|
@ -1809,7 +1809,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
|
|
||||||
let size = Size2D::new(item.bounds().size.width.to_f32_px(),
|
let size = Size2D::new(item.bounds().size.width.to_f32_px(),
|
||||||
item.bounds().size.height.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);
|
state.add_display_item(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ use ipc_channel::ipc::IpcSender;
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, SizeConstraint};
|
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, SizeConstraint};
|
||||||
use model::{style_length, ToGfxMatrix};
|
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::base::{Image, ImageMetadata};
|
||||||
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||||
use range::*;
|
use range::*;
|
||||||
|
@ -467,10 +467,12 @@ 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.
|
/// size of this iframe can be communicated via the constellation to the iframe's own layout thread.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IframeFragmentInfo {
|
pub struct IframeFragmentInfo {
|
||||||
|
/// The frame ID of this iframe.
|
||||||
|
pub frame_id: FrameId,
|
||||||
/// The pipelineID of this iframe.
|
/// The pipelineID of this iframe.
|
||||||
pub pipeline_id: PipelineId,
|
pub pipeline_id: PipelineId,
|
||||||
}
|
}
|
||||||
|
@ -478,8 +480,10 @@ pub struct IframeFragmentInfo {
|
||||||
impl IframeFragmentInfo {
|
impl IframeFragmentInfo {
|
||||||
/// Creates the information specific to an iframe fragment.
|
/// Creates the information specific to an iframe fragment.
|
||||||
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> IframeFragmentInfo {
|
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> IframeFragmentInfo {
|
||||||
|
let frame_id = node.iframe_frame_id();
|
||||||
let pipeline_id = node.iframe_pipeline_id();
|
let pipeline_id = node.iframe_pipeline_id();
|
||||||
IframeFragmentInfo {
|
IframeFragmentInfo {
|
||||||
|
frame_id: frame_id,
|
||||||
pipeline_id: pipeline_id,
|
pipeline_id: pipeline_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,3 +310,4 @@ pub enum FrameType {
|
||||||
IFrame,
|
IFrame,
|
||||||
MozBrowserIFrame,
|
MozBrowserIFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,7 +345,7 @@ impl HTMLFormElement {
|
||||||
let _target = submitter.target();
|
let _target = submitter.target();
|
||||||
// TODO: Handle browsing contexts, partially loaded documents (step 16-17)
|
// 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
|
// Step 18
|
||||||
match (&*scheme, method) {
|
match (&*scheme, method) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ use msg::constellation_msg::{FrameType, FrameId, PipelineId, TraversalDirection}
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use script_layout_interface::message::ReflowQueryType;
|
use script_layout_interface::message::ReflowQueryType;
|
||||||
use script_thread::{ScriptThread, Runnable};
|
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::{MozBrowserEvent, NewLayoutInfo, ScriptMsg as ConstellationMsg};
|
||||||
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
|
@ -69,6 +69,12 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum NavigationType {
|
||||||
|
InitialAboutBlank,
|
||||||
|
Regular,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum ProcessingMode {
|
enum ProcessingMode {
|
||||||
FirstTime,
|
FirstTime,
|
||||||
|
@ -80,6 +86,7 @@ pub struct HTMLIFrameElement {
|
||||||
htmlelement: HTMLElement,
|
htmlelement: HTMLElement,
|
||||||
frame_id: FrameId,
|
frame_id: FrameId,
|
||||||
pipeline_id: Cell<Option<PipelineId>>,
|
pipeline_id: Cell<Option<PipelineId>>,
|
||||||
|
pending_pipeline_id: Cell<Option<PipelineId>>,
|
||||||
sandbox: MutNullableJS<DOMTokenList>,
|
sandbox: MutNullableJS<DOMTokenList>,
|
||||||
sandbox_allowance: Cell<Option<SandboxAllowance>>,
|
sandbox_allowance: Cell<Option<SandboxAllowance>>,
|
||||||
load_blocker: DOMRefCell<Option<LoadBlocker>>,
|
load_blocker: DOMRefCell<Option<LoadBlocker>>,
|
||||||
|
@ -108,12 +115,14 @@ impl HTMLIFrameElement {
|
||||||
pub fn generate_new_pipeline_id(&self) -> (Option<PipelineId>, PipelineId) {
|
pub fn generate_new_pipeline_id(&self) -> (Option<PipelineId>, PipelineId) {
|
||||||
let old_pipeline_id = self.pipeline_id.get();
|
let old_pipeline_id = self.pipeline_id.get();
|
||||||
let new_pipeline_id = PipelineId::new();
|
let new_pipeline_id = PipelineId::new();
|
||||||
self.pipeline_id.set(Some(new_pipeline_id));
|
|
||||||
debug!("Frame {} created pipeline {}.", self.frame_id, new_pipeline_id);
|
debug!("Frame {} created pipeline {}.", self.frame_id, new_pipeline_id);
|
||||||
(old_pipeline_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() {
|
let sandboxed = if self.is_sandboxed() {
|
||||||
IFrameSandboxed
|
IFrameSandboxed
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,6 +145,7 @@ impl HTMLIFrameElement {
|
||||||
|
|
||||||
let window = window_from_node(self);
|
let window = window_from_node(self);
|
||||||
let (old_pipeline_id, new_pipeline_id) = self.generate_new_pipeline_id();
|
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 private_iframe = self.privatebrowsing();
|
||||||
let frame_type = if self.Mozbrowser() { FrameType::MozBrowserIFrame } else { FrameType::IFrame };
|
let frame_type = if self.Mozbrowser() { FrameType::MozBrowserIFrame } else { FrameType::IFrame };
|
||||||
|
|
||||||
|
@ -149,12 +159,13 @@ impl HTMLIFrameElement {
|
||||||
replace: replace,
|
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();
|
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
global_scope
|
global_scope
|
||||||
.constellation_chan()
|
.constellation_chan()
|
||||||
.send(ConstellationMsg::ScriptLoadedAboutBlankInIFrame(load_info, pipeline_sender))
|
.send(ConstellationMsg::ScriptNewIFrame(load_info, pipeline_sender))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let new_layout_info = NewLayoutInfo {
|
let new_layout_info = NewLayoutInfo {
|
||||||
|
@ -168,8 +179,10 @@ impl HTMLIFrameElement {
|
||||||
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
|
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());
|
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
|
||||||
} else {
|
},
|
||||||
|
NavigationType::Regular => {
|
||||||
let load_info = IFrameLoadInfoWithData {
|
let load_info = IFrameLoadInfoWithData {
|
||||||
info: load_info,
|
info: load_info,
|
||||||
load_data: load_data,
|
load_data: load_data,
|
||||||
|
@ -181,6 +194,7 @@ impl HTMLIFrameElement {
|
||||||
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
|
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if PREFS.is_mozbrowser_enabled() {
|
if PREFS.is_mozbrowser_enabled() {
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
||||||
|
@ -192,9 +206,10 @@ impl HTMLIFrameElement {
|
||||||
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
|
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
|
||||||
// TODO: srcdoc
|
// TODO: srcdoc
|
||||||
|
|
||||||
|
let window = window_from_node(self);
|
||||||
|
|
||||||
// https://github.com/whatwg/html/issues/490
|
// https://github.com/whatwg/html/issues/490
|
||||||
if mode == ProcessingMode::FirstTime && !self.upcast::<Element>().has_attribute(&local_name!("src")) {
|
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 = window.dom_manipulation_task_source();
|
||||||
let _ = event_loop.queue(box IFrameLoadEventSteps::new(self),
|
let _ = event_loop.queue(box IFrameLoadEventSteps::new(self),
|
||||||
window.upcast());
|
window.upcast());
|
||||||
|
@ -205,9 +220,15 @@ impl HTMLIFrameElement {
|
||||||
|
|
||||||
// TODO: check ancestor browsing contexts for same URL
|
// 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);
|
let document = document_from_node(self);
|
||||||
self.navigate_or_reload_child_browsing_context(
|
let load_data = LoadData::new(url, creator_pipeline_id, document.get_referrer_policy(), Some(document.url()));
|
||||||
Some(LoadData::new(url, document.get_referrer_policy(), Some(document.url()))), false);
|
self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::Regular, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -225,19 +246,30 @@ impl HTMLIFrameElement {
|
||||||
// Synchronously create a new context and navigate it to about:blank.
|
// Synchronously create a new context and navigate it to about:blank.
|
||||||
let url = ServoUrl::parse("about:blank").unwrap();
|
let url = ServoUrl::parse("about:blank").unwrap();
|
||||||
let document = document_from_node(self);
|
let document = document_from_node(self);
|
||||||
let load_data = LoadData::new(url,
|
let pipeline_id = Some(window_from_node(self).upcast::<GlobalScope>().pipeline_id());
|
||||||
document.get_referrer_policy(),
|
let load_data = LoadData::new(url, pipeline_id, document.get_referrer_policy(), Some(document.url().clone()));
|
||||||
Some(document.url().clone()));
|
self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::InitialAboutBlank, false);
|
||||||
self.navigate_or_reload_child_browsing_context(Some(load_data), 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));
|
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();
|
let mut blocker = self.load_blocker.borrow_mut();
|
||||||
LoadBlocker::terminate(&mut blocker);
|
LoadBlocker::terminate(&mut blocker);
|
||||||
|
}
|
||||||
|
|
||||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
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,
|
fn new_inherited(local_name: LocalName,
|
||||||
|
@ -247,6 +279,7 @@ impl HTMLIFrameElement {
|
||||||
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
||||||
frame_id: FrameId::new(),
|
frame_id: FrameId::new(),
|
||||||
pipeline_id: Cell::new(None),
|
pipeline_id: Cell::new(None),
|
||||||
|
pending_pipeline_id: Cell::new(None),
|
||||||
sandbox: Default::default(),
|
sandbox: Default::default(),
|
||||||
sandbox_allowance: Cell::new(None),
|
sandbox_allowance: Cell::new(None),
|
||||||
load_blocker: DOMRefCell::new(None),
|
load_blocker: DOMRefCell::new(None),
|
||||||
|
@ -296,7 +329,7 @@ impl HTMLIFrameElement {
|
||||||
pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) {
|
pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) {
|
||||||
// TODO(#9592): assert that the load blocker is present at all times when we
|
// 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().
|
// 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
|
// TODO A cross-origin child document would not be easily accessible
|
||||||
// from this script thread. It's unclear how to implement
|
// from this script thread. It's unclear how to implement
|
||||||
|
@ -330,7 +363,8 @@ impl HTMLIFrameElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HTMLIFrameElementLayoutMethods {
|
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_width(&self) -> LengthOrPercentageOrAuto;
|
||||||
fn get_height(&self) -> LengthOrPercentageOrAuto;
|
fn get_height(&self) -> LengthOrPercentageOrAuto;
|
||||||
}
|
}
|
||||||
|
@ -338,12 +372,21 @@ pub trait HTMLIFrameElementLayoutMethods {
|
||||||
impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
|
impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn pipeline_id(self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.unsafe_get()).pipeline_id.get()
|
(*self.unsafe_get()).pipeline_id.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn frame_id(&self) -> FrameId {
|
||||||
|
unsafe {
|
||||||
|
(*self.unsafe_get()).frame_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn get_width(&self) -> LengthOrPercentageOrAuto {
|
fn get_width(&self) -> LengthOrPercentageOrAuto {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -563,7 +606,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
||||||
fn Reload(&self, _hard_reload: bool) -> ErrorResult {
|
fn Reload(&self, _hard_reload: bool) -> ErrorResult {
|
||||||
if self.Mozbrowser() {
|
if self.Mozbrowser() {
|
||||||
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
|
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(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -739,6 +782,7 @@ impl VirtualMethods for HTMLIFrameElement {
|
||||||
// a new iframe. Without this, the constellation gets very
|
// a new iframe. Without this, the constellation gets very
|
||||||
// confused.
|
// confused.
|
||||||
self.pipeline_id.set(None);
|
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 html5ever::{Prefix, Namespace, QualName};
|
||||||
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
||||||
use libc::{self, c_void, uintptr_t};
|
use libc::{self, c_void, uintptr_t};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{FrameId, PipelineId};
|
||||||
use ref_slice::ref_slice;
|
use ref_slice::ref_slice;
|
||||||
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
|
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
|
||||||
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
|
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
|
||||||
|
@ -970,6 +970,7 @@ pub trait LayoutNodeHelpers {
|
||||||
fn image_url(&self) -> Option<ServoUrl>;
|
fn image_url(&self) -> Option<ServoUrl>;
|
||||||
fn canvas_data(&self) -> Option<HTMLCanvasData>;
|
fn canvas_data(&self) -> Option<HTMLCanvasData>;
|
||||||
fn svg_data(&self) -> Option<SVGSVGData>;
|
fn svg_data(&self) -> Option<SVGSVGData>;
|
||||||
|
fn iframe_frame_id(&self) -> FrameId;
|
||||||
fn iframe_pipeline_id(&self) -> PipelineId;
|
fn iframe_pipeline_id(&self) -> PipelineId;
|
||||||
fn opaque(&self) -> OpaqueNode;
|
fn opaque(&self) -> OpaqueNode;
|
||||||
}
|
}
|
||||||
|
@ -1120,6 +1121,12 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
|
||||||
.map(|svg| svg.data())
|
.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 {
|
fn iframe_pipeline_id(&self) -> PipelineId {
|
||||||
let iframe_element = self.downcast::<HTMLIFrameElement>()
|
let iframe_element = self.downcast::<HTMLIFrameElement>()
|
||||||
.expect("not an iframe element!");
|
.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(
|
self.main_thread_script_chan().send(
|
||||||
MainThreadScriptMsg::Navigate(self.upcast::<GlobalScope>().pipeline_id(),
|
MainThreadScriptMsg::Navigate(pipeline_id,
|
||||||
LoadData::new(url, referrer_policy, Some(doc.url())),
|
LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), replace)).unwrap();
|
||||||
replace)).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_fire_timer(&self, timer_id: TimerEventId) {
|
pub fn handle_fire_timer(&self, timer_id: TimerEventId) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ use dom::node::{LayoutNodeHelpers, Node};
|
||||||
use dom::text::Text;
|
use dom::text::Text;
|
||||||
use gfx_traits::ByteIndex;
|
use gfx_traits::ByteIndex;
|
||||||
use html5ever::{LocalName, Namespace};
|
use html5ever::{LocalName, Namespace};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{FrameId, PipelineId};
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress};
|
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress};
|
||||||
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
|
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
|
||||||
|
@ -908,6 +908,11 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
||||||
this.svg_data()
|
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 {
|
fn iframe_pipeline_id(&self) -> PipelineId {
|
||||||
let this = unsafe { self.get_jsmanaged() };
|
let this = unsafe { self.get_jsmanaged() };
|
||||||
this.iframe_pipeline_id()
|
this.iframe_pipeline_id()
|
||||||
|
|
|
@ -46,7 +46,7 @@ use dom::element::Element;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||||
use dom::htmliframeelement::HTMLIFrameElement;
|
use dom::htmliframeelement::{HTMLIFrameElement, NavigationType};
|
||||||
use dom::mutationobserver::MutationObserver;
|
use dom::mutationobserver::MutationObserver;
|
||||||
use dom::node::{Node, NodeDamage, window_from_node};
|
use dom::node::{Node, NodeDamage, window_from_node};
|
||||||
use dom::serviceworker::TrustedServiceWorkerAddress;
|
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::{CompositorEvent, ConstellationControlMsg};
|
||||||
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
|
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
|
||||||
use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
|
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::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource};
|
||||||
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
||||||
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
|
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
|
||||||
|
@ -555,8 +555,8 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread);
|
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread);
|
||||||
|
|
||||||
let origin = MutableOrigin::new(load_data.url.origin());
|
let origin = MutableOrigin::new(load_data.url.origin());
|
||||||
let new_load = InProgressLoad::new(id, frame_id, parent_info, layout_chan, window_size,
|
let new_load = InProgressLoad::new(id, frame_id, parent_info,
|
||||||
load_data.url.clone(), origin);
|
layout_chan, window_size, load_data.url.clone(), origin);
|
||||||
script_thread.start_page_load(new_load, load_data);
|
script_thread.start_page_load(new_load, load_data);
|
||||||
|
|
||||||
let reporter_name = format!("script-reporter-{}", id);
|
let reporter_name = format!("script-reporter-{}", id);
|
||||||
|
@ -827,7 +827,22 @@ impl ScriptThread {
|
||||||
FromConstellation(ConstellationControlMsg::AttachLayout(
|
FromConstellation(ConstellationControlMsg::AttachLayout(
|
||||||
new_layout_info)) => {
|
new_layout_info)) => {
|
||||||
self.profile_event(ScriptThreadEventCategory::AttachLayout, || {
|
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);
|
self.handle_new_layout(new_layout_info, origin);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1043,10 +1058,12 @@ impl ScriptThread {
|
||||||
event),
|
event),
|
||||||
ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
|
||||||
frame_id,
|
frame_id,
|
||||||
new_pipeline_id) =>
|
new_pipeline_id,
|
||||||
|
reason) =>
|
||||||
self.handle_update_pipeline_id(parent_pipeline_id,
|
self.handle_update_pipeline_id(parent_pipeline_id,
|
||||||
frame_id,
|
frame_id,
|
||||||
new_pipeline_id),
|
new_pipeline_id,
|
||||||
|
reason),
|
||||||
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
|
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
|
||||||
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id),
|
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id),
|
||||||
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
|
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
|
||||||
|
@ -1062,8 +1079,6 @@ impl ScriptThread {
|
||||||
self.handle_frame_load_event(parent_id, frame_id, child_id),
|
self.handle_frame_load_event(parent_id, frame_id, child_id),
|
||||||
ConstellationControlMsg::DispatchStorageEvent(pipeline_id, storage, url, key, old_value, new_value) =>
|
ConstellationControlMsg::DispatchStorageEvent(pipeline_id, storage, url, key, old_value, new_value) =>
|
||||||
self.handle_storage_event(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) =>
|
ConstellationControlMsg::ReportCSSError(pipeline_id, filename, line, column, msg) =>
|
||||||
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
||||||
ConstellationControlMsg::Reload(pipeline_id) =>
|
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>) {
|
fn handle_post_message_msg(&self, pipeline_id: PipelineId, origin: Option<ImmutableOrigin>, data: Vec<u8>) {
|
||||||
match { self.documents.borrow().find_window(pipeline_id) } {
|
match { self.documents.borrow().find_window(pipeline_id) } {
|
||||||
None => return warn!("postMessage after pipeline {} closed.", pipeline_id),
|
None => return warn!("postMessage after pipeline {} closed.", pipeline_id),
|
||||||
|
@ -1443,10 +1444,11 @@ impl ScriptThread {
|
||||||
fn handle_update_pipeline_id(&self,
|
fn handle_update_pipeline_id(&self,
|
||||||
parent_pipeline_id: PipelineId,
|
parent_pipeline_id: PipelineId,
|
||||||
frame_id: FrameId,
|
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);
|
let frame_element = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
|
||||||
if let Some(frame_element) = frame_element {
|
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) => {
|
Some(frame_id) => {
|
||||||
let iframe = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
|
let iframe = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
|
||||||
if let Some(iframe) = iframe {
|
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 => {
|
None => {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use SVGSVGData;
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type};
|
use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type};
|
||||||
use html5ever::{Namespace, LocalName};
|
use html5ever::{Namespace, LocalName};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{FrameId, PipelineId};
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -271,6 +271,10 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
|
||||||
|
|
||||||
fn svg_data(&self) -> Option<SVGSVGData>;
|
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
|
/// If this node is an iframe element, returns its pipeline ID. If this node is
|
||||||
/// not an iframe element, fails.
|
/// not an iframe element, fails.
|
||||||
fn iframe_pipeline_id(&self) -> PipelineId;
|
fn iframe_pipeline_id(&self) -> PipelineId;
|
||||||
|
|
|
@ -134,6 +134,8 @@ pub enum LayoutControlMsg {
|
||||||
pub struct LoadData {
|
pub struct LoadData {
|
||||||
/// The URL.
|
/// The URL.
|
||||||
pub url: ServoUrl,
|
pub url: ServoUrl,
|
||||||
|
/// The creator pipeline id if this is an about:blank load.
|
||||||
|
pub creator_pipeline_id: Option<PipelineId>,
|
||||||
/// The method.
|
/// The method.
|
||||||
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
||||||
serialize_with = "::hyper_serde::serialize")]
|
serialize_with = "::hyper_serde::serialize")]
|
||||||
|
@ -152,9 +154,14 @@ pub struct LoadData {
|
||||||
|
|
||||||
impl LoadData {
|
impl LoadData {
|
||||||
/// Create a new `LoadData` object.
|
/// 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 {
|
LoadData {
|
||||||
url: url,
|
url: url,
|
||||||
|
creator_pipeline_id: creator_pipeline_id,
|
||||||
method: Method::Get,
|
method: Method::Get,
|
||||||
headers: Headers::new(),
|
headers: Headers::new(),
|
||||||
data: None,
|
data: None,
|
||||||
|
@ -211,6 +218,15 @@ pub enum DocumentActivity {
|
||||||
FullyActive,
|
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.
|
/// Messages sent from the constellation or layout to the script thread.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum ConstellationControlMsg {
|
pub enum ConstellationControlMsg {
|
||||||
|
@ -249,7 +265,7 @@ pub enum ConstellationControlMsg {
|
||||||
MozBrowserEvent(PipelineId, Option<FrameId>, MozBrowserEvent),
|
MozBrowserEvent(PipelineId, Option<FrameId>, MozBrowserEvent),
|
||||||
/// Updates the current pipeline ID of a given iframe.
|
/// Updates the current pipeline ID of a given iframe.
|
||||||
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
/// 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.
|
/// 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.
|
/// PipelineId is for the parent, FrameId is for the actual frame.
|
||||||
FocusIFrame(PipelineId, FrameId),
|
FocusIFrame(PipelineId, FrameId),
|
||||||
|
@ -274,9 +290,6 @@ pub enum ConstellationControlMsg {
|
||||||
/// Cause a `storage` event to be dispatched at the appropriate window.
|
/// Cause a `storage` event to be dispatched at the appropriate window.
|
||||||
/// The strings are key, old value and new value.
|
/// The strings are key, old value and new value.
|
||||||
DispatchStorageEvent(PipelineId, StorageType, ServoUrl, Option<String>, Option<String>, Option<String>),
|
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
|
/// Report an error from a CSS parser for the given pipeline
|
||||||
ReportCSSError(PipelineId, String, usize, usize, String),
|
ReportCSSError(PipelineId, String, usize, usize, String),
|
||||||
/// Reload the given page.
|
/// Reload the given page.
|
||||||
|
@ -312,7 +325,6 @@ impl fmt::Debug for ConstellationControlMsg {
|
||||||
WebFontLoaded(..) => "WebFontLoaded",
|
WebFontLoaded(..) => "WebFontLoaded",
|
||||||
DispatchFrameLoadEvent { .. } => "DispatchFrameLoadEvent",
|
DispatchFrameLoadEvent { .. } => "DispatchFrameLoadEvent",
|
||||||
DispatchStorageEvent(..) => "DispatchStorageEvent",
|
DispatchStorageEvent(..) => "DispatchStorageEvent",
|
||||||
FramedContentChanged(..) => "FramedContentChanged",
|
|
||||||
ReportCSSError(..) => "ReportCSSError",
|
ReportCSSError(..) => "ReportCSSError",
|
||||||
Reload(..) => "Reload",
|
Reload(..) => "Reload",
|
||||||
WebVREvents(..) => "WebVREvents",
|
WebVREvents(..) => "WebVREvents",
|
||||||
|
|
|
@ -34,8 +34,8 @@ use webrender_traits::ClipId;
|
||||||
pub enum LayoutMsg {
|
pub enum LayoutMsg {
|
||||||
/// Indicates whether this pipeline is currently running animations.
|
/// Indicates whether this pipeline is currently running animations.
|
||||||
ChangeRunningAnimationsState(PipelineId, AnimationState),
|
ChangeRunningAnimationsState(PipelineId, AnimationState),
|
||||||
/// Inform the constellation of the size of the pipeline's viewport.
|
/// Inform the constellation of the size of the frame's viewport.
|
||||||
FrameSizes(Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>),
|
FrameSizes(Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>),
|
||||||
/// Requests that the constellation inform the compositor of the a cursor change.
|
/// Requests that the constellation inform the compositor of the a cursor change.
|
||||||
SetCursor(Cursor),
|
SetCursor(Cursor),
|
||||||
/// Notifies the constellation that the viewport has been constrained in some manner
|
/// Notifies the constellation that the viewport has been constrained in some manner
|
||||||
|
@ -120,8 +120,8 @@ pub enum ScriptMsg {
|
||||||
VisibilityChangeComplete(PipelineId, bool),
|
VisibilityChangeComplete(PipelineId, bool),
|
||||||
/// A load has been requested in an IFrame.
|
/// A load has been requested in an IFrame.
|
||||||
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
|
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
|
||||||
/// A load of `about:blank` has been completed in an IFrame.
|
/// A load of the initial `about:blank` has been completed in an IFrame.
|
||||||
ScriptLoadedAboutBlankInIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
|
ScriptNewIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
|
||||||
/// Requests that the constellation set the contents of the clipboard
|
/// Requests that the constellation set the contents of the clipboard
|
||||||
SetClipboardContents(String),
|
SetClipboardContents(String),
|
||||||
/// Mark a new document as active
|
/// Mark a new document as active
|
||||||
|
|
|
@ -357,7 +357,7 @@ impl Handler {
|
||||||
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
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());
|
let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone());
|
||||||
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
|
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": [
|
||||||
[
|
[
|
||||||
"/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",
|
"56df0cb79a1af927a0209c0bbbb5edb25ccaee5f",
|
||||||
"testharness"
|
"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": [
|
"html/semantics/embedded-content/the-iframe-element/cross_origin_child.html": [
|
||||||
"a42082bb612b280eda5aa598ed750cfce3edd537",
|
"a42082bb612b280eda5aa598ed750cfce3edd537",
|
||||||
"support"
|
"support"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
[matchMedia.html]
|
[matchMedia.html]
|
||||||
|
disabled: true
|
||||||
type: testharness
|
type: testharness
|
||||||
[window.matchMedia exists]
|
[window.matchMedia exists]
|
||||||
expected: FAIL
|
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