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.
4
5#ifndef CHROME_BROWSER_METRICS_SIGNIN_STATUS_METRICS_PROVIDER_H_
6#define CHROME_BROWSER_METRICS_SIGNIN_STATUS_METRICS_PROVIDER_H_
7
8#include <string>
9
10#include "base/gtest_prod_util.h"
11#include "base/memory/weak_ptr.h"
12#include "base/scoped_observer.h"
13#include "chrome/browser/signin/signin_manager_factory.h"
14#include "chrome/browser/ui/browser_list_observer.h"
15#include "components/metrics/metrics_provider.h"
16#include "components/signin/core/browser/signin_manager_base.h"
17
18class Browser;
19class ChromeUserMetricsExtension;
20
21namespace base {
22class FilePath;
23}
24
25namespace metrics {
26class ChromeUserMetricsExtension;
27}
28
29// Collect login status of all opened profiles during one UMA session and record
30// the value into a histogram before UMA log is uploaded. It's currently not
31// supported on platform chromeos, Android or iOS.
32class SigninStatusMetricsProvider : public metrics::MetricsProvider,
33                                    public chrome::BrowserListObserver,
34                                    public SigninManagerBase::Observer,
35                                    public SigninManagerFactory::Observer {
36 public:
37  virtual ~SigninStatusMetricsProvider();
38
39  // metrics::MetricsProvider:
40  virtual void ProvideGeneralMetrics(
41      metrics::ChromeUserMetricsExtension* uma_proto) OVERRIDE;
42
43  // Factory method, creates a new instance of this class.
44  static SigninStatusMetricsProvider* CreateInstance();
45
46 private:
47  // The boolean |is_test| indicates whether or not this is an instance for
48  // testing purpose. If so, skip the initialization. Except for testing
49  // purpose, this class's instance should be created through the static
50  // CreateInstance() method.
51  explicit SigninStatusMetricsProvider(bool is_test);
52
53  FRIEND_TEST_ALL_PREFIXES(SigninStatusMetricsProvider,
54                           UpdateInitialSigninStatus);
55  FRIEND_TEST_ALL_PREFIXES(SigninStatusMetricsProvider,
56                           UpdateStatusWhenBrowserAdded);
57  FRIEND_TEST_ALL_PREFIXES(SigninStatusMetricsProvider, GoogleSigninSucceeded);
58  FRIEND_TEST_ALL_PREFIXES(SigninStatusMetricsProvider, GoogleSignedOut);
59
60  // Possible sign-in status of all opened profiles during one UMA session. For
61  // MIXED_SIGNIN_STATUS, at least one signed-in profile and at least one
62  // unsigned-in profile were opened between two UMA log uploads.
63  enum ProfilesSigninStatus {
64    ALL_PROFILES_SIGNED_IN,
65    ALL_PROFILES_NOT_SIGNED_IN,
66    MIXED_SIGNIN_STATUS,
67    UNKNOWN_SIGNIN_STATUS,
68    ERROR_GETTING_SIGNIN_STATUS,
69    SIGNIN_STATUS_MAX,
70  };
71
72  // chrome::BrowserListObserver:
73  // This will never be called on Android.
74  virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
75
76  // SigninManagerFactory::Observer:
77  virtual void SigninManagerCreated(SigninManagerBase* manager) OVERRIDE;
78  virtual void SigninManagerShutdown(SigninManagerBase* manager) OVERRIDE;
79
80  // SigninManagerBase::Observer:
81  virtual void GoogleSigninSucceeded(const std::string& account_id,
82                                     const std::string& username,
83                                     const std::string& password) OVERRIDE;
84  virtual void GoogleSignedOut(const std::string& account_id,
85                               const std::string& username) OVERRIDE;
86
87  // Obtain sign-in status and add observers.
88  void Initialize();
89
90  // Update the sign-in status based on all currently opened profiles. Called by
91  // ComputeCurrentSigninStatus at class construction and right after each UMA
92  // log upload. |total_count| is the number of opened profiles and
93  // |signed_in_count| represents the number of signed-in profiles among those
94  // |total_count| profiles.
95  void UpdateInitialSigninStatus(size_t total_count, size_t signed_in_count);
96
97  // Update the sign-in status right after a new browser is opened.
98  void UpdateStatusWhenBrowserAdded(bool signed_in);
99
100  // Compute current sign-in status of all opened profiles.
101  void ComputeCurrentSigninStatus();
102
103  // Sets the value of |signin_status_|. It ensures that |signin_status_| will
104  // not be changed if its value is already ERROR_GETTING_SIGNIN_STATUS.
105  void SetSigninStatus(ProfilesSigninStatus new_status);
106
107  // Get the current recorded sign-in status. For testing purpose only.
108  ProfilesSigninStatus GetSigninStatusForTesting();
109
110  // Sign-in status of all profiles seen so far.
111  ProfilesSigninStatus signin_status_;
112
113  // Used to track the SigninManagers that this instance is observing so that
114  // this instance can be removed as an observer on its destruction.
115  ScopedObserver<SigninManagerBase, SigninStatusMetricsProvider>
116      scoped_observer_;
117
118  // Whether the instance is for testing or not.
119  bool is_test_;
120
121  base::WeakPtrFactory<SigninStatusMetricsProvider> weak_ptr_factory_;
122
123  DISALLOW_COPY_AND_ASSIGN(SigninStatusMetricsProvider);
124};
125
126#endif  // CHROME_BROWSER_METRICS_SIGNIN_STATUS_METRICS_PROVIDER_H_
127