// Test that when the animation delegate is null, the animation player // doesn't forward the finish notification. TEST(WebCompositorAnimationPlayerTest, NullDelegate) { scoped_ptr<WebCompositorAnimationDelegate> delegate( new MockWebCompositorAnimationDelegate); EXPECT_CALL(*static_cast<MockWebCompositorAnimationDelegate*>(delegate.get()), notifyAnimationFinished(_, _)) .Times(1); scoped_ptr<CompositorAnimationPlayer> webPlayer(new CompositorAnimationPlayer); cc::AnimationPlayer* player = webPlayer->animationPlayer(); webPlayer->setAnimationDelegate(delegate.get()); player->NotifyAnimationFinished(TimeTicks(), CompositorTargetProperty::SCROLL_OFFSET, 0); webPlayer->setAnimationDelegate(nullptr); player->NotifyAnimationFinished(TimeTicks(), CompositorTargetProperty::SCROLL_OFFSET, 0); }
PendingTask::PendingTask(const tracked_objects::Location& posted_from, const base::Closure& task) : base::TrackingInfo(posted_from, TimeTicks()), task(task), posted_from(posted_from), sequence_num(0), nestable(true) { }
void MessagePumpLibevent::Run(Delegate* delegate) { //DCHECK(keep_running_) << "Quit must have been called outside of Run!"; assert(keep_running_); // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. // Instead, make our own timer and reuse it on each call to event_base_loop(). std::unique_ptr<event> timer_event(new event); for (;;) { bool did_work = delegate->DoWork(); if (!keep_running_) break; event_base_loop(event_base_, EVLOOP_NONBLOCK); did_work |= processed_io_events_; processed_io_events_ = false; if (!keep_running_) break; did_work |= delegate->DoDelayedWork(&delayed_work_time_); if (!keep_running_) break; if (did_work) continue; did_work = delegate->DoIdleWork(); if (!keep_running_) break; if (did_work) continue; // EVLOOP_ONCE tells libevent to only block once, // but to service all pending events when it wakes up. if (delayed_work_time_.is_null()) { event_base_loop(event_base_, EVLOOP_ONCE); } else { TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); if (delay > TimeDelta()) { struct timeval poll_tv; poll_tv.tv_sec = (long)delay.InSeconds(); poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond; event_set(timer_event.get(), -1, 0, timer_callback, event_base_); event_base_set(event_base_, timer_event.get()); event_add(timer_event.get(), &poll_tv); event_base_loop(event_base_, EVLOOP_ONCE); event_del(timer_event.get()); } else { delayed_work_time_ = TimeTicks(); } } } keep_running_ = true; }
void DefaultMessagePump::Run(Delegate* delegate) { // Quit must have been called outside of Run! assert(should_quit_ == false); for (;;) { bool did_work = delegate->DoWork(); if (should_quit_) break; did_work |= delegate->DoDelayedWork(&delayed_work_time_); if (should_quit_) break; if (did_work) continue; did_work = delegate->DoIdleWork(); if (should_quit_) break; if (did_work) continue; if (delayed_work_time_.is_null()) { Wait(); } else { TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); if (delay > TimeDelta()) WaitTimeout(delay); else { // It looks like delayed_work_time_ indicates a time in the past, so we // need to call DoDelayedWork now. delayed_work_time_ = TimeTicks(); } } } should_quit_ = false; }
bool MessageLoop::DoDelayWork(TimeTicks *next_delayed_work_time) { //TODO(tangjie): add nestable task process. if (delayed_work_queue_.empty()) { recent_time_ = *next_delayed_work_time = TimeTicks(); return false; } TimeTicks next_time = delayed_work_queue_.top().delayed_run_time_; if (next_time > recent_time_) { recent_time_ = TimeTicks::Now(); if (next_time > recent_time_) { *next_delayed_work_time = next_time; return false; } } PendingTask task = delayed_work_queue_.top(); delayed_work_queue_.pop(); if (!delayed_work_queue_.empty()) { *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time_; } return DeferOrRunPendingTask(task); }