diff options
-rw-r--r-- | components/compositing/compositor.rs | 3 | ||||
-rw-r--r-- | components/constellation/constellation.rs | 219 | ||||
-rw-r--r-- | components/constellation/frame.rs | 12 | ||||
-rw-r--r-- | components/constellation/pipeline.rs | 7 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 6 | ||||
-rw-r--r-- | components/layout/fragment.rs | 10 | ||||
-rw-r--r-- | components/msg/constellation_msg.rs | 1 | ||||
-rwxr-xr-x | components/script/dom/htmlformelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 134 | ||||
-rw-r--r-- | components/script/dom/node.rs | 9 | ||||
-rw-r--r-- | components/script/dom/window.rs | 6 | ||||
-rw-r--r-- | components/script/layout_wrapper.rs | 7 | ||||
-rw-r--r-- | components/script/script_thread.rs | 54 | ||||
-rw-r--r-- | components/script_layout_interface/wrapper_traits.rs | 6 | ||||
-rw-r--r-- | components/script_traits/lib.rs | 24 | ||||
-rw-r--r-- | components/script_traits/script_msg.rs | 8 | ||||
-rw-r--r-- | components/webdriver_server/lib.rs | 2 | ||||
-rw-r--r-- | tests/wpt/mozilla/meta/css/matchMedia.html.ini | 1 |
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 |