| Index: chrome/browser/chromeos/session_length_limiter.cc
|
| diff --git a/chrome/browser/chromeos/session_length_limiter.cc b/chrome/browser/chromeos/session_length_limiter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fb0d94c27f2bf3b95d53dcde766ad5c3e2dd2fa3
|
| --- /dev/null
|
| +++ b/chrome/browser/chromeos/session_length_limiter.cc
|
| @@ -0,0 +1,177 @@
|
| +// Copyright (c) 2012 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 "chrome/browser/chromeos/session_length_limiter.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/location.h"
|
| +#include "base/logging.h"
|
| +#include "base/prefs/public/pref_service_base.h"
|
| +#include "chrome/browser/chromeos/login/user_manager.h"
|
| +#include "chrome/browser/lifetime/application_lifetime.h"
|
| +#include "chrome/browser/prefs/pref_service.h"
|
| +#include "chrome/common/pref_names.h"
|
| +
|
| +namespace chromeos {
|
| +
|
| +namespace {
|
| +
|
| +// The minimum session time limit that can be set.
|
| +const int kSessionLengthLimitMinMs = 30 * 1000; // 30 seconds.
|
| +
|
| +// The maximum session time limit that can be set.
|
| +const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000; // 24 hours.
|
| +
|
| +// The interval at which to fire periodic callbacks and check whether the
|
| +// session time limit has been reached.
|
| +const int kSessionLengthLimitTimerIntervalMs = 1000;
|
| +
|
| +// A default delegate implementation that returns the current time and does log
|
| +// out the current user when requested. This can be replaced with a mock in
|
| +// tests.
|
| +class SessionLengthLimiterDelegateImpl : public SessionLengthLimiter::Delegate {
|
| + public:
|
| + SessionLengthLimiterDelegateImpl();
|
| + virtual ~SessionLengthLimiterDelegateImpl();
|
| +
|
| + virtual const base::Time GetCurrentTime() const;
|
| + virtual void Logout();
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(SessionLengthLimiterDelegateImpl);
|
| +};
|
| +
|
| +SessionLengthLimiterDelegateImpl::SessionLengthLimiterDelegateImpl() {
|
| +}
|
| +
|
| +SessionLengthLimiterDelegateImpl::~SessionLengthLimiterDelegateImpl() {
|
| +}
|
| +
|
| +const base::Time SessionLengthLimiterDelegateImpl::GetCurrentTime() const {
|
| + return base::Time::Now();
|
| +}
|
| +
|
| +void SessionLengthLimiterDelegateImpl::Logout() {
|
| + browser::AttemptUserExit();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +SessionLengthLimiter::Observer::~Observer() {
|
| +}
|
| +
|
| +SessionLengthLimiter::Delegate::~Delegate() {
|
| +}
|
| +
|
| +SessionLengthLimiter::SessionLengthLimiter(Delegate* delegate,
|
| + PrefService* prefs)
|
| + : delegate_(delegate ? delegate : new SessionLengthLimiterDelegateImpl) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + // Update the session start time in prefs to the current time when going
|
| + // through a user login. If the browser is restarting after a crash instead,
|
| + // only update the value if it appears corrupted (value unset, value lying in
|
| + // the future, zero value).
|
| + int64 session_start_time = prefs->GetInt64(prefs::kSessionStartTime);
|
| + int64 now = delegate_->GetCurrentTime().ToInternalValue();
|
| + if (!UserManager::Get()->HasBrowserRestarted() ||
|
| + session_start_time <= 0 || session_start_time > now) {
|
| + prefs->SetInt64(prefs::kSessionStartTime, now);
|
| + session_start_time = now;
|
| + }
|
| + session_start_time_ = base::Time::FromInternalValue(session_start_time);
|
| +
|
| + // Listen for changes to the session length limit.
|
| + pref_change_registrar_.Init(prefs);
|
| + pref_change_registrar_.Add(
|
| + prefs::kSessionLengthLimit,
|
| + base::Bind(&SessionLengthLimiter::OnSessionLengthLimitChanged,
|
| + base::Unretained(this)));
|
| + OnSessionLengthLimitChanged();
|
| +}
|
| +
|
| +SessionLengthLimiter::~SessionLengthLimiter() {
|
| +}
|
| +
|
| +void SessionLengthLimiter::Shutdown() {
|
| + pref_change_registrar_.RemoveAll();
|
| +}
|
| +
|
| +void SessionLengthLimiter::AddObserver(Observer* observer) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + observers_.AddObserver(observer);
|
| + observer->SessionTimeRemainingChanged(GetRemainingTime().get());
|
| +}
|
| +
|
| +void SessionLengthLimiter::RemoveObserver(Observer* observer) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +void SessionLengthLimiter::OnSessionLengthLimitChanged() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + int limit;
|
| + const PrefServiceBase::Preference* session_length_limit_pref =
|
| + pref_change_registrar_.prefs()->
|
| + FindPreference(prefs::kSessionLengthLimit);
|
| + // If no session length limit is set, stop the timer, calling the observers
|
| + // one last time to notify them that there is no more limit.
|
| + if (session_length_limit_pref->IsDefaultValue() ||
|
| + !session_length_limit_pref->GetValue()->GetAsInteger(&limit)) {
|
| + session_length_limit_ = base::TimeDelta();
|
| + StopTimer();
|
| + return;
|
| + }
|
| + // If a session length limit is set, clamp it to the valid range and start
|
| + // the timer after calling the observers immediately to notify them that there
|
| + // now is a limit.
|
| + session_length_limit_ = base::TimeDelta::FromMilliseconds(
|
| + std::min(std::max(limit, kSessionLengthLimitMinMs),
|
| + kSessionLengthLimitMaxMs));
|
| + StartTimer();
|
| +}
|
| +
|
| +void SessionLengthLimiter::StartTimer() {
|
| + TimerTick();
|
| + if (repeating_timer_.IsRunning())
|
| + return;
|
| + repeating_timer_.Start(
|
| + FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(kSessionLengthLimitTimerIntervalMs),
|
| + this,
|
| + &SessionLengthLimiter::TimerTick);
|
| +}
|
| +
|
| +void SessionLengthLimiter::StopTimer() {
|
| + if (repeating_timer_.IsRunning())
|
| + repeating_timer_.Stop();
|
| + TimerTick();
|
| +}
|
| +
|
| +void SessionLengthLimiter::TimerTick() {
|
| + scoped_ptr<base::TimeDelta> remaining = GetRemainingTime();
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + SessionTimeRemainingChanged(remaining.get()));
|
| + // End the session if a limit is set and the remaining time reaches zero.
|
| + if (remaining && *remaining == base::TimeDelta())
|
| + delegate_->Logout();
|
| +}
|
| +
|
| +scoped_ptr<base::TimeDelta> SessionLengthLimiter::GetRemainingTime() const {
|
| + // If no limit is set, return |NULL|.
|
| + const base::TimeDelta kZeroTimeDelta = base::TimeDelta();
|
| + if (session_length_limit_ == kZeroTimeDelta)
|
| + return scoped_ptr<base::TimeDelta>();
|
| + // If a limit is set, return the remaining time, clamped so that it never
|
| + // falls below zero.
|
| + base::TimeDelta remaining = session_length_limit_ -
|
| + (delegate_->GetCurrentTime() - session_start_time_);
|
| + if (remaining < kZeroTimeDelta)
|
| + remaining = kZeroTimeDelta;
|
| + return scoped_ptr<base::TimeDelta>(new base::TimeDelta(remaining));
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|