aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConnor Brewster <connor.brewster@eagles.oc.edu>2017-04-17 18:48:11 -0500
committerConnor Brewster <connor.brewster@eagles.oc.edu>2017-05-12 11:53:43 -0600
commitd004db95cf135dd5ac49c2b83b55feadcb480372 (patch)
treece7b65297fba8a6aca72d1d2549e1e6150f8462a
parentf5794055108adf508bb0fd16222c4e5cf1d416d8 (diff)
downloadservo-d004db95cf135dd5ac49c2b83b55feadcb480372.tar.gz
servo-d004db95cf135dd5ac49c2b83b55feadcb480372.zip
Make non-initial about:blank loads asynchronous
Don't update iframe pipeline until load completes To preserve the previous functionality of delaying load events when a new navigation is triggered, pending pipeline id represents the current pending load. The load event is only fired if the load message's pipeline id matches the pending pipeline id. Track frame size on Frame instead of Pipeline Disabled matchMedia test Track creator pipeline id
-rw-r--r--components/compositing/compositor.rs3
-rw-r--r--components/constellation/constellation.rs219
-rw-r--r--components/constellation/frame.rs12
-rw-r--r--components/constellation/pipeline.rs7
-rw-r--r--components/layout/display_list_builder.rs6
-rw-r--r--components/layout/fragment.rs10
-rw-r--r--components/msg/constellation_msg.rs1
-rwxr-xr-xcomponents/script/dom/htmlformelement.rs2
-rw-r--r--components/script/dom/htmliframeelement.rs134
-rw-r--r--components/script/dom/node.rs9
-rw-r--r--components/script/dom/window.rs6
-rw-r--r--components/script/layout_wrapper.rs7
-rw-r--r--components/script/script_thread.rs54
-rw-r--r--components/script_layout_interface/wrapper_traits.rs6
-rw-r--r--components/script_traits/lib.rs24
-rw-r--r--components/script_traits/script_msg.rs8
-rw-r--r--components/webdriver_server/lib.rs2
-rw-r--r--tests/wpt/mozilla/meta/css/matchMedia.html.ini1
18 files changed, 308 insertions, 203 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index eb2a964ac23..cbe8e31667e 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -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) {
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 731486c4e16..01a59070730 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -101,7 +101,7 @@ use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState,
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
-use script_traits::{SWManagerMsg, ScopeThings, WindowSizeType};
+use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WindowSizeType};
use serde::{Deserialize, Serialize};
use servo_config::opts;
use servo_config::prefs::PREFS;
@@ -599,17 +599,31 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let (event_loop, host) = match sandbox {
IFrameSandboxState::IFrameSandboxed => (None, None),
- IFrameSandboxState::IFrameUnsandboxed => match reg_host(&load_data.url) {
- None => (None, None),
- Some(host) => {
- let event_loop = self.event_loops.get(&top_level_frame_id)
- .and_then(|map| map.get(&host))
- .and_then(|weak| weak.upgrade());
- match event_loop {
- None => (None, Some(host)),
- Some(event_loop) => (Some(event_loop.clone()), None),
+ IFrameSandboxState::IFrameUnsandboxed => {
+ // If this is an about:blank load, it must share the creator's event loop.
+ // This must match the logic in the script thread when determining the proper origin.
+ if load_data.url.as_str() != "about:blank" {
+ match reg_host(&load_data.url) {
+ None => (None, None),
+ Some(host) => {
+ let event_loop = self.event_loops.get(&top_level_frame_id)
+ .and_then(|map| map.get(&host))
+ .and_then(|weak| weak.upgrade());
+ match event_loop {
+ None => (None, Some(host)),
+ Some(event_loop) => (Some(event_loop.clone()), None),
+ }
+ },
}
- },
+ } else if let Some(parent) = parent_info
+ .and_then(|(pipeline_id, _)| self.pipelines.get(&pipeline_id)) {
+ (Some(parent.event_loop.clone()), None)
+ } else if let Some(creator) = load_data.creator_pipeline_id
+ .and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) {
+ (Some(creator.event_loop.clone()), None)
+ } else {
+ (None, None)
+ }
},
};
@@ -735,7 +749,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
/// Create a new frame and update the internal bookkeeping.
- fn new_frame(&mut self, frame_id: FrameId, pipeline_id: PipelineId, load_data: LoadData) {
+ fn new_frame(&mut self,
+ frame_id: FrameId,
+ pipeline_id: PipelineId,
+ load_data: LoadData) {
let frame = Frame::new(frame_id, pipeline_id, load_data);
self.frames.insert(frame_id, frame);
@@ -915,11 +932,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
load_info.info.new_pipeline_id);
self.handle_script_loaded_url_in_iframe_msg(load_info);
}
- FromScriptMsg::ScriptLoadedAboutBlankInIFrame(load_info, lc) => {
+ FromScriptMsg::ScriptNewIFrame(load_info, layout_sender) => {
debug!("constellation got loaded `about:blank` in iframe message {:?} {:?}",
load_info.parent_pipeline_id,
load_info.new_pipeline_id);
- self.handle_script_loaded_about_blank_in_iframe_msg(load_info, lc);
+ self.handle_script_new_iframe(load_info, layout_sender);
}
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
self.handle_change_running_animations_state(pipeline_id, animation_state)
@@ -1277,10 +1294,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Notify the browser chrome that the pipeline has failed
self.trigger_mozbrowsererror(top_level_frame_id, reason, backtrace);
- let pipeline_id = self.frames.get(&top_level_frame_id).map(|frame| frame.pipeline_id);
- let pipeline_url = pipeline_id.and_then(|id| self.pipelines.get(&id).map(|pipeline| pipeline.url.clone()));
- let parent_info = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.parent_info));
- let window_size = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.size));
+ let (window_size, pipeline_id) = {
+ let frame = self.frames.get(&top_level_frame_id);
+ let window_size = frame.and_then(|frame| frame.size);
+ let pipeline_id = frame.map(|frame| frame.pipeline_id);
+ (window_size, pipeline_id)
+ };
+
+ let (pipeline_url, parent_info) = {
+ let pipeline = pipeline_id.and_then(|id| self.pipelines.get(&id));
+ let pipeline_url = pipeline.map(|pipeline| pipeline.url.clone());
+ let parent_info = pipeline.and_then(|pipeline| pipeline.parent_info);
+ (pipeline_url, parent_info)
+ };
self.close_frame_children(top_level_frame_id, DiscardBrowsingContext::No, ExitPipelineMode::Force);
@@ -1295,7 +1321,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
warn!("creating replacement pipeline for about:failure");
let new_pipeline_id = PipelineId::new();
- let load_data = LoadData::new(failure_url, None, None);
+ let load_data = LoadData::new(failure_url, None, None, None);
let sandbox = IFrameSandboxState::IFrameSandboxed;
self.new_pipeline(new_pipeline_id, top_level_frame_id, parent_info,
window_size, load_data.clone(), sandbox, false);
@@ -1340,7 +1366,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let window_size = self.window_size.initial_viewport;
let root_pipeline_id = PipelineId::new();
let root_frame_id = self.root_frame_id;
- let load_data = LoadData::new(url.clone(), None, None);
+ let load_data = LoadData::new(url.clone(), None, None, None);
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
self.new_pipeline(root_pipeline_id, root_frame_id, None, Some(window_size), load_data.clone(), sandbox, false);
self.handle_load_start_msg(root_pipeline_id);
@@ -1353,29 +1379,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
fn handle_frame_size_msg(&mut self,
- iframe_sizes: Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>) {
- for (pipeline_id, size) in iframe_sizes {
- let result = {
- let pipeline = match self.pipelines.get_mut(&pipeline_id) {
- Some(pipeline) => pipeline,
- None => continue,
- };
-
- if pipeline.size == Some(size) {
- continue;
- }
-
- pipeline.size = Some(size);
- let msg = ConstellationControlMsg::Resize(pipeline_id, WindowSizeData {
- initial_viewport: size,
- device_pixel_ratio: self.window_size.device_pixel_ratio,
- }, WindowSizeType::Initial);
-
- pipeline.event_loop.send(msg)
+ iframe_sizes: Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>) {
+ for (frame_id, size) in iframe_sizes {
+ let window_size = WindowSizeData {
+ initial_viewport: size,
+ device_pixel_ratio: self.window_size.device_pixel_ratio,
};
- if let Err(e) = result {
- self.handle_send_error(pipeline_id, e);
- }
+
+ self.resize_frame(window_size, WindowSizeType::Initial, frame_id);
}
}
@@ -1423,12 +1434,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};
// TODO - loaddata here should have referrer info (not None, None)
- LoadData::new(url, None, None)
+ LoadData::new(url, Some(source_pipeline.id), None, None)
});
let is_private = load_info.info.is_private || source_pipeline.is_private;
- let window_size = old_pipeline.and_then(|old_pipeline| old_pipeline.size);
+ let window_size = self.frames.get(&load_info.info.frame_id).and_then(|frame| frame.size);
(load_data, window_size, is_private)
};
@@ -1456,9 +1467,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
is_private);
}
- fn handle_script_loaded_about_blank_in_iframe_msg(&mut self,
- load_info: IFrameLoadInfo,
- layout_sender: IpcSender<LayoutControlMsg>) {
+ fn handle_script_new_iframe(&mut self,
+ load_info: IFrameLoadInfo,
+ layout_sender: IpcSender<LayoutControlMsg>) {
let IFrameLoadInfo {
parent_pipeline_id,
new_pipeline_id,
@@ -1486,12 +1497,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.compositor_proxy.clone_compositor_proxy(),
is_private || parent_pipeline.is_private,
url.clone(),
- None,
parent_pipeline.visible)
};
// TODO: Referrer?
- let load_data = LoadData::new(url, None, None);
+ let load_data = LoadData::new(url, Some(parent_pipeline_id), None, None);
let replace_instant = if replace {
self.frames.get(&frame_id).map(|frame| frame.instant)
@@ -1641,7 +1651,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// changes would be overridden by changing the subframe associated with source_id.
// Create the new pipeline
- let window_size = self.pipelines.get(&source_id).and_then(|source| source.size);
+ let window_size = self.frames.get(&root_frame_id).and_then(|frame| frame.size);
let new_pipeline_id = PipelineId::new();
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
let replace_instant = if replace {
@@ -1959,7 +1969,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
},
WebDriverCommandMsg::Refresh(pipeline_id, reply) => {
let load_data = match self.pipelines.get(&pipeline_id) {
- Some(pipeline) => LoadData::new(pipeline.url.clone(), None, None),
+ Some(pipeline) => LoadData::new(pipeline.url.clone(), None, None, None),
None => return warn!("Pipeline {:?} Refresh after closure.", pipeline_id),
};
self.load_url_for_webdriver(pipeline_id, load_data, reply, true);
@@ -2019,8 +2029,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let load_data = entry.load_data;
let (parent_info, window_size, is_private) = match self.frames.get(&frame_id) {
Some(frame) => match self.pipelines.get(&frame.pipeline_id) {
- Some(pipeline) => (pipeline.parent_info, pipeline.size, pipeline.is_private),
- None => (None, None, false),
+ Some(pipeline) => (pipeline.parent_info, frame.size, pipeline.is_private),
+ None => (None, frame.size, false),
},
None => return warn!("no frame to traverse"),
};
@@ -2101,7 +2111,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Update the owning iframe to point to the new pipeline id.
// This makes things like contentDocument work correctly.
if let Some((parent_pipeline_id, _)) = parent_info {
- let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, frame_id, pipeline_id);
+ let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
+ frame_id, pipeline_id, UpdatePipelineIdReason::Traversal);
let result = match self.pipelines.get(&parent_pipeline_id) {
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
Some(pipeline) => pipeline.event_loop.send(msg),
@@ -2245,7 +2256,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
if new_frame {
- self.new_frame(frame_change.frame_id, frame_change.new_pipeline_id, frame_change.load_data);
+ self.new_frame(frame_change.frame_id,
+ frame_change.new_pipeline_id,
+ frame_change.load_data);
self.update_activity(frame_change.new_pipeline_id);
self.notify_history_changed(frame_change.new_pipeline_id);
};
@@ -2275,7 +2288,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
if let Some((parent_pipeline_id, _)) = pipeline.parent_info {
if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) {
- let msg = ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, pipeline.frame_id);
+ let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
+ pipeline.frame_id, pipeline_id, UpdatePipelineIdReason::Navigation);
let _ = parent_pipeline.event_loop.send(msg);
}
}
@@ -2298,45 +2312,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn handle_window_size_msg(&mut self, new_size: WindowSizeData, size_type: WindowSizeType) {
debug!("handle_window_size_msg: {:?}", new_size.initial_viewport.to_untyped());
- if let Some(frame) = self.frames.get(&self.root_frame_id) {
- // Send Resize (or ResizeInactive) messages to each
- // pipeline in the frame tree.
- let pipeline_id = frame.pipeline_id;
- let pipeline = match self.pipelines.get(&pipeline_id) {
- None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
- Some(pipeline) => pipeline,
- };
- let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
- pipeline.id,
- new_size,
- size_type
- ));
- let pipelines = frame.prev.iter().chain(frame.next.iter())
- .filter_map(|entry| entry.pipeline_id)
- .filter_map(|pipeline_id| self.pipelines.get(&pipeline_id));
- for pipeline in pipelines {
- let _ = pipeline.event_loop.send(ConstellationControlMsg::ResizeInactive(
- pipeline.id,
- new_size
- ));
- }
- }
-
- // Send resize message to any pending pipelines that aren't loaded yet.
- for pending_frame in &self.pending_frames {
- let pipeline_id = pending_frame.new_pipeline_id;
- let pipeline = match self.pipelines.get(&pipeline_id) {
- None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; }
- Some(pipeline) => pipeline,
- };
- if pipeline.parent_info.is_none() {
- let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
- pipeline.id,
- new_size,
- size_type
- ));
- }
- }
+ let frame_id = self.root_frame_id;
+ self.resize_frame(new_size, size_type, frame_id);
if let Some(resize_channel) = self.webdriver.resize_channel.take() {
let _ = resize_channel.send(new_size);
@@ -2422,7 +2399,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// size for the pipeline, then its painting should be up to date. If the constellation
// *hasn't* received a size, it could be that the layer was hidden by script before the
// compositor discovered it, so we just don't check the layer.
- if let Some(size) = pipeline.size {
+ if let Some(size) = frame.size {
// If the rectangle for this pipeline is zero sized, it will
// never be painted. In this case, don't query the layout
// thread as it won't contribute to the final output image.
@@ -2509,6 +2486,54 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.set_activity(pipeline_id, self.get_activity(pipeline_id));
}
+ /// Handle updating the size of a frame. This notifies every pipeline in the frame of the new
+ /// size.
+ fn resize_frame(&mut self, new_size: WindowSizeData, size_type: WindowSizeType, frame_id: FrameId) {
+ if let Some(frame) = self.frames.get_mut(&frame_id) {
+ frame.size = Some(new_size.initial_viewport);
+ }
+
+ if let Some(frame) = self.frames.get(&frame_id) {
+ // Send Resize (or ResizeInactive) messages to each
+ // pipeline in the frame tree.
+ let pipeline_id = frame.pipeline_id;
+ let pipeline = match self.pipelines.get(&pipeline_id) {
+ None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
+ Some(pipeline) => pipeline,
+ };
+ let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
+ pipeline.id,
+ new_size,
+ size_type
+ ));
+ let pipelines = frame.prev.iter().chain(frame.next.iter())
+ .filter_map(|entry| entry.pipeline_id)
+ .filter_map(|pipeline_id| self.pipelines.get(&pipeline_id));
+ for pipeline in pipelines {
+ let _ = pipeline.event_loop.send(ConstellationControlMsg::ResizeInactive(
+ pipeline.id,
+ new_size
+ ));
+ }
+ }
+
+ // Send resize message to any pending pipelines that aren't loaded yet.
+ for pending_frame in &self.pending_frames {
+ let pipeline_id = pending_frame.new_pipeline_id;
+ let pipeline = match self.pipelines.get(&pipeline_id) {
+ None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; }
+ Some(pipeline) => pipeline,
+ };
+ if pipeline.frame_id == frame_id {
+ let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
+ pipeline.id,
+ new_size,
+ size_type
+ ));
+ }
+ }
+ }
+
fn clear_joint_session_future(&mut self, frame_id: FrameId) {
let frame_ids: Vec<FrameId> = self.full_frame_tree_iter(frame_id)
.map(|frame| frame.id)
@@ -2652,7 +2677,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.pipelines.get(&frame.pipeline_id).map(|pipeline: &Pipeline| {
let mut frame_tree = SendableFrameTree {
pipeline: pipeline.to_sendable(),
- size: pipeline.size,
+ size: frame.size,
children: vec!(),
};
diff --git a/components/constellation/frame.rs b/components/constellation/frame.rs
index 74aabee2de0..ac85c14d214 100644
--- a/components/constellation/frame.rs
+++ b/components/constellation/frame.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use 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,
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index aa380a8e5c1..60401f4313c 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -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,
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 472a34529ca..5f9a783c896 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -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);
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 9f98ff318ec..c4dfefcc696 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -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,
}
}
diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs
index 5b5110099f6..02d4157f20c 100644
--- a/components/msg/constellation_msg.rs
+++ b/components/msg/constellation_msg.rs
@@ -310,3 +310,4 @@ pub enum FrameType {
IFrame,
MozBrowserIFrame,
}
+
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 4397364f68f..53867c755f8 100755
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -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) {
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index e1a7fb7c672..554dc82f7d3 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -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;
@@ -70,6 +70,12 @@ bitflags! {
}
#[derive(PartialEq)]
+pub enum NavigationType {
+ InitialAboutBlank,
+ Regular,
+}
+
+#[derive(PartialEq)]
enum ProcessingMode {
FirstTime,
NotFirstTime,
@@ -80,6 +86,7 @@ pub struct HTMLIFrameElement {
htmlelement: HTMLElement,
frame_id: FrameId,
pipeline_id: Cell<Option<PipelineId>>,
+ pending_pipeline_id: Cell<Option<PipelineId>>,
sandbox: MutNullableJS<DOMTokenList>,
sandbox_allowance: Cell<Option<SandboxAllowance>>,
load_blocker: DOMRefCell<Option<LoadBlocker>>,
@@ -108,12 +115,14 @@ impl HTMLIFrameElement {
pub fn generate_new_pipeline_id(&self) -> (Option<PipelineId>, PipelineId) {
let old_pipeline_id = self.pipeline_id.get();
let new_pipeline_id = PipelineId::new();
- self.pipeline_id.set(Some(new_pipeline_id));
debug!("Frame {} created pipeline {}.", self.frame_id, new_pipeline_id);
(old_pipeline_id, new_pipeline_id)
}
- pub fn navigate_or_reload_child_browsing_context(&self, load_data: Option<LoadData>, replace: bool) {
+ pub fn navigate_or_reload_child_browsing_context(&self,
+ load_data: Option<LoadData>,
+ nav_type: NavigationType,
+ replace: bool) {
let sandboxed = if self.is_sandboxed() {
IFrameSandboxed
} else {
@@ -136,6 +145,7 @@ impl HTMLIFrameElement {
let window = window_from_node(self);
let (old_pipeline_id, new_pipeline_id) = self.generate_new_pipeline_id();
+ self.pending_pipeline_id.set(Some(new_pipeline_id));
let private_iframe = self.privatebrowsing();
let frame_type = if self.Mozbrowser() { FrameType::MozBrowserIFrame } else { FrameType::IFrame };
@@ -149,37 +159,41 @@ impl HTMLIFrameElement {
replace: replace,
};
- if load_data.as_ref().map_or(false, |d| d.url.as_str() == "about:blank") {
- let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
-
- global_scope
- .constellation_chan()
- .send(ConstellationMsg::ScriptLoadedAboutBlankInIFrame(load_info, pipeline_sender))
- .unwrap();
-
- let new_layout_info = NewLayoutInfo {
- parent_info: Some((global_scope.pipeline_id(), frame_type)),
- new_pipeline_id: new_pipeline_id,
- frame_id: self.frame_id,
- load_data: load_data.unwrap(),
- pipeline_port: pipeline_receiver,
- content_process_shutdown_chan: None,
- window_size: None,
- layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
- };
-
- ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
- } else {
- let load_info = IFrameLoadInfoWithData {
- info: load_info,
- load_data: load_data,
- old_pipeline_id: old_pipeline_id,
- sandbox: sandboxed,
- };
- global_scope
+ match nav_type {
+ NavigationType::InitialAboutBlank => {
+ let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
+
+ global_scope
+ .constellation_chan()
+ .send(ConstellationMsg::ScriptNewIFrame(load_info, pipeline_sender))
+ .unwrap();
+
+ let new_layout_info = NewLayoutInfo {
+ parent_info: Some((global_scope.pipeline_id(), frame_type)),
+ new_pipeline_id: new_pipeline_id,
+ frame_id: self.frame_id,
+ load_data: load_data.unwrap(),
+ pipeline_port: pipeline_receiver,
+ content_process_shutdown_chan: None,
+ window_size: None,
+ layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
+ };
+
+ self.pipeline_id.set(Some(new_pipeline_id));
+ ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
+ },
+ NavigationType::Regular => {
+ let load_info = IFrameLoadInfoWithData {
+ info: load_info,
+ load_data: load_data,
+ old_pipeline_id: old_pipeline_id,
+ sandbox: sandboxed,
+ };
+ global_scope
.constellation_chan()
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
.unwrap();
+ }
}
if PREFS.is_mozbrowser_enabled() {
@@ -192,9 +206,10 @@ impl HTMLIFrameElement {
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
// TODO: srcdoc
+ let window = window_from_node(self);
+
// https://github.com/whatwg/html/issues/490
if mode == ProcessingMode::FirstTime && !self.upcast::<Element>().has_attribute(&local_name!("src")) {
- let window = window_from_node(self);
let event_loop = window.dom_manipulation_task_source();
let _ = event_loop.queue(box IFrameLoadEventSteps::new(self),
window.upcast());
@@ -205,9 +220,15 @@ impl HTMLIFrameElement {
// TODO: check ancestor browsing contexts for same URL
+ let creator_pipeline_id = if url.as_str() == "about:blank" {
+ Some(window.upcast::<GlobalScope>().pipeline_id())
+ } else {
+ None
+ };
+
let document = document_from_node(self);
- self.navigate_or_reload_child_browsing_context(
- Some(LoadData::new(url, document.get_referrer_policy(), Some(document.url()))), false);
+ let load_data = LoadData::new(url, creator_pipeline_id, document.get_referrer_policy(), Some(document.url()));
+ self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::Regular, false);
}
#[allow(unsafe_code)]
@@ -225,19 +246,30 @@ impl HTMLIFrameElement {
// Synchronously create a new context and navigate it to about:blank.
let url = ServoUrl::parse("about:blank").unwrap();
let document = document_from_node(self);
- let load_data = LoadData::new(url,
- document.get_referrer_policy(),
- Some(document.url().clone()));
- self.navigate_or_reload_child_browsing_context(Some(load_data), false);
+ let pipeline_id = Some(window_from_node(self).upcast::<GlobalScope>().pipeline_id());
+ let load_data = LoadData::new(url, pipeline_id, document.get_referrer_policy(), Some(document.url().clone()));
+ self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::InitialAboutBlank, false);
}
- pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId) {
+ pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId, reason: UpdatePipelineIdReason) {
+ if self.pending_pipeline_id.get() != Some(new_pipeline_id) && reason == UpdatePipelineIdReason::Navigation {
+ return;
+ }
+
self.pipeline_id.set(Some(new_pipeline_id));
- let mut blocker = self.load_blocker.borrow_mut();
- LoadBlocker::terminate(&mut blocker);
+ // Only terminate the load blocker if the pipeline id was updated due to a traversal.
+ // The load blocker will be terminated for a navigation in iframe_load_event_steps.
+ if reason == UpdatePipelineIdReason::Traversal {
+ let mut blocker = self.load_blocker.borrow_mut();
+ LoadBlocker::terminate(&mut blocker);
+ }
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
+ let window = window_from_node(self);
+ window.reflow(ReflowGoal::ForDisplay,
+ ReflowQueryType::NoQuery,
+ ReflowReason::FramedContentChanged);
}
fn new_inherited(local_name: LocalName,
@@ -247,6 +279,7 @@ impl HTMLIFrameElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
frame_id: FrameId::new(),
pipeline_id: Cell::new(None),
+ pending_pipeline_id: Cell::new(None),
sandbox: Default::default(),
sandbox_allowance: Cell::new(None),
load_blocker: DOMRefCell::new(None),
@@ -296,7 +329,7 @@ impl HTMLIFrameElement {
pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) {
// TODO(#9592): assert that the load blocker is present at all times when we
// can guarantee that it's created for the case of iframe.reload().
- if Some(loaded_pipeline) != self.pipeline_id() { return; }
+ if Some(loaded_pipeline) != self.pending_pipeline_id.get() { return; }
// TODO A cross-origin child document would not be easily accessible
// from this script thread. It's unclear how to implement
@@ -330,7 +363,8 @@ impl HTMLIFrameElement {
}
pub trait HTMLIFrameElementLayoutMethods {
- fn pipeline_id(self) -> Option<PipelineId>;
+ fn pipeline_id(&self) -> Option<PipelineId>;
+ fn frame_id(&self) -> FrameId;
fn get_width(&self) -> LengthOrPercentageOrAuto;
fn get_height(&self) -> LengthOrPercentageOrAuto;
}
@@ -338,12 +372,21 @@ pub trait HTMLIFrameElementLayoutMethods {
impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
#[inline]
#[allow(unsafe_code)]
- fn pipeline_id(self) -> Option<PipelineId> {
+ fn pipeline_id(&self) -> Option<PipelineId> {
unsafe {
(*self.unsafe_get()).pipeline_id.get()
}
}
+ #[inline]
+ #[allow(unsafe_code)]
+ fn frame_id(&self) -> FrameId {
+ unsafe {
+ (*self.unsafe_get()).frame_id
+ }
+ }
+
+
#[allow(unsafe_code)]
fn get_width(&self) -> LengthOrPercentageOrAuto {
unsafe {
@@ -563,7 +606,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
fn Reload(&self, _hard_reload: bool) -> ErrorResult {
if self.Mozbrowser() {
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
- self.navigate_or_reload_child_browsing_context(None, true);
+ self.navigate_or_reload_child_browsing_context(None, NavigationType::Regular, true);
}
Ok(())
} else {
@@ -739,6 +782,7 @@ impl VirtualMethods for HTMLIFrameElement {
// a new iframe. Without this, the constellation gets very
// confused.
self.pipeline_id.set(None);
+ self.pending_pipeline_id.set(None);
}
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 31e48b5b695..81a06850757 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -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!");
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 6b8857b81b1..137f82cfab8 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -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) {
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index 7ae6a7e621e..278856c67f3 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -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()
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 96167cec236..2f065a90d91 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -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 => {
diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs
index e39d27614c5..80b05a285b7 100644
--- a/components/script_layout_interface/wrapper_traits.rs
+++ b/components/script_layout_interface/wrapper_traits.rs
@@ -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;
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 954c1386fa2..29baf8821e6 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -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",
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index 47a7b103c8c..0402e3ddad6 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -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
diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs
index 210c5b0f9c8..250ad21813b 100644
--- a/components/webdriver_server/lib.rs
+++ b/components/webdriver_server/lib.rs
@@ -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();
diff --git a/tests/wpt/mozilla/meta/css/matchMedia.html.ini b/tests/wpt/mozilla/meta/css/matchMedia.html.ini
index 8c726be5a03..dded0e3276d 100644
--- a/tests/wpt/mozilla/meta/css/matchMedia.html.ini
+++ b/tests/wpt/mozilla/meta/css/matchMedia.html.ini
@@ -1,4 +1,5 @@
[matchMedia.html]
+ disabled: true
type: testharness
[window.matchMedia exists]
expected: FAIL