mirror of
https://github.com/servo/servo.git
synced 2025-07-24 07:40:27 +01:00
Add thaw/freeze messages that can suspend/resume webcontent timers #4907
This commit is contained in:
parent
dc31d96f65
commit
c2961c94b4
6 changed files with 105 additions and 9 deletions
|
@ -37,7 +37,7 @@ pub struct TimerId(i32);
|
|||
struct TimerHandle {
|
||||
handle: TimerId,
|
||||
data: TimerData,
|
||||
cancel_chan: Option<Sender<()>>,
|
||||
control_chan: Option<Sender<TimerControlMsg>>,
|
||||
}
|
||||
|
||||
#[jstraceable]
|
||||
|
@ -56,7 +56,13 @@ impl<H: Writer + Hasher> Hash<H> for TimerId {
|
|||
|
||||
impl TimerHandle {
|
||||
fn cancel(&mut self) {
|
||||
self.cancel_chan.as_ref().map(|chan| chan.send(()).ok());
|
||||
self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Cancel).ok());
|
||||
}
|
||||
fn suspend(&mut self) {
|
||||
self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Suspend).ok());
|
||||
}
|
||||
fn resume(&mut self) {
|
||||
self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Resume).ok());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,6 +91,15 @@ pub enum IsInterval {
|
|||
NonInterval,
|
||||
}
|
||||
|
||||
// Messages sent control timers from script task
|
||||
#[jstraceable]
|
||||
#[derive(PartialEq, Copy, Clone, Show)]
|
||||
pub enum TimerControlMsg {
|
||||
Cancel,
|
||||
Suspend,
|
||||
Resume
|
||||
}
|
||||
|
||||
// Holder for the various JS values associated with setTimeout
|
||||
// (ie. function value to invoke and all arguments to pass
|
||||
// to the function when calling it)
|
||||
|
@ -106,6 +121,17 @@ impl TimerManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn suspend(&self) {
|
||||
for (_, timer_handle) in self.active_timers.borrow_mut().iter_mut() {
|
||||
timer_handle.suspend();
|
||||
}
|
||||
}
|
||||
pub fn resume(&self) {
|
||||
for (_, timer_handle) in self.active_timers.borrow_mut().iter_mut() {
|
||||
timer_handle.resume();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_blocks)]
|
||||
pub fn set_timeout_or_interval(&self,
|
||||
callback: TimerCallback,
|
||||
|
@ -122,7 +148,7 @@ impl TimerManager {
|
|||
// Spawn a new timer task; it will dispatch the `ScriptMsg::FireTimer`
|
||||
// to the relevant script handler that will deal with it.
|
||||
let tm = Timer::new().unwrap();
|
||||
let (cancel_chan, cancel_port) = channel();
|
||||
let (control_chan, control_port) = channel();
|
||||
let spawn_name = match source {
|
||||
TimerSource::FromWindow(_) if is_interval == IsInterval::Interval => "Window:SetInterval",
|
||||
TimerSource::FromWorker if is_interval == IsInterval::Interval => "Worker:SetInterval",
|
||||
|
@ -137,31 +163,47 @@ impl TimerManager {
|
|||
} else {
|
||||
tm.oneshot(duration)
|
||||
};
|
||||
let cancel_port = cancel_port;
|
||||
let control_port = control_port;
|
||||
|
||||
let select = Select::new();
|
||||
let mut timeout_handle = select.handle(&timeout_port);
|
||||
unsafe { timeout_handle.add() };
|
||||
let mut cancel_handle = select.handle(&cancel_port);
|
||||
unsafe { cancel_handle.add() };
|
||||
let mut control_handle = select.handle(&control_port);
|
||||
unsafe { control_handle.add() };
|
||||
|
||||
loop {
|
||||
let id = select.wait();
|
||||
|
||||
if id == timeout_handle.id() {
|
||||
timeout_port.recv().unwrap();
|
||||
script_chan.send(ScriptMsg::FireTimer(source, TimerId(handle)));
|
||||
if is_interval == IsInterval::NonInterval {
|
||||
break;
|
||||
}
|
||||
} else if id == cancel_handle.id() {
|
||||
break;
|
||||
} else if id == control_handle.id() {;
|
||||
match control_port.recv().unwrap() {
|
||||
TimerControlMsg::Suspend => {
|
||||
let msg = control_port.recv().unwrap();
|
||||
match msg {
|
||||
TimerControlMsg::Suspend => panic!("Nothing to suspend!"),
|
||||
TimerControlMsg::Resume => {},
|
||||
TimerControlMsg::Cancel => {
|
||||
break;
|
||||
},
|
||||
}
|
||||
},
|
||||
TimerControlMsg::Resume => panic!("Nothing to resume!"),
|
||||
TimerControlMsg::Cancel => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let timer_id = TimerId(handle);
|
||||
let timer = TimerHandle {
|
||||
handle: timer_id,
|
||||
cancel_chan: Some(cancel_chan),
|
||||
control_chan: Some(control_chan),
|
||||
data: TimerData {
|
||||
is_interval: is_interval,
|
||||
callback: callback,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue