| // 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 |