1 // Copyright 2017 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_UKM_OBSERVERS_UKM_CONSENT_STATE_OBSERVER_H_
6 #define COMPONENTS_UKM_OBSERVERS_UKM_CONSENT_STATE_OBSERVER_H_
7 
8 #include <map>
9 
10 #include "base/scoped_observer.h"
11 #include "components/sync/driver/sync_service.h"
12 #include "components/sync/driver/sync_service_observer.h"
13 #include "components/unified_consent/url_keyed_data_collection_consent_helper.h"
14 
15 class PrefService;
16 
17 namespace ukm {
18 
19 // Observer that monitors whether UKM is allowed for all profiles.
20 //
21 // For one profile, UKM is allowed iff URL-keyed anonymized data collection is
22 // enabled.
23 class UkmConsentStateObserver
24     : public syncer::SyncServiceObserver,
25       public unified_consent::UrlKeyedDataCollectionConsentHelper::Observer {
26  public:
27   UkmConsentStateObserver();
28   ~UkmConsentStateObserver() override;
29 
30   // Starts observing whether UKM is allowed for a profile.
31   // |pref_service| is the pref service of a profile.
32   void StartObserving(syncer::SyncService* sync_service,
33                       PrefService* pref_service);
34 
35   // Returns true iff all UKM is allowed for all profile states. This means that
36   // URL-keyed anonymized data collection is enabled for all profiles.
37   virtual bool IsUkmAllowedForAllProfiles();
38 
39   // Returns true iff sync is in a state that allows UKM to capture extensions.
40   // This means that all profiles have EXTENSIONS data type enabled for syncing.
41   virtual bool IsUkmAllowedWithExtensionsForAllProfiles();
42 
43  protected:
44   // Called after UKM consent state changed.
45   // If |must_purge| is true, the UKM is not allowed for some profile, and local
46   // data must be purged.
47   virtual void OnUkmAllowedStateChanged(bool must_purge) = 0;
48 
49  private:
50   // syncer::SyncServiceObserver:
51   void OnStateChanged(syncer::SyncService* sync) override;
52   void OnSyncShutdown(syncer::SyncService* sync) override;
53 
54   // unified_consent::UrlKeyedDataCollectionConsentHelper::Observer:
55   void OnUrlKeyedDataCollectionConsentStateChanged(
56       unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper)
57       override;
58 
59   // Recomputes |ukm_allowed_for_all_profiles_| and
60   // |ukm_allowed_with_extensions_for_all_profiles_| from |previous_states_|;
61   void UpdateUkmAllowedForAllProfiles(bool must_purge);
62 
63   // Returns true iff all profile states in |previous_states_| allow UKM.
64   // If there are no profiles being observed, this returns false.
65   bool CheckPreviousStatesAllowUkm();
66 
67   // Returns true iff all profile states in |previous_states_| allow extension
68   // UKM. If there are no profiles are being observed, this returns false.
69   bool CheckPreviousStatesAllowExtensionUkm();
70 
71   // Tracks observed sync services, for cleanup.
72   ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
73       sync_observer_;
74 
75   // State data about profiles that we need to remember.
76   struct ProfileState {
77     // Returns true if this state allows UKM (i.e. URL-keyed anonymized
78     // data collection is enabled).
79     bool AllowsUkm() const;
80 
81     // Returns true if |AllowsUkm| and if sync extensions are enabled.
82     bool AllowsUkmWithExtension() const;
83 
84     // Whether anonymized data collection is enabled.
85     bool anonymized_data_collection_enabled = false;
86 
87     // If the user has extension sync enabled.
88     bool extensions_enabled = false;
89   };
90 
91   // Updates the UKM enabled state for a profile and then triggers an update of
92   // the state for all profiles.
93   // |sync| and |consent_helper| must not be null.
94   void UpdateProfileState(
95       syncer::SyncService* sync,
96       unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper);
97 
98   // Gets the current state of a profile.
99   // |sync| and |consent_helper| must not be null.
100   static ProfileState GetProfileState(
101       syncer::SyncService* sync,
102       unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper);
103 
104   // The state of the profile being observed.
105   //
106   // Note: UKM consent does not rely on sync but there must be exactly one
107   // sync service per profile, so it is safe to key the profile states by the
108   // sync service.
109   std::map<syncer::SyncService*, ProfileState> previous_states_;
110 
111   // The list of URL-keyed anonymized data collection consent helpers.
112   //
113   // Note: UrlKeyedDataCollectionConsentHelper does not rely on sync but there
114   // must be exactly one per Chromium profile. As there is a single sync service
115   // per profile, it is safe to key them by sync service instead of introducing
116   // an additional map.
117   std::map<
118       syncer::SyncService*,
119       std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>>
120       consent_helpers_;
121 
122   // Tracks if UKM is allowed on all profiles after the last state change.
123   bool ukm_allowed_for_all_profiles_ = false;
124 
125   // Tracks if extension sync was enabled on all profiles after the last state
126   // change.
127   bool ukm_allowed_with_extensions_for_all_profiles_ = false;
128 
129   DISALLOW_COPY_AND_ASSIGN(UkmConsentStateObserver);
130 };
131 
132 }  // namespace ukm
133 
134 #endif  // COMPONENTS_UKM_OBSERVERS_UKM_CONSENT_STATE_OBSERVER_H_
135