blob: f2beb37db27fa1087bcca5259387209beb33233e [file] [log] [blame]
// Copyright 2021 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/android/metrics/android_session_durations_service.h"
#include "base/metrics/histogram_functions.h"
namespace {
class IncognitoSessionDurationsMetricsRecorder {
public:
IncognitoSessionDurationsMetricsRecorder() = default;
~IncognitoSessionDurationsMetricsRecorder() { OnAppEnterBackground(); }
void OnAppEnterForeground() {
// When Chrome recovers from a crash while in Incognito, it creates the
// Incognito profile first and then brings it to foreground. In this case we
// should prevent double counting.
if (is_foreground_)
return;
is_foreground_ = true;
// |session_start_| is null prior to start of a new session. Therefore we
// only need to record the current time.
if (session_start_.is_null()) {
session_start_ = base::Time::Now();
return;
}
// Record the previously reported duration, so that subtracting this
// histogram from 'Profile.Incognito.MovedToBackgroundAfterDuration' would
// offset for the sessions that were recorded there, but were resumed
// later.
base::UmaHistogramCustomCounts(
"Profile.Incognito.ResumedAfterReportedDuration",
last_reported_duration_.InMinutes(), 1,
base::TimeDelta::FromDays(28).InMinutes(), 50);
}
void OnAppEnterBackground() {
// This function may be called when Chrome is already in background and a
// proper shutdown of the service takes place.
if (!is_foreground_)
return;
is_foreground_ = false;
last_reported_duration_ = base::Time::Now() - session_start_;
base::UmaHistogramCustomCounts(
"Profile.Incognito.MovedToBackgroundAfterDuration",
last_reported_duration_.InMinutes(), 1,
base::TimeDelta::FromDays(28).InMinutes(), 50);
}
void SetSessionStartTimeForTesting(base::Time session_start) {
session_start_ = session_start;
}
private:
base::Time session_start_;
base::TimeDelta last_reported_duration_;
bool is_foreground_ = false;
};
} // namespace
AndroidSessionDurationsService::AndroidSessionDurationsService() = default;
AndroidSessionDurationsService::~AndroidSessionDurationsService() = default;
void AndroidSessionDurationsService::InitializeForRegularProfile(
syncer::SyncService* sync_service,
signin::IdentityManager* identity_manager) {
DCHECK(!incognito_session_metrics_recorder_);
DCHECK(!sync_session_metrics_recorder_);
sync_session_metrics_recorder_ =
std::make_unique<syncer::SyncSessionDurationsMetricsRecorder>(
sync_service, identity_manager);
// The AndroidSessionDurationsService object is created as soon as
// the profile is initialized. On Android, the profile is initialized as part
// of the native code initialization, which is done soon after the application
// enters foreground and before any of the Chrome UI is shown. Let's start
// tracking the session now.
OnAppEnterForeground(base::TimeTicks::Now());
}
void AndroidSessionDurationsService::InitializeForIncognitoProfile() {
DCHECK(!incognito_session_metrics_recorder_);
DCHECK(!sync_session_metrics_recorder_);
incognito_session_metrics_recorder_ =
std::make_unique<IncognitoSessionDurationsMetricsRecorder>();
OnAppEnterForeground(base::TimeTicks::Now());
}
void AndroidSessionDurationsService::Shutdown() {
sync_session_metrics_recorder_.reset();
incognito_session_metrics_recorder_.reset();
}
void AndroidSessionDurationsService::OnAppEnterForeground(
base::TimeTicks session_start) {
if (sync_session_metrics_recorder_)
sync_session_metrics_recorder_->OnSessionStarted(session_start);
else
incognito_session_metrics_recorder_->OnAppEnterForeground();
}
void AndroidSessionDurationsService::OnAppEnterBackground(
base::TimeDelta session_length) {
if (sync_session_metrics_recorder_)
sync_session_metrics_recorder_->OnSessionEnded(session_length);
else
incognito_session_metrics_recorder_->OnAppEnterBackground();
}
void AndroidSessionDurationsService::SetSessionStartTimeForTesting(
base::Time session_start) {
if (incognito_session_metrics_recorder_) {
incognito_session_metrics_recorder_
->SetSessionStartTimeForTesting( // IN-TEST
session_start);
return;
}
NOTIMPLEMENTED();
}