| Index: components/mus/ws/user_activity_monitor.cc
|
| diff --git a/components/mus/ws/user_activity_monitor.cc b/components/mus/ws/user_activity_monitor.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3cd66419a27456442c3604193ea93759eddad86b
|
| --- /dev/null
|
| +++ b/components/mus/ws/user_activity_monitor.cc
|
| @@ -0,0 +1,134 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "components/mus/ws/user_activity_monitor.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/time/default_tick_clock.h"
|
| +
|
| +namespace mus {
|
| +namespace ws {
|
| +
|
| +UserActivityMonitor::UserActivityMonitor(std::unique_ptr<base::TickClock> clock)
|
| + : now_clock_(std::move(clock)) {
|
| + if (!now_clock_)
|
| + now_clock_ = base::WrapUnique(new base::DefaultTickClock);
|
| + last_activity_ = now_clock_->NowTicks();
|
| +}
|
| +
|
| +UserActivityMonitor::~UserActivityMonitor() {}
|
| +
|
| +void UserActivityMonitor::OnUserActivity() {
|
| + base::TimeTicks now = now_clock_->NowTicks();
|
| + for (auto& pair : activity_observers_) {
|
| + ActivityObserverInfo* info = &(pair.first);
|
| + if (info->last_activity_notification.is_null() ||
|
| + (now - info->last_activity_notification) > info->delay) {
|
| + pair.second->OnUserActivity();
|
| + info->last_activity_notification = now;
|
| + }
|
| + }
|
| +
|
| + // Wake up all the 'idle' observers.
|
| + for (auto& pair : idle_observers_) {
|
| + IdleObserverInfo* info = &(pair.first);
|
| + if (info->idle_state == mojom::UserIdleObserver::IdleState::ACTIVE)
|
| + continue;
|
| + info->last_idle_state_notification = now;
|
| + info->idle_state = mojom::UserIdleObserver::IdleState::ACTIVE;
|
| + pair.second->OnUserIdleStateChanged(info->idle_state);
|
| + }
|
| +
|
| + last_activity_ = now;
|
| +
|
| + // Start the timer if there are some idle observers.
|
| + if (idle_timer_.IsRunning())
|
| + idle_timer_.Reset();
|
| +}
|
| +
|
| +void UserActivityMonitor::Add(mojom::UserActivityMonitorRequest request) {
|
| + bindings_.AddBinding(this, std::move(request));
|
| +}
|
| +
|
| +void UserActivityMonitor::AddUserActivityObserver(
|
| + uint32_t delay_between_notify_secs,
|
| + mojom::UserActivityObserverPtr observer) {
|
| + ActivityObserverInfo info;
|
| + info.delay = base::TimeDelta::FromSeconds(delay_between_notify_secs);
|
| + observer.set_connection_error_handler(
|
| + base::Bind(&UserActivityMonitor::OnActivityObserverDisconnected,
|
| + base::Unretained(this), observer.get()));
|
| + activity_observers_.push_back(std::make_pair(info, std::move(observer)));
|
| +}
|
| +
|
| +void UserActivityMonitor::AddUserIdleObserver(
|
| + uint32_t idleness_in_minutes,
|
| + mojom::UserIdleObserverPtr observer) {
|
| + IdleObserverInfo info;
|
| + info.idle_duration = base::TimeDelta::FromMinutes(idleness_in_minutes);
|
| + base::TimeTicks now = now_clock_->NowTicks();
|
| + DCHECK(!last_activity_.is_null());
|
| + bool user_is_active = (now - last_activity_ < info.idle_duration);
|
| + info.idle_state = user_is_active ? mojom::UserIdleObserver::IdleState::ACTIVE
|
| + : mojom::UserIdleObserver::IdleState::IDLE;
|
| + info.last_idle_state_notification = now;
|
| + observer->OnUserIdleStateChanged(info.idle_state);
|
| + observer.set_connection_error_handler(
|
| + base::Bind(&UserActivityMonitor::OnIdleObserverDisconnected,
|
| + base::Unretained(this), observer.get()));
|
| + idle_observers_.push_back(std::make_pair(info, std::move(observer)));
|
| + if (user_is_active)
|
| + ActivateIdleTimer();
|
| +}
|
| +
|
| +void UserActivityMonitor::ActivateIdleTimer() {
|
| + if (idle_timer_.IsRunning())
|
| + return;
|
| + idle_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(1), this,
|
| + &UserActivityMonitor::OnMinuteTimer);
|
| +}
|
| +
|
| +void UserActivityMonitor::OnMinuteTimer() {
|
| + base::TimeTicks now = now_clock_->NowTicks();
|
| + bool active_observer = false;
|
| + for (auto& pair : idle_observers_) {
|
| + IdleObserverInfo* info = &(pair.first);
|
| + if (info->idle_state == mojom::UserIdleObserver::IdleState::IDLE)
|
| + continue;
|
| + if (now - info->last_idle_state_notification < info->idle_duration) {
|
| + active_observer = true;
|
| + continue;
|
| + }
|
| + info->last_idle_state_notification = now;
|
| + info->idle_state = mojom::UserIdleObserver::IdleState::IDLE;
|
| + pair.second->OnUserIdleStateChanged(info->idle_state);
|
| + }
|
| + // All observers are already notified of IDLE. No point running the timer
|
| + // anymore.
|
| + if (!active_observer)
|
| + idle_timer_.Stop();
|
| +}
|
| +
|
| +void UserActivityMonitor::OnActivityObserverDisconnected(
|
| + mojom::UserActivityObserver* observer) {
|
| + activity_observers_.erase(std::remove_if(
|
| + activity_observers_.begin(), activity_observers_.end(),
|
| + [observer](const std::pair<ActivityObserverInfo,
|
| + mojom::UserActivityObserverPtr>& pair) {
|
| + return pair.second.get() == observer;
|
| + }));
|
| +}
|
| +
|
| +void UserActivityMonitor::OnIdleObserverDisconnected(
|
| + mojom::UserIdleObserver* observer) {
|
| + idle_observers_.erase(std::remove_if(
|
| + idle_observers_.begin(), idle_observers_.end(),
|
| + [observer](
|
| + const std::pair<IdleObserverInfo, mojom::UserIdleObserverPtr>& pair) {
|
| + return pair.second.get() == observer;
|
| + }));
|
| +}
|
| +
|
| +} // namespace ws
|
| +} // namespace mus
|
|
|