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