Skip to content

Commit

Permalink
Added Hats APIs to TrackingProtectionOnboarding Service
Browse files Browse the repository at this point in the history
Bug: b:296559721
Change-Id: I4db4caebfc8c4e312b647ae361e3a5cc2b535637
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4986885
Reviewed-by: Nicola Tommasi <tommasin@chromium.org>
Commit-Queue: Abe Boujane <boujane@google.com>
Auto-Submit: Abe Boujane <boujane@google.com>
Cr-Commit-Position: refs/heads/main@{#1216876}
  • Loading branch information
Abe Boujane authored and Chromium LUCI CQ committed Oct 30, 2023
1 parent e831131 commit ed70399
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 0 deletions.
161 changes: 161 additions & 0 deletions components/privacy_sandbox/tracking_protection_onboarding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/notreached.h"
#include "base/time/time.h"
#include "components/prefs/pref_service.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
Expand All @@ -24,7 +25,17 @@ using ::privacy_sandbox::tracking_protection::
using ::privacy_sandbox::tracking_protection::
TrackingProtectionOnboardingStatus;

using ::privacy_sandbox::tracking_protection::
TrackingProtectionSentimentSurveyGroup;

using NoticeType = privacy_sandbox::TrackingProtectionOnboarding::NoticeType;
using SentimentSurveyGroup =
privacy_sandbox::TrackingProtectionOnboarding::SentimentSurveyGroup;

constexpr base::TimeDelta kHatsImmediateStartTimeDelta = base::Minutes(2);
constexpr base::TimeDelta kHatsImmediateEndTimeDelta = base::Hours(1);
constexpr base::TimeDelta kHatsDelayedStartTimeDelta = base::Days(14);
constexpr base::TimeDelta kHatsDelayedEndTimeDelta = base::Days(15);

TrackingProtectionOnboardingStatus GetInternalOnboardingStatus(
PrefService* pref_service) {
Expand All @@ -48,6 +59,27 @@ TrackingProtectionOnboardingAckAction ToInternalAckAction(
}
}

SentimentSurveyGroup GetSurveyGroup(PrefService* pref_service) {
auto internal_group = static_cast<TrackingProtectionSentimentSurveyGroup>(
pref_service->GetInteger(prefs::kTrackingProtectionSentimentSurveyGroup));
switch (internal_group) {
case tracking_protection::TrackingProtectionSentimentSurveyGroup::kNotSet:
return SentimentSurveyGroup::kNotSet;
case tracking_protection::TrackingProtectionSentimentSurveyGroup::
kControlImmediate:
return SentimentSurveyGroup::kControlImmediate;
case tracking_protection::TrackingProtectionSentimentSurveyGroup::
kTreatmentImmediate:
return SentimentSurveyGroup::kTreatmentImmediate;
case tracking_protection::TrackingProtectionSentimentSurveyGroup::
kControlDelayed:
return SentimentSurveyGroup::kControlDelayed;
case tracking_protection::TrackingProtectionSentimentSurveyGroup::
kTreatmentDelayed:
return SentimentSurveyGroup::kTreatmentDelayed;
}
}

void RecordActionMetrics(TrackingProtectionOnboarding::NoticeAction action) {
switch (action) {
case TrackingProtectionOnboarding::NoticeAction::kOther:
Expand Down Expand Up @@ -188,6 +220,58 @@ void OffboardingNoticeActionTaken(
static_cast<int>(ToInternalAckAction(action)));
}

void MaybeSetStartAndEndSurveyTime(PrefService* pref_service) {
if (pref_service->HasPrefPath(
prefs::kTrackingProtectionSentimentSurveyStartTime)) {
return;
}

auto group = GetSurveyGroup(pref_service);
// Setting the start and end time when applicable.
// First, start by determining the anchor time. Control should be the first
// time this function runs. Treatment should be when the notice was acked.
// If the anchor time isn't year ready, return early.
base::Time anchor_time;
switch (group) {
case SentimentSurveyGroup::kNotSet:
return;
case SentimentSurveyGroup::kControlImmediate:
case SentimentSurveyGroup::kControlDelayed:
anchor_time = base::Time::Now();
break;
case SentimentSurveyGroup::kTreatmentImmediate:
case SentimentSurveyGroup::kTreatmentDelayed:
if (!pref_service->HasPrefPath(
prefs::kTrackingProtectionOnboardingAckedSince)) {
return;
}
anchor_time =
pref_service->GetTime(prefs::kTrackingProtectionOnboardingAckedSince);
break;
}

// Anchor time must be ready. Use it to set the start and end survey time on
// the profile.
switch (group) {
case SentimentSurveyGroup::kNotSet:
NOTREACHED_NORETURN();
case SentimentSurveyGroup::kControlImmediate:
case SentimentSurveyGroup::kTreatmentImmediate:
pref_service->SetTime(prefs::kTrackingProtectionSentimentSurveyStartTime,
anchor_time + kHatsImmediateStartTimeDelta);
pref_service->SetTime(prefs::kTrackingProtectionSentimentSurveyEndTime,
anchor_time + kHatsImmediateEndTimeDelta);
return;
case SentimentSurveyGroup::kTreatmentDelayed:
case SentimentSurveyGroup::kControlDelayed:
pref_service->SetTime(prefs::kTrackingProtectionSentimentSurveyStartTime,
anchor_time + kHatsDelayedStartTimeDelta);
pref_service->SetTime(prefs::kTrackingProtectionSentimentSurveyEndTime,
anchor_time + kHatsDelayedEndTimeDelta);
return;
}
}

} // namespace

TrackingProtectionOnboarding::TrackingProtectionOnboarding(
Expand Down Expand Up @@ -238,6 +322,8 @@ void TrackingProtectionOnboarding::OnOnboardingPrefChanged() const {
}

void TrackingProtectionOnboarding::OnOnboardingAckedChanged() const {
// Maybe set the Hats start and end time now that the profile is onboarded.
MaybeSetStartAndEndSurveyTime(pref_service_);
for (auto& observer : observers_) {
observer.OnShouldShowNoticeUpdated();
}
Expand Down Expand Up @@ -284,6 +370,81 @@ void TrackingProtectionOnboarding::MaybeMarkIneligible() {
"PrivacySandbox.TrackingProtection.Onboarding.MaybeMarkIneligible", true);
}

bool TrackingProtectionOnboarding::RequiresSentimentSurveyGroup() {
// If the pref is in the default value, it means we haven't added this profile
// to any of the groups yet.
return !pref_service_->HasPrefPath(
prefs::kTrackingProtectionSentimentSurveyGroup);
}

void TrackingProtectionOnboarding::RegisterSentimentSurveyGroup(
SentimentSurveyGroup group) {
// Setting the group first.
tracking_protection::TrackingProtectionSentimentSurveyGroup internal_group;
switch (group) {
case SentimentSurveyGroup::kNotSet:
return;
case SentimentSurveyGroup::kControlImmediate:
internal_group =
TrackingProtectionSentimentSurveyGroup::kControlImmediate;
break;
case SentimentSurveyGroup::kTreatmentImmediate:
internal_group =
TrackingProtectionSentimentSurveyGroup::kTreatmentImmediate;
break;
case SentimentSurveyGroup::kControlDelayed:
internal_group = TrackingProtectionSentimentSurveyGroup::kControlDelayed;
break;
case SentimentSurveyGroup::kTreatmentDelayed:
internal_group =
TrackingProtectionSentimentSurveyGroup::kTreatmentDelayed;
break;
}

pref_service_->SetInteger(prefs::kTrackingProtectionSentimentSurveyGroup,
static_cast<int>(internal_group));

MaybeSetStartAndEndSurveyTime(pref_service_);
}

TrackingProtectionOnboarding::SentimentSurveyGroup
TrackingProtectionOnboarding::GetEligibleSurveyGroup() {
SentimentSurveyGroup group = GetSurveyGroup(pref_service_);

if (group == SentimentSurveyGroup::kNotSet) {
return group;
}

// If Start time isn't set, it means the profile isn't yet eligible. This is
// because all surveys MUST have a start time.
if (!pref_service_->HasPrefPath(
prefs::kTrackingProtectionSentimentSurveyStartTime)) {
return SentimentSurveyGroup::kNotSet;
}

if (base::Time::Now() <
pref_service_->GetTime(
prefs::kTrackingProtectionSentimentSurveyStartTime)) {
return SentimentSurveyGroup::kNotSet;
}

// No additional filtering if the end time isn't set. This is to support open
// ended surveys.
if (!pref_service_->HasPrefPath(
prefs::kTrackingProtectionSentimentSurveyEndTime)) {
return group;
}

// At this point, an end date is set, so we need to use it for filtering.
if (base::Time::Now() >
pref_service_->GetTime(
prefs::kTrackingProtectionSentimentSurveyEndTime)) {
return SentimentSurveyGroup::kNotSet;
}

return group;
}

void TrackingProtectionOnboarding::MaybeResetOnboardingPrefs() {
// Clearing the prefs is only allowed in Beta, Canary and Dev for testing.
switch (channel_) {
Expand Down
25 changes: 25 additions & 0 deletions components/privacy_sandbox/tracking_protection_onboarding.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ class TrackingProtectionOnboarding : public KeyedService {
kMaxValue = kOffboarded,
};

// Enum used for interfacing with the onboarding service to indicate the HaTS
// group the profile belongs to.
enum class SentimentSurveyGroup {
kNotSet = 0,
kControlImmediate = 1,
kTreatmentImmediate = 2,
kControlDelayed = 3,
kTreatmentDelayed = 4,
};

// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.privacy_sandbox
enum class NoticeAction {
// Other action taken - notice dismissed due to other actions.
Expand Down Expand Up @@ -141,6 +151,21 @@ class TrackingProtectionOnboarding : public KeyedService {
// the user.
bool ShouldShowOnboardingNotice();

// HaTS
// TODO(b:308320418) These should ideally live in a separate Tracking
// Protection HaTS service, and not be tied to the onboarding one.

// Returns whether or not the profile requires a fresh survey registration.
bool RequiresSentimentSurveyGroup();

// Registers the profile in the requested group, and optionally sets its start
// and end survey time.
void RegisterSentimentSurveyGroup(SentimentSurveyGroup group);

// Computes HaTS eligibility for the profile. Will return kNotSet if the
// profile isn't to be shown a survey.
SentimentSurveyGroup GetEligibleSurveyGroup();

// Returns the time delta from Onboarded to Acknowledged.
std::optional<base::TimeDelta> OnboardedToAcknowledged();

Expand Down

0 comments on commit ed70399

Please sign in to comment.