1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/metrics/family_link_user_metrics_provider.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram_functions.h"
10 #include "chrome/browser/chromeos/profiles/profile_helper.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/signin/identity_manager_factory.h"
13 #include "components/session_manager/core/session_manager.h"
14 #include "components/signin/public/identity_manager/consent_level.h"
15 #include "components/signin/public/identity_manager/identity_manager.h"
16 #include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
17 #include "components/signin/public/identity_manager/scope_set.h"
18 #include "components/user_manager/user.h"
19 #include "components/user_manager/user_manager.h"
20 #include "google_apis/gaia/oauth2_id_token_decoder.h"
21
22 namespace {
23
24 constexpr char kHistogramName[] = "ChromeOS.FamilyLinkUser.LogSegment";
25
26 } // namespace
27
FamilyLinkUserMetricsProvider()28 FamilyLinkUserMetricsProvider::FamilyLinkUserMetricsProvider() {
29 session_manager::SessionManager* session_manager =
30 session_manager::SessionManager::Get();
31 // The |session_manager| is nullptr only for unit tests.
32 if (session_manager)
33 session_manager->AddObserver(this);
34 }
35
~FamilyLinkUserMetricsProvider()36 FamilyLinkUserMetricsProvider::~FamilyLinkUserMetricsProvider() {
37 session_manager::SessionManager* session_manager =
38 session_manager::SessionManager::Get();
39 // The |session_manager| is nullptr only for unit tests.
40 if (session_manager)
41 session_manager->RemoveObserver(this);
42 }
43
44 // This function is called at unpredictable intervals throughout the entire
45 // ChromeOS session, so guarantee it will never crash.
ProvideCurrentSessionData(metrics::ChromeUserMetricsExtension * uma_proto_unused)46 void FamilyLinkUserMetricsProvider::ProvideCurrentSessionData(
47 metrics::ChromeUserMetricsExtension* uma_proto_unused) {
48 if (!log_segment_)
49 return;
50 base::UmaHistogramEnumeration(kHistogramName, log_segment_.value());
51 }
52
OnUserSessionStarted(bool is_primary_user)53 void FamilyLinkUserMetricsProvider::OnUserSessionStarted(bool is_primary_user) {
54 if (!is_primary_user)
55 return;
56
57 const user_manager::User* primary_user =
58 user_manager::UserManager::Get()->GetPrimaryUser();
59 DCHECK(primary_user);
60 if (!primary_user->IsChild()) {
61 SetLogSegment(LogSegment::kOther);
62 return;
63 }
64
65 DCHECK(primary_user->is_profile_created());
66 Profile* profile =
67 chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user);
68 DCHECK(profile);
69 DCHECK(chromeos::ProfileHelper::IsRegularProfile(profile));
70
71 signin::IdentityManager* identity_manager =
72 IdentityManagerFactory::GetForProfile(profile);
73 DCHECK(identity_manager);
74
75 DCHECK(!access_token_fetcher_);
76 access_token_fetcher_ =
77 std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
78 /*consumer_name=*/"FamilyLinkUserMetricsProvider", identity_manager,
79 signin::ScopeSet(),
80 base::BindOnce(
81 &FamilyLinkUserMetricsProvider::OnAccessTokenRequestCompleted,
82 // It is safe to use base::Unretained as |this| owns
83 // |access_token_fetcher_|. See comments in
84 // primary_account_access_token_fetcher.h.
85 base::Unretained(this)),
86 signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate,
87 signin::ConsentLevel::kNotRequired);
88 }
89
90 // static
GetHistogramNameForTesting()91 const char* FamilyLinkUserMetricsProvider::GetHistogramNameForTesting() {
92 return kHistogramName;
93 }
94
SetLogSegment(LogSegment log_segment)95 void FamilyLinkUserMetricsProvider::SetLogSegment(LogSegment log_segment) {
96 log_segment_ = log_segment;
97 }
98
OnAccessTokenRequestCompleted(GoogleServiceAuthError error,signin::AccessTokenInfo access_token_info)99 void FamilyLinkUserMetricsProvider::OnAccessTokenRequestCompleted(
100 GoogleServiceAuthError error,
101 signin::AccessTokenInfo access_token_info) {
102 access_token_fetcher_.reset();
103
104 if (error.state() != GoogleServiceAuthError::NONE)
105 return;
106
107 gaia::TokenServiceFlags service_flags =
108 gaia::ParseServiceFlags(access_token_info.id_token);
109 LogSegment log_segment = service_flags.is_child_account
110 ? LogSegment::kUnderConsentAge
111 : LogSegment::kOverConsentAge;
112 SetLogSegment(log_segment);
113 }
114