1 // Copyright 2018 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 COMPONENTS_SYNC_DRIVER_SYNC_SESSION_DURATIONS_METRICS_RECORDER_H_
6 #define COMPONENTS_SYNC_DRIVER_SYNC_SESSION_DURATIONS_METRICS_RECORDER_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/scoped_observer.h"
13 #include "base/timer/elapsed_timer.h"
14 #include "components/keyed_service/core/keyed_service.h"
15 #include "components/signin/public/identity_manager/identity_manager.h"
16 #include "components/sync/driver/sync_service.h"
17 #include "components/sync/driver/sync_service_observer.h"
18 
19 namespace syncer {
20 
21 // Tracks the active browsing time that the user spends signed in and/or syncing
22 // as fraction of their total browsing time.
23 class SyncSessionDurationsMetricsRecorder
24     : public syncer::SyncServiceObserver,
25       public signin::IdentityManager::Observer {
26  public:
27   // Callers must ensure that the parameters outlive this object.
28   SyncSessionDurationsMetricsRecorder(
29       SyncService* sync_service,
30       signin::IdentityManager* identity_manager);
31   ~SyncSessionDurationsMetricsRecorder() override;
32 
33   // Informs this service that a session started at |session_start| time.
34   void OnSessionStarted(base::TimeTicks session_start);
35   void OnSessionEnded(base::TimeDelta session_length);
36 
37   // syncer::SyncServiceObserver:
38   void OnStateChanged(syncer::SyncService* sync) override;
39 
40   // IdentityManager::Observer:
41   void OnRefreshTokenUpdatedForAccount(
42       const CoreAccountInfo& account_info) override;
43   void OnRefreshTokenRemovedForAccount(
44       const CoreAccountId& account_id) override;
45   void OnRefreshTokensLoaded() override;
46   void OnErrorStateOfRefreshTokenUpdatedForAccount(
47       const CoreAccountInfo& account_info,
48       const GoogleServiceAuthError& error) override;
49   void OnAccountsInCookieUpdated(
50       const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
51       const GoogleServiceAuthError& error) override;
52 
53  private:
54   // The state the feature is in. The state starts as UNKNOWN. After it moves
55   // out of UNKNOWN, it can alternate between OFF and ON.
56   enum class FeatureState { UNKNOWN, OFF, ON };
57 
58   void LogSigninDuration(base::TimeDelta session_length);
59 
60   void LogSyncAndAccountDuration(base::TimeDelta session_length);
61 
62   bool ShouldLogUpdate(FeatureState new_sync_status,
63                        FeatureState new_account_status);
64 
65   void UpdateSyncAndAccountStatus(FeatureState new_sync_status,
66                                   FeatureState new_account_status);
67 
68   void HandleSyncAndAccountChange();
69 
70   // Returns |FeatureState::ON| iff there is at least one account in
71   // |identity_manager| that has a valid refresh token.
72   FeatureState DetermineAccountStatus() const;
73 
74   SyncService* const sync_service_;
75   signin::IdentityManager* const identity_manager_;
76 
77   ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
78       sync_observer_{this};
79   ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
80       identity_manager_observer_{this};
81 
82   // Tracks the elapsed active session time while the browser is open. The timer
83   // is absent if there's no active session.
84   std::unique_ptr<base::ElapsedTimer> total_session_timer_;
85 
86   FeatureState signin_status_ = FeatureState::UNKNOWN;
87   // Tracks the elapsed active session time in the current signin status. The
88   // timer is absent if there's no active session.
89   std::unique_ptr<base::ElapsedTimer> signin_session_timer_;
90 
91   // Whether or not Chrome curently has a valid refresh token for an account.
92   FeatureState account_status_ = FeatureState::UNKNOWN;
93   // Whether or not sync is currently active.
94   FeatureState sync_status_ = FeatureState::UNKNOWN;
95   // Tracks the elapsed active session time in the current sync and account
96   // status. The timer is absent if there's no active session.
97   std::unique_ptr<base::ElapsedTimer> sync_account_session_timer_;
98 
99   DISALLOW_COPY_AND_ASSIGN(SyncSessionDurationsMetricsRecorder);
100 };
101 
102 }  // namespace syncer
103 
104 #endif  // COMPONENTS_SYNC_DRIVER_SYNC_SESSION_DURATIONS_METRICS_RECORDER_H_
105