Scope Servo live runtimes by profile
This commit is contained in:
@@ -31,7 +31,7 @@ pub(crate) fn transient_profile_data_dir(
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub(crate) enum ProfileDataMode {
|
pub(crate) enum ProfileDataMode {
|
||||||
Persistent,
|
Persistent,
|
||||||
Transient,
|
Transient,
|
||||||
|
|||||||
@@ -16,13 +16,23 @@ use super::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub(super) struct WebSurfaceRuntime {
|
pub(super) struct WebSurfaceRuntime {
|
||||||
state: RuntimeState,
|
clients: BTreeMap<WebSurfaceRuntimeScope, ScopedRuntimeClient>,
|
||||||
sessions: BTreeMap<TabId, WebSurfaceSession>,
|
sessions: BTreeMap<TabId, WebSurfaceSession>,
|
||||||
|
client_factory: LiveRuntimeClientFactory,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSurfaceRuntime {
|
impl WebSurfaceRuntime {
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
Self { state: RuntimeState::Empty, sessions: BTreeMap::new() }
|
Self {
|
||||||
|
clients: BTreeMap::new(),
|
||||||
|
sessions: BTreeMap::new(),
|
||||||
|
client_factory: new_servo_live_client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn new_with_client_factory(client_factory: LiveRuntimeClientFactory) -> Self {
|
||||||
|
Self { clients: BTreeMap::new(), sessions: BTreeMap::new(), client_factory }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn ensure_tab(
|
pub(super) fn ensure_tab(
|
||||||
@@ -38,19 +48,13 @@ impl WebSurfaceRuntime {
|
|||||||
|
|
||||||
let requested_url = tab.url().as_str().to_string();
|
let requested_url = tab.url().as_str().to_string();
|
||||||
let zoom_percent = tab.zoom_percent();
|
let zoom_percent = tab.zoom_percent();
|
||||||
let (state, sessions) = (&mut self.state, &mut self.sessions);
|
|
||||||
let RuntimeState::Ready { scope: active_scope, client, .. } = state else {
|
|
||||||
return Err("Servo live runtime is unavailable".to_string());
|
|
||||||
};
|
|
||||||
if active_scope != &scope {
|
|
||||||
return Err(active_scope.error_for(&scope));
|
|
||||||
}
|
|
||||||
let (scroll_delta_x, scroll_delta_y, scroll_point_x, scroll_point_y) =
|
let (scroll_delta_x, scroll_delta_y, scroll_point_x, scroll_point_y) =
|
||||||
scroll_wire_fields(input.scroll_delta, input.scroll_point)?;
|
scroll_wire_fields(input.scroll_delta, input.scroll_point)?;
|
||||||
let user_navigation_input = input_requests_history_navigation(&input);
|
let user_navigation_input = input_requests_history_navigation(&input);
|
||||||
|
|
||||||
let session = sessions.entry(tab.id().clone()).or_insert_with(WebSurfaceSession::default);
|
|
||||||
let next_scroll_offset = input.scroll_offset;
|
let next_scroll_offset = input.scroll_offset;
|
||||||
|
let started_loading = {
|
||||||
|
let session = session_for_scope(&mut self.sessions, tab.id(), scope.clone());
|
||||||
let started_loading = session.started_loading(&requested_url, size, zoom_percent);
|
let started_loading = session.started_loading(&requested_url, size, zoom_percent);
|
||||||
if started_loading {
|
if started_loading {
|
||||||
session.pending_user_navigation = false;
|
session.pending_user_navigation = false;
|
||||||
@@ -58,7 +62,11 @@ impl WebSurfaceRuntime {
|
|||||||
if user_navigation_input {
|
if user_navigation_input {
|
||||||
session.pending_user_navigation = true;
|
session.pending_user_navigation = true;
|
||||||
}
|
}
|
||||||
let frame = client
|
started_loading
|
||||||
|
};
|
||||||
|
|
||||||
|
let frame = self
|
||||||
|
.client_for_scope(&scope)?
|
||||||
.ensure(ServoLiveEnsureRequest {
|
.ensure(ServoLiveEnsureRequest {
|
||||||
tab_id: tab.id().as_str().to_string(),
|
tab_id: tab.id().as_str().to_string(),
|
||||||
profile_id: tab.profile_id().as_str().to_string(),
|
profile_id: tab.profile_id().as_str().to_string(),
|
||||||
@@ -77,8 +85,7 @@ impl WebSurfaceRuntime {
|
|||||||
hover_y: input.hover_point.map(|point| point.y()),
|
hover_y: input.hover_point.map(|point| point.y()),
|
||||||
typed_text: input.typed_text,
|
typed_text: input.typed_text,
|
||||||
site_permissions: permissions.iter().map(ServoLiveSitePermission::from).collect(),
|
site_permissions: permissions.iter().map(ServoLiveSitePermission::from).collect(),
|
||||||
})
|
})?
|
||||||
.map_err(|error| error.to_string())?
|
|
||||||
.map(|frame| {
|
.map(|frame| {
|
||||||
WebSurfaceFrame::from_live_frame(
|
WebSurfaceFrame::from_live_frame(
|
||||||
requested_url.clone(),
|
requested_url.clone(),
|
||||||
@@ -89,10 +96,13 @@ impl WebSurfaceRuntime {
|
|||||||
.map_err(|error| error.to_string())
|
.map_err(|error| error.to_string())
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let url_change = frame
|
let url_change = frame.as_ref().and_then(|frame| {
|
||||||
.as_ref()
|
self.sessions
|
||||||
.and_then(|frame| session.url_change_for(tab.id(), requested_url.as_str(), frame));
|
.get_mut(tab.id())
|
||||||
|
.and_then(|session| session.url_change_for(tab.id(), requested_url.as_str(), frame))
|
||||||
|
});
|
||||||
|
|
||||||
|
let session = session_for_scope(&mut self.sessions, tab.id(), scope);
|
||||||
session.requested_url = requested_url.clone();
|
session.requested_url = requested_url.clone();
|
||||||
session.size = size;
|
session.size = size;
|
||||||
session.zoom_percent = zoom_percent;
|
session.zoom_percent = zoom_percent;
|
||||||
@@ -102,43 +112,37 @@ impl WebSurfaceRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn tick(&mut self, visible_tab_ids: &[TabId]) -> Vec<WebSurfaceRuntimeFrame> {
|
pub(super) fn tick(&mut self, visible_tab_ids: &[TabId]) -> Vec<WebSurfaceRuntimeFrame> {
|
||||||
let (state, sessions) = (&mut self.state, &mut self.sessions);
|
|
||||||
let RuntimeState::Ready { client, .. } = state else {
|
|
||||||
return Vec::new();
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut frames = Vec::new();
|
let mut frames = Vec::new();
|
||||||
for (tab_id, session) in sessions {
|
for job in visible_poll_jobs(&self.sessions, visible_tab_ids) {
|
||||||
if !visible_tab_ids.iter().any(|visible_tab_id| visible_tab_id == tab_id) {
|
let result = match self.clients.get_mut(&job.scope) {
|
||||||
continue;
|
Some(client) => client.client.poll(job.tab_id.as_str().to_string()),
|
||||||
}
|
None => Err(missing_runtime_message(&job.scope)),
|
||||||
match client.poll(tab_id.as_str().to_string()) {
|
};
|
||||||
|
match result {
|
||||||
Ok(Some(frame)) => match WebSurfaceFrame::from_live_frame(
|
Ok(Some(frame)) => match WebSurfaceFrame::from_live_frame(
|
||||||
session.requested_url.clone(),
|
job.requested_url.clone(),
|
||||||
session.scroll_offset,
|
job.scroll_offset,
|
||||||
session.zoom_percent,
|
job.zoom_percent,
|
||||||
frame,
|
frame,
|
||||||
) {
|
) {
|
||||||
Ok(frame) => {
|
Ok(frame) => {
|
||||||
let requested_url = session.requested_url.clone();
|
let url_change = self.sessions.get_mut(&job.tab_id).and_then(|session| {
|
||||||
let url_change =
|
session.url_change_for(&job.tab_id, job.requested_url.as_str(), &frame)
|
||||||
session.url_change_for(tab_id, requested_url.as_str(), &frame);
|
});
|
||||||
frames.push(WebSurfaceRuntimeFrame::Ready {
|
frames.push(WebSurfaceRuntimeFrame::Ready {
|
||||||
tab_id: tab_id.clone(),
|
tab_id: job.tab_id,
|
||||||
frame: Box::new(frame),
|
frame: Box::new(frame),
|
||||||
url_change,
|
url_change,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(error) => frames.push(WebSurfaceRuntimeFrame::Failed {
|
Err(error) => frames.push(WebSurfaceRuntimeFrame::Failed {
|
||||||
tab_id: tab_id.clone(),
|
tab_id: job.tab_id,
|
||||||
message: error.to_string(),
|
message: error.to_string(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
Err(error) => frames.push(WebSurfaceRuntimeFrame::Failed {
|
Err(error) => frames
|
||||||
tab_id: tab_id.clone(),
|
.push(WebSurfaceRuntimeFrame::Failed { tab_id: job.tab_id, message: error }),
|
||||||
message: error.to_string(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,38 +150,82 @@ impl WebSurfaceRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_runtime(&mut self, scope: WebSurfaceRuntimeScope) -> Result<(), String> {
|
fn ensure_runtime(&mut self, scope: WebSurfaceRuntimeScope) -> Result<(), String> {
|
||||||
match &self.state {
|
if self.clients.contains_key(&scope) {
|
||||||
RuntimeState::Empty => {
|
return Ok(());
|
||||||
|
}
|
||||||
let (config_dir, transient_profile_data_dir) = config_dir_for_scope(&scope)?;
|
let (config_dir, transient_profile_data_dir) = config_dir_for_scope(&scope)?;
|
||||||
let client = ServoLiveClient::new(config_dir).map_err(|error| error.to_string())?;
|
let client = (self.client_factory)(config_dir)?;
|
||||||
self.state = RuntimeState::Ready { scope, client, transient_profile_data_dir };
|
self.clients.insert(scope, ScopedRuntimeClient { client, transient_profile_data_dir });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
RuntimeState::Ready { scope: active_scope, .. } if active_scope == &scope => Ok(()),
|
|
||||||
RuntimeState::Ready { scope: active_scope, .. } => Err(active_scope.error_for(&scope)),
|
fn client_for_scope(
|
||||||
|
&mut self,
|
||||||
|
scope: &WebSurfaceRuntimeScope,
|
||||||
|
) -> Result<&mut dyn LiveRuntimeClient, String> {
|
||||||
|
match self.clients.get_mut(scope) {
|
||||||
|
Some(client) => Ok(client.client.as_mut()),
|
||||||
|
None => Err(missing_runtime_message(scope)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn client_count_for_test(&self) -> usize {
|
||||||
|
self.clients.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn session_scope_for_test(&self, tab_id: &TabId) -> Option<&WebSurfaceRuntimeScope> {
|
||||||
|
self.sessions.get(tab_id).map(|session| &session.scope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WebSurfaceRuntime {
|
impl Drop for WebSurfaceRuntime {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let RuntimeState::Ready { transient_profile_data_dir: Some(path), .. } = &self.state else {
|
let transient_profile_data_dirs = self
|
||||||
return;
|
.clients
|
||||||
};
|
.values()
|
||||||
|
.filter_map(|client| client.transient_profile_data_dir.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.clients.clear();
|
||||||
|
for path in transient_profile_data_dirs {
|
||||||
let _ = fs::remove_dir_all(path);
|
let _ = fs::remove_dir_all(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RuntimeState {
|
|
||||||
Empty,
|
|
||||||
Ready {
|
|
||||||
scope: WebSurfaceRuntimeScope,
|
|
||||||
client: ServoLiveClient,
|
|
||||||
transient_profile_data_dir: Option<PathBuf>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
type LiveRuntimeClientFactory = fn(PathBuf) -> Result<Box<dyn LiveRuntimeClient>, String>;
|
||||||
|
|
||||||
|
trait LiveRuntimeClient {
|
||||||
|
fn ensure(&mut self, request: ServoLiveEnsureRequest) -> Result<Option<WebLiveFrame>, String>;
|
||||||
|
|
||||||
|
fn poll(&mut self, tab_id: String) -> Result<Option<WebLiveFrame>, String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebLiveFrame = crate::services::servo_live::ServoLiveFrame;
|
||||||
|
|
||||||
|
impl LiveRuntimeClient for ServoLiveClient {
|
||||||
|
fn ensure(&mut self, request: ServoLiveEnsureRequest) -> Result<Option<WebLiveFrame>, String> {
|
||||||
|
ServoLiveClient::ensure(self, request).map_err(|error| error.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&mut self, tab_id: String) -> Result<Option<WebLiveFrame>, String> {
|
||||||
|
ServoLiveClient::poll(self, tab_id).map_err(|error| error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_servo_live_client(config_dir: PathBuf) -> Result<Box<dyn LiveRuntimeClient>, String> {
|
||||||
|
ServoLiveClient::new(config_dir)
|
||||||
|
.map(|client| Box::new(client) as Box<dyn LiveRuntimeClient>)
|
||||||
|
.map_err(|error| error.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScopedRuntimeClient {
|
||||||
|
client: Box<dyn LiveRuntimeClient>,
|
||||||
|
transient_profile_data_dir: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
struct WebSurfaceRuntimeScope {
|
struct WebSurfaceRuntimeScope {
|
||||||
profile_id: ProfileId,
|
profile_id: ProfileId,
|
||||||
profile_data_mode: ProfileDataMode,
|
profile_data_mode: ProfileDataMode,
|
||||||
@@ -187,20 +235,11 @@ impl WebSurfaceRuntimeScope {
|
|||||||
fn new(profile_id: ProfileId, profile_data_mode: ProfileDataMode) -> Self {
|
fn new(profile_id: ProfileId, profile_data_mode: ProfileDataMode) -> Self {
|
||||||
Self { profile_id, profile_data_mode }
|
Self { profile_id, profile_data_mode }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_for(&self, requested: &Self) -> String {
|
|
||||||
format!(
|
|
||||||
"Servo live runtime is already attached to profile {} ({:?}); requested profile {} ({:?})",
|
|
||||||
self.profile_id.as_str(),
|
|
||||||
self.profile_data_mode,
|
|
||||||
requested.profile_id.as_str(),
|
|
||||||
requested.profile_data_mode
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone)]
|
||||||
struct WebSurfaceSession {
|
struct WebSurfaceSession {
|
||||||
|
scope: WebSurfaceRuntimeScope,
|
||||||
requested_url: String,
|
requested_url: String,
|
||||||
size: WebSurfaceSize,
|
size: WebSurfaceSize,
|
||||||
zoom_percent: u16,
|
zoom_percent: u16,
|
||||||
@@ -209,6 +248,17 @@ struct WebSurfaceSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WebSurfaceSession {
|
impl WebSurfaceSession {
|
||||||
|
fn new(scope: WebSurfaceRuntimeScope) -> Self {
|
||||||
|
Self {
|
||||||
|
scope,
|
||||||
|
requested_url: String::new(),
|
||||||
|
size: WebSurfaceSize::default(),
|
||||||
|
zoom_percent: 0,
|
||||||
|
scroll_offset: WebSurfaceScrollOffset::default(),
|
||||||
|
pending_user_navigation: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn started_loading(
|
fn started_loading(
|
||||||
&self,
|
&self,
|
||||||
requested_url: &str,
|
requested_url: &str,
|
||||||
@@ -245,6 +295,15 @@ impl WebSurfaceSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct WebSurfacePollJob {
|
||||||
|
tab_id: TabId,
|
||||||
|
scope: WebSurfaceRuntimeScope,
|
||||||
|
requested_url: String,
|
||||||
|
scroll_offset: WebSurfaceScrollOffset,
|
||||||
|
zoom_percent: u16,
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct WebSurfaceEnsureResult {
|
pub(super) struct WebSurfaceEnsureResult {
|
||||||
pub(super) requested_url: String,
|
pub(super) requested_url: String,
|
||||||
pub(super) started_loading: bool,
|
pub(super) started_loading: bool,
|
||||||
@@ -290,6 +349,46 @@ fn config_dir_for_scope(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn session_for_scope<'a>(
|
||||||
|
sessions: &'a mut BTreeMap<TabId, WebSurfaceSession>,
|
||||||
|
tab_id: &TabId,
|
||||||
|
scope: WebSurfaceRuntimeScope,
|
||||||
|
) -> &'a mut WebSurfaceSession {
|
||||||
|
let session =
|
||||||
|
sessions.entry(tab_id.clone()).or_insert_with(|| WebSurfaceSession::new(scope.clone()));
|
||||||
|
if session.scope != scope {
|
||||||
|
*session = WebSurfaceSession::new(scope);
|
||||||
|
}
|
||||||
|
session
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visible_poll_jobs(
|
||||||
|
sessions: &BTreeMap<TabId, WebSurfaceSession>,
|
||||||
|
visible_tab_ids: &[TabId],
|
||||||
|
) -> Vec<WebSurfacePollJob> {
|
||||||
|
sessions
|
||||||
|
.iter()
|
||||||
|
.filter(|(tab_id, _)| {
|
||||||
|
visible_tab_ids.iter().any(|visible_tab_id| visible_tab_id == *tab_id)
|
||||||
|
})
|
||||||
|
.map(|(tab_id, session)| WebSurfacePollJob {
|
||||||
|
tab_id: tab_id.clone(),
|
||||||
|
scope: session.scope.clone(),
|
||||||
|
requested_url: session.requested_url.clone(),
|
||||||
|
scroll_offset: session.scroll_offset,
|
||||||
|
zoom_percent: session.zoom_percent,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn missing_runtime_message(scope: &WebSurfaceRuntimeScope) -> String {
|
||||||
|
format!(
|
||||||
|
"Servo live runtime is unavailable for profile {} ({:?})",
|
||||||
|
scope.profile_id.as_str(),
|
||||||
|
scope.profile_data_mode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn scroll_wire_fields(
|
fn scroll_wire_fields(
|
||||||
delta: Option<super::web_surface_geometry::WebSurfaceScrollDelta>,
|
delta: Option<super::web_surface_geometry::WebSurfaceScrollDelta>,
|
||||||
point: Option<super::web_surface_geometry::WebSurfaceClickPoint>,
|
point: Option<super::web_surface_geometry::WebSurfaceClickPoint>,
|
||||||
@@ -318,3 +417,7 @@ impl From<&WebSurfaceSitePermission> for ServoLiveSitePermission {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "web_surface_runtime_tests.rs"]
|
||||||
|
mod tests;
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use ely_domain::{BrowserTab, ProfileId, SpaceId, TabId, UrlText};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
services::ProfileDataMode,
|
||||||
|
shell::{
|
||||||
|
web_surface_geometry::{WebSurfaceScrollOffset, WebSurfaceSize},
|
||||||
|
web_surface_state::WebSurfacePendingInput,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runtime_keeps_independent_clients_for_profile_scopes() -> Result<(), String> {
|
||||||
|
let mut runtime = WebSurfaceRuntime::new_with_client_factory(fake_client_factory);
|
||||||
|
let first_profile = ProfileId::new();
|
||||||
|
let second_profile = ProfileId::new();
|
||||||
|
let first_tab = web_tab(TabId::new(), first_profile.clone(), "https://example.com/first")?;
|
||||||
|
let second_tab = web_tab(TabId::new(), second_profile.clone(), "https://example.com/second")?;
|
||||||
|
|
||||||
|
runtime.ensure_tab(
|
||||||
|
&first_tab,
|
||||||
|
surface_size(),
|
||||||
|
ProfileDataMode::Transient,
|
||||||
|
&[],
|
||||||
|
pending_input(),
|
||||||
|
)?;
|
||||||
|
runtime.ensure_tab(
|
||||||
|
&second_tab,
|
||||||
|
surface_size(),
|
||||||
|
ProfileDataMode::Transient,
|
||||||
|
&[],
|
||||||
|
pending_input(),
|
||||||
|
)?;
|
||||||
|
runtime.ensure_tab(
|
||||||
|
&first_tab,
|
||||||
|
surface_size(),
|
||||||
|
ProfileDataMode::Transient,
|
||||||
|
&[],
|
||||||
|
pending_input(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_eq!(runtime.client_count_for_test(), 2);
|
||||||
|
assert_eq!(
|
||||||
|
runtime.session_scope_for_test(first_tab.id()),
|
||||||
|
Some(&WebSurfaceRuntimeScope::new(first_profile, ProfileDataMode::Transient)),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
runtime.session_scope_for_test(second_tab.id()),
|
||||||
|
Some(&WebSurfaceRuntimeScope::new(second_profile, ProfileDataMode::Transient)),
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_scope_change_resets_tab_state() {
|
||||||
|
let tab_id = TabId::new();
|
||||||
|
let first_scope = WebSurfaceRuntimeScope::new(ProfileId::new(), ProfileDataMode::Persistent);
|
||||||
|
let second_scope = WebSurfaceRuntimeScope::new(ProfileId::new(), ProfileDataMode::Transient);
|
||||||
|
let mut sessions = BTreeMap::new();
|
||||||
|
|
||||||
|
let session = session_for_scope(&mut sessions, &tab_id, first_scope);
|
||||||
|
session.requested_url = "https://example.com/old".to_string();
|
||||||
|
session.size = surface_size();
|
||||||
|
session.zoom_percent = 150;
|
||||||
|
session.scroll_offset = WebSurfaceScrollOffset::default();
|
||||||
|
session.pending_user_navigation = true;
|
||||||
|
|
||||||
|
let session = session_for_scope(&mut sessions, &tab_id, second_scope.clone());
|
||||||
|
|
||||||
|
assert_eq!(session.scope, second_scope);
|
||||||
|
assert_eq!(session.requested_url, "");
|
||||||
|
assert_eq!(session.size, WebSurfaceSize::default());
|
||||||
|
assert_eq!(session.zoom_percent, 0);
|
||||||
|
assert_eq!(session.scroll_offset, WebSurfaceScrollOffset::default());
|
||||||
|
assert!(!session.pending_user_navigation);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FakeLiveRuntimeClient;
|
||||||
|
|
||||||
|
impl LiveRuntimeClient for FakeLiveRuntimeClient {
|
||||||
|
fn ensure(&mut self, _request: ServoLiveEnsureRequest) -> Result<Option<WebLiveFrame>, String> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&mut self, _tab_id: String) -> Result<Option<WebLiveFrame>, String> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_client_factory(
|
||||||
|
_config_dir: std::path::PathBuf,
|
||||||
|
) -> Result<Box<dyn LiveRuntimeClient>, String> {
|
||||||
|
Ok(Box::new(FakeLiveRuntimeClient))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn web_tab(tab_id: TabId, profile_id: ProfileId, url: &str) -> Result<BrowserTab, String> {
|
||||||
|
let url = UrlText::parse(url).map_err(|error| error.to_string())?;
|
||||||
|
Ok(BrowserTab::new(tab_id, SpaceId::new(), profile_id, "Web", url))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn surface_size() -> WebSurfaceSize {
|
||||||
|
WebSurfaceSize { width: 640, height: 480, device_pixel_ratio_percent: 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pending_input() -> WebSurfacePendingInput {
|
||||||
|
WebSurfacePendingInput {
|
||||||
|
scroll_offset: WebSurfaceScrollOffset::default(),
|
||||||
|
scroll_delta: None,
|
||||||
|
scroll_point: None,
|
||||||
|
click_point: None,
|
||||||
|
hover_point: None,
|
||||||
|
typed_text: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user