Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notify embedder when history changes #15794

Merged
merged 1 commit into from Apr 25, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Notify embedder when history changes

  • Loading branch information
paulrouget committed Apr 18, 2017
commit e49354813597616db0473c88c94a715705e5aaff
@@ -494,10 +494,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.change_page_title(pipeline_id, title);
}

(Msg::ChangePageUrl(pipeline_id, url), ShutdownState::NotShuttingDown) => {
self.change_page_url(pipeline_id, url);
}

(Msg::SetFrameTree(frame_tree, response_chan),
ShutdownState::NotShuttingDown) => {
self.set_frame_tree(&frame_tree, response_chan);
@@ -532,11 +528,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.window.status(message);
}

(Msg::LoadStart(back, forward), ShutdownState::NotShuttingDown) => {
self.window.load_start(back, forward);
(Msg::LoadStart, ShutdownState::NotShuttingDown) => {
self.window.load_start();
}

(Msg::LoadComplete(back, forward, root), ShutdownState::NotShuttingDown) => {
(Msg::LoadComplete, ShutdownState::NotShuttingDown) => {
self.got_load_complete_message = true;

// If we're painting in headless mode, schedule a recomposite.
@@ -547,7 +543,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// Inform the embedder that the load has finished.
//
// TODO(pcwalton): Specify which frame's load completed.
self.window.load_end(back, forward, root);
self.window.load_end();
}

(Msg::AllowNavigation(url, response_chan), ShutdownState::NotShuttingDown) => {
@@ -625,6 +621,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.window.head_parsed();
}

(Msg::HistoryChanged(entries, current), ShutdownState::NotShuttingDown) => {
self.window.history_changed(entries, current);
}

(Msg::PipelineVisibilityChanged(pipeline_id, visible), ShutdownState::NotShuttingDown) => {
self.pipeline_details(pipeline_id).visible = visible;
if visible {
@@ -720,10 +720,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}

fn change_page_url(&mut self, _: PipelineId, url: ServoUrl) {
self.window.set_page_url(url);
}

fn set_frame_tree(&mut self,
frame_tree: &SendableFrameTree,
response_chan: IpcSender<()>) {
@@ -923,7 +919,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.got_load_complete_message = false;
match ServoUrl::parse(&url_string) {
Ok(url) => {
self.window.set_page_url(url.clone());
let msg = match self.root_pipeline {
Some(ref pipeline) => ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, None, None)),
None => ConstellationMsg::InitLoadUrl(url)
@@ -14,7 +14,7 @@ use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId};
use net_traits::image::base::Image;
use profile_traits::mem;
use profile_traits::time;
use script_traits::{AnimationState, ConstellationMsg, EventResult};
use script_traits::{AnimationState, ConstellationMsg, EventResult, LoadData};
use servo_url::ServoUrl;
use std::fmt::{Debug, Error, Formatter};
use std::sync::mpsc::{Receiver, Sender};
@@ -76,16 +76,16 @@ pub enum Msg {
ScrollFragmentPoint(PipelineId, ScrollRootId, Point2D<f32>, bool),
/// Alerts the compositor that the current page has changed its title.
ChangePageTitle(PipelineId, Option<String>),
/// Alerts the compositor that the current page has changed its URL.
ChangePageUrl(PipelineId, ServoUrl),
/// 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, IpcSender<()>),
/// The load of a page has begun: (can go back, can go forward).
LoadStart(bool, bool),
/// The load of a page has completed: (can go back, can go forward, is root frame).
LoadComplete(bool, bool, bool),
/// The load of a page has begun
LoadStart,
/// The load of a page has completed
LoadComplete,
/// The history state has changed.
HistoryChanged(Vec<LoadData>, usize),
/// Wether or not to follow a link
AllowNavigation(ServoUrl, IpcSender<bool>),
/// We hit the delayed composition timeout. (See `delayed_composition.rs`.)
@@ -143,11 +143,11 @@ impl Debug for Msg {
Msg::ScrollFragmentPoint(..) => write!(f, "ScrollFragmentPoint"),
Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"),
Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
Msg::ChangePageUrl(..) => write!(f, "ChangePageUrl"),
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::DelayedCompositionTimeout(..) => write!(f, "DelayedCompositionTimeout"),
Msg::Recomposite(..) => write!(f, "Recomposite"),
Msg::KeyEvent(..) => write!(f, "KeyEvent"),
@@ -13,7 +13,7 @@ use euclid::size::TypedSize2D;
use gleam::gl;
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use net_traits::net_error_list::NetError;
use script_traits::{DevicePixel, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
use script_traits::{DevicePixel, LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl;
use std::fmt::{Debug, Error, Formatter};
@@ -129,20 +129,20 @@ pub trait WindowMethods {

/// Sets the page title for the current page.
fn set_page_title(&self, title: Option<String>);
/// Sets the load data for the current page.
fn set_page_url(&self, url: ServoUrl);
/// Called when the browser chrome should display a status message.
fn status(&self, Option<String>);
/// Called when the browser has started loading a frame.
fn load_start(&self, back: bool, forward: bool);
fn load_start(&self);
/// Called when the browser is done loading a frame.
fn load_end(&self, back: bool, forward: bool, root: bool);
fn load_end(&self);
/// Called when the browser encounters an error while loading a URL
fn load_error(&self, code: NetError, url: String);
/// Wether or not to follow a link
fn allow_navigation(&self, url: ServoUrl) -> bool;
/// Called when the <head> tag has finished parsing
fn head_parsed(&self);
/// Called when the history state has changed.
fn history_changed(&self, Vec<LoadData>, usize);

/// Returns the scale factor of the system (device pixels / device independent pixels).
fn hidpi_factor(&self) -> ScaleFactor<f32, DeviceIndependentPixel, DevicePixel>;
@@ -1351,7 +1351,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
load_data: load_data,
replace_instant: None,
});
self.compositor_proxy.send(ToCompositorMsg::ChangePageUrl(root_pipeline_id, url));
}

fn handle_frame_size_msg(&mut self,
@@ -1664,11 +1663,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
}

fn handle_load_start_msg(&mut self, pipeline_id: PipelineId) {
let frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
let forward = !self.joint_session_future_is_empty(frame_id);
let back = !self.joint_session_past_is_empty(frame_id);
self.compositor_proxy.send(ToCompositorMsg::LoadStart(back, forward));
fn handle_load_start_msg(&mut self, _pipeline_id: PipelineId) {
self.compositor_proxy.send(ToCompositorMsg::LoadStart);
}

fn handle_load_complete_msg(&mut self, pipeline_id: PipelineId) {
@@ -1683,11 +1679,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
if webdriver_reset {
self.webdriver.load_channel = None;
}
let frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
let forward = !self.joint_session_future_is_empty(frame_id);
let back = !self.joint_session_past_is_empty(frame_id);
let root = self.root_frame_id == frame_id;
self.compositor_proxy.send(ToCompositorMsg::LoadComplete(back, forward, root));
self.compositor_proxy.send(ToCompositorMsg::LoadComplete);
self.handle_subframe_loaded(pipeline_id);
}

@@ -2102,6 +2094,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Deactivate the old pipeline, and activate the new one.
self.update_activity(old_pipeline_id);
self.update_activity(pipeline_id);
self.notify_history_changed(pipeline_id);

// Set paint permissions correctly for the compositor layers.
self.send_frame_tree();
@@ -2124,6 +2117,64 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
}

fn notify_history_changed(&self, pipeline_id: PipelineId) {
// Send a flat projection of the history.
// The final vector is a concatenation of the LoadData of the past entries,
// the current entry and the future entries.
// LoadData of inner frames are ignored and replaced with the LoadData of the parent.

let top_level_frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);

// Ignore LoadData of non-top-level frames.
let keep_load_data_if_top_frame = |state: &FrameState| {
match state.pipeline_id {
None => Some(state.load_data.clone()),
Some(pipeline_id) => {
match self.pipelines.get(&pipeline_id) {
None => Some(state.load_data.clone()),
Some(pipeline) => match pipeline.parent_info {
None => Some(state.load_data.clone()),
Some(_) => None,
}
}
}
}
};

// If LoadData was ignored, use the LoadData of the previous FrameState, which
// is the LoadData of the parent frame.
let resolve_load_data = |previous_load_data: &mut LoadData, load_data| {
let load_data = match load_data {
None => previous_load_data.clone(),
Some(load_data) => load_data,
};
*previous_load_data = load_data.clone();
Some(load_data)
};

let current_load_data = match self.frames.get(&top_level_frame_id) {
Some(frame) => frame.load_data.clone(),
None => return warn!("notify_history_changed error after top-level frame closed."),
};

let mut entries: Vec<LoadData> = self.joint_session_past(top_level_frame_id)
.map(&keep_load_data_if_top_frame)

This comment has been minimized.

@asajeffrey

asajeffrey Apr 17, 2017

Member

Do we need this &? It makes the function call a dynamic rather than static dispatch.

This comment has been minimized.

@paulrouget

paulrouget Apr 17, 2017

Author Contributor

This callback is called twice. Moved in the first map. How can I use it twice then?

Also, in general, I'd be interested to understand why it's bad to use &.

This comment has been minimized.

@asajeffrey

asajeffrey Apr 17, 2017

Member

Oh, perhaps you're okay in this case, since it's a pointer to a closure, so Rust will probably generate a new type for it. In the case of a declared fn foo, .map(&foo) will perform dynamic dispatch, since &foo has type &fn(S) -> T, which blocks other code optimizations.

.scan(current_load_data.clone(), &resolve_load_data)
.collect();

entries.reverse();

let current_index = entries.len();

entries.push(current_load_data.clone());

entries.extend(self.joint_session_future(top_level_frame_id)
.map(&keep_load_data_if_top_frame)
.scan(current_load_data.clone(), &resolve_load_data));

self.compositor_proxy.send(ToCompositorMsg::HistoryChanged(entries, current_index));
}

fn get_top_level_frame_for_pipeline(&self, mut pipeline_id: PipelineId) -> FrameId {
if PREFS.is_mozbrowser_enabled() {
loop {
@@ -2197,6 +2248,7 @@ 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.update_activity(frame_change.new_pipeline_id);
self.notify_history_changed(frame_change.new_pipeline_id);
};

if let Some(old_pipeline_id) = navigated {
@@ -2206,6 +2258,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Clear the joint session future
let top_level_frame_id = self.get_top_level_frame_for_pipeline(frame_change.new_pipeline_id);
self.clear_joint_session_future(top_level_frame_id);
self.notify_history_changed(frame_change.new_pipeline_id);
}

if location_changed {
@@ -26,7 +26,7 @@ use euclid::size::{Size2D, TypedSize2D};
use gleam::gl;
use msg::constellation_msg::{Key, KeyModifiers};
use net_traits::net_error_list::NetError;
use script_traits::DevicePixel;
use script_traits::{DevicePixel, LoadData};
use servo_geometry::DeviceIndependentPixel;
use std::cell::RefCell;
use std::ffi::CString;
@@ -350,15 +350,15 @@ impl WindowMethods for Window {
}
}

fn load_start(&self, back: bool, forward: bool) {
fn load_start(&self) {
let browser = self.cef_browser.borrow();
let browser = match *browser {
None => return,
Some(ref browser) => browser,
};
let back = browser.downcast().back.get();
let forward = browser.downcast().forward.get();
browser.downcast().loading.set(true);
browser.downcast().back.set(back);
browser.downcast().forward.set(forward);
browser.downcast().favicons.borrow_mut().clear();
if check_ptr_exist!(browser.get_host().get_client(), get_load_handler) &&
check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_loading_state_change) {
@@ -369,16 +369,16 @@ impl WindowMethods for Window {
}
}

fn load_end(&self, back: bool, forward: bool, _: bool) {
fn load_end(&self) {
// FIXME(pcwalton): The status code 200 is a lie.
let browser = self.cef_browser.borrow();
let browser = match *browser {
None => return,
Some(ref browser) => browser,
};
let back = browser.downcast().back.get();
let forward = browser.downcast().forward.get();
browser.downcast().loading.set(false);
browser.downcast().back.set(back);
browser.downcast().forward.set(forward);
if check_ptr_exist!(browser.get_host().get_client(), get_load_handler) &&
check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_loading_state_change) {
browser.get_host()
@@ -448,20 +448,21 @@ impl WindowMethods for Window {
}
}

fn set_page_url(&self, url: ServoUrl) {
// it seems to be the case that load start is always called
// IMMEDIATELY before address change, so just stick it here
on_load_start(self);
fn history_changed(&self, history: Vec<LoadData>, current: usize) {
let browser = self.cef_browser.borrow();
let browser = match *browser {
None => return,
Some(ref browser) => browser,
};

let can_go_back = current > 0;
let can_go_forward = current < history.len() - 1;

browser.downcast().back.set(can_go_back);
browser.downcast().forward.set(can_go_forward);
let frame = browser.get_main_frame();
let servoframe = frame.downcast();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let mut frame_url = servoframe.url.borrow_mut();
*frame_url = url.into_string();
let mut frame_url = frame.downcast().url.borrow_mut();
*frame_url = history[current].url.to_string();
let utf16_chars: Vec<u16> = frame_url.encode_utf16().collect();
if check_ptr_exist!(browser.get_host().get_client(), get_display_handler) &&
check_ptr_exist!(browser.get_host().get_client().get_display_handler(), on_address_change) {
@@ -516,21 +517,6 @@ impl CompositorProxy for CefCompositorProxy {
}
}

fn on_load_start(window: &Window) {
let browser = window.cef_browser.borrow();
let browser = match *browser {
None => return,
Some(ref browser) => browser,
};
if check_ptr_exist!(browser.get_host().get_client(), get_load_handler) &&
check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_load_start) {
browser.get_host()
.get_client()
.get_load_handler()
.on_load_start((*browser).clone(), browser.get_main_frame());
}
}

#[cfg(target_os="macos")]
pub fn app_wakeup() {
use cocoa::appkit::{NSApp, NSApplication, NSApplicationDefined};
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.