[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 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. |
| 4 | |
| 5 | #include "components/domain_reliability/monitor.h" |
| 6 | |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 9 | #include "base/command_line.h" |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 10 | #include "base/logging.h" |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 11 | #include "base/memory/ptr_util.h" |
vadimt | c839723 | 2014-12-19 17:34:14 | [diff] [blame] | 12 | #include "base/profiler/scoped_tracker.h" |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 13 | #include "base/single_thread_task_runner.h" |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 14 | #include "base/task_runner.h" |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 15 | #include "components/domain_reliability/baked_in_configs.h" |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 16 | #include "components/domain_reliability/google_configs.h" |
ttuttle | 2935096c | 2016-02-09 22:31:44 | [diff] [blame] | 17 | #include "components/domain_reliability/header.h" |
ttuttle | b160737 | 2016-02-09 16:27:16 | [diff] [blame] | 18 | #include "components/domain_reliability/quic_error_mapping.h" |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 19 | #include "net/base/ip_endpoint.h" |
[email protected] | 48b99c9 | 2014-04-21 22:23:20 | [diff] [blame] | 20 | #include "net/base/load_flags.h" |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 21 | #include "net/base/net_errors.h" |
[email protected] | 563dc476 | 2014-05-11 00:43:49 | [diff] [blame] | 22 | #include "net/http/http_response_headers.h" |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 23 | #include "net/url_request/url_request.h" |
| 24 | #include "net/url_request/url_request_context.h" |
| 25 | #include "net/url_request/url_request_context_getter.h" |
| 26 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 27 | namespace domain_reliability { |
| 28 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | int URLRequestStatusToNetError(const net::URLRequestStatus& status) { |
| 32 | switch (status.status()) { |
| 33 | case net::URLRequestStatus::SUCCESS: |
| 34 | return net::OK; |
| 35 | case net::URLRequestStatus::IO_PENDING: |
| 36 | return net::ERR_IO_PENDING; |
| 37 | case net::URLRequestStatus::CANCELED: |
| 38 | return net::ERR_ABORTED; |
| 39 | case net::URLRequestStatus::FAILED: |
| 40 | return status.error(); |
| 41 | default: |
| 42 | NOTREACHED(); |
| 43 | return net::ERR_UNEXPECTED; |
| 44 | } |
| 45 | } |
| 46 | |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 47 | // Creates a new beacon based on |beacon_template| but fills in the status, |
| 48 | // chrome_error, and server_ip fields based on the endpoint and result of |
| 49 | // |attempt|. |
| 50 | // |
| 51 | // If there is no matching status for the result, returns false (which |
| 52 | // means the attempt should not result in a beacon being reported). |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 53 | std::unique_ptr<DomainReliabilityBeacon> CreateBeaconFromAttempt( |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 54 | const DomainReliabilityBeacon& beacon_template, |
| 55 | const net::ConnectionAttempt& attempt) { |
| 56 | std::string status; |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 57 | if (!GetDomainReliabilityBeaconStatus( |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 58 | attempt.result, beacon_template.http_response_code, &status)) { |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 59 | return std::unique_ptr<DomainReliabilityBeacon>(); |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 60 | } |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 61 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 62 | std::unique_ptr<DomainReliabilityBeacon> beacon( |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 63 | new DomainReliabilityBeacon(beacon_template)); |
| 64 | beacon->status = status; |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 65 | beacon->chrome_error = attempt.result; |
| 66 | if (!attempt.endpoint.address().empty()) |
| 67 | beacon->server_ip = attempt.endpoint.ToString(); |
| 68 | else |
| 69 | beacon->server_ip = ""; |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 70 | return beacon; |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 71 | } |
| 72 | |
ttuttle | 2935096c | 2016-02-09 22:31:44 | [diff] [blame] | 73 | const char* kDomainReliabilityHeaderName = "NEL"; |
| 74 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 75 | } // namespace |
| 76 | |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 77 | DomainReliabilityMonitor::DomainReliabilityMonitor( |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 78 | const std::string& upload_reporter_string, |
grt | 2792ed7 | 2015-02-20 19:40:21 | [diff] [blame] | 79 | const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, |
| 80 | const scoped_refptr<base::SingleThreadTaskRunner>& network_thread) |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 81 | : time_(new ActualTime()), |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 82 | upload_reporter_string_(upload_reporter_string), |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 83 | scheduler_params_( |
| 84 | DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()), |
| 85 | dispatcher_(time_.get()), |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 86 | context_manager_(this), |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 87 | pref_task_runner_(pref_thread), |
| 88 | network_task_runner_(network_thread), |
| 89 | moved_to_network_thread_(false), |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 90 | discard_uploads_set_(false), |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 91 | weak_factory_(this) { |
| 92 | DCHECK(OnPrefThread()); |
ttuttle | 743f4ae | 2014-11-04 20:22:32 | [diff] [blame] | 93 | net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 94 | } |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 95 | |
| 96 | DomainReliabilityMonitor::DomainReliabilityMonitor( |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 97 | const std::string& upload_reporter_string, |
grt | 2792ed7 | 2015-02-20 19:40:21 | [diff] [blame] | 98 | const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, |
| 99 | const scoped_refptr<base::SingleThreadTaskRunner>& network_thread, |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 100 | std::unique_ptr<MockableTime> time) |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 101 | : time_(std::move(time)), |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 102 | upload_reporter_string_(upload_reporter_string), |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 103 | scheduler_params_( |
| 104 | DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()), |
| 105 | dispatcher_(time_.get()), |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 106 | context_manager_(this), |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 107 | pref_task_runner_(pref_thread), |
| 108 | network_task_runner_(network_thread), |
| 109 | moved_to_network_thread_(false), |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 110 | discard_uploads_set_(false), |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 111 | weak_factory_(this) { |
| 112 | DCHECK(OnPrefThread()); |
ttuttle | 743f4ae | 2014-11-04 20:22:32 | [diff] [blame] | 113 | net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 114 | } |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 115 | |
| 116 | DomainReliabilityMonitor::~DomainReliabilityMonitor() { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 117 | if (moved_to_network_thread_) |
| 118 | DCHECK(OnNetworkThread()); |
| 119 | else |
| 120 | DCHECK(OnPrefThread()); |
| 121 | |
ttuttle | 743f4ae | 2014-11-04 20:22:32 | [diff] [blame] | 122 | net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 123 | } |
| 124 | |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 125 | void DomainReliabilityMonitor::MoveToNetworkThread() { |
| 126 | DCHECK(OnPrefThread()); |
| 127 | DCHECK(!moved_to_network_thread_); |
| 128 | |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 129 | moved_to_network_thread_ = true; |
| 130 | } |
| 131 | |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 132 | void DomainReliabilityMonitor::InitURLRequestContext( |
| 133 | net::URLRequestContext* url_request_context) { |
| 134 | DCHECK(OnNetworkThread()); |
| 135 | DCHECK(moved_to_network_thread_); |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 136 | |
| 137 | scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = |
| 138 | new net::TrivialURLRequestContextGetter(url_request_context, |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 139 | network_task_runner_); |
| 140 | InitURLRequestContext(url_request_context_getter); |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 141 | } |
| 142 | |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 143 | void DomainReliabilityMonitor::InitURLRequestContext( |
grt | 2792ed7 | 2015-02-20 19:40:21 | [diff] [blame] | 144 | const scoped_refptr<net::URLRequestContextGetter>& |
| 145 | url_request_context_getter) { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 146 | DCHECK(OnNetworkThread()); |
| 147 | DCHECK(moved_to_network_thread_); |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 148 | |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 149 | // Make sure the URLRequestContext actually lives on what was declared to be |
| 150 | // the network thread. |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 151 | DCHECK(url_request_context_getter->GetNetworkTaskRunner()-> |
| 152 | RunsTasksOnCurrentThread()); |
| 153 | |
ttuttle | 280a73d | 2014-11-13 21:38:04 | [diff] [blame] | 154 | uploader_ = DomainReliabilityUploader::Create(time_.get(), |
| 155 | url_request_context_getter); |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 156 | } |
| 157 | |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 158 | void DomainReliabilityMonitor::AddBakedInConfigs() { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 159 | DCHECK(OnNetworkThread()); |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 160 | DCHECK(moved_to_network_thread_); |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 161 | |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 162 | for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) { |
grt | 2792ed7 | 2015-02-20 19:40:21 | [diff] [blame] | 163 | base::StringPiece json(kBakedInJsonConfigs[i]); |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 164 | std::unique_ptr<const DomainReliabilityConfig> config = |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 165 | DomainReliabilityConfig::FromJSON(json); |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 166 | if (!config) { |
| 167 | DLOG(WARNING) << "Baked-in Domain Reliability config failed to parse: " |
| 168 | << json; |
grt | 2792ed7 | 2015-02-20 19:40:21 | [diff] [blame] | 169 | continue; |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 170 | } |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 171 | context_manager_.AddContextForConfig(std::move(config)); |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 172 | } |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 173 | |
| 174 | std::vector<DomainReliabilityConfig*> google_configs; |
| 175 | GetAllGoogleConfigs(&google_configs); |
| 176 | for (auto google_config : google_configs) |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 177 | context_manager_.AddContextForConfig(base::WrapUnique(google_config)); |
[email protected] | 5f404b3 | 2014-04-22 17:16:14 | [diff] [blame] | 178 | } |
| 179 | |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 180 | void DomainReliabilityMonitor::SetDiscardUploads(bool discard_uploads) { |
| 181 | DCHECK(OnNetworkThread()); |
| 182 | DCHECK(moved_to_network_thread_); |
| 183 | DCHECK(uploader_); |
| 184 | |
| 185 | uploader_->set_discard_uploads(discard_uploads); |
| 186 | discard_uploads_set_ = true; |
| 187 | } |
| 188 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 189 | void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 190 | DCHECK(OnNetworkThread()); |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 191 | DCHECK(discard_uploads_set_); |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 192 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 193 | // Record the redirect itself in addition to the final request. |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 194 | OnRequestLegComplete(RequestInfo(*request)); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request, |
| 198 | bool started) { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 199 | DCHECK(OnNetworkThread()); |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 200 | DCHECK(discard_uploads_set_); |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 201 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 202 | if (!started) |
| 203 | return; |
| 204 | RequestInfo request_info(*request); |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 205 | OnRequestLegComplete(request_info); |
| 206 | |
| 207 | if (request_info.response_info.network_accessed) { |
[email protected] | a5553ace | 2014-04-15 03:42:28 | [diff] [blame] | 208 | // A request was just using the network, so now is a good time to run any |
| 209 | // pending and eligible uploads. |
| 210 | dispatcher_.RunEligibleTasks(); |
| 211 | } |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 212 | } |
| 213 | |
ttuttle | 743f4ae | 2014-11-04 20:22:32 | [diff] [blame] | 214 | void DomainReliabilityMonitor::OnNetworkChanged( |
| 215 | net::NetworkChangeNotifier::ConnectionType type) { |
| 216 | last_network_change_time_ = time_->NowTicks(); |
| 217 | } |
| 218 | |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 219 | void DomainReliabilityMonitor::ClearBrowsingData( |
| 220 | DomainReliabilityClearMode mode) { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 221 | DCHECK(OnNetworkThread()); |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 222 | |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 223 | switch (mode) { |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 224 | case CLEAR_BEACONS: |
| 225 | context_manager_.ClearBeaconsInAllContexts(); |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 226 | break; |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 227 | case CLEAR_CONTEXTS: |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 228 | context_manager_.RemoveAllContexts(); |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 229 | break; |
| 230 | case MAX_CLEAR_MODE: |
| 231 | NOTREACHED(); |
| 232 | } |
| 233 | } |
| 234 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 235 | std::unique_ptr<base::Value> DomainReliabilityMonitor::GetWebUIData() const { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 236 | DCHECK(OnNetworkThread()); |
| 237 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 238 | std::unique_ptr<base::DictionaryValue> data_value( |
| 239 | new base::DictionaryValue()); |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 240 | data_value->Set("contexts", context_manager_.GetWebUIData()); |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 241 | return std::move(data_value); |
[email protected] | a6093f41 | 2014-07-10 00:57:09 | [diff] [blame] | 242 | } |
| 243 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 244 | DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting( |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 245 | std::unique_ptr<const DomainReliabilityConfig> config) { |
ttuttle | fa8427f9 | 2014-08-25 19:38:03 | [diff] [blame] | 246 | DCHECK(OnNetworkThread()); |
| 247 | |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 248 | return context_manager_.AddContextForConfig(std::move(config)); |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 249 | } |
| 250 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 251 | std::unique_ptr<DomainReliabilityContext> |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 252 | DomainReliabilityMonitor::CreateContextForConfig( |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 253 | std::unique_ptr<const DomainReliabilityConfig> config) { |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 254 | DCHECK(OnNetworkThread()); |
| 255 | DCHECK(config); |
| 256 | DCHECK(config->IsValid()); |
| 257 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 258 | return base::WrapUnique(new DomainReliabilityContext( |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 259 | time_.get(), scheduler_params_, upload_reporter_string_, |
| 260 | &last_network_change_time_, &dispatcher_, uploader_.get(), |
| 261 | std::move(config))); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | DomainReliabilityMonitor::RequestInfo::RequestInfo() {} |
| 265 | |
| 266 | DomainReliabilityMonitor::RequestInfo::RequestInfo( |
| 267 | const net::URLRequest& request) |
| 268 | : url(request.url()), |
| 269 | status(request.status()), |
[email protected] | 563dc476 | 2014-05-11 00:43:49 | [diff] [blame] | 270 | response_info(request.response_info()), |
[email protected] | d1acfe0 | 2014-04-24 17:15:29 | [diff] [blame] | 271 | load_flags(request.load_flags()), |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 272 | upload_depth( |
| 273 | DomainReliabilityUploader::GetURLRequestUploadDepth(request)) { |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 274 | request.GetLoadTimingInfo(&load_timing_info); |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 275 | request.GetConnectionAttempts(&connection_attempts); |
zhongyi | c51f4ed | 2015-12-08 00:41:13 | [diff] [blame] | 276 | request.PopulateNetErrorDetails(&details); |
ttuttle | 661a7b9 | 2015-09-29 22:36:33 | [diff] [blame] | 277 | if (!request.GetRemoteEndpoint(&remote_endpoint)) |
| 278 | remote_endpoint = net::IPEndPoint(); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 279 | } |
| 280 | |
vmpstr | b6449d51 | 2016-02-25 23:55:40 | [diff] [blame] | 281 | DomainReliabilityMonitor::RequestInfo::RequestInfo(const RequestInfo& other) = |
| 282 | default; |
| 283 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 284 | DomainReliabilityMonitor::RequestInfo::~RequestInfo() {} |
| 285 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 286 | // static |
| 287 | bool DomainReliabilityMonitor::RequestInfo::ShouldReportRequest( |
| 288 | const DomainReliabilityMonitor::RequestInfo& request) { |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 289 | // Don't report requests that weren't supposed to send cookies. |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 290 | if (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) |
| 291 | return false; |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 292 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 293 | // Report requests that accessed the network or failed with an error code |
| 294 | // that Domain Reliability is interested in. |
| 295 | if (request.response_info.network_accessed) |
| 296 | return true; |
| 297 | if (URLRequestStatusToNetError(request.status) != net::OK) |
| 298 | return true; |
zhongyi | 93fa5a9 | 2016-03-14 18:10:57 | [diff] [blame] | 299 | if (request.details.quic_port_migration_detected) |
| 300 | return true; |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 301 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 302 | return false; |
[email protected] | a5553ace | 2014-04-15 03:42:28 | [diff] [blame] | 303 | } |
| 304 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 305 | void DomainReliabilityMonitor::OnRequestLegComplete( |
| 306 | const RequestInfo& request) { |
ttuttle | 91f1bbd | 2014-10-07 05:57:54 | [diff] [blame] | 307 | // Check these again because unit tests call this directly. |
| 308 | DCHECK(OnNetworkThread()); |
| 309 | DCHECK(discard_uploads_set_); |
| 310 | |
ttuttle | 2935096c | 2016-02-09 22:31:44 | [diff] [blame] | 311 | MaybeHandleHeader(request); |
| 312 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 313 | if (!RequestInfo::ShouldReportRequest(request)) |
| 314 | return; |
| 315 | |
[email protected] | 563dc476 | 2014-05-11 00:43:49 | [diff] [blame] | 316 | int response_code; |
dcheng | 45252e8e | 2014-08-26 17:59:54 | [diff] [blame] | 317 | if (request.response_info.headers.get()) |
[email protected] | 563dc476 | 2014-05-11 00:43:49 | [diff] [blame] | 318 | response_code = request.response_info.headers->response_code(); |
| 319 | else |
| 320 | response_code = -1; |
[email protected] | 563dc476 | 2014-05-11 00:43:49 | [diff] [blame] | 321 | |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 322 | net::ConnectionAttempt url_request_attempt( |
ttuttle | 661a7b9 | 2015-09-29 22:36:33 | [diff] [blame] | 323 | request.remote_endpoint, URLRequestStatusToNetError(request.status)); |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 324 | |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 325 | DomainReliabilityBeacon beacon_template; |
zhongyi | 2ed4a6a | 2016-02-26 19:45:42 | [diff] [blame] | 326 | if (request.response_info.connection_info != |
| 327 | net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN) { |
| 328 | beacon_template.protocol = |
| 329 | GetDomainReliabilityProtocol(request.response_info.connection_info, |
| 330 | request.response_info.ssl_info.is_valid()); |
| 331 | } else { |
| 332 | // Use the connection info from the network error details if the response |
| 333 | // is unavailable. |
| 334 | beacon_template.protocol = |
| 335 | GetDomainReliabilityProtocol(request.details.connection_info, |
| 336 | request.response_info.ssl_info.is_valid()); |
| 337 | } |
zhongyi | 291d030 | 2015-12-14 07:06:25 | [diff] [blame] | 338 | GetDomainReliabilityBeaconQuicError(request.details.quic_connection_error, |
| 339 | &beacon_template.quic_error); |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 340 | beacon_template.http_response_code = response_code; |
| 341 | beacon_template.start_time = request.load_timing_info.request_start; |
| 342 | beacon_template.elapsed = time_->NowTicks() - beacon_template.start_time; |
| 343 | beacon_template.was_proxied = request.response_info.was_fetched_via_proxy; |
| 344 | beacon_template.url = request.url; |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 345 | beacon_template.upload_depth = request.upload_depth; |
zhongyi | c51f4ed | 2015-12-08 00:41:13 | [diff] [blame] | 346 | beacon_template.details = request.details; |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 347 | |
| 348 | // This is not foolproof -- it's possible that we'll see the same error twice |
| 349 | // (e.g. an SSL error during connection on one attempt, and then an error |
| 350 | // that maps to the same code during a read). |
ttuttle | 960fcbf | 2016-04-19 13:26:32 | [diff] [blame] | 351 | // TODO(juliatuttle): Find a way for this code to reliably tell whether we |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 352 | // eventually established a connection or not. |
| 353 | bool url_request_attempt_is_duplicate = false; |
| 354 | for (const auto& attempt : request.connection_attempts) { |
| 355 | if (attempt.result == url_request_attempt.result) |
| 356 | url_request_attempt_is_duplicate = true; |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 357 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 358 | std::unique_ptr<DomainReliabilityBeacon> beacon = |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 359 | CreateBeaconFromAttempt(beacon_template, attempt); |
| 360 | if (beacon) |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 361 | context_manager_.RouteBeacon(std::move(beacon)); |
ttuttle | 8feb018 | 2015-05-15 23:40:32 | [diff] [blame] | 362 | } |
| 363 | |
| 364 | if (url_request_attempt_is_duplicate) |
| 365 | return; |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 366 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 367 | std::unique_ptr<DomainReliabilityBeacon> beacon = |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 368 | CreateBeaconFromAttempt(beacon_template, url_request_attempt); |
| 369 | if (beacon) |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 370 | context_manager_.RouteBeacon(std::move(beacon)); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 371 | } |
| 372 | |
ttuttle | 2935096c | 2016-02-09 22:31:44 | [diff] [blame] | 373 | void DomainReliabilityMonitor::MaybeHandleHeader( |
| 374 | const RequestInfo& request) { |
| 375 | if (!request.response_info.headers.get()) |
| 376 | return; |
| 377 | |
| 378 | size_t iter = 0; |
| 379 | std::string kHeaderNameString(kDomainReliabilityHeaderName); |
| 380 | |
| 381 | std::string header_value; |
| 382 | if (!request.response_info.headers->EnumerateHeader( |
| 383 | &iter, kHeaderNameString, &header_value)) { |
| 384 | // No header found. |
| 385 | return; |
| 386 | } |
| 387 | |
| 388 | std::string ignored_header_value; |
| 389 | if (request.response_info.headers->EnumerateHeader( |
| 390 | &iter, kHeaderNameString, &ignored_header_value)) { |
| 391 | LOG(WARNING) << "Request to " << request.url << " had (at least) two " |
| 392 | << kHeaderNameString << " headers: \"" << header_value |
| 393 | << "\" and \"" << ignored_header_value << "\"."; |
| 394 | return; |
| 395 | } |
| 396 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 397 | std::unique_ptr<DomainReliabilityHeader> parsed = |
ttuttle | 2935096c | 2016-02-09 22:31:44 | [diff] [blame] | 398 | DomainReliabilityHeader::Parse(header_value); |
| 399 | GURL origin = request.url.GetOrigin(); |
| 400 | switch (parsed->status()) { |
| 401 | case DomainReliabilityHeader::PARSE_SET_CONFIG: |
| 402 | { |
| 403 | base::TimeDelta max_age = parsed->max_age(); |
| 404 | context_manager_.SetConfig(origin, parsed->ReleaseConfig(), max_age); |
| 405 | } |
| 406 | break; |
| 407 | case DomainReliabilityHeader::PARSE_CLEAR_CONFIG: |
| 408 | context_manager_.ClearConfig(origin); |
| 409 | break; |
| 410 | case DomainReliabilityHeader::PARSE_ERROR: |
| 411 | LOG(WARNING) << "Request to " << request.url << " had invalid " |
| 412 | << kHeaderNameString << " header \"" << header_value |
| 413 | << "\"."; |
| 414 | break; |
| 415 | } |
| 416 | } |
| 417 | |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 418 | base::WeakPtr<DomainReliabilityMonitor> |
| 419 | DomainReliabilityMonitor::MakeWeakPtr() { |
| 420 | return weak_factory_.GetWeakPtr(); |
| 421 | } |
| 422 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 423 | } // namespace domain_reliability |