This source file includes following definitions.
- GetCurrentTime
- StopSession
- RegisterPrefs
- user_activity_seen_
- OnUserActivity
- RestoreStateAfterCrash
- UpdateSessionStartTime
- UpdateLimit
#include "chrome/browser/chromeos/session_length_limiter.h"
#include <algorithm>
#include "ash/shell.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/pref_names.h"
#include "ui/events/event.h"
#include "ui/wm/core/user_activity_detector.h"
namespace chromeos {
namespace {
const int kSessionLengthLimitMinMs = 30 * 1000;
const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000;
class SessionLengthLimiterDelegateImpl : public SessionLengthLimiter::Delegate {
public:
SessionLengthLimiterDelegateImpl();
virtual ~SessionLengthLimiterDelegateImpl();
virtual const base::TimeTicks GetCurrentTime() const OVERRIDE;
virtual void StopSession() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(SessionLengthLimiterDelegateImpl);
};
SessionLengthLimiterDelegateImpl::SessionLengthLimiterDelegateImpl() {
}
SessionLengthLimiterDelegateImpl::~SessionLengthLimiterDelegateImpl() {
}
const base::TimeTicks SessionLengthLimiterDelegateImpl::GetCurrentTime() const {
return base::TimeTicks::Now();
}
void SessionLengthLimiterDelegateImpl::StopSession() {
chrome::AttemptUserExit();
}
}
SessionLengthLimiter::Delegate::~Delegate() {
}
void SessionLengthLimiter::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kSessionUserActivitySeen, false);
registry->RegisterInt64Pref(prefs::kSessionStartTime, 0);
registry->RegisterIntegerPref(prefs::kSessionLengthLimit, 0);
registry->RegisterBooleanPref(prefs::kSessionWaitForInitialUserActivity,
false);
}
SessionLengthLimiter::SessionLengthLimiter(Delegate* delegate,
bool browser_restarted)
: delegate_(delegate ? delegate : new SessionLengthLimiterDelegateImpl),
user_activity_seen_(false) {
DCHECK(thread_checker_.CalledOnValidThread());
PrefService* local_state = g_browser_process->local_state();
pref_change_registrar_.Init(local_state);
pref_change_registrar_.Add(prefs::kSessionLengthLimit,
base::Bind(&SessionLengthLimiter::UpdateLimit,
base::Unretained(this)));
pref_change_registrar_.Add(
prefs::kSessionWaitForInitialUserActivity,
base::Bind(&SessionLengthLimiter::UpdateSessionStartTime,
base::Unretained(this)));
if (!browser_restarted || !RestoreStateAfterCrash()) {
local_state->ClearPref(prefs::kSessionUserActivitySeen);
UpdateSessionStartTime();
}
if (!user_activity_seen_ && ash::Shell::HasInstance())
ash::Shell::GetInstance()->user_activity_detector()->AddObserver(this);
}
SessionLengthLimiter::~SessionLengthLimiter() {
if (!user_activity_seen_ && ash::Shell::HasInstance())
ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this);
}
void SessionLengthLimiter::OnUserActivity(const ui::Event* event) {
if (user_activity_seen_)
return;
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this);
user_activity_seen_ = true;
PrefService* local_state = g_browser_process->local_state();
local_state->SetBoolean(prefs::kSessionUserActivitySeen, true);
if (session_start_time_.is_null()) {
session_start_time_ = delegate_->GetCurrentTime();
local_state->SetInt64(prefs::kSessionStartTime,
session_start_time_.ToInternalValue());
}
local_state->CommitPendingWrite();
UpdateLimit();
}
bool SessionLengthLimiter::RestoreStateAfterCrash() {
PrefService* local_state = g_browser_process->local_state();
const base::TimeTicks session_start_time =
base::TimeTicks::FromInternalValue(
local_state->GetInt64(prefs::kSessionStartTime));
if (session_start_time.is_null() ||
session_start_time >= delegate_->GetCurrentTime()) {
return false;
}
session_start_time_ = session_start_time;
user_activity_seen_ =
local_state->GetBoolean(prefs::kSessionUserActivitySeen);
UpdateLimit();
return true;
}
void SessionLengthLimiter::UpdateSessionStartTime() {
DCHECK(thread_checker_.CalledOnValidThread());
if (user_activity_seen_)
return;
PrefService* local_state = g_browser_process->local_state();
if (local_state->GetBoolean(prefs::kSessionWaitForInitialUserActivity)) {
session_start_time_ = base::TimeTicks();
local_state->ClearPref(prefs::kSessionStartTime);
} else {
session_start_time_ = delegate_->GetCurrentTime();
local_state->SetInt64(prefs::kSessionStartTime,
session_start_time_.ToInternalValue());
}
local_state->CommitPendingWrite();
UpdateLimit();
}
void SessionLengthLimiter::UpdateLimit() {
DCHECK(thread_checker_.CalledOnValidThread());
timer_.reset();
if (session_start_time_.is_null())
return;
int limit;
const PrefService::Preference* session_length_limit_pref =
pref_change_registrar_.prefs()->
FindPreference(prefs::kSessionLengthLimit);
if (session_length_limit_pref->IsDefaultValue() ||
!session_length_limit_pref->GetValue()->GetAsInteger(&limit)) {
return;
}
const base::TimeDelta session_length_limit =
base::TimeDelta::FromMilliseconds(std::min(std::max(
limit, kSessionLengthLimitMinMs), kSessionLengthLimitMaxMs));
const base::TimeDelta remaining = session_length_limit -
(delegate_->GetCurrentTime() - session_start_time_);
if (remaining <= base::TimeDelta()) {
delegate_->StopSession();
return;
}
timer_.reset(new base::OneShotTimer<SessionLengthLimiter::Delegate>);
timer_->Start(FROM_HERE, remaining, delegate_.get(),
&SessionLengthLimiter::Delegate::StopSession);
}
}