Make castv2 performance test work.
[chromium-blink-merge.git] / chrome / browser / metrics / signin_status_metrics_provider.cc
blobed68b45b96c3b9297fde147c74977ac817d442da
1 // Copyright 2014 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.
5 #include "chrome/browser/metrics/signin_status_metrics_provider.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_info_cache.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_list.h"
19 #include "components/signin/core/browser/signin_manager.h"
21 #if !defined(OS_ANDROID)
22 #include "chrome/browser/ui/browser_finder.h"
23 #endif
25 namespace {
27 // The event of calling function ComputeCurrentSigninStatus and the errors
28 // occurred during the function execution.
29 enum ComputeSigninStatus {
30 ENTERED_COMPUTE_SIGNIN_STATUS,
31 ERROR_NO_PROFILE_FOUND,
32 NO_BROWSER_OPENED,
33 USER_SIGNIN_WHEN_STATUS_UNKNOWN,
34 USER_SIGNOUT_WHEN_STATUS_UNKNOWN,
35 TRY_TO_OVERRIDE_ERROR_STATUS,
36 COMPUTE_SIGNIN_STATUS_MAX,
39 void RecordComputeSigninStatusHistogram(ComputeSigninStatus status) {
40 UMA_HISTOGRAM_ENUMERATION("UMA.ComputeCurrentSigninStatus", status,
41 COMPUTE_SIGNIN_STATUS_MAX);
44 } // namespace
46 SigninStatusMetricsProvider::SigninStatusMetricsProvider(bool is_test)
47 : scoped_observer_(this),
48 is_test_(is_test),
49 weak_ptr_factory_(this) {
50 if (is_test_)
51 return;
53 // Postpone the initialization until all threads are created.
54 base::MessageLoop::current()->PostTask(
55 FROM_HERE,
56 base::Bind(&SigninStatusMetricsProvider::Initialize,
57 weak_ptr_factory_.GetWeakPtr()));
60 SigninStatusMetricsProvider::~SigninStatusMetricsProvider() {
61 if (is_test_)
62 return;
64 #if !defined(OS_ANDROID)
65 BrowserList::RemoveObserver(this);
66 #endif
68 SigninManagerFactory* factory = SigninManagerFactory::GetInstance();
69 if (factory)
70 factory->RemoveObserver(this);
73 void SigninStatusMetricsProvider::ProvideGeneralMetrics(
74 metrics::ChromeUserMetricsExtension* uma_proto) {
75 RecordSigninStatusHistogram(signin_status());
76 // After a histogram value is recorded, a new UMA session will be started, so
77 // we need to re-check the current sign-in status regardless of the previous
78 // recorded |signin_status_| value.
79 ResetSigninStatus();
80 ComputeCurrentSigninStatus();
83 // static
84 SigninStatusMetricsProvider* SigninStatusMetricsProvider::CreateInstance() {
85 return new SigninStatusMetricsProvider(false);
88 void SigninStatusMetricsProvider::OnBrowserAdded(Browser* browser) {
89 if (signin_status() == MIXED_SIGNIN_STATUS)
90 return;
92 SigninManager* manager = SigninManagerFactory::GetForProfile(
93 browser->profile());
95 // Nothing will change if the opened browser is in incognito mode.
96 if (!manager)
97 return;
99 const bool signed_in = manager->IsAuthenticated();
100 UpdateStatusWhenBrowserAdded(signed_in);
103 void SigninStatusMetricsProvider::SigninManagerCreated(
104 SigninManagerBase* manager) {
105 // Whenever a new profile is created, a new SigninManagerBase will be created
106 // for it. This ensures that all sign-in or sign-out actions of all opened
107 // profiles are being monitored.
108 scoped_observer_.Add(manager);
110 // If the status is unknown, it means this is the first created
111 // SigninManagerBase and the corresponding profile should be the only opened
112 // profile.
113 if (signin_status() == UNKNOWN_SIGNIN_STATUS) {
114 size_t signed_in_count =
115 manager->IsAuthenticated() ? 1 : 0;
116 UpdateInitialSigninStatus(1, signed_in_count);
120 void SigninStatusMetricsProvider::SigninManagerShutdown(
121 SigninManagerBase* manager) {
122 if (scoped_observer_.IsObserving(manager))
123 scoped_observer_.Remove(manager);
126 void SigninStatusMetricsProvider::GoogleSigninSucceeded(
127 const std::string& account_id,
128 const std::string& username,
129 const std::string& password) {
130 SigninStatus recorded_signin_status = signin_status();
131 if (recorded_signin_status == ALL_PROFILES_NOT_SIGNED_IN) {
132 SetSigninStatus(MIXED_SIGNIN_STATUS);
133 } else if (recorded_signin_status == UNKNOWN_SIGNIN_STATUS) {
134 // There should have at least one browser opened if the user can sign in, so
135 // signin_status_ value should not be unknown.
136 SetSigninStatus(ERROR_GETTING_SIGNIN_STATUS);
137 RecordComputeSigninStatusHistogram(USER_SIGNIN_WHEN_STATUS_UNKNOWN);
141 void SigninStatusMetricsProvider::GoogleSignedOut(const std::string& account_id,
142 const std::string& username) {
143 SigninStatus recorded_signin_status = signin_status();
144 if (recorded_signin_status == ALL_PROFILES_SIGNED_IN) {
145 SetSigninStatus(MIXED_SIGNIN_STATUS);
146 } else if (recorded_signin_status == UNKNOWN_SIGNIN_STATUS) {
147 // There should have at least one browser opened if the user can sign out,
148 // so signin_status_ value should not be unknown.
149 SetSigninStatus(ERROR_GETTING_SIGNIN_STATUS);
150 RecordComputeSigninStatusHistogram(USER_SIGNOUT_WHEN_STATUS_UNKNOWN);
154 void SigninStatusMetricsProvider::Initialize() {
155 // Add observers.
156 #if !defined(OS_ANDROID)
157 // On Android, there is always only one profile in any situation, opening new
158 // windows (which is possible with only some Android devices) will not change
159 // the opened profiles signin status.
160 BrowserList::AddObserver(this);
161 #endif
162 SigninManagerFactory::GetInstance()->AddObserver(this);
164 // Start observing all already-created SigninManagers.
165 ProfileManager* profile_manager = g_browser_process->profile_manager();
166 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
167 for (size_t i = 0; i < profiles.size(); ++i) {
168 SigninManager* manager = SigninManagerFactory::GetForProfileIfExists(
169 profiles[i]);
170 if (manager) {
171 DCHECK(!scoped_observer_.IsObserving(manager));
172 scoped_observer_.Add(manager);
176 // It is possible that when this object is created, no SigninManager is
177 // created yet, for example, when Chrome is opened for the first time after
178 // installation on desktop, or when Chrome on Android is loaded into memory.
179 if (profiles.empty()) {
180 SetSigninStatus(UNKNOWN_SIGNIN_STATUS);
181 } else {
182 ComputeCurrentSigninStatus();
186 void SigninStatusMetricsProvider::UpdateInitialSigninStatus(
187 size_t total_count,
188 size_t signed_in_profiles_count) {
189 // total_count is known to be bigger than 0.
190 if (signed_in_profiles_count == 0) {
191 SetSigninStatus(ALL_PROFILES_NOT_SIGNED_IN);
192 } else if (total_count == signed_in_profiles_count) {
193 SetSigninStatus(ALL_PROFILES_SIGNED_IN);
194 } else {
195 SetSigninStatus(MIXED_SIGNIN_STATUS);
199 void SigninStatusMetricsProvider::UpdateStatusWhenBrowserAdded(bool signed_in) {
200 #if !defined(OS_ANDROID)
201 SigninStatus recorded_signin_status = signin_status();
202 if ((recorded_signin_status == ALL_PROFILES_NOT_SIGNED_IN && signed_in) ||
203 (recorded_signin_status == ALL_PROFILES_SIGNED_IN && !signed_in)) {
204 SetSigninStatus(MIXED_SIGNIN_STATUS);
205 } else if (recorded_signin_status == UNKNOWN_SIGNIN_STATUS) {
206 // If when function ProvideGeneralMetrics() is called, Chrome is
207 // running in the background with no browser window opened, |signin_status_|
208 // will be reset to |UNKNOWN_SIGNIN_STATUS|. Then this newly added browser
209 // is the only opened browser/profile and its signin status represents
210 // the whole status.
211 SetSigninStatus(signed_in ? ALL_PROFILES_SIGNED_IN :
212 ALL_PROFILES_NOT_SIGNED_IN);
214 #endif
217 void SigninStatusMetricsProvider::ComputeCurrentSigninStatus() {
218 ProfileManager* profile_manager = g_browser_process->profile_manager();
219 std::vector<Profile*> profile_list = profile_manager->GetLoadedProfiles();
221 size_t opened_profiles_count = 0;
222 size_t signed_in_profiles_count = 0;
224 for (size_t i = 0; i < profile_list.size(); ++i) {
225 #if !defined(OS_ANDROID)
226 if (chrome::GetTotalBrowserCountForProfile(profile_list[i]) == 0) {
227 // The profile is loaded, but there's no opened browser for this profile.
228 continue;
230 #endif
231 opened_profiles_count++;
232 SigninManager* manager = SigninManagerFactory::GetForProfile(
233 profile_list[i]->GetOriginalProfile());
234 if (manager && manager->IsAuthenticated())
235 signed_in_profiles_count++;
238 RecordComputeSigninStatusHistogram(ENTERED_COMPUTE_SIGNIN_STATUS);
239 if (profile_list.empty()) {
240 // This should not happen. If it does, record it in histogram.
241 RecordComputeSigninStatusHistogram(ERROR_NO_PROFILE_FOUND);
242 SetSigninStatus(ERROR_GETTING_SIGNIN_STATUS);
243 } else if (opened_profiles_count == 0) {
244 // The code indicates that Chrome is running in the background but no
245 // browser window is opened.
246 RecordComputeSigninStatusHistogram(NO_BROWSER_OPENED);
247 SetSigninStatus(UNKNOWN_SIGNIN_STATUS);
248 } else {
249 UpdateInitialSigninStatus(opened_profiles_count, signed_in_profiles_count);
253 SigninStatusMetricsProvider::SigninStatus
254 SigninStatusMetricsProvider::GetSigninStatusForTesting() {
255 return signin_status();