1 // Copyright (c) 2012 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_VARIATIONS_VARIATIONS_SERVICE_H_ 6 #define CHROME_BROWSER_METRICS_VARIATIONS_VARIATIONS_SERVICE_H_ 7 8 #include <string> 9 10 #include "base/compiler_specific.h" 11 #include "base/gtest_prod_util.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/metrics/field_trial.h" 15 #include "base/observer_list.h" 16 #include "base/time/time.h" 17 #include "chrome/browser/metrics/variations/variations_request_scheduler.h" 18 #include "chrome/browser/metrics/variations/variations_seed_store.h" 19 #include "chrome/browser/web_resource/resource_request_allowed_notifier.h" 20 #include "chrome/common/chrome_version_info.h" 21 #include "components/variations/variations_seed_simulator.h" 22 #include "net/url_request/url_fetcher_delegate.h" 23 #include "url/gurl.h" 24 25 #if defined(OS_WIN) 26 #include "chrome/browser/metrics/variations/variations_registry_syncer_win.h" 27 #endif 28 29 class PrefService; 30 class PrefRegistrySimple; 31 32 namespace base { 33 class Version; 34 } 35 36 namespace metrics { 37 class MetricsStateManager; 38 } 39 40 namespace user_prefs { 41 class PrefRegistrySyncable; 42 } 43 44 namespace variations { 45 class VariationsSeed; 46 } 47 48 namespace chrome_variations { 49 50 // Used to setup field trials based on stored variations seed data, and fetch 51 // new seed data from the variations server. 52 class VariationsService 53 : public net::URLFetcherDelegate, 54 public ResourceRequestAllowedNotifier::Observer { 55 public: 56 class Observer { 57 public: 58 // How critical a detected experiment change is. Whether it should be 59 // handled on a "best-effort" basis or, for a more critical change, if it 60 // should be given higher priority. 61 enum Severity { 62 BEST_EFFORT, 63 CRITICAL, 64 }; 65 66 // Called when the VariationsService detects that there will be significant 67 // experiment changes on a restart. This notification can then be used to 68 // update UI (i.e. badging an icon). 69 virtual void OnExperimentChangesDetected(Severity severity) = 0; 70 71 protected: 72 virtual ~Observer() {} 73 }; 74 75 virtual ~VariationsService(); 76 77 // Creates field trials based on Variations Seed loaded from local prefs. If 78 // there is a problem loading the seed data, all trials specified by the seed 79 // may not be created. 80 bool CreateTrialsFromSeed(); 81 82 // Calls FetchVariationsSeed once and repeats this periodically. See 83 // implementation for details on the period. Must be called after 84 // |CreateTrialsFromSeed|. 85 void StartRepeatedVariationsSeedFetch(); 86 87 // Adds an observer to listen for detected experiment changes. 88 void AddObserver(Observer* observer); 89 90 // Removes a previously-added observer. 91 void RemoveObserver(Observer* observer); 92 93 // Called when the application enters foreground. This may trigger a 94 // FetchVariationsSeed call. 95 // TODO(rkaplow): Handle this and the similar event in metrics_service by 96 // observing an 'OnAppEnterForeground' event instead of requiring the frontend 97 // code to notify each service individually. 98 void OnAppEnterForeground(); 99 100 #if defined(OS_WIN) 101 // Starts syncing Google Update Variation IDs with the registry. 102 void StartGoogleUpdateRegistrySync(); 103 #endif 104 105 // Exposed for testing. 106 void SetCreateTrialsFromSeedCalledForTesting(bool called); 107 108 // Returns the variations server URL, which can vary if a command-line flag is 109 // set and/or the variations restrict pref is set in |local_prefs|. Declared 110 // static for test purposes. 111 static GURL GetVariationsServerURL(PrefService* local_prefs); 112 113 // Exposed for testing. 114 static std::string GetDefaultVariationsServerURLForTesting(); 115 116 // Register Variations related prefs in Local State. 117 static void RegisterPrefs(PrefRegistrySimple* registry); 118 119 // Register Variations related prefs in the Profile prefs. 120 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); 121 122 // Factory method for creating a VariationsService. Does not take ownership of 123 // |state_manager|. Caller should ensure that |state_manager| is valid for the 124 // lifetime of this class. 125 static scoped_ptr<VariationsService> Create( 126 PrefService* local_state, 127 metrics::MetricsStateManager* state_manager); 128 129 // Set the PrefService responsible for getting policy-related preferences, 130 // such as the restrict parameter. 131 void set_policy_pref_service(PrefService* service) { 132 DCHECK(service); 133 policy_pref_service_ = service; 134 } 135 136 protected: 137 // Starts the fetching process once, where |OnURLFetchComplete| is called with 138 // the response. 139 virtual void DoActualFetch(); 140 141 // Stores the seed to prefs. Set as virtual and protected so that it can be 142 // overridden by tests. 143 virtual void StoreSeed(const std::string& seed_data, 144 const std::string& seed_signature, 145 const base::Time& date_fetched); 146 147 // Creates the VariationsService with the given |local_state| prefs service 148 // and |state_manager|. This instance will take ownership of |notifier|. 149 // Does not take ownership of |state_manager|. Caller should ensure that 150 // |state_manager| is valid for the lifetime of this class. Use the |Create| 151 // factory method to create a VariationsService. 152 VariationsService(ResourceRequestAllowedNotifier* notifier, 153 PrefService* local_state, 154 metrics::MetricsStateManager* state_manager); 155 156 private: 157 FRIEND_TEST_ALL_PREFIXES(VariationsServiceTest, Observer); 158 FRIEND_TEST_ALL_PREFIXES(VariationsServiceTest, SeedStoredWhenOKStatus); 159 FRIEND_TEST_ALL_PREFIXES(VariationsServiceTest, SeedNotStoredWhenNonOKStatus); 160 FRIEND_TEST_ALL_PREFIXES(VariationsServiceTest, SeedDateUpdatedOn304Status); 161 162 // Checks if prerequisites for fetching the Variations seed are met, and if 163 // so, performs the actual fetch using |DoActualFetch|. 164 void FetchVariationsSeed(); 165 166 // Notify any observers of this service based on the simulation |result|. 167 void NotifyObservers( 168 const variations::VariationsSeedSimulator::Result& result); 169 170 // net::URLFetcherDelegate implementation: 171 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 172 173 // ResourceRequestAllowedNotifier::Observer implementation: 174 virtual void OnResourceRequestsAllowed() OVERRIDE; 175 176 // Performs a variations seed simulation with the given |seed| and |version| 177 // and logs the simulation results as histograms. 178 void PerformSimulationWithVersion(scoped_ptr<variations::VariationsSeed> seed, 179 const base::Version& version); 180 181 // Record the time of the most recent successful fetch. 182 void RecordLastFetchTime(); 183 184 // The pref service used to store persist the variations seed. 185 PrefService* local_state_; 186 187 // Used for instantiating entropy providers for variations seed simulation. 188 // Weak pointer. 189 metrics::MetricsStateManager* state_manager_; 190 191 // Used to obtain policy-related preferences. Depending on the platform, will 192 // either be Local State or Profile prefs. 193 PrefService* policy_pref_service_; 194 195 VariationsSeedStore seed_store_; 196 197 // Contains the scheduler instance that handles timing for requests to the 198 // server. Initially NULL and instantiated when the initial fetch is 199 // requested. 200 scoped_ptr<VariationsRequestScheduler> request_scheduler_; 201 202 // Contains the current seed request. Will only have a value while a request 203 // is pending, and will be reset by |OnURLFetchComplete|. 204 scoped_ptr<net::URLFetcher> pending_seed_request_; 205 206 // The URL to use for querying the Variations server. 207 GURL variations_server_url_; 208 209 // Tracks whether |CreateTrialsFromSeed| has been called, to ensure that 210 // it gets called prior to |StartRepeatedVariationsSeedFetch|. 211 bool create_trials_from_seed_called_; 212 213 // Tracks whether the initial request to the variations server had completed. 214 bool initial_request_completed_; 215 216 // Helper class used to tell this service if it's allowed to make network 217 // resource requests. 218 scoped_ptr<ResourceRequestAllowedNotifier> resource_request_allowed_notifier_; 219 220 // The start time of the last seed request. This is used to measure the 221 // latency of seed requests. Initially zero. 222 base::TimeTicks last_request_started_time_; 223 224 // List of observers of the VariationsService. 225 ObserverList<Observer> observer_list_; 226 227 #if defined(OS_WIN) 228 // Helper that handles synchronizing Variations with the Registry. 229 VariationsRegistrySyncer registry_syncer_; 230 #endif 231 232 base::WeakPtrFactory<VariationsService> weak_ptr_factory_; 233 234 DISALLOW_COPY_AND_ASSIGN(VariationsService); 235 }; 236 237 } // namespace chrome_variations 238 239 #endif // CHROME_BROWSER_METRICS_VARIATIONS_VARIATIONS_SERVICE_H_ 240