mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Make session history aware of URLs
This commit is contained in:
parent
05fe8fa08d
commit
e7ef9cfb30
11 changed files with 192 additions and 56 deletions
|
@ -26,6 +26,7 @@ file
|
||||||
fullscreenchange
|
fullscreenchange
|
||||||
fullscreenerror
|
fullscreenerror
|
||||||
gattserverdisconnected
|
gattserverdisconnected
|
||||||
|
hashchange
|
||||||
hidden
|
hidden
|
||||||
image
|
image
|
||||||
input
|
input
|
||||||
|
|
|
@ -140,6 +140,7 @@ use session_history::{JointSessionHistory, NeedsToReload, SessionHistoryChange,
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::mem::replace;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -1074,13 +1075,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.handle_traverse_history_msg(source_top_ctx_id, direction);
|
self.handle_traverse_history_msg(source_top_ctx_id, direction);
|
||||||
}
|
}
|
||||||
// Handle a push history state request.
|
// Handle a push history state request.
|
||||||
FromScriptMsg::PushHistoryState(history_state_id) => {
|
FromScriptMsg::PushHistoryState(history_state_id, url) => {
|
||||||
debug!("constellation got push history state message from script");
|
debug!("constellation got push history state message from script");
|
||||||
self.handle_push_history_state_msg(source_pipeline_id, history_state_id);
|
self.handle_push_history_state_msg(source_pipeline_id, history_state_id, url);
|
||||||
}
|
}
|
||||||
FromScriptMsg::ReplaceHistoryState(history_state_id) => {
|
FromScriptMsg::ReplaceHistoryState(history_state_id, url) => {
|
||||||
debug!("constellation got replace history state message from script");
|
debug!("constellation got replace history state message from script");
|
||||||
self.handle_replace_history_state_msg(source_pipeline_id, history_state_id);
|
self.handle_replace_history_state_msg(source_pipeline_id, history_state_id, url);
|
||||||
}
|
}
|
||||||
// Handle a joint session history length request.
|
// Handle a joint session history length request.
|
||||||
FromScriptMsg::JointSessionHistoryLength(sender) => {
|
FromScriptMsg::JointSessionHistoryLength(sender) => {
|
||||||
|
@ -1938,11 +1939,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
direction: TraversalDirection)
|
direction: TraversalDirection)
|
||||||
{
|
{
|
||||||
let mut browsing_context_changes = HashMap::<BrowsingContextId, NeedsToReload>::new();
|
let mut browsing_context_changes = HashMap::<BrowsingContextId, NeedsToReload>::new();
|
||||||
let mut pipeline_changes = HashMap::<PipelineId, Option<HistoryStateId>>::new();
|
let mut pipeline_changes = HashMap::<PipelineId, (Option<HistoryStateId>, ServoUrl)>::new();
|
||||||
|
let mut url_to_load = HashMap::<PipelineId, ServoUrl>::new();
|
||||||
{
|
{
|
||||||
let session_history = self.joint_session_histories
|
let session_history = self.get_joint_session_history(top_level_browsing_context_id);
|
||||||
.entry(top_level_browsing_context_id).or_insert(JointSessionHistory::new());
|
|
||||||
|
|
||||||
match direction {
|
match direction {
|
||||||
TraversalDirection::Forward(forward) => {
|
TraversalDirection::Forward(forward) => {
|
||||||
let future_length = session_history.future.len();
|
let future_length = session_history.future.len();
|
||||||
|
@ -1955,12 +1955,18 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
match diff {
|
match diff {
|
||||||
SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref new_reloader, .. } => {
|
SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref new_reloader, .. } => {
|
||||||
browsing_context_changes.insert(browsing_context_id, new_reloader.clone());
|
browsing_context_changes.insert(browsing_context_id, new_reloader.clone());
|
||||||
},
|
}
|
||||||
SessionHistoryDiff::PipelineDiff { ref pipeline_reloader, new_history_state_id, .. } => {
|
SessionHistoryDiff::PipelineDiff {
|
||||||
// TODO(cbrewster): Handle the case where the pipeline needs to be reloaded.
|
ref pipeline_reloader,
|
||||||
// We should use the history state URL to change the URL that is reloaded.
|
new_history_state_id,
|
||||||
if let NeedsToReload::No(pipeline_id) = *pipeline_reloader {
|
ref new_url,
|
||||||
pipeline_changes.insert(pipeline_id, Some(new_history_state_id));
|
..
|
||||||
|
} => match *pipeline_reloader {
|
||||||
|
NeedsToReload::No(pipeline_id) => {
|
||||||
|
pipeline_changes.insert(pipeline_id, (Some(new_history_state_id), new_url.clone()));
|
||||||
|
}
|
||||||
|
NeedsToReload::Yes(pipeline_id, ..) => {
|
||||||
|
url_to_load.insert(pipeline_id, new_url.clone());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1979,11 +1985,17 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref old_reloader, .. } => {
|
SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref old_reloader, .. } => {
|
||||||
browsing_context_changes.insert(browsing_context_id, old_reloader.clone());
|
browsing_context_changes.insert(browsing_context_id, old_reloader.clone());
|
||||||
},
|
},
|
||||||
SessionHistoryDiff::PipelineDiff { ref pipeline_reloader, old_history_state_id, .. } => {
|
SessionHistoryDiff::PipelineDiff {
|
||||||
// TODO(cbrewster): Handle the case where the pipeline needs to be reloaded.
|
ref pipeline_reloader,
|
||||||
// We should use the history state URL to change the URL that is reloaded.
|
old_history_state_id,
|
||||||
if let NeedsToReload::No(pipeline_id) = *pipeline_reloader {
|
ref old_url,
|
||||||
pipeline_changes.insert(pipeline_id, old_history_state_id);
|
..
|
||||||
|
} => match *pipeline_reloader {
|
||||||
|
NeedsToReload::No(pipeline_id) => {
|
||||||
|
pipeline_changes.insert(pipeline_id, (old_history_state_id, old_url.clone()));
|
||||||
|
}
|
||||||
|
NeedsToReload::Yes(pipeline_id, ..) => {
|
||||||
|
url_to_load.insert(pipeline_id, old_url.clone());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1993,12 +2005,17 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (browsing_context_id, pipeline_id) in browsing_context_changes.drain() {
|
for (browsing_context_id, mut pipeline_reloader) in browsing_context_changes.drain() {
|
||||||
self.update_browsing_context(browsing_context_id, pipeline_id);
|
if let NeedsToReload::Yes(pipeline_id, ref mut load_data) = pipeline_reloader {
|
||||||
|
if let Some(url) = url_to_load.get(&pipeline_id) {
|
||||||
|
load_data.url = url.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.update_browsing_context(browsing_context_id, pipeline_reloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pipeline_id, history_state_id) in pipeline_changes.drain() {
|
for (pipeline_id, (history_state_id, url)) in pipeline_changes.drain() {
|
||||||
self.update_pipeline(pipeline_id, history_state_id);
|
self.update_pipeline(pipeline_id, history_state_id, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.notify_history_changed(top_level_browsing_context_id);
|
self.notify_history_changed(top_level_browsing_context_id);
|
||||||
|
@ -2076,12 +2093,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pipeline(&mut self, pipeline_id: PipelineId, history_state_id: Option<HistoryStateId>) {
|
fn update_pipeline(&mut self, pipeline_id: PipelineId, history_state_id: Option<HistoryStateId>, url: ServoUrl) {
|
||||||
let result = match self.pipelines.get_mut(&pipeline_id) {
|
let result = match self.pipelines.get_mut(&pipeline_id) {
|
||||||
None => return warn!("Pipeline {} history state updated after closure", pipeline_id),
|
None => return warn!("Pipeline {} history state updated after closure", pipeline_id),
|
||||||
Some(pipeline) => {
|
Some(pipeline) => {
|
||||||
let msg = ConstellationControlMsg::UpdateHistoryStateId(pipeline_id, history_state_id);
|
let msg = ConstellationControlMsg::UpdateHistoryState(pipeline_id, history_state_id, url.clone());
|
||||||
pipeline.history_state_id = history_state_id;
|
pipeline.history_state_id = history_state_id;
|
||||||
|
pipeline.url = url;
|
||||||
pipeline.event_loop.send(msg)
|
pipeline.event_loop.send(msg)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -2100,13 +2118,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let _ = sender.send(length as u32);
|
let _ = sender.send(length as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_push_history_state_msg(&mut self, pipeline_id: PipelineId, history_state_id: HistoryStateId) {
|
fn handle_push_history_state_msg(
|
||||||
let (top_level_browsing_context_id, old_state_id) = match self.pipelines.get_mut(&pipeline_id) {
|
&mut self,
|
||||||
|
pipeline_id: PipelineId,
|
||||||
|
history_state_id: HistoryStateId,
|
||||||
|
url: ServoUrl)
|
||||||
|
{
|
||||||
|
let (top_level_browsing_context_id, old_state_id, old_url) = match self.pipelines.get_mut(&pipeline_id) {
|
||||||
Some(pipeline) => {
|
Some(pipeline) => {
|
||||||
let old_history_state_id = pipeline.history_state_id;
|
let old_history_state_id = pipeline.history_state_id;
|
||||||
|
let old_url = replace(&mut pipeline.url, url.clone());
|
||||||
pipeline.history_state_id = Some(history_state_id);
|
pipeline.history_state_id = Some(history_state_id);
|
||||||
pipeline.history_states.insert(history_state_id);
|
pipeline.history_states.insert(history_state_id);
|
||||||
(pipeline.top_level_browsing_context_id, old_history_state_id)
|
(pipeline.top_level_browsing_context_id, old_history_state_id, old_url)
|
||||||
}
|
}
|
||||||
None => return warn!("Push history state {} for closed pipeline {}", history_state_id, pipeline_id),
|
None => return warn!("Push history state {} for closed pipeline {}", history_state_id, pipeline_id),
|
||||||
};
|
};
|
||||||
|
@ -2115,18 +2139,30 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let diff = SessionHistoryDiff::PipelineDiff {
|
let diff = SessionHistoryDiff::PipelineDiff {
|
||||||
pipeline_reloader: NeedsToReload::No(pipeline_id),
|
pipeline_reloader: NeedsToReload::No(pipeline_id),
|
||||||
new_history_state_id: history_state_id,
|
new_history_state_id: history_state_id,
|
||||||
|
new_url: url,
|
||||||
old_history_state_id: old_state_id,
|
old_history_state_id: old_state_id,
|
||||||
|
old_url: old_url,
|
||||||
};
|
};
|
||||||
session_history.push_diff(diff);
|
session_history.push_diff(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_replace_history_state_msg(&mut self, pipeline_id: PipelineId, history_state_id: HistoryStateId) {
|
fn handle_replace_history_state_msg(
|
||||||
match self.pipelines.get_mut(&pipeline_id) {
|
&mut self,
|
||||||
|
pipeline_id: PipelineId,
|
||||||
|
history_state_id: HistoryStateId,
|
||||||
|
url: ServoUrl)
|
||||||
|
{
|
||||||
|
let top_level_browsing_context_id = match self.pipelines.get_mut(&pipeline_id) {
|
||||||
Some(pipeline) => {
|
Some(pipeline) => {
|
||||||
pipeline.history_state_id = Some(history_state_id);
|
pipeline.history_state_id = Some(history_state_id);
|
||||||
|
pipeline.url = url.clone();
|
||||||
|
pipeline.top_level_browsing_context_id
|
||||||
}
|
}
|
||||||
None => return warn!("Replace history state {} for closed pipeline {}", history_state_id, pipeline_id),
|
None => return warn!("Replace history state {} for closed pipeline {}", history_state_id, pipeline_id),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let session_history = self.get_joint_session_history(top_level_browsing_context_id);
|
||||||
|
session_history.replace_history_state(pipeline_id, history_state_id, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_key_msg(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) {
|
fn handle_key_msg(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) {
|
||||||
|
@ -2493,7 +2529,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) = change.replace {
|
let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) = change.replace {
|
||||||
let session_history = self.joint_session_histories
|
let session_history = self.joint_session_histories
|
||||||
.entry(change.top_level_browsing_context_id).or_insert(JointSessionHistory::new());
|
.entry(change.top_level_browsing_context_id).or_insert(JointSessionHistory::new());
|
||||||
session_history.replace(replace_reloader.clone(),
|
session_history.replace_reloader(replace_reloader.clone(),
|
||||||
NeedsToReload::No(change.new_pipeline_id));
|
NeedsToReload::No(change.new_pipeline_id));
|
||||||
|
|
||||||
match replace_reloader {
|
match replace_reloader {
|
||||||
|
@ -2595,7 +2631,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let mut dead_pipelines = vec![];
|
let mut dead_pipelines = vec![];
|
||||||
for evicted_id in pipelines_to_evict {
|
for evicted_id in pipelines_to_evict {
|
||||||
let load_data = match self.pipelines.get(&evicted_id) {
|
let load_data = match self.pipelines.get(&evicted_id) {
|
||||||
Some(pipeline) => pipeline.load_data.clone(),
|
Some(pipeline) => {
|
||||||
|
let mut load_data = pipeline.load_data.clone();
|
||||||
|
load_data.url = pipeline.url.clone();
|
||||||
|
load_data
|
||||||
|
},
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2606,7 +2646,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let session_history = self.get_joint_session_history(top_level_browsing_context_id);
|
let session_history = self.get_joint_session_history(top_level_browsing_context_id);
|
||||||
|
|
||||||
for (alive_id, dead) in dead_pipelines {
|
for (alive_id, dead) in dead_pipelines {
|
||||||
session_history.replace(NeedsToReload::No(alive_id), dead);
|
session_history.replace_reloader(NeedsToReload::No(alive_id), dead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId};
|
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId};
|
||||||
use script_traits::LoadData;
|
use script_traits::LoadData;
|
||||||
|
use servo_url::ServoUrl;
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
|
|
||||||
|
@ -37,9 +38,29 @@ impl JointSessionHistory {
|
||||||
mem::replace(&mut self.future, vec![])
|
mem::replace(&mut self.future, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace(&mut self, old_reloader: NeedsToReload, new_reloader: NeedsToReload) {
|
pub fn replace_reloader(&mut self, old_reloader: NeedsToReload, new_reloader: NeedsToReload) {
|
||||||
for diff in self.past.iter_mut().chain(self.future.iter_mut()) {
|
for diff in self.past.iter_mut().chain(self.future.iter_mut()) {
|
||||||
diff.replace(&old_reloader, &new_reloader);
|
diff.replace_reloader(&old_reloader, &new_reloader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace_history_state(&mut self, pipeline_id: PipelineId, history_state_id: HistoryStateId, url: ServoUrl) {
|
||||||
|
if let Some(SessionHistoryDiff::PipelineDiff { ref mut new_history_state_id, ref mut new_url, .. }) =
|
||||||
|
self.past.iter_mut().find(|diff| match diff {
|
||||||
|
SessionHistoryDiff::PipelineDiff { pipeline_reloader: NeedsToReload::No(id), .. } => pipeline_id == *id,
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
*new_history_state_id = history_state_id;
|
||||||
|
*new_url = url.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(SessionHistoryDiff::PipelineDiff { ref mut old_history_state_id, ref mut old_url, .. }) =
|
||||||
|
self.future.iter_mut().find(|diff| match diff {
|
||||||
|
SessionHistoryDiff::PipelineDiff { pipeline_reloader: NeedsToReload::No(id), .. } => pipeline_id == *id,
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
*old_history_state_id = Some(history_state_id);
|
||||||
|
*old_url = url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,8 +167,12 @@ pub enum SessionHistoryDiff {
|
||||||
pipeline_reloader: NeedsToReload,
|
pipeline_reloader: NeedsToReload,
|
||||||
/// The old history state id.
|
/// The old history state id.
|
||||||
old_history_state_id: Option<HistoryStateId>,
|
old_history_state_id: Option<HistoryStateId>,
|
||||||
|
/// The old url
|
||||||
|
old_url: ServoUrl,
|
||||||
/// The new history state id.
|
/// The new history state id.
|
||||||
new_history_state_id: HistoryStateId,
|
new_history_state_id: HistoryStateId,
|
||||||
|
/// The new url
|
||||||
|
new_url: ServoUrl,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +204,7 @@ impl SessionHistoryDiff {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces all occurances of the replaced pipeline with a new pipeline
|
/// Replaces all occurances of the replaced pipeline with a new pipeline
|
||||||
pub fn replace(&mut self, replaced_reloader: &NeedsToReload, reloader: &NeedsToReload) {
|
pub fn replace_reloader(&mut self, replaced_reloader: &NeedsToReload, reloader: &NeedsToReload) {
|
||||||
match *self {
|
match *self {
|
||||||
SessionHistoryDiff::BrowsingContextDiff { ref mut old_reloader, ref mut new_reloader, .. } => {
|
SessionHistoryDiff::BrowsingContextDiff { ref mut old_reloader, ref mut new_reloader, .. } => {
|
||||||
if *old_reloader == *replaced_reloader {
|
if *old_reloader == *replaced_reloader {
|
||||||
|
|
|
@ -12,8 +12,10 @@ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::root::{Dom, DomRoot};
|
use dom::bindings::root::{Dom, DomRoot};
|
||||||
use dom::bindings::str::{DOMString, USVString};
|
use dom::bindings::str::{DOMString, USVString};
|
||||||
use dom::bindings::structuredclone::StructuredCloneData;
|
use dom::bindings::structuredclone::StructuredCloneData;
|
||||||
|
use dom::event::Event;
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
|
use dom::hashchangeevent::HashChangeEvent;
|
||||||
use dom::popstateevent::PopStateEvent;
|
use dom::popstateevent::PopStateEvent;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -71,8 +73,22 @@ impl History {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#history-traversal
|
||||||
|
// Steps 5-16
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn activate_state(&self, state_id: Option<HistoryStateId>) {
|
pub fn activate_state(&self, state_id: Option<HistoryStateId>, url: ServoUrl) {
|
||||||
|
// Steps 5
|
||||||
|
let document = self.window.Document();
|
||||||
|
let old_url = document.url().clone();
|
||||||
|
document.set_url(url.clone());
|
||||||
|
|
||||||
|
// Step 6
|
||||||
|
let hash_changed = old_url.fragment() != url.fragment();
|
||||||
|
|
||||||
|
// TODO: Step 8 - scroll restoration
|
||||||
|
|
||||||
|
// Step 11
|
||||||
|
let state_changed = state_id != self.state_id.get();
|
||||||
self.state_id.set(state_id);
|
self.state_id.set(state_id);
|
||||||
let serialized_data = match state_id {
|
let serialized_data = match state_id {
|
||||||
Some(state_id) => {
|
Some(state_id) => {
|
||||||
|
@ -98,8 +114,26 @@ impl History {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
// TODO: Queue events on DOM Manipulation task source if non-blocking flag is set.
|
||||||
PopStateEvent::dispatch_jsval(self.window.upcast::<EventTarget>(), &*self.window, self.state.handle());
|
// Step 16.1
|
||||||
|
if state_changed {
|
||||||
|
PopStateEvent::dispatch_jsval(
|
||||||
|
self.window.upcast::<EventTarget>(),
|
||||||
|
&*self.window,
|
||||||
|
unsafe { self.state.handle() }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 16.3
|
||||||
|
if hash_changed {
|
||||||
|
let event = HashChangeEvent::new(
|
||||||
|
&self.window,
|
||||||
|
atom!("hashchange"),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
old_url.into_string(),
|
||||||
|
url.into_string());
|
||||||
|
event.upcast::<Event>().fire(self.window.upcast::<EventTarget>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +209,7 @@ impl History {
|
||||||
PushOrReplace::Push => {
|
PushOrReplace::Push => {
|
||||||
let state_id = HistoryStateId::new();
|
let state_id = HistoryStateId::new();
|
||||||
self.state_id.set(Some(state_id));
|
self.state_id.set(Some(state_id));
|
||||||
let msg = ScriptMsg::PushHistoryState(state_id);
|
let msg = ScriptMsg::PushHistoryState(state_id, new_url.clone());
|
||||||
let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
|
let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
|
||||||
state_id
|
state_id
|
||||||
},
|
},
|
||||||
|
@ -188,7 +222,7 @@ impl History {
|
||||||
state_id
|
state_id
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let msg = ScriptMsg::ReplaceHistoryState(state_id);
|
let msg = ScriptMsg::ReplaceHistoryState(state_id, new_url.clone());
|
||||||
let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
|
let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
|
||||||
state_id
|
state_id
|
||||||
},
|
},
|
||||||
|
|
|
@ -1169,7 +1169,7 @@ impl ScriptThread {
|
||||||
Navigate(id, ..) => Some(id),
|
Navigate(id, ..) => Some(id),
|
||||||
PostMessage(id, ..) => Some(id),
|
PostMessage(id, ..) => Some(id),
|
||||||
UpdatePipelineId(_, _, id, _) => Some(id),
|
UpdatePipelineId(_, _, id, _) => Some(id),
|
||||||
UpdateHistoryStateId(id, ..) => Some(id),
|
UpdateHistoryState(id, ..) => Some(id),
|
||||||
RemoveHistoryStates(id, ..) => Some(id),
|
RemoveHistoryStates(id, ..) => Some(id),
|
||||||
FocusIFrame(id, ..) => Some(id),
|
FocusIFrame(id, ..) => Some(id),
|
||||||
WebDriverScriptCommand(id, ..) => Some(id),
|
WebDriverScriptCommand(id, ..) => Some(id),
|
||||||
|
@ -1297,8 +1297,8 @@ impl ScriptThread {
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
new_pipeline_id,
|
new_pipeline_id,
|
||||||
reason),
|
reason),
|
||||||
ConstellationControlMsg::UpdateHistoryStateId(pipeline_id, history_state_id) =>
|
ConstellationControlMsg::UpdateHistoryState(pipeline_id, history_state_id, url) =>
|
||||||
self.handle_update_history_state_id_msg(pipeline_id, history_state_id),
|
self.handle_update_history_state_msg(pipeline_id, history_state_id, url),
|
||||||
ConstellationControlMsg::RemoveHistoryStates(pipeline_id, history_states) =>
|
ConstellationControlMsg::RemoveHistoryStates(pipeline_id, history_states) =>
|
||||||
self.handle_remove_history_states(pipeline_id, history_states),
|
self.handle_remove_history_states(pipeline_id, history_states),
|
||||||
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
|
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
|
||||||
|
@ -1679,10 +1679,14 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_update_history_state_id_msg(&self, pipeline_id: PipelineId, history_state_id: Option<HistoryStateId>) {
|
fn handle_update_history_state_msg(
|
||||||
|
&self, pipeline_id: PipelineId,
|
||||||
|
history_state_id: Option<HistoryStateId>,
|
||||||
|
url: ServoUrl,
|
||||||
|
) {
|
||||||
match { self.documents.borrow().find_window(pipeline_id) } {
|
match { self.documents.borrow().find_window(pipeline_id) } {
|
||||||
None => return warn!("update history state after pipeline {} closed.", pipeline_id),
|
None => return warn!("update history state after pipeline {} closed.", pipeline_id),
|
||||||
Some(window) => window.History().r().activate_state(history_state_id),
|
Some(window) => window.History().r().activate_state(history_state_id, url),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,8 +289,8 @@ pub enum ConstellationControlMsg {
|
||||||
/// Updates the current pipeline ID of a given iframe.
|
/// Updates the current pipeline ID of a given iframe.
|
||||||
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
||||||
UpdatePipelineId(PipelineId, BrowsingContextId, PipelineId, UpdatePipelineIdReason),
|
UpdatePipelineId(PipelineId, BrowsingContextId, PipelineId, UpdatePipelineIdReason),
|
||||||
/// Updates the history state of a given pipeline.
|
/// Updates the history state and url of a given pipeline.
|
||||||
UpdateHistoryStateId(PipelineId, Option<HistoryStateId>),
|
UpdateHistoryState(PipelineId, Option<HistoryStateId>, ServoUrl),
|
||||||
/// Removes inaccesible history states.
|
/// Removes inaccesible history states.
|
||||||
RemoveHistoryStates(PipelineId, Vec<HistoryStateId>),
|
RemoveHistoryStates(PipelineId, Vec<HistoryStateId>),
|
||||||
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
|
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
|
||||||
|
@ -347,7 +347,7 @@ impl fmt::Debug for ConstellationControlMsg {
|
||||||
Navigate(..) => "Navigate",
|
Navigate(..) => "Navigate",
|
||||||
PostMessage(..) => "PostMessage",
|
PostMessage(..) => "PostMessage",
|
||||||
UpdatePipelineId(..) => "UpdatePipelineId",
|
UpdatePipelineId(..) => "UpdatePipelineId",
|
||||||
UpdateHistoryStateId(..) => "UpdateHistoryStateId",
|
UpdateHistoryState(..) => "UpdateHistoryState",
|
||||||
RemoveHistoryStates(..) => "RemoveHistoryStates",
|
RemoveHistoryStates(..) => "RemoveHistoryStates",
|
||||||
FocusIFrame(..) => "FocusIFrame",
|
FocusIFrame(..) => "FocusIFrame",
|
||||||
WebDriverScriptCommand(..) => "WebDriverScriptCommand",
|
WebDriverScriptCommand(..) => "WebDriverScriptCommand",
|
||||||
|
|
|
@ -105,9 +105,9 @@ pub enum ScriptMsg {
|
||||||
/// HTMLIFrameElement Forward or Back traversal.
|
/// HTMLIFrameElement Forward or Back traversal.
|
||||||
TraverseHistory(TraversalDirection),
|
TraverseHistory(TraversalDirection),
|
||||||
/// Inform the constellation of a pushed history state.
|
/// Inform the constellation of a pushed history state.
|
||||||
PushHistoryState(HistoryStateId),
|
PushHistoryState(HistoryStateId, ServoUrl),
|
||||||
/// Inform the constellation of a replaced history state.
|
/// Inform the constellation of a replaced history state.
|
||||||
ReplaceHistoryState(HistoryStateId),
|
ReplaceHistoryState(HistoryStateId, ServoUrl),
|
||||||
/// Gets the length of the joint session history from the constellation.
|
/// Gets the length of the joint session history from the constellation.
|
||||||
JointSessionHistoryLength(IpcSender<u32>),
|
JointSessionHistoryLength(IpcSender<u32>),
|
||||||
/// Favicon detected
|
/// Favicon detected
|
||||||
|
|
|
@ -327481,6 +327481,12 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"html/browsers/history/the-history-interface/history_pushstate_url.html": [
|
||||||
|
[
|
||||||
|
"/html/browsers/history/the-history-interface/history_pushstate_url.html",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"html/browsers/history/the-history-interface/history_replacestate.html": [
|
"html/browsers/history/the-history-interface/history_replacestate.html": [
|
||||||
[
|
[
|
||||||
"/html/browsers/history/the-history-interface/history_replacestate.html",
|
"/html/browsers/history/the-history-interface/history_replacestate.html",
|
||||||
|
@ -554878,6 +554884,10 @@
|
||||||
"8add09b76d8662f4343188a1ac36fe71fd4a225d",
|
"8add09b76d8662f4343188a1ac36fe71fd4a225d",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
|
"html/browsers/history/the-history-interface/history_pushstate_url.html": [
|
||||||
|
"d5e1649c88102f27da5fe1ac16715cfee7f70f84",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
"html/browsers/history/the-history-interface/history_replacestate.html": [
|
"html/browsers/history/the-history-interface/history_replacestate.html": [
|
||||||
"91cf4970bfa565ee8b846582bdbe608d38902fe7",
|
"91cf4970bfa565ee8b846582bdbe608d38902fe7",
|
||||||
"testharness"
|
"testharness"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
[scroll-restoration-fragment-scrolling-samedoc.html]
|
[scroll-restoration-fragment-scrolling-samedoc.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
bug: https://github.com/servo/servo/issues/14970
|
bug: https://github.com/servo/servo/issues/14970
|
||||||
[Manual scroll restoration should take precedent over scrolling to fragment in cross doc navigation]
|
[Manual scroll restoration should take precedent over scrolling to fragment in cross doc navigation]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
[scroll-restoration-navigation-samedoc.html]
|
[scroll-restoration-navigation-samedoc.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
bug: https://github.com/servo/servo/issues/14970
|
bug: https://github.com/servo/servo/issues/14970
|
||||||
[history.{push,replace}State retain scroll restoration mode and navigation in the same document respects it]
|
[history.{push,replace}State retain scroll restoration mode and navigation in the same document respects it]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>History pushState sets the url</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
async_test(function(t) {
|
||||||
|
var oldLocation = window.location.toString();
|
||||||
|
window.history.pushState(null, "", "#hash");
|
||||||
|
assert_equals(oldLocation + "#hash", window.location.toString(), "pushState updates url");
|
||||||
|
history.back();
|
||||||
|
window.onhashchange = () => {
|
||||||
|
assert_equals(oldLocation, window.location.toString(), 'history traversal restores old url');
|
||||||
|
t.done();
|
||||||
|
};
|
||||||
|
}, "history pushState sets url");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue