Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / components / domain_reliability / monitor.cc
blobc3a00ab92454cd2e700dd3e3f4fcc179e3cc7d8b
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.
5 #include "components/domain_reliability/monitor.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/profiler/scoped_tracker.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/task_runner.h"
12 #include "base/time/time.h"
13 #include "components/domain_reliability/baked_in_configs.h"
14 #include "net/base/load_flags.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/url_request/url_request.h"
17 #include "net/url_request/url_request_context.h"
18 #include "net/url_request/url_request_context_getter.h"
20 namespace domain_reliability {
22 DomainReliabilityMonitor::DomainReliabilityMonitor(
23 const std::string& upload_reporter_string,
24 const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread,
25 const scoped_refptr<base::SingleThreadTaskRunner>& network_thread)
26 : time_(new ActualTime()),
27 upload_reporter_string_(upload_reporter_string),
28 scheduler_params_(
29 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
30 dispatcher_(time_.get()),
31 context_manager_(this),
32 pref_task_runner_(pref_thread),
33 network_task_runner_(network_thread),
34 moved_to_network_thread_(false),
35 discard_uploads_set_(false),
36 weak_factory_(this) {
37 DCHECK(OnPrefThread());
38 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
41 DomainReliabilityMonitor::DomainReliabilityMonitor(
42 const std::string& upload_reporter_string,
43 const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread,
44 const scoped_refptr<base::SingleThreadTaskRunner>& network_thread,
45 scoped_ptr<MockableTime> time)
46 : time_(time.Pass()),
47 upload_reporter_string_(upload_reporter_string),
48 scheduler_params_(
49 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
50 dispatcher_(time_.get()),
51 context_manager_(this),
52 pref_task_runner_(pref_thread),
53 network_task_runner_(network_thread),
54 moved_to_network_thread_(false),
55 discard_uploads_set_(false),
56 weak_factory_(this) {
57 DCHECK(OnPrefThread());
58 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
61 DomainReliabilityMonitor::~DomainReliabilityMonitor() {
62 if (moved_to_network_thread_)
63 DCHECK(OnNetworkThread());
64 else
65 DCHECK(OnPrefThread());
67 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
70 void DomainReliabilityMonitor::MoveToNetworkThread() {
71 DCHECK(OnPrefThread());
72 DCHECK(!moved_to_network_thread_);
74 moved_to_network_thread_ = true;
77 void DomainReliabilityMonitor::InitURLRequestContext(
78 net::URLRequestContext* url_request_context) {
79 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed.
80 tracked_objects::ScopedTracker tracking_profile(
81 FROM_HERE_WITH_EXPLICIT_FUNCTION(
82 "436671 DomainReliabilityMonitor::InitURLRequestContext"));
84 DCHECK(OnNetworkThread());
85 DCHECK(moved_to_network_thread_);
87 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
88 new net::TrivialURLRequestContextGetter(url_request_context,
89 network_task_runner_);
90 InitURLRequestContext(url_request_context_getter);
93 void DomainReliabilityMonitor::InitURLRequestContext(
94 const scoped_refptr<net::URLRequestContextGetter>&
95 url_request_context_getter) {
96 DCHECK(OnNetworkThread());
97 DCHECK(moved_to_network_thread_);
99 // Make sure the URLRequestContext actually lives on what was declared to be
100 // the network thread.
101 DCHECK(url_request_context_getter->GetNetworkTaskRunner()->
102 RunsTasksOnCurrentThread());
104 uploader_ = DomainReliabilityUploader::Create(time_.get(),
105 url_request_context_getter);
108 void DomainReliabilityMonitor::AddBakedInConfigs() {
109 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed.
110 tracked_objects::ScopedTracker tracking_profile(
111 FROM_HERE_WITH_EXPLICIT_FUNCTION(
112 "436671 DomainReliabilityMonitor::AddBakedInConfigs"));
114 DCHECK(OnNetworkThread());
115 DCHECK(moved_to_network_thread_);
117 base::Time now = base::Time::Now();
118 for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
119 base::StringPiece json(kBakedInJsonConfigs[i]);
120 scoped_ptr<const DomainReliabilityConfig> config =
121 DomainReliabilityConfig::FromJSON(json);
122 if (!config) {
123 continue;
124 } else if (config->IsExpired(now)) {
125 LOG(WARNING) << "Baked-in Domain Reliability config for "
126 << config->domain << " is expired.";
127 continue;
129 context_manager_.AddContextForConfig(config.Pass());
133 void DomainReliabilityMonitor::SetDiscardUploads(bool discard_uploads) {
134 DCHECK(OnNetworkThread());
135 DCHECK(moved_to_network_thread_);
136 DCHECK(uploader_);
138 uploader_->set_discard_uploads(discard_uploads);
139 discard_uploads_set_ = true;
142 void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
143 DCHECK(OnNetworkThread());
144 DCHECK(discard_uploads_set_);
146 // Record the redirect itself in addition to the final request.
147 OnRequestLegComplete(RequestInfo(*request));
150 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
151 bool started) {
152 DCHECK(OnNetworkThread());
153 DCHECK(discard_uploads_set_);
155 if (!started)
156 return;
157 RequestInfo request_info(*request);
158 if (request_info.AccessedNetwork()) {
159 OnRequestLegComplete(request_info);
160 // A request was just using the network, so now is a good time to run any
161 // pending and eligible uploads.
162 dispatcher_.RunEligibleTasks();
166 void DomainReliabilityMonitor::OnNetworkChanged(
167 net::NetworkChangeNotifier::ConnectionType type) {
168 last_network_change_time_ = time_->NowTicks();
171 void DomainReliabilityMonitor::ClearBrowsingData(
172 DomainReliabilityClearMode mode) {
173 DCHECK(OnNetworkThread());
175 switch (mode) {
176 case CLEAR_BEACONS:
177 context_manager_.ClearBeaconsInAllContexts();
178 break;
179 case CLEAR_CONTEXTS:
180 context_manager_.RemoveAllContexts();
181 break;
182 case MAX_CLEAR_MODE:
183 NOTREACHED();
187 scoped_ptr<base::Value> DomainReliabilityMonitor::GetWebUIData() const {
188 DCHECK(OnNetworkThread());
190 scoped_ptr<base::DictionaryValue> data_value(new base::DictionaryValue());
191 data_value->Set("contexts", context_manager_.GetWebUIData());
192 return data_value.Pass();
195 DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
196 scoped_ptr<const DomainReliabilityConfig> config) {
197 DCHECK(OnNetworkThread());
199 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed.
200 tracked_objects::ScopedTracker tracking_profile(
201 FROM_HERE_WITH_EXPLICIT_FUNCTION(
202 "436671 DomainReliabilityConfig::AddContextForConfig"));
204 return context_manager_.AddContextForConfig(config.Pass());
207 scoped_ptr<DomainReliabilityContext>
208 DomainReliabilityMonitor::CreateContextForConfig(
209 scoped_ptr<const DomainReliabilityConfig> config) {
210 DCHECK(OnNetworkThread());
211 DCHECK(config);
212 DCHECK(config->IsValid());
214 return make_scoped_ptr(new DomainReliabilityContext(
215 time_.get(),
216 scheduler_params_,
217 upload_reporter_string_,
218 &last_network_change_time_,
219 &dispatcher_,
220 uploader_.get(),
221 config.Pass()));
224 DomainReliabilityMonitor::RequestInfo::RequestInfo() {}
226 DomainReliabilityMonitor::RequestInfo::RequestInfo(
227 const net::URLRequest& request)
228 : url(request.url()),
229 status(request.status()),
230 response_info(request.response_info()),
231 load_flags(request.load_flags()),
232 is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
233 request.GetLoadTimingInfo(&load_timing_info);
236 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
238 bool DomainReliabilityMonitor::RequestInfo::AccessedNetwork() const {
239 return status.status() != net::URLRequestStatus::CANCELED &&
240 response_info.network_accessed;
243 void DomainReliabilityMonitor::OnRequestLegComplete(
244 const RequestInfo& request) {
245 // Check these again because unit tests call this directly.
246 DCHECK(OnNetworkThread());
247 DCHECK(discard_uploads_set_);
249 int response_code;
250 if (request.response_info.headers.get())
251 response_code = request.response_info.headers->response_code();
252 else
253 response_code = -1;
254 std::string beacon_status;
256 int error_code = net::OK;
257 if (request.status.status() == net::URLRequestStatus::FAILED)
258 error_code = request.status.error();
260 // Ignore requests where:
261 // 1. The request did not access the network.
262 // 2. The request is not supposed to send cookies (to avoid associating the
263 // request with any potentially unique data in the config).
264 // 3. The request was itself a Domain Reliability upload (to avoid loops).
265 // 4. There is no matching beacon status for the error or HTTP response code
266 // (to avoid leaking network-local errors).
267 if (!request.AccessedNetwork() ||
268 (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
269 request.is_upload ||
270 !GetDomainReliabilityBeaconStatus(
271 error_code, response_code, &beacon_status)) {
272 return;
275 DomainReliabilityBeacon beacon;
276 beacon.status = beacon_status;
277 beacon.chrome_error = error_code;
278 // If the response was cached, the socket address was the address that the
279 // response was originally received from, so it shouldn't be copied into the
280 // beacon.
282 // TODO(ttuttle): Wire up a way to get the real socket address in that case.
283 if (!request.response_info.was_cached &&
284 !request.response_info.was_fetched_via_proxy) {
285 beacon.server_ip = request.response_info.socket_address.host();
287 beacon.protocol = GetDomainReliabilityProtocol(
288 request.response_info.connection_info,
289 request.response_info.ssl_info.is_valid());
290 beacon.http_response_code = response_code;
291 beacon.start_time = request.load_timing_info.request_start;
292 beacon.elapsed = time_->NowTicks() - beacon.start_time;
293 beacon.domain = request.url.host();
294 context_manager_.RouteBeacon(request.url, beacon);
297 base::WeakPtr<DomainReliabilityMonitor>
298 DomainReliabilityMonitor::MakeWeakPtr() {
299 return weak_factory_.GetWeakPtr();
302 } // namespace domain_reliability