ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / components / domain_reliability / monitor.cc
blob070b62deb09271eb0d35c3432887400ad8e80a0a
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 pref_task_runner_(pref_thread),
32 network_task_runner_(network_thread),
33 moved_to_network_thread_(false),
34 discard_uploads_set_(false),
35 weak_factory_(this) {
36 DCHECK(OnPrefThread());
37 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
40 DomainReliabilityMonitor::DomainReliabilityMonitor(
41 const std::string& upload_reporter_string,
42 const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread,
43 const scoped_refptr<base::SingleThreadTaskRunner>& network_thread,
44 scoped_ptr<MockableTime> time)
45 : time_(time.Pass()),
46 upload_reporter_string_(upload_reporter_string),
47 scheduler_params_(
48 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
49 dispatcher_(time_.get()),
50 pref_task_runner_(pref_thread),
51 network_task_runner_(network_thread),
52 moved_to_network_thread_(false),
53 discard_uploads_set_(false),
54 weak_factory_(this) {
55 DCHECK(OnPrefThread());
56 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
59 DomainReliabilityMonitor::~DomainReliabilityMonitor() {
60 if (moved_to_network_thread_)
61 DCHECK(OnNetworkThread());
62 else
63 DCHECK(OnPrefThread());
65 ClearContexts();
66 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
69 void DomainReliabilityMonitor::MoveToNetworkThread() {
70 DCHECK(OnPrefThread());
71 DCHECK(!moved_to_network_thread_);
73 moved_to_network_thread_ = true;
76 void DomainReliabilityMonitor::InitURLRequestContext(
77 net::URLRequestContext* url_request_context) {
78 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed.
79 tracked_objects::ScopedTracker tracking_profile(
80 FROM_HERE_WITH_EXPLICIT_FUNCTION(
81 "436671 DomainReliabilityMonitor::InitURLRequestContext"));
83 DCHECK(OnNetworkThread());
84 DCHECK(moved_to_network_thread_);
86 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
87 new net::TrivialURLRequestContextGetter(url_request_context,
88 network_task_runner_);
89 InitURLRequestContext(url_request_context_getter);
92 void DomainReliabilityMonitor::InitURLRequestContext(
93 const scoped_refptr<net::URLRequestContextGetter>&
94 url_request_context_getter) {
95 DCHECK(OnNetworkThread());
96 DCHECK(moved_to_network_thread_);
98 // Make sure the URLRequestContext actually lives on what was declared to be
99 // the network thread.
100 DCHECK(url_request_context_getter->GetNetworkTaskRunner()->
101 RunsTasksOnCurrentThread());
103 uploader_ = DomainReliabilityUploader::Create(time_.get(),
104 url_request_context_getter);
107 void DomainReliabilityMonitor::AddBakedInConfigs() {
108 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed.
109 tracked_objects::ScopedTracker tracking_profile(
110 FROM_HERE_WITH_EXPLICIT_FUNCTION(
111 "436671 DomainReliabilityMonitor::AddBakedInConfigs"));
113 DCHECK(OnNetworkThread());
114 DCHECK(moved_to_network_thread_);
116 base::Time now = base::Time::Now();
117 for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
118 base::StringPiece json(kBakedInJsonConfigs[i]);
119 scoped_ptr<const DomainReliabilityConfig> config =
120 DomainReliabilityConfig::FromJSON(json);
121 if (!config) {
122 continue;
123 } else if (config->IsExpired(now)) {
124 LOG(WARNING) << "Baked-in Domain Reliability config for "
125 << config->domain << " is expired.";
126 continue;
128 AddContext(config.Pass());
132 void DomainReliabilityMonitor::SetDiscardUploads(bool discard_uploads) {
133 DCHECK(OnNetworkThread());
134 DCHECK(moved_to_network_thread_);
135 DCHECK(uploader_);
137 uploader_->set_discard_uploads(discard_uploads);
138 discard_uploads_set_ = true;
141 void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
142 DCHECK(OnNetworkThread());
143 DCHECK(discard_uploads_set_);
145 // Record the redirect itself in addition to the final request.
146 OnRequestLegComplete(RequestInfo(*request));
149 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
150 bool started) {
151 DCHECK(OnNetworkThread());
152 DCHECK(discard_uploads_set_);
154 if (!started)
155 return;
156 RequestInfo request_info(*request);
157 if (request_info.AccessedNetwork()) {
158 OnRequestLegComplete(request_info);
159 // A request was just using the network, so now is a good time to run any
160 // pending and eligible uploads.
161 dispatcher_.RunEligibleTasks();
165 void DomainReliabilityMonitor::OnNetworkChanged(
166 net::NetworkChangeNotifier::ConnectionType type) {
167 last_network_change_time_ = time_->NowTicks();
170 void DomainReliabilityMonitor::ClearBrowsingData(
171 DomainReliabilityClearMode mode) {
172 DCHECK(OnNetworkThread());
174 switch (mode) {
175 case CLEAR_BEACONS: {
176 ContextMap::const_iterator it;
177 for (it = contexts_.begin(); it != contexts_.end(); ++it)
178 it->second->ClearBeacons();
179 break;
181 case CLEAR_CONTEXTS:
182 ClearContexts();
183 break;
184 case MAX_CLEAR_MODE:
185 NOTREACHED();
189 scoped_ptr<base::Value> DomainReliabilityMonitor::GetWebUIData() const {
190 DCHECK(OnNetworkThread());
192 base::ListValue* contexts_value = new base::ListValue();
193 for (ContextMap::const_iterator it = contexts_.begin();
194 it != contexts_.end();
195 ++it) {
196 contexts_value->Append(it->second->GetWebUIData().release());
199 base::DictionaryValue* data_value = new base::DictionaryValue();
200 data_value->Set("contexts", contexts_value);
202 return scoped_ptr<base::Value>(data_value);
205 DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
206 scoped_ptr<const DomainReliabilityConfig> config) {
207 DCHECK(OnNetworkThread());
209 return AddContext(config.Pass());
212 DomainReliabilityMonitor::RequestInfo::RequestInfo() {}
214 DomainReliabilityMonitor::RequestInfo::RequestInfo(
215 const net::URLRequest& request)
216 : url(request.url()),
217 status(request.status()),
218 response_info(request.response_info()),
219 load_flags(request.load_flags()),
220 is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
221 request.GetLoadTimingInfo(&load_timing_info);
224 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
226 bool DomainReliabilityMonitor::RequestInfo::AccessedNetwork() const {
227 return status.status() != net::URLRequestStatus::CANCELED &&
228 response_info.network_accessed;
231 DomainReliabilityContext* DomainReliabilityMonitor::AddContext(
232 scoped_ptr<const DomainReliabilityConfig> config) {
233 DCHECK(OnNetworkThread());
234 DCHECK(config);
235 DCHECK(config->IsValid());
237 // Grab a copy of the domain before transferring ownership of |config|.
238 std::string domain = config->domain;
240 DomainReliabilityContext* context =
241 new DomainReliabilityContext(time_.get(),
242 scheduler_params_,
243 upload_reporter_string_,
244 &last_network_change_time_,
245 &dispatcher_,
246 uploader_.get(),
247 config.Pass());
249 std::pair<ContextMap::iterator, bool> map_it =
250 contexts_.insert(make_pair(domain, context));
251 // Make sure the domain wasn't already in the map.
252 DCHECK(map_it.second);
254 return map_it.first->second;
257 void DomainReliabilityMonitor::ClearContexts() {
258 STLDeleteContainerPairSecondPointers(
259 contexts_.begin(), contexts_.end());
260 contexts_.clear();
263 void DomainReliabilityMonitor::OnRequestLegComplete(
264 const RequestInfo& request) {
265 // Check these again because unit tests call this directly.
266 DCHECK(OnNetworkThread());
267 DCHECK(discard_uploads_set_);
269 int response_code;
270 if (request.response_info.headers.get())
271 response_code = request.response_info.headers->response_code();
272 else
273 response_code = -1;
274 std::string beacon_status;
276 int error_code = net::OK;
277 if (request.status.status() == net::URLRequestStatus::FAILED)
278 error_code = request.status.error();
280 DomainReliabilityContext* context = GetContextForHost(request.url.host());
282 // Ignore requests where:
283 // 1. There is no context for the request host.
284 // 2. The request did not access the network.
285 // 3. The request is not supposed to send cookies (to avoid associating the
286 // request with any potentially unique data in the config).
287 // 4. The request was itself a Domain Reliability upload (to avoid loops).
288 // 5. There is no defined beacon status for the error or HTTP response code
289 // (to avoid leaking network-local errors).
290 if (!context ||
291 !request.AccessedNetwork() ||
292 (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
293 request.is_upload ||
294 !GetDomainReliabilityBeaconStatus(
295 error_code, response_code, &beacon_status)) {
296 return;
299 DomainReliabilityBeacon beacon;
300 beacon.status = beacon_status;
301 beacon.chrome_error = error_code;
302 // If the response was cached, the socket address was the address that the
303 // response was originally received from, so it shouldn't be copied into the
304 // beacon.
306 // TODO(ttuttle): Wire up a way to get the real socket address in that case.
307 if (!request.response_info.was_cached &&
308 !request.response_info.was_fetched_via_proxy) {
309 beacon.server_ip = request.response_info.socket_address.host();
311 beacon.protocol = GetDomainReliabilityProtocol(
312 request.response_info.connection_info,
313 request.response_info.ssl_info.is_valid());
314 beacon.http_response_code = response_code;
315 beacon.start_time = request.load_timing_info.request_start;
316 beacon.elapsed = time_->NowTicks() - beacon.start_time;
317 beacon.domain = request.url.host();
318 context->OnBeacon(request.url, beacon);
321 // TODO(ttuttle): Keep a separate wildcard_contexts_ map to avoid having to
322 // prepend '*.' to domains.
323 DomainReliabilityContext* DomainReliabilityMonitor::GetContextForHost(
324 const std::string& host) const {
325 DCHECK(OnNetworkThread());
327 ContextMap::const_iterator context_it;
329 context_it = contexts_.find(host);
330 if (context_it != contexts_.end())
331 return context_it->second;
333 std::string host_with_asterisk = "*." + host;
334 context_it = contexts_.find(host_with_asterisk);
335 if (context_it != contexts_.end())
336 return context_it->second;
338 size_t dot_pos = host.find('.');
339 if (dot_pos == std::string::npos)
340 return NULL;
342 // TODO(ttuttle): Make sure parent is not in PSL before using.
344 std::string parent_with_asterisk = "*." + host.substr(dot_pos + 1);
345 context_it = contexts_.find(parent_with_asterisk);
346 if (context_it != contexts_.end())
347 return context_it->second;
349 return NULL;
352 base::WeakPtr<DomainReliabilityMonitor>
353 DomainReliabilityMonitor::MakeWeakPtr() {
354 return weak_factory_.GetWeakPtr();
357 } // namespace domain_reliability