blob: ccead333e590b9122a0a9e89c0ae0208520c8a33 [file] [log] [blame]
// Copyright 2017 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/feature_engagement/session_duration_updater.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
namespace feature_engagement {
SessionDurationUpdater::SessionDurationUpdater(
PrefService* pref_service,
const char* observed_session_time_dict_key)
: duration_tracker_observer_(this),
pref_service_(pref_service),
observed_session_time_dict_key_(observed_session_time_dict_key) {
AddDurationTrackerObserver();
}
SessionDurationUpdater::~SessionDurationUpdater() = default;
// static
void SessionDurationUpdater::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterDictionaryPref(prefs::kObservedSessionTime);
}
base::TimeDelta SessionDurationUpdater::GetCumulativeElapsedSessionTime() {
base::TimeDelta elapsed_time = GetRecordedObservedSessionTime();
return current_session_timer_
? elapsed_time + current_session_timer_.get()->Elapsed()
: elapsed_time;
}
base::TimeDelta SessionDurationUpdater::GetRecordedObservedSessionTime() {
const base::DictionaryValue* dict =
pref_service_->GetDictionary(prefs::kObservedSessionTime);
const base::Value* dict_value =
dict->FindKey(observed_session_time_dict_key_);
const double stored_value = dict_value ? dict_value->GetDouble() : 0L;
return base::TimeDelta::FromSeconds(stored_value);
}
void SessionDurationUpdater::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
// Re-adds SessionDurationUpdater as an observer of
// DesktopSessionDurationTracker if another feature is added after
// SessionDurationUpdater was removed.
if (!duration_tracker_observer_.IsObserving(
metrics::DesktopSessionDurationTracker::Get())) {
if (!current_session_timer_)
current_session_timer_ = std::make_unique<base::ElapsedTimer>();
AddDurationTrackerObserver();
}
}
void SessionDurationUpdater::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
// If all the observer Features have removed themselves due to their active
// time limits have been reached, the SessionDurationUpdater removes itself
// as an observer of DesktopSessionDurationTracker.
if (!observer_list_.might_have_observers()) {
current_session_timer_.reset();
RemoveDurationTrackerObserver();
}
}
void SessionDurationUpdater::OnSessionStarted(base::TimeTicks session_start) {
current_session_timer_ = std::make_unique<base::ElapsedTimer>();
}
void SessionDurationUpdater::OnSessionEnded(base::TimeDelta elapsed) {
// This case is only used during testing as that is the only case that
// DesktopSessionDurationTracker isn't calling this on its observer.
if (!duration_tracker_observer_.IsObserving(
metrics::DesktopSessionDurationTracker::Get())) {
return;
}
base::TimeDelta elapsed_session_time;
const base::DictionaryValue* dict =
pref_service_->GetDictionary(prefs::kObservedSessionTime);
const base::Value* dict_value =
dict->FindKey(observed_session_time_dict_key_);
const double stored_value = dict_value ? dict_value->GetDouble() : 0L;
elapsed_session_time += base::TimeDelta::FromSeconds(stored_value) + elapsed;
DictionaryPrefUpdate update(pref_service_, prefs::kObservedSessionTime);
update->SetKey(
observed_session_time_dict_key_,
base::Value(static_cast<double>(elapsed_session_time.InSeconds())));
current_session_timer_.reset();
for (Observer& observer : observer_list_)
observer.OnSessionEnded(elapsed_session_time);
}
void SessionDurationUpdater::AddDurationTrackerObserver() {
duration_tracker_observer_.Add(metrics::DesktopSessionDurationTracker::Get());
}
void SessionDurationUpdater::RemoveDurationTrackerObserver() {
duration_tracker_observer_.Remove(
metrics::DesktopSessionDurationTracker::Get());
}
PrefService* SessionDurationUpdater::GetPrefs() {
return pref_service_;
}
} // namespace feature_engagement