OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/metrics/variations_service.h" | 5 #include "chrome/browser/metrics/variations_service.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/build_time.h" | 10 #include "base/build_time.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/version.h" | 15 #include "base/version.h" |
16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/metrics/proto/trials_seed.pb.h" | 17 #include "chrome/browser/metrics/proto/trials_seed.pb.h" |
18 #include "chrome/browser/prefs/pref_service.h" | 18 #include "chrome/browser/prefs/pref_service.h" |
19 #include "chrome/browser/upgrade_detector.h" | |
20 #include "chrome/common/chrome_notification_types.h" | |
21 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
22 #include "chrome/common/metrics/experiments_helper.h" | 20 #include "chrome/common/metrics/experiments_helper.h" |
23 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
24 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/browser/notification_service.h" | |
26 #include "content/public/common/url_fetcher.h" | 23 #include "content/public/common/url_fetcher.h" |
27 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
28 #include "net/base/load_flags.h" | 25 #include "net/base/load_flags.h" |
29 #include "net/base/network_change_notifier.h" | 26 #include "net/base/network_change_notifier.h" |
30 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
31 #include "net/url_request/url_fetcher.h" | 28 #include "net/url_request/url_fetcher.h" |
32 #include "net/url_request/url_request_status.h" | 29 #include "net/url_request/url_request_status.h" |
33 | 30 |
34 namespace chrome_variations { | 31 namespace chrome_variations { |
35 | 32 |
36 namespace { | 33 namespace { |
37 | 34 |
38 // Default server of variations seed info. | 35 // Default server of Variations seed info. |
39 const char kDefaultVariationsServerURL[] = | 36 const char kDefaultVariationsServerURL[] = |
40 "https://clients4.google.com/chrome-variations/seed"; | 37 "https://clients4.google.com/chrome-variations/seed"; |
41 const int kMaxRetrySeedFetch = 5; | 38 const int kMaxRetrySeedFetch = 5; |
42 | 39 |
43 // Time between seed fetches, in hours. | 40 // Time between seed fetches, in hours. |
44 const int kSeedFetchPeriodHours = 5; | 41 const int kSeedFetchPeriodHours = 5; |
45 | 42 |
46 // Maps Study_Channel enum values to corresponding chrome::VersionInfo::Channel | 43 // Maps Study_Channel enum values to corresponding chrome::VersionInfo::Channel |
47 // enum values. | 44 // enum values. |
48 chrome::VersionInfo::Channel ConvertStudyChannelToVersionChannel( | 45 chrome::VersionInfo::Channel ConvertStudyChannelToVersionChannel( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 #else | 77 #else |
81 #error Unknown platform | 78 #error Unknown platform |
82 #endif | 79 #endif |
83 } | 80 } |
84 | 81 |
85 // Converts |date_time| in Study date format to base::Time. | 82 // Converts |date_time| in Study date format to base::Time. |
86 base::Time ConvertStudyDateToBaseTime(int64 date_time) { | 83 base::Time ConvertStudyDateToBaseTime(int64 date_time) { |
87 return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(date_time); | 84 return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(date_time); |
88 } | 85 } |
89 | 86 |
90 // Determine and return the Variations server URL. | 87 // Determine and return the variations server URL. |
91 GURL GetVariationsServerURL() { | 88 GURL GetVariationsServerURL() { |
92 std::string server_url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 89 std::string server_url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
93 switches::kVariationsServerURL)); | 90 switches::kVariationsServerURL)); |
94 if (server_url.empty()) | 91 if (server_url.empty()) |
95 server_url = kDefaultVariationsServerURL; | 92 server_url = kDefaultVariationsServerURL; |
96 GURL url_as_gurl = GURL(server_url); | 93 GURL url_as_gurl = GURL(server_url); |
97 DCHECK(url_as_gurl.is_valid()); | 94 DCHECK(url_as_gurl.is_valid()); |
98 return url_as_gurl; | 95 return url_as_gurl; |
99 } | 96 } |
100 | 97 |
101 } // namespace | 98 } // namespace |
102 | 99 |
103 VariationsService::VariationsService() | 100 VariationsService::VariationsService() |
104 : variations_server_url_(GetVariationsServerURL()), | 101 : variations_server_url_(GetVariationsServerURL()), |
105 create_trials_from_seed_called_(false) { | 102 create_trials_from_seed_called_(false) { |
106 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED, | |
107 content::Source<UpgradeDetector>(UpgradeDetector::GetInstance())); | |
108 } | 103 } |
109 | 104 |
110 VariationsService::~VariationsService() {} | 105 VariationsService::~VariationsService() {} |
111 | 106 |
112 bool VariationsService::CreateTrialsFromSeed(PrefService* local_prefs) { | 107 bool VariationsService::CreateTrialsFromSeed(PrefService* local_prefs) { |
113 create_trials_from_seed_called_ = true; | 108 create_trials_from_seed_called_ = true; |
114 | 109 |
115 TrialsSeed seed; | 110 TrialsSeed seed; |
116 if (!LoadTrialsSeedFromPref(local_prefs, &seed)) | 111 if (!LoadTrialsSeedFromPref(local_prefs, &seed)) |
117 return false; | 112 return false; |
(...skipping 13 matching lines...) Expand all Loading... |
131 | 126 |
132 for (int i = 0; i < seed.study_size(); ++i) { | 127 for (int i = 0; i < seed.study_size(); ++i) { |
133 if (ShouldAddStudy(seed.study(i), current_version_info, reference_date)) | 128 if (ShouldAddStudy(seed.study(i), current_version_info, reference_date)) |
134 CreateTrialFromStudy(seed.study(i), reference_date); | 129 CreateTrialFromStudy(seed.study(i), reference_date); |
135 } | 130 } |
136 | 131 |
137 return true; | 132 return true; |
138 } | 133 } |
139 | 134 |
140 void VariationsService::StartRepeatedVariationsSeedFetch() { | 135 void VariationsService::StartRepeatedVariationsSeedFetch() { |
141 DCHECK(CalledOnValidThread()); | 136 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
142 | 137 |
143 // Check that |CreateTrialsFromSeed| was called, which is necessary to | 138 // Check that |CreateTrialsFromSeed| was called, which is necessary to |
144 // retrieve the serial number that will be sent to the server. | 139 // retrieve the serial number that will be sent to the server. |
145 DCHECK(create_trials_from_seed_called_); | 140 DCHECK(create_trials_from_seed_called_); |
146 | 141 |
147 // Perform the first fetch. | 142 // Perform the first fetch. |
148 FetchVariationsSeed(); | 143 FetchVariationsSeed(); |
149 | 144 |
150 // Repeat this periodically. | 145 // Repeat this periodically. |
151 timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kSeedFetchPeriodHours), | 146 timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kSeedFetchPeriodHours), |
152 this, &VariationsService::FetchVariationsSeed); | 147 this, &VariationsService::FetchVariationsSeed); |
153 } | 148 } |
154 | 149 |
155 // static | |
156 void VariationsService::RegisterPrefs(PrefService* prefs) { | |
157 prefs->RegisterStringPref(prefs::kVariationsSeed, std::string()); | |
158 prefs->RegisterInt64Pref(prefs::kVariationsSeedDate, | |
159 base::Time().ToInternalValue()); | |
160 } | |
161 | |
162 void VariationsService::FetchVariationsSeed() { | 150 void VariationsService::FetchVariationsSeed() { |
163 DCHECK(CalledOnValidThread()); | 151 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
164 | 152 |
165 const bool is_offline = net::NetworkChangeNotifier::IsOffline(); | 153 const bool is_offline = net::NetworkChangeNotifier::IsOffline(); |
166 UMA_HISTOGRAM_BOOLEAN("Variations.NetworkAvailability", !is_offline); | 154 UMA_HISTOGRAM_BOOLEAN("Variations.NetworkAvailability", !is_offline); |
167 if (is_offline) { | 155 if (is_offline) { |
168 DVLOG(1) << "Network was offline."; | 156 DVLOG(1) << "Network was offline."; |
169 return; | 157 return; |
170 } | 158 } |
171 | 159 |
172 pending_seed_request_.reset(net::URLFetcher::Create( | 160 pending_seed_request_.reset(net::URLFetcher::Create( |
173 variations_server_url_, net::URLFetcher::GET, this)); | 161 variations_server_url_, net::URLFetcher::GET, this)); |
174 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 162 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
175 net::LOAD_DO_NOT_SAVE_COOKIES); | 163 net::LOAD_DO_NOT_SAVE_COOKIES); |
176 pending_seed_request_->SetRequestContext( | 164 pending_seed_request_->SetRequestContext( |
177 g_browser_process->system_request_context()); | 165 g_browser_process->system_request_context()); |
178 pending_seed_request_->SetMaxRetries(kMaxRetrySeedFetch); | 166 pending_seed_request_->SetMaxRetries(kMaxRetrySeedFetch); |
179 if (!variations_serial_number_.empty()) { | 167 if (!variations_serial_number_.empty()) { |
180 pending_seed_request_->AddExtraRequestHeader("If-Match:" + | 168 pending_seed_request_->AddExtraRequestHeader("If-Match:" + |
181 variations_serial_number_); | 169 variations_serial_number_); |
182 } | 170 } |
183 pending_seed_request_->Start(); | 171 pending_seed_request_->Start(); |
184 } | 172 } |
185 | 173 |
186 void VariationsService::Observe(int type, | |
187 const content::NotificationSource& source, | |
188 const content::NotificationDetails& details) { | |
189 DCHECK(CalledOnValidThread()); | |
190 DCHECK_EQ(chrome::NOTIFICATION_UPGRADE_RECOMMENDED, type); | |
191 | |
192 // An upgrade is ready, so attempt to fetch the Variations seed in case there | |
193 // were updates. | |
194 FetchVariationsSeed(); | |
195 | |
196 // Since we explicitly call FetchVariationsSeed here, we can reset the timer | |
197 // so that we don't retry for another full period. | |
198 if (timer_.IsRunning()) | |
199 timer_.Reset(); | |
200 } | |
201 | |
202 void VariationsService::OnURLFetchComplete(const net::URLFetcher* source) { | 174 void VariationsService::OnURLFetchComplete(const net::URLFetcher* source) { |
203 DCHECK_EQ(pending_seed_request_.get(), source); | 175 DCHECK_EQ(pending_seed_request_.get(), source); |
204 // When we're done handling the request, the fetcher will be deleted. | 176 // When we're done handling the request, the fetcher will be deleted. |
205 scoped_ptr<const net::URLFetcher> request( | 177 scoped_ptr<const net::URLFetcher> request( |
206 pending_seed_request_.release()); | 178 pending_seed_request_.release()); |
207 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS) { | 179 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS) { |
208 DVLOG(1) << "Variations server request failed."; | 180 DVLOG(1) << "Variations server request failed."; |
209 return; | 181 return; |
210 } | 182 } |
211 | 183 |
212 if (request->GetResponseCode() != 200) { | 184 if (request->GetResponseCode() != 200) { |
213 DVLOG(1) << "Variations server request returned non-200 response code: " | 185 DVLOG(1) << "Variations server request returned non-200 response code: " |
214 << request->GetResponseCode(); | 186 << request->GetResponseCode(); |
215 return; | 187 return; |
216 } | 188 } |
217 | 189 |
218 std::string seed_data; | 190 std::string seed_data; |
219 bool success = request->GetResponseAsString(&seed_data); | 191 bool success = request->GetResponseAsString(&seed_data); |
220 DCHECK(success); | 192 DCHECK(success); |
221 | 193 |
222 base::Time response_date; | 194 base::Time response_date; |
223 success = request->GetResponseHeaders()->GetDateValue(&response_date); | 195 success = request->GetResponseHeaders()->GetDateValue(&response_date); |
224 DCHECK(success || response_date.is_null()); | 196 DCHECK(success || response_date.is_null()); |
225 | 197 |
226 StoreSeedData(seed_data, response_date, g_browser_process->local_state()); | 198 StoreSeedData(seed_data, response_date, g_browser_process->local_state()); |
227 } | 199 } |
228 | 200 |
| 201 // static |
| 202 void VariationsService::RegisterPrefs(PrefService* prefs) { |
| 203 prefs->RegisterStringPref(prefs::kVariationsSeed, std::string()); |
| 204 prefs->RegisterInt64Pref(prefs::kVariationsSeedDate, |
| 205 base::Time().ToInternalValue()); |
| 206 } |
| 207 |
229 bool VariationsService::StoreSeedData(const std::string& seed_data, | 208 bool VariationsService::StoreSeedData(const std::string& seed_data, |
230 const base::Time& seed_date, | 209 const base::Time& seed_date, |
231 PrefService* local_prefs) { | 210 PrefService* local_prefs) { |
232 // Only store the seed data if it parses correctly. | 211 // Only store the seed data if it parses correctly. |
233 TrialsSeed seed; | 212 TrialsSeed seed; |
234 if (!seed.ParseFromString(seed_data)) { | 213 if (!seed.ParseFromString(seed_data)) { |
235 VLOG(1) << "Variations Seed data from server is not in valid proto format, " | 214 VLOG(1) << "Variations Seed data from server is not in valid proto format, " |
236 << "rejecting the seed."; | 215 << "rejecting the seed."; |
237 return false; | 216 return false; |
238 } | 217 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 variation_id); | 464 variation_id); |
486 } | 465 } |
487 } | 466 } |
488 | 467 |
489 trial->SetForced(); | 468 trial->SetForced(); |
490 if (IsStudyExpired(study, reference_date)) | 469 if (IsStudyExpired(study, reference_date)) |
491 trial->Disable(); | 470 trial->Disable(); |
492 } | 471 } |
493 | 472 |
494 } // namespace chrome_variations | 473 } // namespace chrome_variations |
OLD | NEW |