From 899aa0c371d96b040ac5923be333d786033067ae Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Tue, 18 Jul 2017 08:16:45 +0200 Subject: [PATCH] Add TopLevelBrowsingContextId to messages between Embedder <-> Compositor <-> Constellation --- components/compositing/compositor.rs | 136 +++++++------------- components/compositing/compositor_thread.rs | 34 ++--- components/compositing/windowing.rs | 38 +++--- components/constellation/constellation.rs | 68 +++++++--- components/script_traits/lib.rs | 2 +- ports/glutin/window.rs | 30 ++--- 6 files changed, 148 insertions(+), 160 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 4dd167fa925..b9d536d295f 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -11,19 +11,17 @@ use gfx_traits::Epoch; use gleam::gl; use image::{DynamicImage, ImageFormat, RgbImage}; use ipc_channel::ipc::{self, IpcSharedMemory}; -use msg::constellation_msg::{Key, KeyModifiers, KeyState}; -use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId, TraversalDirection}; +use msg::constellation_msg::{KeyState, PipelineId, PipelineIndex, PipelineNamespaceId}; use net_traits::image::base::{Image, PixelFormat}; use profile_traits::time::{self, ProfilerCategory, profile}; use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg}; -use script_traits::{ConstellationMsg, LayoutControlMsg, LoadData, MouseButton}; +use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton}; use script_traits::{MouseEventType, ScrollState}; use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId, WindowSizeData, WindowSizeType}; use script_traits::CompositorEvent::{self, MouseMoveEvent, MouseButtonEvent, TouchEvent, TouchpadPressureEvent}; use servo_config::opts; use servo_config::prefs::PREFS; use servo_geometry::DeviceIndependentPixel; -use servo_url::ServoUrl; use std::collections::HashMap; use std::fs::File; use std::rc::Rc; @@ -460,8 +458,8 @@ impl IOCompositor { self.change_running_animations_state(pipeline_id, animation_state); } - (Msg::ChangePageTitle(pipeline_id, title), ShutdownState::NotShuttingDown) => { - self.change_page_title(pipeline_id, title); + (Msg::ChangePageTitle(top_level_browsing_context, title), ShutdownState::NotShuttingDown) => { + self.window.set_page_title(top_level_browsing_context, title); } (Msg::SetFrameTree(frame_tree), @@ -475,55 +473,56 @@ impl IOCompositor { self.scroll_fragment_to_point(scroll_root_id, point); } - (Msg::MoveTo(point), + (Msg::MoveTo(top_level_browsing_context_id, point), ShutdownState::NotShuttingDown) => { - self.window.set_position(point); + self.window.set_position(top_level_browsing_context_id, point); } - (Msg::ResizeTo(size), + (Msg::ResizeTo(top_level_browsing_context_id, size), ShutdownState::NotShuttingDown) => { - self.window.set_inner_size(size); + self.window.set_inner_size(top_level_browsing_context_id, size); } - (Msg::GetClientWindow(send), + (Msg::GetClientWindow(top_level_browsing_context_id, send), ShutdownState::NotShuttingDown) => { - let rect = self.window.client_window(); + let rect = self.window.client_window(top_level_browsing_context_id); if let Err(e) = send.send(rect) { warn!("Sending response to get client window failed ({}).", e); } } - (Msg::Status(message), ShutdownState::NotShuttingDown) => { - self.window.status(message); + (Msg::Status(top_level_browsing_context_id, message), + ShutdownState::NotShuttingDown) => { + self.window.status(top_level_browsing_context_id, message); } - (Msg::LoadStart, ShutdownState::NotShuttingDown) => { - self.window.load_start(); + (Msg::LoadStart(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => { + self.window.load_start(top_level_browsing_context_id); } - (Msg::LoadComplete, ShutdownState::NotShuttingDown) => { + (Msg::LoadComplete(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => { // If we're painting in headless mode, schedule a recomposite. if opts::get().output_file.is_some() || opts::get().exit_after_load { self.composite_if_necessary(CompositingReason::Headless); } // Inform the embedder that the load has finished. - // - // TODO(pcwalton): Specify which frame's load completed. - self.window.load_end(); + self.window.load_end(top_level_browsing_context_id); } - (Msg::AllowNavigation(url, response_chan), ShutdownState::NotShuttingDown) => { - self.window.allow_navigation(url, response_chan); + (Msg::AllowNavigation(top_level_browsing_context_id, url, response_chan), + ShutdownState::NotShuttingDown) => { + self.window.allow_navigation(top_level_browsing_context_id, url, response_chan); } (Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => { self.composition_request = CompositionRequest::CompositeNow(reason) } - (Msg::KeyEvent(ch, key, state, modified), ShutdownState::NotShuttingDown) => { + (Msg::KeyEvent(top_level_browsing_context_id, ch, key, state, modified), + ShutdownState::NotShuttingDown) => { if state == KeyState::Pressed { - self.window.handle_key(ch, key, modified); + self.window.handle_key(top_level_browsing_context_id, ch, key, modified); } } @@ -567,16 +566,16 @@ impl IOCompositor { self.composite_if_necessary(CompositingReason::Headless); } - (Msg::NewFavicon(url), ShutdownState::NotShuttingDown) => { - self.window.set_favicon(url); + (Msg::NewFavicon(top_level_browsing_context_id, url), ShutdownState::NotShuttingDown) => { + self.window.set_favicon(top_level_browsing_context_id, url); } - (Msg::HeadParsed, ShutdownState::NotShuttingDown) => { - self.window.head_parsed(); + (Msg::HeadParsed(top_level_browsing_context_id), ShutdownState::NotShuttingDown) => { + self.window.head_parsed(top_level_browsing_context_id); } - (Msg::HistoryChanged(entries, current), ShutdownState::NotShuttingDown) => { - self.window.history_changed(entries, current); + (Msg::HistoryChanged(top_level_browsing_context_id, entries, current), ShutdownState::NotShuttingDown) => { + self.window.history_changed(top_level_browsing_context_id, entries, current); } (Msg::PipelineVisibilityChanged(pipeline_id, visible), ShutdownState::NotShuttingDown) => { @@ -606,8 +605,8 @@ impl IOCompositor { func(); } - (Msg::SetFullscreenState(state), ShutdownState::NotShuttingDown) => { - self.window.set_fullscreen_state(state); + (Msg::SetFullscreenState(top_level_browsing_context_id, state), ShutdownState::NotShuttingDown) => { + self.window.set_fullscreen_state(top_level_browsing_context_id, state); } // When we are shutting_down, we need to avoid performing operations @@ -665,15 +664,6 @@ impl IOCompositor { } } - fn change_page_title(&mut self, pipeline_id: PipelineId, title: Option) { - let set_title = self.root_pipeline.as_ref().map_or(false, |root_pipeline| { - root_pipeline.id == pipeline_id - }); - if set_title { - self.window.set_page_title(title); - } - } - fn set_frame_tree(&mut self, frame_tree: &SendableFrameTree) { debug!("Setting the frame tree for pipeline {}", frame_tree.pipeline.id); @@ -743,8 +733,11 @@ impl IOCompositor { self.on_resize_window_event(size); } - WindowEvent::LoadUrl(url_string) => { - self.on_load_url_window_event(url_string); + WindowEvent::LoadUrl(top_level_browsing_context_id, url) => { + let msg = ConstellationMsg::LoadUrl(top_level_browsing_context_id, url); + if let Err(e) = self.constellation_chan.send(msg) { + warn!("Sending load url to constellation failed ({}).", e); + } } WindowEvent::MouseWindowEventClass(mouse_window_event) => { @@ -788,8 +781,11 @@ impl IOCompositor { self.on_pinch_zoom_window_event(magnification); } - WindowEvent::Navigation(direction) => { - self.on_navigation_window_event(direction); + WindowEvent::Navigation(top_level_browsing_context_id, direction) => { + let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction); + if let Err(e) = self.constellation_chan.send(msg) { + warn!("Sending navigation to constellation failed ({}).", e); + } } WindowEvent::TouchpadPressure(cursor, pressure, stage) => { @@ -797,7 +793,10 @@ impl IOCompositor { } WindowEvent::KeyEvent(ch, key, state, modifiers) => { - self.on_key_event(ch, key, state, modifiers); + let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers); + if let Err(e) = self.constellation_chan.send(msg) { + warn!("Sending key event to constellation failed ({}).", e); + } } WindowEvent::Quit => { @@ -807,11 +806,7 @@ impl IOCompositor { } } - WindowEvent::Reload => { - let top_level_browsing_context_id = match self.root_pipeline { - Some(ref pipeline) => pipeline.top_level_browsing_context_id, - None => return warn!("Window reload without root pipeline."), - }; + WindowEvent::Reload(top_level_browsing_context_id) => { let msg = ConstellationMsg::Reload(top_level_browsing_context_id); if let Err(e) = self.constellation_chan.send(msg) { warn!("Sending reload to constellation failed ({}).", e); @@ -850,23 +845,6 @@ impl IOCompositor { self.send_window_size(WindowSizeType::Resize); } - fn on_load_url_window_event(&mut self, url_string: String) { - debug!("osmain: loading URL `{}`", url_string); - match ServoUrl::parse(&url_string) { - Ok(url) => { - let msg = match self.root_pipeline { - 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) { - warn!("Sending load url to constellation failed ({}).", e); - } - }, - Err(e) => warn!("Parsing URL {} failed ({}).", url_string, e), - } - } - fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) { if opts::get().convert_mouse_to_touch { match mouse_window_event { @@ -1291,28 +1269,6 @@ impl IOCompositor { }); } - fn on_navigation_window_event(&self, direction: TraversalDirection) { - let top_level_browsing_context_id = match self.root_pipeline { - Some(ref pipeline) => pipeline.top_level_browsing_context_id, - None => return warn!("Sending navigation to constellation with no root pipeline."), - }; - let msg = ConstellationMsg::TraverseHistory(top_level_browsing_context_id, direction); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending navigation to constellation failed ({}).", e); - } - } - - fn on_key_event(&mut self, - ch: Option, - key: Key, - state: KeyState, - modifiers: KeyModifiers) { - let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending key event to constellation failed ({}).", e); - } - } - fn send_viewport_rects(&self) { let mut scroll_states_per_pipeline = HashMap::new(); for scroll_layer_state in self.webrender_api.get_scroll_node_state(self.webrender_document) { diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs index 8ca12300676..ddba55cbf55 100644 --- a/components/compositing/compositor_thread.rs +++ b/components/compositing/compositor_thread.rs @@ -8,7 +8,7 @@ use SendableFrameTree; use compositor::CompositingReason; use euclid::{Point2D, Size2D}; use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId}; +use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId}; use net_traits::image::base::Image; use profile_traits::mem; use profile_traits::time; @@ -87,23 +87,23 @@ pub enum Msg { /// Scroll a page in a window ScrollFragmentPoint(webrender_api::ClipId, Point2D, bool), /// Alerts the compositor that the current page has changed its title. - ChangePageTitle(PipelineId, Option), + ChangePageTitle(TopLevelBrowsingContextId, Option), /// Alerts the compositor that the given pipeline has changed whether it is running animations. ChangeRunningAnimationsState(PipelineId, AnimationState), /// Replaces the current frame tree, typically called during main frame navigation. SetFrameTree(SendableFrameTree), /// The load of a page has begun - LoadStart, + LoadStart(TopLevelBrowsingContextId), /// The load of a page has completed - LoadComplete, + LoadComplete(TopLevelBrowsingContextId), /// The history state has changed. - HistoryChanged(Vec, usize), + HistoryChanged(TopLevelBrowsingContextId, Vec, usize), /// Wether or not to follow a link - AllowNavigation(ServoUrl, IpcSender), + AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender), /// Composite. Recomposite(CompositingReason), /// Sends an unconsumed key event back to the compositor. - KeyEvent(Option, Key, KeyState, KeyModifiers), + KeyEvent(Option, Option, Key, KeyState, KeyModifiers), /// Script has handled a touch event, and either prevented or allowed default actions. TouchEventProcessed(EventResult), /// Changes the cursor. @@ -115,17 +115,17 @@ pub enum Msg { /// A reply to the compositor asking if the output image is stable. IsReadyToSaveImageReply(bool), /// A favicon was detected - NewFavicon(ServoUrl), + NewFavicon(TopLevelBrowsingContextId, ServoUrl), /// tag finished parsing - HeadParsed, + HeadParsed(TopLevelBrowsingContextId), /// A status message to be displayed by the browser chrome. - Status(Option), + Status(TopLevelBrowsingContextId, Option), /// Get Window Informations size and position - GetClientWindow(IpcSender<(Size2D, Point2D)>), + GetClientWindow(TopLevelBrowsingContextId, IpcSender<(Size2D, Point2D)>), /// Move the window to a point - MoveTo(Point2D), + MoveTo(TopLevelBrowsingContextId, Point2D), /// Resize the window to size - ResizeTo(Size2D), + ResizeTo(TopLevelBrowsingContextId, Size2D), /// Pipeline visibility changed PipelineVisibilityChanged(PipelineId, bool), /// WebRender has successfully processed a scroll. The boolean specifies whether a composite is @@ -142,7 +142,7 @@ pub enum Msg { /// Required to allow WGL GLContext sharing in Windows. Dispatch(Box), /// Enter or exit fullscreen - SetFullscreenState(bool), + SetFullscreenState(TopLevelBrowsingContextId, bool), } impl Debug for Msg { @@ -154,9 +154,9 @@ impl Debug for Msg { Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"), Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"), Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), - Msg::LoadComplete => write!(f, "LoadComplete"), + Msg::LoadComplete(..) => write!(f, "LoadComplete"), Msg::AllowNavigation(..) => write!(f, "AllowNavigation"), - Msg::LoadStart => write!(f, "LoadStart"), + Msg::LoadStart(..) => write!(f, "LoadStart"), Msg::HistoryChanged(..) => write!(f, "HistoryChanged"), Msg::Recomposite(..) => write!(f, "Recomposite"), Msg::KeyEvent(..) => write!(f, "KeyEvent"), @@ -166,7 +166,7 @@ impl Debug for Msg { Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"), Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"), Msg::NewFavicon(..) => write!(f, "NewFavicon"), - Msg::HeadParsed => write!(f, "HeadParsed"), + Msg::HeadParsed(..) => write!(f, "HeadParsed"), Msg::Status(..) => write!(f, "Status"), Msg::GetClientWindow(..) => write!(f, "GetClientWindow"), Msg::MoveTo(..) => write!(f, "MoveTo"), diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 4c018997645..8831b12b1c9 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -9,7 +9,7 @@ use euclid::{Point2D, Size2D}; use euclid::{ScaleFactor, TypedPoint2D, TypedSize2D}; use gleam::gl; use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::{Key, KeyModifiers, KeyState, TraversalDirection}; +use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection}; use net_traits::net_error_list::NetError; use script_traits::{LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase}; use servo_geometry::DeviceIndependentPixel; @@ -45,7 +45,7 @@ pub enum WindowEvent { /// Touchpad Pressure TouchpadPressure(TypedPoint2D, f32, TouchpadPressurePhase), /// Sent when a new URL is to be loaded. - LoadUrl(String), + LoadUrl(TopLevelBrowsingContextId, ServoUrl), /// Sent when a mouse hit test is to be performed. MouseWindowEventClass(MouseWindowEvent), /// Sent when a mouse move. @@ -62,15 +62,15 @@ pub enum WindowEvent { /// Sent when the user resets zoom to default. ResetZoom, /// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace). - Navigation(TraversalDirection), + Navigation(TopLevelBrowsingContextId, TraversalDirection), /// Sent when the user quits the application Quit, /// Sent when a key input state changes KeyEvent(Option, Key, KeyState, KeyModifiers), /// Sent when Ctr+R/Apple+R is called to reload the current page. - Reload, /// Toggles the Web renderer profiler on and off ToggleWebRenderProfiler, + Reload(TopLevelBrowsingContextId), } impl Debug for WindowEvent { @@ -91,8 +91,8 @@ impl Debug for WindowEvent { WindowEvent::ResetZoom => write!(f, "ResetZoom"), WindowEvent::Navigation(..) => write!(f, "Navigation"), WindowEvent::Quit => write!(f, "Quit"), - WindowEvent::Reload => write!(f, "Reload"), WindowEvent::ToggleWebRenderProfiler => write!(f, "ToggleWebRenderProfiler"), + WindowEvent::Reload(..) => write!(f, "Reload"), } } } @@ -114,30 +114,30 @@ pub trait WindowMethods { fn present(&self); /// Return the size of the window with head and borders and position of the window values - fn client_window(&self) -> (Size2D, Point2D); + fn client_window(&self, ctx: TopLevelBrowsingContextId) -> (Size2D, Point2D); /// Set the size inside of borders and head - fn set_inner_size(&self, size: Size2D); + fn set_inner_size(&self, ctx: TopLevelBrowsingContextId, size: Size2D); /// Set the window position - fn set_position(&self, point: Point2D); + fn set_position(&self, ctx: TopLevelBrowsingContextId, point: Point2D); /// Set fullscreen state - fn set_fullscreen_state(&self, state: bool); + fn set_fullscreen_state(&self, ctx: TopLevelBrowsingContextId, state: bool); /// Sets the page title for the current page. - fn set_page_title(&self, title: Option); + fn set_page_title(&self, ctx: TopLevelBrowsingContextId, title: Option); /// Called when the browser chrome should display a status message. - fn status(&self, Option); + fn status(&self, ctx: TopLevelBrowsingContextId, Option); /// Called when the browser has started loading a frame. - fn load_start(&self); + fn load_start(&self, ctx: TopLevelBrowsingContextId); /// Called when the browser is done loading a frame. - fn load_end(&self); + fn load_end(&self, ctx: TopLevelBrowsingContextId); /// Called when the browser encounters an error while loading a URL - fn load_error(&self, code: NetError, url: String); + fn load_error(&self, ctx: TopLevelBrowsingContextId, code: NetError, url: String); /// Wether or not to follow a link - fn allow_navigation(&self, url: ServoUrl, IpcSender); + fn allow_navigation(&self, ctx: TopLevelBrowsingContextId, url: ServoUrl, IpcSender); /// Called when the tag has finished parsing - fn head_parsed(&self); + fn head_parsed(&self, ctx: TopLevelBrowsingContextId); /// Called when the history state has changed. - fn history_changed(&self, Vec, usize); + fn history_changed(&self, ctx: TopLevelBrowsingContextId, Vec, usize); /// Returns the scale factor of the system (device pixels / device independent pixels). fn hidpi_factor(&self) -> ScaleFactor; @@ -154,13 +154,13 @@ pub trait WindowMethods { fn set_cursor(&self, cursor: Cursor); /// Process a key event. - fn handle_key(&self, ch: Option, key: Key, mods: KeyModifiers); + fn handle_key(&self, ctx: Option, ch: Option, key: Key, mods: KeyModifiers); /// Does this window support a clipboard fn supports_clipboard(&self) -> bool; /// Add a favicon - fn set_favicon(&self, url: ServoUrl); + fn set_favicon(&self, ctx: TopLevelBrowsingContextId, url: ServoUrl); /// Return the GL function pointer trait. fn gl(&self) -> Rc; diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index bccc351becd..15d7d18a87f 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -807,9 +807,8 @@ impl Constellation } } - fn add_pending_change(&mut self, change: SessionHistoryChange) - { - self.handle_load_start_msg(change.new_pipeline_id); + fn add_pending_change(&mut self, change: SessionHistoryChange) { + self.handle_load_start_msg(change.top_level_browsing_context_id, change.new_pipeline_id); self.pending_changes.push(change); } @@ -934,9 +933,15 @@ impl Constellation // Load a new page from a typed url // If there is already a pending page (self.pending_changes), it will not be overridden; // However, if the id is not encompassed by another change, it will be. - FromCompositorMsg::LoadUrl(source_id, load_data) => { + FromCompositorMsg::LoadUrl(top_level_browsing_context_id, url) => { debug!("constellation got URL load message from compositor"); - self.handle_load_url_msg(source_id, load_data, false); + let load_data = LoadData::new(url, None, None, None); + let ctx_id = BrowsingContextId::from(top_level_browsing_context_id); + let pipeline_id = match self.browsing_contexts.get(&ctx_id) { + Some(ctx) => ctx.pipeline_id, + None => return warn!("LoadUrl for unknow browsing context: {:?}", top_level_browsing_context_id), + }; + self.handle_load_url_msg(top_level_browsing_context_id, pipeline_id, load_data, false); } FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => { let is_ready = self.handle_is_ready_to_save_image(pipeline_states); @@ -1718,14 +1723,17 @@ impl Constellation } } - fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData, replace: bool) { - self.load_url(source_id, load_data, replace); + fn handle_load_url_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId, + load_data: LoadData, replace: bool) { + self.load_url(top_level_browsing_context_id, source_id, load_data, replace); } - fn load_url(&mut self, source_id: PipelineId, load_data: LoadData, replace: bool) -> Option { + fn load_url(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId, + load_data: LoadData, replace: bool) -> Option { // Allow the embedder to handle the url itself let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); - self.compositor_proxy.send(ToCompositorMsg::AllowNavigation(load_data.url.clone(), chan)); + let msg = ToCompositorMsg::AllowNavigation(top_level_browsing_context_id, load_data.url.clone(), chan); + self.compositor_proxy.send(msg); if let Ok(false) = port.recv() { return None; } @@ -1815,11 +1823,16 @@ impl Constellation } } - fn handle_load_start_msg(&mut self, _pipeline_id: PipelineId) { - self.compositor_proxy.send(ToCompositorMsg::LoadStart); + fn handle_load_start_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, + pipeline_id: PipelineId) { + if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() { + // Notify embedder top level document started loading. + self.compositor_proxy.send(ToCompositorMsg::LoadStart(top_level_browsing_context_id)); + } } - fn handle_load_complete_msg(&mut self, pipeline_id: PipelineId) { + fn handle_load_complete_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, + pipeline_id: PipelineId) { let mut webdriver_reset = false; if let Some((expected_pipeline_id, ref reply_chan)) = self.webdriver.load_channel { debug!("Sending load to WebDriver"); @@ -1831,7 +1844,25 @@ impl Constellation if webdriver_reset { self.webdriver.load_channel = None; } - self.compositor_proxy.send(ToCompositorMsg::LoadComplete); + + // Notify the embedder that the TopLevelBrowsingContext current document + // has finished loading. + // We need to make sure the pipeline that has finished loading is the current + // pipeline and that no pending pipeline will replace the current one. + let pipeline_is_top_level_pipeline = self.browsing_contexts + .get(&BrowsingContextId::from(top_level_browsing_context_id)) + .map(|ctx| ctx.pipeline_id == pipeline_id) + .unwrap_or(false); + if pipeline_is_top_level_pipeline { + // Is there any pending pipeline that will replace the current top level pipeline + let current_top_level_pipeline_will_be_replaced = self.pending_changes.iter() + .any(|change| change.browsing_context_id == top_level_browsing_context_id); + + if !current_top_level_pipeline_will_be_replaced { + // Notify embedder top level document finished loading. + self.compositor_proxy.send(ToCompositorMsg::LoadComplete(top_level_browsing_context_id)); + } + } self.handle_subframe_loaded(pipeline_id); } @@ -1897,7 +1928,7 @@ impl Constellation } }, None => { - let event = ToCompositorMsg::KeyEvent(ch, key, state, mods); + let event = ToCompositorMsg::KeyEvent(None, ch, key, state, mods); self.compositor_proxy.clone_compositor_proxy().send(event); } } @@ -2088,9 +2119,9 @@ impl Constellation WebDriverCommandMsg::GetWindowSize(_, reply) => { let _ = reply.send(self.window_size); }, - WebDriverCommandMsg::SetWindowSize(_, size, reply) => { + WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, reply) => { self.webdriver.resize_channel = Some(reply); - self.compositor_proxy.send(ToCompositorMsg::ResizeTo(size)); + self.compositor_proxy.send(ToCompositorMsg::ResizeTo(top_level_browsing_context_id, size)); }, WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, reply) => { self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, false); @@ -2324,7 +2355,8 @@ impl Constellation .map(&keep_load_data_if_top_browsing_context) .scan(current_load_data.clone(), &resolve_load_data)); - self.compositor_proxy.send(ToCompositorMsg::HistoryChanged(entries, current_index)); + let msg = ToCompositorMsg::HistoryChanged(top_level_browsing_context_id, entries, current_index); + self.compositor_proxy.send(msg); } fn load_url_for_webdriver(&mut self, @@ -2338,7 +2370,7 @@ impl Constellation Some(browsing_context) => browsing_context.pipeline_id, None => return warn!("Webdriver load for closed browsing context {}.", browsing_context_id), }; - if let Some(new_pipeline_id) = self.load_url(pipeline_id, load_data, replace) { + if let Some(new_pipeline_id) = self.load_url(top_level_browsing_context_id, pipeline_id, load_data, replace) { self.webdriver.load_channel = Some((new_pipeline_id, reply)); } } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index a9023e3c2a3..34363b8f992 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -747,7 +747,7 @@ pub enum ConstellationMsg { /// Inform the constellation of a key event. KeyEvent(Option, Key, KeyState, KeyModifiers), /// Request to load a page. - LoadUrl(PipelineId, LoadData), + LoadUrl(TopLevelBrowsingContextId, ServoUrl), /// Request to traverse the joint session history of the provided browsing context. TraverseHistory(TopLevelBrowsingContextId, TraversalDirection), /// Inform the constellation of a window being resized. diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 2dbd0aecd38..1f82d7fb3c2 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -19,7 +19,7 @@ use glutin::ScanCode; use glutin::TouchPhase; #[cfg(target_os = "macos")] use glutin::os::macos::{ActivationPolicy, WindowBuilderExt}; -use msg::constellation_msg::{self, Key}; +use msg::constellation_msg::{self, Key, TopLevelBrowsingContextId as BrowserId}; use msg::constellation_msg::{ALT, CONTROL, KeyState, NONE, SHIFT, SUPER, TraversalDirection}; use net_traits::net_error_list::NetError; #[cfg(any(target_os = "linux", target_os = "macos"))] @@ -995,7 +995,7 @@ impl WindowMethods for Window { } } - fn client_window(&self) -> (Size2D, Point2D) { + fn client_window(&self, _: BrowserId) -> (Size2D, Point2D) { match self.kind { WindowKind::Window(ref window) => { // TODO(ajeffrey): can this fail? @@ -1018,7 +1018,7 @@ impl WindowMethods for Window { self.animation_state.set(state); } - fn set_inner_size(&self, size: Size2D) { + fn set_inner_size(&self, _: BrowserId, size: Size2D) { match self.kind { WindowKind::Window(ref window) => { window.set_inner_size(size.width as u32, size.height as u32) @@ -1027,7 +1027,7 @@ impl WindowMethods for Window { } } - fn set_position(&self, point: Point2D) { + fn set_position(&self, _: BrowserId, point: Point2D) { match self.kind { WindowKind::Window(ref window) => { window.set_position(point.x, point.y) @@ -1036,7 +1036,7 @@ impl WindowMethods for Window { } } - fn set_fullscreen_state(&self, _state: bool) { + fn set_fullscreen_state(&self, _: BrowserId, _state: bool) { match self.kind { WindowKind::Window(..) => { warn!("Fullscreen is not implemented!") @@ -1098,7 +1098,7 @@ impl WindowMethods for Window { ScaleFactor::new(ppi as f32 / 96.0) } - fn set_page_title(&self, title: Option) { + fn set_page_title(&self, _: BrowserId, title: Option) { match self.kind { WindowKind::Window(ref window) => { let fallback_title: String = if let Some(ref current_url) = *self.current_url.borrow() { @@ -1118,13 +1118,13 @@ impl WindowMethods for Window { } } - fn status(&self, _: Option) { + fn status(&self, _: BrowserId, _: Option) { } - fn load_start(&self) { + fn load_start(&self, _: BrowserId) { } - fn load_end(&self) { + fn load_end(&self, _: BrowserId) { if opts::get().no_native_titlebar { match self.kind { WindowKind::Window(ref window) => { @@ -1135,14 +1135,14 @@ impl WindowMethods for Window { } } - fn history_changed(&self, history: Vec, current: usize) { + fn history_changed(&self, _: BrowserId, history: Vec, current: usize) { *self.current_url.borrow_mut() = Some(history[current].url.clone()); } - fn load_error(&self, _: NetError, _: String) { + fn load_error(&self, _: BrowserId, _: NetError, _: String) { } - fn head_parsed(&self) { + fn head_parsed(&self, _: BrowserId) { } /// Has no effect on Android. @@ -1194,7 +1194,7 @@ impl WindowMethods for Window { } } - fn set_favicon(&self, _: ServoUrl) { + fn set_favicon(&self, _: BrowserId, _: ServoUrl) { } fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool { @@ -1202,7 +1202,7 @@ impl WindowMethods for Window { } /// Helper function to handle keyboard events. - fn handle_key(&self, ch: Option, key: Key, mods: constellation_msg::KeyModifiers) { + fn handle_key(&self, _: Option, ch: Option, key: Key, mods: constellation_msg::KeyModifiers) { match (mods, ch, key) { (_, Some('+'), _) => { if mods & !SHIFT == CMD_OR_CONTROL { @@ -1302,7 +1302,7 @@ impl WindowMethods for Window { } } - fn allow_navigation(&self, _: ServoUrl, response_chan: IpcSender) { + fn allow_navigation(&self, _: BrowserId, _: ServoUrl, response_chan: IpcSender) { if let Err(e) = response_chan.send(true) { warn!("Failed to send allow_navigation() response: {}", e); };