| OLD | NEW |
| (Empty) |
| 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 #include "net/http/http_network_transaction.h" | |
| 6 | |
| 7 #include <set> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/bind_helpers.h" | |
| 12 #include "base/compiler_specific.h" | |
| 13 #include "base/format_macros.h" | |
| 14 #include "base/memory/scoped_ptr.h" | |
| 15 #include "base/metrics/field_trial.h" | |
| 16 #include "base/metrics/histogram.h" | |
| 17 #include "base/profiler/scoped_tracker.h" | |
| 18 #include "base/stl_util.h" | |
| 19 #include "base/strings/string_number_conversions.h" | |
| 20 #include "base/strings/string_util.h" | |
| 21 #include "base/strings/stringprintf.h" | |
| 22 #include "base/time/time.h" | |
| 23 #include "base/values.h" | |
| 24 #include "build/build_config.h" | |
| 25 #include "net/base/auth.h" | |
| 26 #include "net/base/host_port_pair.h" | |
| 27 #include "net/base/io_buffer.h" | |
| 28 #include "net/base/load_flags.h" | |
| 29 #include "net/base/load_timing_info.h" | |
| 30 #include "net/base/net_errors.h" | |
| 31 #include "net/base/net_util.h" | |
| 32 #include "net/base/upload_data_stream.h" | |
| 33 #include "net/http/http_auth.h" | |
| 34 #include "net/http/http_auth_handler.h" | |
| 35 #include "net/http/http_auth_handler_factory.h" | |
| 36 #include "net/http/http_basic_stream.h" | |
| 37 #include "net/http/http_chunked_decoder.h" | |
| 38 #include "net/http/http_network_session.h" | |
| 39 #include "net/http/http_proxy_client_socket.h" | |
| 40 #include "net/http/http_proxy_client_socket_pool.h" | |
| 41 #include "net/http/http_request_headers.h" | |
| 42 #include "net/http/http_request_info.h" | |
| 43 #include "net/http/http_response_headers.h" | |
| 44 #include "net/http/http_response_info.h" | |
| 45 #include "net/http/http_server_properties.h" | |
| 46 #include "net/http/http_status_code.h" | |
| 47 #include "net/http/http_stream.h" | |
| 48 #include "net/http/http_stream_factory.h" | |
| 49 #include "net/http/http_util.h" | |
| 50 #include "net/http/transport_security_state.h" | |
| 51 #include "net/http/url_security_manager.h" | |
| 52 #include "net/socket/client_socket_factory.h" | |
| 53 #include "net/socket/socks_client_socket_pool.h" | |
| 54 #include "net/socket/ssl_client_socket.h" | |
| 55 #include "net/socket/ssl_client_socket_pool.h" | |
| 56 #include "net/socket/transport_client_socket_pool.h" | |
| 57 #include "net/spdy/hpack_huffman_aggregator.h" | |
| 58 #include "net/spdy/spdy_http_stream.h" | |
| 59 #include "net/spdy/spdy_session.h" | |
| 60 #include "net/spdy/spdy_session_pool.h" | |
| 61 #include "net/ssl/ssl_cert_request_info.h" | |
| 62 #include "net/ssl/ssl_connection_status_flags.h" | |
| 63 #include "url/gurl.h" | |
| 64 #include "url/url_canon.h" | |
| 65 | |
| 66 namespace net { | |
| 67 | |
| 68 namespace { | |
| 69 | |
| 70 void ProcessAlternateProtocol( | |
| 71 HttpNetworkSession* session, | |
| 72 const HttpResponseHeaders& headers, | |
| 73 const HostPortPair& http_host_port_pair) { | |
| 74 if (!headers.HasHeader(kAlternateProtocolHeader)) | |
| 75 return; | |
| 76 | |
| 77 std::vector<std::string> alternate_protocol_values; | |
| 78 void* iter = NULL; | |
| 79 std::string alternate_protocol_str; | |
| 80 while (headers.EnumerateHeader(&iter, kAlternateProtocolHeader, | |
| 81 &alternate_protocol_str)) { | |
| 82 alternate_protocol_values.push_back(alternate_protocol_str); | |
| 83 } | |
| 84 | |
| 85 session->http_stream_factory()->ProcessAlternateProtocol( | |
| 86 session->http_server_properties(), | |
| 87 alternate_protocol_values, | |
| 88 http_host_port_pair, | |
| 89 *session); | |
| 90 } | |
| 91 | |
| 92 base::Value* NetLogSSLVersionFallbackCallback( | |
| 93 const GURL* url, | |
| 94 int net_error, | |
| 95 uint16 version_before, | |
| 96 uint16 version_after, | |
| 97 NetLog::LogLevel /* log_level */) { | |
| 98 base::DictionaryValue* dict = new base::DictionaryValue(); | |
| 99 dict->SetString("host_and_port", GetHostAndPort(*url)); | |
| 100 dict->SetInteger("net_error", net_error); | |
| 101 dict->SetInteger("version_before", version_before); | |
| 102 dict->SetInteger("version_after", version_after); | |
| 103 return dict; | |
| 104 } | |
| 105 | |
| 106 } // namespace | |
| 107 | |
| 108 //----------------------------------------------------------------------------- | |
| 109 | |
| 110 HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority, | |
| 111 HttpNetworkSession* session) | |
| 112 : pending_auth_target_(HttpAuth::AUTH_NONE), | |
| 113 io_callback_(base::Bind(&HttpNetworkTransaction::OnIOComplete, | |
| 114 base::Unretained(this))), | |
| 115 session_(session), | |
| 116 request_(NULL), | |
| 117 priority_(priority), | |
| 118 headers_valid_(false), | |
| 119 fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK), | |
| 120 request_headers_(), | |
| 121 read_buf_len_(0), | |
| 122 total_received_bytes_(0), | |
| 123 next_state_(STATE_NONE), | |
| 124 establishing_tunnel_(false), | |
| 125 websocket_handshake_stream_base_create_helper_(NULL) { | |
| 126 session->ssl_config_service()->GetSSLConfig(&server_ssl_config_); | |
| 127 session->GetNextProtos(&server_ssl_config_.next_protos); | |
| 128 proxy_ssl_config_ = server_ssl_config_; | |
| 129 } | |
| 130 | |
| 131 HttpNetworkTransaction::~HttpNetworkTransaction() { | |
| 132 if (stream_.get()) { | |
| 133 HttpResponseHeaders* headers = GetResponseHeaders(); | |
| 134 // TODO(mbelshe): The stream_ should be able to compute whether or not the | |
| 135 // stream should be kept alive. No reason to compute here | |
| 136 // and pass it in. | |
| 137 bool try_to_keep_alive = | |
| 138 next_state_ == STATE_NONE && | |
| 139 stream_->CanFindEndOfResponse() && | |
| 140 (!headers || headers->IsKeepAlive()); | |
| 141 if (!try_to_keep_alive) { | |
| 142 stream_->Close(true /* not reusable */); | |
| 143 } else { | |
| 144 if (stream_->IsResponseBodyComplete()) { | |
| 145 // If the response body is complete, we can just reuse the socket. | |
| 146 stream_->Close(false /* reusable */); | |
| 147 } else if (stream_->IsSpdyHttpStream()) { | |
| 148 // Doesn't really matter for SpdyHttpStream. Just close it. | |
| 149 stream_->Close(true /* not reusable */); | |
| 150 } else { | |
| 151 // Otherwise, we try to drain the response body. | |
| 152 HttpStream* stream = stream_.release(); | |
| 153 stream->Drain(session_); | |
| 154 } | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 if (request_ && request_->upload_data_stream) | |
| 159 request_->upload_data_stream->Reset(); // Invalidate pending callbacks. | |
| 160 } | |
| 161 | |
| 162 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, | |
| 163 const CompletionCallback& callback, | |
| 164 const BoundNetLog& net_log) { | |
| 165 net_log_ = net_log; | |
| 166 request_ = request_info; | |
| 167 | |
| 168 if (request_->load_flags & LOAD_DISABLE_CERT_REVOCATION_CHECKING) { | |
| 169 server_ssl_config_.rev_checking_enabled = false; | |
| 170 proxy_ssl_config_.rev_checking_enabled = false; | |
| 171 } | |
| 172 | |
| 173 if (request_->load_flags & LOAD_PREFETCH) | |
| 174 response_.unused_since_prefetch = true; | |
| 175 | |
| 176 // Channel ID is disabled if privacy mode is enabled for this request. | |
| 177 if (request_->privacy_mode == PRIVACY_MODE_ENABLED) | |
| 178 server_ssl_config_.channel_id_enabled = false; | |
| 179 | |
| 180 if (server_ssl_config_.fastradio_padding_enabled) { | |
| 181 server_ssl_config_.fastradio_padding_eligible = | |
| 182 session_->ssl_config_service()->SupportsFastradioPadding( | |
| 183 request_info->url); | |
| 184 } | |
| 185 | |
| 186 next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM; | |
| 187 int rv = DoLoop(OK); | |
| 188 if (rv == ERR_IO_PENDING) | |
| 189 callback_ = callback; | |
| 190 return rv; | |
| 191 } | |
| 192 | |
| 193 int HttpNetworkTransaction::RestartIgnoringLastError( | |
| 194 const CompletionCallback& callback) { | |
| 195 DCHECK(!stream_.get()); | |
| 196 DCHECK(!stream_request_.get()); | |
| 197 DCHECK_EQ(STATE_NONE, next_state_); | |
| 198 | |
| 199 next_state_ = STATE_CREATE_STREAM; | |
| 200 | |
| 201 int rv = DoLoop(OK); | |
| 202 if (rv == ERR_IO_PENDING) | |
| 203 callback_ = callback; | |
| 204 return rv; | |
| 205 } | |
| 206 | |
| 207 int HttpNetworkTransaction::RestartWithCertificate( | |
| 208 X509Certificate* client_cert, const CompletionCallback& callback) { | |
| 209 // In HandleCertificateRequest(), we always tear down existing stream | |
| 210 // requests to force a new connection. So we shouldn't have one here. | |
| 211 DCHECK(!stream_request_.get()); | |
| 212 DCHECK(!stream_.get()); | |
| 213 DCHECK_EQ(STATE_NONE, next_state_); | |
| 214 | |
| 215 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ? | |
| 216 &proxy_ssl_config_ : &server_ssl_config_; | |
| 217 ssl_config->send_client_cert = true; | |
| 218 ssl_config->client_cert = client_cert; | |
| 219 session_->ssl_client_auth_cache()->Add( | |
| 220 response_.cert_request_info->host_and_port, client_cert); | |
| 221 // Reset the other member variables. | |
| 222 // Note: this is necessary only with SSL renegotiation. | |
| 223 ResetStateForRestart(); | |
| 224 next_state_ = STATE_CREATE_STREAM; | |
| 225 int rv = DoLoop(OK); | |
| 226 if (rv == ERR_IO_PENDING) | |
| 227 callback_ = callback; | |
| 228 return rv; | |
| 229 } | |
| 230 | |
| 231 int HttpNetworkTransaction::RestartWithAuth( | |
| 232 const AuthCredentials& credentials, const CompletionCallback& callback) { | |
| 233 HttpAuth::Target target = pending_auth_target_; | |
| 234 if (target == HttpAuth::AUTH_NONE) { | |
| 235 NOTREACHED(); | |
| 236 return ERR_UNEXPECTED; | |
| 237 } | |
| 238 pending_auth_target_ = HttpAuth::AUTH_NONE; | |
| 239 | |
| 240 auth_controllers_[target]->ResetAuth(credentials); | |
| 241 | |
| 242 DCHECK(callback_.is_null()); | |
| 243 | |
| 244 int rv = OK; | |
| 245 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) { | |
| 246 // In this case, we've gathered credentials for use with proxy | |
| 247 // authentication of a tunnel. | |
| 248 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 249 DCHECK(stream_request_ != NULL); | |
| 250 auth_controllers_[target] = NULL; | |
| 251 ResetStateForRestart(); | |
| 252 rv = stream_request_->RestartTunnelWithProxyAuth(credentials); | |
| 253 } else { | |
| 254 // In this case, we've gathered credentials for the server or the proxy | |
| 255 // but it is not during the tunneling phase. | |
| 256 DCHECK(stream_request_ == NULL); | |
| 257 PrepareForAuthRestart(target); | |
| 258 rv = DoLoop(OK); | |
| 259 } | |
| 260 | |
| 261 if (rv == ERR_IO_PENDING) | |
| 262 callback_ = callback; | |
| 263 return rv; | |
| 264 } | |
| 265 | |
| 266 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) { | |
| 267 DCHECK(HaveAuth(target)); | |
| 268 DCHECK(!stream_request_.get()); | |
| 269 | |
| 270 bool keep_alive = false; | |
| 271 // Even if the server says the connection is keep-alive, we have to be | |
| 272 // able to find the end of each response in order to reuse the connection. | |
| 273 if (GetResponseHeaders()->IsKeepAlive() && | |
| 274 stream_->CanFindEndOfResponse()) { | |
| 275 // If the response body hasn't been completely read, we need to drain | |
| 276 // it first. | |
| 277 if (!stream_->IsResponseBodyComplete()) { | |
| 278 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | |
| 279 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket. | |
| 280 read_buf_len_ = kDrainBodyBufferSize; | |
| 281 return; | |
| 282 } | |
| 283 keep_alive = true; | |
| 284 } | |
| 285 | |
| 286 // We don't need to drain the response body, so we act as if we had drained | |
| 287 // the response body. | |
| 288 DidDrainBodyForAuthRestart(keep_alive); | |
| 289 } | |
| 290 | |
| 291 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { | |
| 292 DCHECK(!stream_request_.get()); | |
| 293 | |
| 294 if (stream_.get()) { | |
| 295 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 296 HttpStream* new_stream = NULL; | |
| 297 if (keep_alive && stream_->IsConnectionReusable()) { | |
| 298 // We should call connection_->set_idle_time(), but this doesn't occur | |
| 299 // often enough to be worth the trouble. | |
| 300 stream_->SetConnectionReused(); | |
| 301 new_stream = stream_->RenewStreamForAuth(); | |
| 302 } | |
| 303 | |
| 304 if (!new_stream) { | |
| 305 // Close the stream and mark it as not_reusable. Even in the | |
| 306 // keep_alive case, we've determined that the stream_ is not | |
| 307 // reusable if new_stream is NULL. | |
| 308 stream_->Close(true); | |
| 309 next_state_ = STATE_CREATE_STREAM; | |
| 310 } else { | |
| 311 // Renewed streams shouldn't carry over received bytes. | |
| 312 DCHECK_EQ(0, new_stream->GetTotalReceivedBytes()); | |
| 313 next_state_ = STATE_INIT_STREAM; | |
| 314 } | |
| 315 stream_.reset(new_stream); | |
| 316 } | |
| 317 | |
| 318 // Reset the other member variables. | |
| 319 ResetStateForAuthRestart(); | |
| 320 } | |
| 321 | |
| 322 bool HttpNetworkTransaction::IsReadyToRestartForAuth() { | |
| 323 return pending_auth_target_ != HttpAuth::AUTH_NONE && | |
| 324 HaveAuth(pending_auth_target_); | |
| 325 } | |
| 326 | |
| 327 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, | |
| 328 const CompletionCallback& callback) { | |
| 329 DCHECK(buf); | |
| 330 DCHECK_LT(0, buf_len); | |
| 331 | |
| 332 State next_state = STATE_NONE; | |
| 333 | |
| 334 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders()); | |
| 335 if (headers_valid_ && headers.get() && stream_request_.get()) { | |
| 336 // We're trying to read the body of the response but we're still trying | |
| 337 // to establish an SSL tunnel through an HTTP proxy. We can't read these | |
| 338 // bytes when establishing a tunnel because they might be controlled by | |
| 339 // an active network attacker. We don't worry about this for HTTP | |
| 340 // because an active network attacker can already control HTTP sessions. | |
| 341 // We reach this case when the user cancels a 407 proxy auth prompt. We | |
| 342 // also don't worry about this for an HTTPS Proxy, because the | |
| 343 // communication with the proxy is secure. | |
| 344 // See http://crbug.com/8473. | |
| 345 DCHECK(proxy_info_.is_http() || proxy_info_.is_https()); | |
| 346 DCHECK_EQ(headers->response_code(), HTTP_PROXY_AUTHENTICATION_REQUIRED); | |
| 347 LOG(WARNING) << "Blocked proxy response with status " | |
| 348 << headers->response_code() << " to CONNECT request for " | |
| 349 << GetHostAndPort(request_->url) << "."; | |
| 350 return ERR_TUNNEL_CONNECTION_FAILED; | |
| 351 } | |
| 352 | |
| 353 // Are we using SPDY or HTTP? | |
| 354 next_state = STATE_READ_BODY; | |
| 355 | |
| 356 read_buf_ = buf; | |
| 357 read_buf_len_ = buf_len; | |
| 358 | |
| 359 next_state_ = next_state; | |
| 360 int rv = DoLoop(OK); | |
| 361 if (rv == ERR_IO_PENDING) | |
| 362 callback_ = callback; | |
| 363 return rv; | |
| 364 } | |
| 365 | |
| 366 void HttpNetworkTransaction::StopCaching() {} | |
| 367 | |
| 368 bool HttpNetworkTransaction::GetFullRequestHeaders( | |
| 369 HttpRequestHeaders* headers) const { | |
| 370 // TODO(ttuttle): Make sure we've populated request_headers_. | |
| 371 *headers = request_headers_; | |
| 372 return true; | |
| 373 } | |
| 374 | |
| 375 int64 HttpNetworkTransaction::GetTotalReceivedBytes() const { | |
| 376 int64 total_received_bytes = total_received_bytes_; | |
| 377 if (stream_) | |
| 378 total_received_bytes += stream_->GetTotalReceivedBytes(); | |
| 379 return total_received_bytes; | |
| 380 } | |
| 381 | |
| 382 void HttpNetworkTransaction::DoneReading() {} | |
| 383 | |
| 384 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { | |
| 385 return ((headers_valid_ && response_.headers.get()) || | |
| 386 response_.ssl_info.cert.get() || response_.cert_request_info.get()) | |
| 387 ? &response_ | |
| 388 : NULL; | |
| 389 } | |
| 390 | |
| 391 LoadState HttpNetworkTransaction::GetLoadState() const { | |
| 392 // TODO(wtc): Define a new LoadState value for the | |
| 393 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request. | |
| 394 switch (next_state_) { | |
| 395 case STATE_CREATE_STREAM: | |
| 396 return LOAD_STATE_WAITING_FOR_DELEGATE; | |
| 397 case STATE_CREATE_STREAM_COMPLETE: | |
| 398 return stream_request_->GetLoadState(); | |
| 399 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | |
| 400 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: | |
| 401 case STATE_SEND_REQUEST_COMPLETE: | |
| 402 return LOAD_STATE_SENDING_REQUEST; | |
| 403 case STATE_READ_HEADERS_COMPLETE: | |
| 404 return LOAD_STATE_WAITING_FOR_RESPONSE; | |
| 405 case STATE_READ_BODY_COMPLETE: | |
| 406 return LOAD_STATE_READING_RESPONSE; | |
| 407 default: | |
| 408 return LOAD_STATE_IDLE; | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 UploadProgress HttpNetworkTransaction::GetUploadProgress() const { | |
| 413 if (!stream_.get()) | |
| 414 return UploadProgress(); | |
| 415 | |
| 416 return stream_->GetUploadProgress(); | |
| 417 } | |
| 418 | |
| 419 void HttpNetworkTransaction::SetQuicServerInfo( | |
| 420 QuicServerInfo* quic_server_info) {} | |
| 421 | |
| 422 bool HttpNetworkTransaction::GetLoadTimingInfo( | |
| 423 LoadTimingInfo* load_timing_info) const { | |
| 424 if (!stream_ || !stream_->GetLoadTimingInfo(load_timing_info)) | |
| 425 return false; | |
| 426 | |
| 427 load_timing_info->proxy_resolve_start = | |
| 428 proxy_info_.proxy_resolve_start_time(); | |
| 429 load_timing_info->proxy_resolve_end = proxy_info_.proxy_resolve_end_time(); | |
| 430 load_timing_info->send_start = send_start_time_; | |
| 431 load_timing_info->send_end = send_end_time_; | |
| 432 return true; | |
| 433 } | |
| 434 | |
| 435 void HttpNetworkTransaction::SetPriority(RequestPriority priority) { | |
| 436 priority_ = priority; | |
| 437 if (stream_request_) | |
| 438 stream_request_->SetPriority(priority); | |
| 439 if (stream_) | |
| 440 stream_->SetPriority(priority); | |
| 441 } | |
| 442 | |
| 443 void HttpNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( | |
| 444 WebSocketHandshakeStreamBase::CreateHelper* create_helper) { | |
| 445 websocket_handshake_stream_base_create_helper_ = create_helper; | |
| 446 } | |
| 447 | |
| 448 void HttpNetworkTransaction::SetBeforeNetworkStartCallback( | |
| 449 const BeforeNetworkStartCallback& callback) { | |
| 450 before_network_start_callback_ = callback; | |
| 451 } | |
| 452 | |
| 453 void HttpNetworkTransaction::SetBeforeProxyHeadersSentCallback( | |
| 454 const BeforeProxyHeadersSentCallback& callback) { | |
| 455 before_proxy_headers_sent_callback_ = callback; | |
| 456 } | |
| 457 | |
| 458 int HttpNetworkTransaction::ResumeNetworkStart() { | |
| 459 DCHECK_EQ(next_state_, STATE_CREATE_STREAM); | |
| 460 return DoLoop(OK); | |
| 461 } | |
| 462 | |
| 463 void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config, | |
| 464 const ProxyInfo& used_proxy_info, | |
| 465 HttpStream* stream) { | |
| 466 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 467 DCHECK(stream_request_.get()); | |
| 468 | |
| 469 if (stream_) | |
| 470 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 471 stream_.reset(stream); | |
| 472 server_ssl_config_ = used_ssl_config; | |
| 473 proxy_info_ = used_proxy_info; | |
| 474 response_.was_npn_negotiated = stream_request_->was_npn_negotiated(); | |
| 475 response_.npn_negotiated_protocol = SSLClientSocket::NextProtoToString( | |
| 476 stream_request_->protocol_negotiated()); | |
| 477 response_.was_fetched_via_spdy = stream_request_->using_spdy(); | |
| 478 response_.was_fetched_via_proxy = !proxy_info_.is_direct(); | |
| 479 if (response_.was_fetched_via_proxy && !proxy_info_.is_empty()) | |
| 480 response_.proxy_server = proxy_info_.proxy_server().host_port_pair(); | |
| 481 OnIOComplete(OK); | |
| 482 } | |
| 483 | |
| 484 void HttpNetworkTransaction::OnWebSocketHandshakeStreamReady( | |
| 485 const SSLConfig& used_ssl_config, | |
| 486 const ProxyInfo& used_proxy_info, | |
| 487 WebSocketHandshakeStreamBase* stream) { | |
| 488 OnStreamReady(used_ssl_config, used_proxy_info, stream); | |
| 489 } | |
| 490 | |
| 491 void HttpNetworkTransaction::OnStreamFailed(int result, | |
| 492 const SSLConfig& used_ssl_config) { | |
| 493 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 494 DCHECK_NE(OK, result); | |
| 495 DCHECK(stream_request_.get()); | |
| 496 DCHECK(!stream_.get()); | |
| 497 server_ssl_config_ = used_ssl_config; | |
| 498 | |
| 499 OnIOComplete(result); | |
| 500 } | |
| 501 | |
| 502 void HttpNetworkTransaction::OnCertificateError( | |
| 503 int result, | |
| 504 const SSLConfig& used_ssl_config, | |
| 505 const SSLInfo& ssl_info) { | |
| 506 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 507 DCHECK_NE(OK, result); | |
| 508 DCHECK(stream_request_.get()); | |
| 509 DCHECK(!stream_.get()); | |
| 510 | |
| 511 response_.ssl_info = ssl_info; | |
| 512 server_ssl_config_ = used_ssl_config; | |
| 513 | |
| 514 // TODO(mbelshe): For now, we're going to pass the error through, and that | |
| 515 // will close the stream_request in all cases. This means that we're always | |
| 516 // going to restart an entire STATE_CREATE_STREAM, even if the connection is | |
| 517 // good and the user chooses to ignore the error. This is not ideal, but not | |
| 518 // the end of the world either. | |
| 519 | |
| 520 OnIOComplete(result); | |
| 521 } | |
| 522 | |
| 523 void HttpNetworkTransaction::OnNeedsProxyAuth( | |
| 524 const HttpResponseInfo& proxy_response, | |
| 525 const SSLConfig& used_ssl_config, | |
| 526 const ProxyInfo& used_proxy_info, | |
| 527 HttpAuthController* auth_controller) { | |
| 528 DCHECK(stream_request_.get()); | |
| 529 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 530 | |
| 531 establishing_tunnel_ = true; | |
| 532 response_.headers = proxy_response.headers; | |
| 533 response_.auth_challenge = proxy_response.auth_challenge; | |
| 534 headers_valid_ = true; | |
| 535 server_ssl_config_ = used_ssl_config; | |
| 536 proxy_info_ = used_proxy_info; | |
| 537 | |
| 538 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller; | |
| 539 pending_auth_target_ = HttpAuth::AUTH_PROXY; | |
| 540 | |
| 541 DoCallback(OK); | |
| 542 } | |
| 543 | |
| 544 void HttpNetworkTransaction::OnNeedsClientAuth( | |
| 545 const SSLConfig& used_ssl_config, | |
| 546 SSLCertRequestInfo* cert_info) { | |
| 547 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 548 | |
| 549 server_ssl_config_ = used_ssl_config; | |
| 550 response_.cert_request_info = cert_info; | |
| 551 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED); | |
| 552 } | |
| 553 | |
| 554 void HttpNetworkTransaction::OnHttpsProxyTunnelResponse( | |
| 555 const HttpResponseInfo& response_info, | |
| 556 const SSLConfig& used_ssl_config, | |
| 557 const ProxyInfo& used_proxy_info, | |
| 558 HttpStream* stream) { | |
| 559 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); | |
| 560 | |
| 561 headers_valid_ = true; | |
| 562 response_ = response_info; | |
| 563 server_ssl_config_ = used_ssl_config; | |
| 564 proxy_info_ = used_proxy_info; | |
| 565 if (stream_) | |
| 566 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 567 stream_.reset(stream); | |
| 568 stream_request_.reset(); // we're done with the stream request | |
| 569 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); | |
| 570 } | |
| 571 | |
| 572 bool HttpNetworkTransaction::is_https_request() const { | |
| 573 return request_->url.SchemeIs("https"); | |
| 574 } | |
| 575 | |
| 576 bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const { | |
| 577 return (proxy_info_.is_http() || proxy_info_.is_https() || | |
| 578 proxy_info_.is_quic()) && | |
| 579 !(request_->url.SchemeIs("https") || request_->url.SchemeIsWSOrWSS()); | |
| 580 } | |
| 581 | |
| 582 void HttpNetworkTransaction::DoCallback(int rv) { | |
| 583 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 584 DCHECK(!callback_.is_null()); | |
| 585 | |
| 586 // Since Run may result in Read being called, clear user_callback_ up front. | |
| 587 CompletionCallback c = callback_; | |
| 588 callback_.Reset(); | |
| 589 c.Run(rv); | |
| 590 } | |
| 591 | |
| 592 void HttpNetworkTransaction::OnIOComplete(int result) { | |
| 593 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed. | |
| 594 tracked_objects::ScopedTracker tracking_profile1( | |
| 595 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 596 "424359 HttpNetworkTransaction::OnIOComplete 1")); | |
| 597 | |
| 598 int rv = DoLoop(result); | |
| 599 | |
| 600 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed. | |
| 601 tracked_objects::ScopedTracker tracking_profile2( | |
| 602 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 603 "424359 HttpNetworkTransaction::OnIOComplete 2")); | |
| 604 | |
| 605 if (rv != ERR_IO_PENDING) | |
| 606 DoCallback(rv); | |
| 607 } | |
| 608 | |
| 609 int HttpNetworkTransaction::DoLoop(int result) { | |
| 610 DCHECK(next_state_ != STATE_NONE); | |
| 611 | |
| 612 int rv = result; | |
| 613 do { | |
| 614 State state = next_state_; | |
| 615 next_state_ = STATE_NONE; | |
| 616 switch (state) { | |
| 617 case STATE_NOTIFY_BEFORE_CREATE_STREAM: | |
| 618 DCHECK_EQ(OK, rv); | |
| 619 rv = DoNotifyBeforeCreateStream(); | |
| 620 break; | |
| 621 case STATE_CREATE_STREAM: | |
| 622 DCHECK_EQ(OK, rv); | |
| 623 rv = DoCreateStream(); | |
| 624 break; | |
| 625 case STATE_CREATE_STREAM_COMPLETE: | |
| 626 rv = DoCreateStreamComplete(rv); | |
| 627 break; | |
| 628 case STATE_INIT_STREAM: | |
| 629 DCHECK_EQ(OK, rv); | |
| 630 rv = DoInitStream(); | |
| 631 break; | |
| 632 case STATE_INIT_STREAM_COMPLETE: | |
| 633 rv = DoInitStreamComplete(rv); | |
| 634 break; | |
| 635 case STATE_GENERATE_PROXY_AUTH_TOKEN: | |
| 636 DCHECK_EQ(OK, rv); | |
| 637 rv = DoGenerateProxyAuthToken(); | |
| 638 break; | |
| 639 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | |
| 640 rv = DoGenerateProxyAuthTokenComplete(rv); | |
| 641 break; | |
| 642 case STATE_GENERATE_SERVER_AUTH_TOKEN: | |
| 643 DCHECK_EQ(OK, rv); | |
| 644 rv = DoGenerateServerAuthToken(); | |
| 645 break; | |
| 646 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: | |
| 647 rv = DoGenerateServerAuthTokenComplete(rv); | |
| 648 break; | |
| 649 case STATE_INIT_REQUEST_BODY: | |
| 650 DCHECK_EQ(OK, rv); | |
| 651 rv = DoInitRequestBody(); | |
| 652 break; | |
| 653 case STATE_INIT_REQUEST_BODY_COMPLETE: | |
| 654 rv = DoInitRequestBodyComplete(rv); | |
| 655 break; | |
| 656 case STATE_BUILD_REQUEST: | |
| 657 DCHECK_EQ(OK, rv); | |
| 658 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST); | |
| 659 rv = DoBuildRequest(); | |
| 660 break; | |
| 661 case STATE_BUILD_REQUEST_COMPLETE: | |
| 662 rv = DoBuildRequestComplete(rv); | |
| 663 break; | |
| 664 case STATE_SEND_REQUEST: | |
| 665 DCHECK_EQ(OK, rv); | |
| 666 rv = DoSendRequest(); | |
| 667 break; | |
| 668 case STATE_SEND_REQUEST_COMPLETE: | |
| 669 rv = DoSendRequestComplete(rv); | |
| 670 net_log_.EndEventWithNetErrorCode( | |
| 671 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv); | |
| 672 break; | |
| 673 case STATE_READ_HEADERS: | |
| 674 DCHECK_EQ(OK, rv); | |
| 675 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS); | |
| 676 rv = DoReadHeaders(); | |
| 677 break; | |
| 678 case STATE_READ_HEADERS_COMPLETE: | |
| 679 rv = DoReadHeadersComplete(rv); | |
| 680 net_log_.EndEventWithNetErrorCode( | |
| 681 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv); | |
| 682 break; | |
| 683 case STATE_READ_BODY: | |
| 684 DCHECK_EQ(OK, rv); | |
| 685 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY); | |
| 686 rv = DoReadBody(); | |
| 687 break; | |
| 688 case STATE_READ_BODY_COMPLETE: | |
| 689 rv = DoReadBodyComplete(rv); | |
| 690 net_log_.EndEventWithNetErrorCode( | |
| 691 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv); | |
| 692 break; | |
| 693 case STATE_DRAIN_BODY_FOR_AUTH_RESTART: | |
| 694 DCHECK_EQ(OK, rv); | |
| 695 net_log_.BeginEvent( | |
| 696 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART); | |
| 697 rv = DoDrainBodyForAuthRestart(); | |
| 698 break; | |
| 699 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE: | |
| 700 rv = DoDrainBodyForAuthRestartComplete(rv); | |
| 701 net_log_.EndEventWithNetErrorCode( | |
| 702 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv); | |
| 703 break; | |
| 704 default: | |
| 705 NOTREACHED() << "bad state"; | |
| 706 rv = ERR_FAILED; | |
| 707 break; | |
| 708 } | |
| 709 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
| 710 | |
| 711 return rv; | |
| 712 } | |
| 713 | |
| 714 int HttpNetworkTransaction::DoNotifyBeforeCreateStream() { | |
| 715 next_state_ = STATE_CREATE_STREAM; | |
| 716 bool defer = false; | |
| 717 if (!before_network_start_callback_.is_null()) | |
| 718 before_network_start_callback_.Run(&defer); | |
| 719 if (!defer) | |
| 720 return OK; | |
| 721 return ERR_IO_PENDING; | |
| 722 } | |
| 723 | |
| 724 int HttpNetworkTransaction::DoCreateStream() { | |
| 725 next_state_ = STATE_CREATE_STREAM_COMPLETE; | |
| 726 if (ForWebSocketHandshake()) { | |
| 727 stream_request_.reset( | |
| 728 session_->http_stream_factory_for_websocket() | |
| 729 ->RequestWebSocketHandshakeStream( | |
| 730 *request_, | |
| 731 priority_, | |
| 732 server_ssl_config_, | |
| 733 proxy_ssl_config_, | |
| 734 this, | |
| 735 websocket_handshake_stream_base_create_helper_, | |
| 736 net_log_)); | |
| 737 } else { | |
| 738 stream_request_.reset( | |
| 739 session_->http_stream_factory()->RequestStream( | |
| 740 *request_, | |
| 741 priority_, | |
| 742 server_ssl_config_, | |
| 743 proxy_ssl_config_, | |
| 744 this, | |
| 745 net_log_)); | |
| 746 } | |
| 747 DCHECK(stream_request_.get()); | |
| 748 return ERR_IO_PENDING; | |
| 749 } | |
| 750 | |
| 751 int HttpNetworkTransaction::DoCreateStreamComplete(int result) { | |
| 752 if (result == OK) { | |
| 753 next_state_ = STATE_INIT_STREAM; | |
| 754 DCHECK(stream_.get()); | |
| 755 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | |
| 756 result = HandleCertificateRequest(result); | |
| 757 } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { | |
| 758 // Return OK and let the caller read the proxy's error page | |
| 759 next_state_ = STATE_NONE; | |
| 760 return OK; | |
| 761 } else if (result == ERR_HTTP_1_1_REQUIRED || | |
| 762 result == ERR_PROXY_HTTP_1_1_REQUIRED) { | |
| 763 return HandleHttp11Required(result); | |
| 764 } | |
| 765 | |
| 766 // Handle possible handshake errors that may have occurred if the stream | |
| 767 // used SSL for one or more of the layers. | |
| 768 result = HandleSSLHandshakeError(result); | |
| 769 | |
| 770 // At this point we are done with the stream_request_. | |
| 771 stream_request_.reset(); | |
| 772 return result; | |
| 773 } | |
| 774 | |
| 775 int HttpNetworkTransaction::DoInitStream() { | |
| 776 DCHECK(stream_.get()); | |
| 777 next_state_ = STATE_INIT_STREAM_COMPLETE; | |
| 778 return stream_->InitializeStream(request_, priority_, net_log_, io_callback_); | |
| 779 } | |
| 780 | |
| 781 int HttpNetworkTransaction::DoInitStreamComplete(int result) { | |
| 782 if (result == OK) { | |
| 783 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | |
| 784 } else { | |
| 785 if (result < 0) | |
| 786 result = HandleIOError(result); | |
| 787 | |
| 788 // The stream initialization failed, so this stream will never be useful. | |
| 789 if (stream_) | |
| 790 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 791 stream_.reset(); | |
| 792 } | |
| 793 | |
| 794 return result; | |
| 795 } | |
| 796 | |
| 797 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { | |
| 798 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; | |
| 799 if (!ShouldApplyProxyAuth()) | |
| 800 return OK; | |
| 801 HttpAuth::Target target = HttpAuth::AUTH_PROXY; | |
| 802 if (!auth_controllers_[target].get()) | |
| 803 auth_controllers_[target] = | |
| 804 new HttpAuthController(target, | |
| 805 AuthURL(target), | |
| 806 session_->http_auth_cache(), | |
| 807 session_->http_auth_handler_factory()); | |
| 808 return auth_controllers_[target]->MaybeGenerateAuthToken(request_, | |
| 809 io_callback_, | |
| 810 net_log_); | |
| 811 } | |
| 812 | |
| 813 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { | |
| 814 DCHECK_NE(ERR_IO_PENDING, rv); | |
| 815 if (rv == OK) | |
| 816 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN; | |
| 817 return rv; | |
| 818 } | |
| 819 | |
| 820 int HttpNetworkTransaction::DoGenerateServerAuthToken() { | |
| 821 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE; | |
| 822 HttpAuth::Target target = HttpAuth::AUTH_SERVER; | |
| 823 if (!auth_controllers_[target].get()) { | |
| 824 auth_controllers_[target] = | |
| 825 new HttpAuthController(target, | |
| 826 AuthURL(target), | |
| 827 session_->http_auth_cache(), | |
| 828 session_->http_auth_handler_factory()); | |
| 829 if (request_->load_flags & LOAD_DO_NOT_USE_EMBEDDED_IDENTITY) | |
| 830 auth_controllers_[target]->DisableEmbeddedIdentity(); | |
| 831 } | |
| 832 if (!ShouldApplyServerAuth()) | |
| 833 return OK; | |
| 834 return auth_controllers_[target]->MaybeGenerateAuthToken(request_, | |
| 835 io_callback_, | |
| 836 net_log_); | |
| 837 } | |
| 838 | |
| 839 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { | |
| 840 DCHECK_NE(ERR_IO_PENDING, rv); | |
| 841 if (rv == OK) | |
| 842 next_state_ = STATE_INIT_REQUEST_BODY; | |
| 843 return rv; | |
| 844 } | |
| 845 | |
| 846 void HttpNetworkTransaction::BuildRequestHeaders( | |
| 847 bool using_http_proxy_without_tunnel) { | |
| 848 request_headers_.SetHeader(HttpRequestHeaders::kHost, | |
| 849 GetHostAndOptionalPort(request_->url)); | |
| 850 | |
| 851 // For compat with HTTP/1.0 servers and proxies: | |
| 852 if (using_http_proxy_without_tunnel) { | |
| 853 request_headers_.SetHeader(HttpRequestHeaders::kProxyConnection, | |
| 854 "keep-alive"); | |
| 855 } else { | |
| 856 request_headers_.SetHeader(HttpRequestHeaders::kConnection, "keep-alive"); | |
| 857 } | |
| 858 | |
| 859 // Add a content length header? | |
| 860 if (request_->upload_data_stream) { | |
| 861 if (request_->upload_data_stream->is_chunked()) { | |
| 862 request_headers_.SetHeader( | |
| 863 HttpRequestHeaders::kTransferEncoding, "chunked"); | |
| 864 } else { | |
| 865 request_headers_.SetHeader( | |
| 866 HttpRequestHeaders::kContentLength, | |
| 867 base::Uint64ToString(request_->upload_data_stream->size())); | |
| 868 } | |
| 869 } else if (request_->method == "POST" || request_->method == "PUT" || | |
| 870 request_->method == "HEAD") { | |
| 871 // An empty POST/PUT request still needs a content length. As for HEAD, | |
| 872 // IE and Safari also add a content length header. Presumably it is to | |
| 873 // support sending a HEAD request to an URL that only expects to be sent a | |
| 874 // POST or some other method that normally would have a message body. | |
| 875 request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0"); | |
| 876 } | |
| 877 | |
| 878 // Honor load flags that impact proxy caches. | |
| 879 if (request_->load_flags & LOAD_BYPASS_CACHE) { | |
| 880 request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache"); | |
| 881 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "no-cache"); | |
| 882 } else if (request_->load_flags & LOAD_VALIDATE_CACHE) { | |
| 883 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0"); | |
| 884 } | |
| 885 | |
| 886 if (ShouldApplyProxyAuth() && HaveAuth(HttpAuth::AUTH_PROXY)) | |
| 887 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader( | |
| 888 &request_headers_); | |
| 889 if (ShouldApplyServerAuth() && HaveAuth(HttpAuth::AUTH_SERVER)) | |
| 890 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader( | |
| 891 &request_headers_); | |
| 892 | |
| 893 request_headers_.MergeFrom(request_->extra_headers); | |
| 894 | |
| 895 if (using_http_proxy_without_tunnel && | |
| 896 !before_proxy_headers_sent_callback_.is_null()) | |
| 897 before_proxy_headers_sent_callback_.Run(proxy_info_, &request_headers_); | |
| 898 | |
| 899 response_.did_use_http_auth = | |
| 900 request_headers_.HasHeader(HttpRequestHeaders::kAuthorization) || | |
| 901 request_headers_.HasHeader(HttpRequestHeaders::kProxyAuthorization); | |
| 902 } | |
| 903 | |
| 904 int HttpNetworkTransaction::DoInitRequestBody() { | |
| 905 next_state_ = STATE_INIT_REQUEST_BODY_COMPLETE; | |
| 906 int rv = OK; | |
| 907 if (request_->upload_data_stream) | |
| 908 rv = request_->upload_data_stream->Init(io_callback_); | |
| 909 return rv; | |
| 910 } | |
| 911 | |
| 912 int HttpNetworkTransaction::DoInitRequestBodyComplete(int result) { | |
| 913 if (result == OK) | |
| 914 next_state_ = STATE_BUILD_REQUEST; | |
| 915 return result; | |
| 916 } | |
| 917 | |
| 918 int HttpNetworkTransaction::DoBuildRequest() { | |
| 919 next_state_ = STATE_BUILD_REQUEST_COMPLETE; | |
| 920 headers_valid_ = false; | |
| 921 | |
| 922 // This is constructed lazily (instead of within our Start method), so that | |
| 923 // we have proxy info available. | |
| 924 if (request_headers_.IsEmpty()) { | |
| 925 bool using_http_proxy_without_tunnel = UsingHttpProxyWithoutTunnel(); | |
| 926 BuildRequestHeaders(using_http_proxy_without_tunnel); | |
| 927 } | |
| 928 | |
| 929 return OK; | |
| 930 } | |
| 931 | |
| 932 int HttpNetworkTransaction::DoBuildRequestComplete(int result) { | |
| 933 if (result == OK) | |
| 934 next_state_ = STATE_SEND_REQUEST; | |
| 935 return result; | |
| 936 } | |
| 937 | |
| 938 int HttpNetworkTransaction::DoSendRequest() { | |
| 939 send_start_time_ = base::TimeTicks::Now(); | |
| 940 next_state_ = STATE_SEND_REQUEST_COMPLETE; | |
| 941 | |
| 942 return stream_->SendRequest(request_headers_, &response_, io_callback_); | |
| 943 } | |
| 944 | |
| 945 int HttpNetworkTransaction::DoSendRequestComplete(int result) { | |
| 946 send_end_time_ = base::TimeTicks::Now(); | |
| 947 if (result < 0) | |
| 948 return HandleIOError(result); | |
| 949 response_.network_accessed = true; | |
| 950 next_state_ = STATE_READ_HEADERS; | |
| 951 return OK; | |
| 952 } | |
| 953 | |
| 954 int HttpNetworkTransaction::DoReadHeaders() { | |
| 955 next_state_ = STATE_READ_HEADERS_COMPLETE; | |
| 956 return stream_->ReadResponseHeaders(io_callback_); | |
| 957 } | |
| 958 | |
| 959 int HttpNetworkTransaction::DoReadHeadersComplete(int result) { | |
| 960 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here | |
| 961 // due to SSL renegotiation. | |
| 962 if (IsCertificateError(result)) { | |
| 963 // We don't handle a certificate error during SSL renegotiation, so we | |
| 964 // have to return an error that's not in the certificate error range | |
| 965 // (-2xx). | |
| 966 LOG(ERROR) << "Got a server certificate with error " << result | |
| 967 << " during SSL renegotiation"; | |
| 968 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; | |
| 969 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | |
| 970 // TODO(wtc): Need a test case for this code path! | |
| 971 DCHECK(stream_.get()); | |
| 972 DCHECK(is_https_request()); | |
| 973 response_.cert_request_info = new SSLCertRequestInfo; | |
| 974 stream_->GetSSLCertRequestInfo(response_.cert_request_info.get()); | |
| 975 result = HandleCertificateRequest(result); | |
| 976 if (result == OK) | |
| 977 return result; | |
| 978 } | |
| 979 | |
| 980 if (result == ERR_HTTP_1_1_REQUIRED || | |
| 981 result == ERR_PROXY_HTTP_1_1_REQUIRED) { | |
| 982 return HandleHttp11Required(result); | |
| 983 } | |
| 984 | |
| 985 // ERR_CONNECTION_CLOSED is treated differently at this point; if partial | |
| 986 // response headers were received, we do the best we can to make sense of it | |
| 987 // and send it back up the stack. | |
| 988 // | |
| 989 // TODO(davidben): Consider moving this to HttpBasicStream, It's a little | |
| 990 // bizarre for SPDY. Assuming this logic is useful at all. | |
| 991 // TODO(davidben): Bubble the error code up so we do not cache? | |
| 992 if (result == ERR_CONNECTION_CLOSED && response_.headers.get()) | |
| 993 result = OK; | |
| 994 | |
| 995 if (result < 0) | |
| 996 return HandleIOError(result); | |
| 997 | |
| 998 DCHECK(response_.headers.get()); | |
| 999 | |
| 1000 // On a 408 response from the server ("Request Timeout") on a stale socket, | |
| 1001 // retry the request. | |
| 1002 // Headers can be NULL because of http://crbug.com/384554. | |
| 1003 if (response_.headers.get() && response_.headers->response_code() == 408 && | |
| 1004 stream_->IsConnectionReused()) { | |
| 1005 net_log_.AddEventWithNetErrorCode( | |
| 1006 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, | |
| 1007 response_.headers->response_code()); | |
| 1008 // This will close the socket - it would be weird to try and reuse it, even | |
| 1009 // if the server doesn't actually close it. | |
| 1010 ResetConnectionAndRequestForResend(); | |
| 1011 return OK; | |
| 1012 } | |
| 1013 | |
| 1014 // Like Net.HttpResponseCode, but only for MAIN_FRAME loads. | |
| 1015 if (request_->load_flags & LOAD_MAIN_FRAME) { | |
| 1016 const int response_code = response_.headers->response_code(); | |
| 1017 UMA_HISTOGRAM_ENUMERATION( | |
| 1018 "Net.HttpResponseCode_Nxx_MainFrame", response_code/100, 10); | |
| 1019 } | |
| 1020 | |
| 1021 net_log_.AddEvent( | |
| 1022 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS, | |
| 1023 base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers)); | |
| 1024 | |
| 1025 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) { | |
| 1026 // HTTP/0.9 doesn't support the PUT method, so lack of response headers | |
| 1027 // indicates a buggy server. See: | |
| 1028 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921 | |
| 1029 if (request_->method == "PUT") | |
| 1030 return ERR_METHOD_NOT_SUPPORTED; | |
| 1031 } | |
| 1032 | |
| 1033 // Check for an intermediate 100 Continue response. An origin server is | |
| 1034 // allowed to send this response even if we didn't ask for it, so we just | |
| 1035 // need to skip over it. | |
| 1036 // We treat any other 1xx in this same way (although in practice getting | |
| 1037 // a 1xx that isn't a 100 is rare). | |
| 1038 // Unless this is a WebSocket request, in which case we pass it on up. | |
| 1039 if (response_.headers->response_code() / 100 == 1 && | |
| 1040 !ForWebSocketHandshake()) { | |
| 1041 response_.headers = new HttpResponseHeaders(std::string()); | |
| 1042 next_state_ = STATE_READ_HEADERS; | |
| 1043 return OK; | |
| 1044 } | |
| 1045 | |
| 1046 ProcessAlternateProtocol(session_, *response_.headers.get(), | |
| 1047 HostPortPair::FromURL(request_->url)); | |
| 1048 | |
| 1049 int rv = HandleAuthChallenge(); | |
| 1050 if (rv != OK) | |
| 1051 return rv; | |
| 1052 | |
| 1053 if (is_https_request()) | |
| 1054 stream_->GetSSLInfo(&response_.ssl_info); | |
| 1055 | |
| 1056 headers_valid_ = true; | |
| 1057 | |
| 1058 if (session_->huffman_aggregator()) { | |
| 1059 session_->huffman_aggregator()->AggregateTransactionCharacterCounts( | |
| 1060 *request_, | |
| 1061 request_headers_, | |
| 1062 proxy_info_.proxy_server(), | |
| 1063 *response_.headers.get()); | |
| 1064 } | |
| 1065 return OK; | |
| 1066 } | |
| 1067 | |
| 1068 int HttpNetworkTransaction::DoReadBody() { | |
| 1069 DCHECK(read_buf_.get()); | |
| 1070 DCHECK_GT(read_buf_len_, 0); | |
| 1071 DCHECK(stream_ != NULL); | |
| 1072 | |
| 1073 next_state_ = STATE_READ_BODY_COMPLETE; | |
| 1074 return stream_->ReadResponseBody( | |
| 1075 read_buf_.get(), read_buf_len_, io_callback_); | |
| 1076 } | |
| 1077 | |
| 1078 int HttpNetworkTransaction::DoReadBodyComplete(int result) { | |
| 1079 // We are done with the Read call. | |
| 1080 bool done = false; | |
| 1081 if (result <= 0) { | |
| 1082 DCHECK_NE(ERR_IO_PENDING, result); | |
| 1083 done = true; | |
| 1084 } | |
| 1085 | |
| 1086 bool keep_alive = false; | |
| 1087 if (stream_->IsResponseBodyComplete()) { | |
| 1088 // Note: Just because IsResponseBodyComplete is true, we're not | |
| 1089 // necessarily "done". We're only "done" when it is the last | |
| 1090 // read on this HttpNetworkTransaction, which will be signified | |
| 1091 // by a zero-length read. | |
| 1092 // TODO(mbelshe): The keepalive property is really a property of | |
| 1093 // the stream. No need to compute it here just to pass back | |
| 1094 // to the stream's Close function. | |
| 1095 // TODO(rtenneti): CanFindEndOfResponse should return false if there are no | |
| 1096 // ResponseHeaders. | |
| 1097 if (stream_->CanFindEndOfResponse()) { | |
| 1098 HttpResponseHeaders* headers = GetResponseHeaders(); | |
| 1099 if (headers) | |
| 1100 keep_alive = headers->IsKeepAlive(); | |
| 1101 } | |
| 1102 } | |
| 1103 | |
| 1104 // Clean up connection if we are done. | |
| 1105 if (done) { | |
| 1106 stream_->Close(!keep_alive); | |
| 1107 // Note: we don't reset the stream here. We've closed it, but we still | |
| 1108 // need it around so that callers can call methods such as | |
| 1109 // GetUploadProgress() and have them be meaningful. | |
| 1110 // TODO(mbelshe): This means we closed the stream here, and we close it | |
| 1111 // again in ~HttpNetworkTransaction. Clean that up. | |
| 1112 | |
| 1113 // The next Read call will return 0 (EOF). | |
| 1114 } | |
| 1115 | |
| 1116 // Clear these to avoid leaving around old state. | |
| 1117 read_buf_ = NULL; | |
| 1118 read_buf_len_ = 0; | |
| 1119 | |
| 1120 return result; | |
| 1121 } | |
| 1122 | |
| 1123 int HttpNetworkTransaction::DoDrainBodyForAuthRestart() { | |
| 1124 // This method differs from DoReadBody only in the next_state_. So we just | |
| 1125 // call DoReadBody and override the next_state_. Perhaps there is a more | |
| 1126 // elegant way for these two methods to share code. | |
| 1127 int rv = DoReadBody(); | |
| 1128 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE); | |
| 1129 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE; | |
| 1130 return rv; | |
| 1131 } | |
| 1132 | |
| 1133 // TODO(wtc): This method and the DoReadBodyComplete method are almost | |
| 1134 // the same. Figure out a good way for these two methods to share code. | |
| 1135 int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) { | |
| 1136 // keep_alive defaults to true because the very reason we're draining the | |
| 1137 // response body is to reuse the connection for auth restart. | |
| 1138 bool done = false, keep_alive = true; | |
| 1139 if (result < 0) { | |
| 1140 // Error or closed connection while reading the socket. | |
| 1141 done = true; | |
| 1142 keep_alive = false; | |
| 1143 } else if (stream_->IsResponseBodyComplete()) { | |
| 1144 done = true; | |
| 1145 } | |
| 1146 | |
| 1147 if (done) { | |
| 1148 DidDrainBodyForAuthRestart(keep_alive); | |
| 1149 } else { | |
| 1150 // Keep draining. | |
| 1151 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | |
| 1152 } | |
| 1153 | |
| 1154 return OK; | |
| 1155 } | |
| 1156 | |
| 1157 int HttpNetworkTransaction::HandleCertificateRequest(int error) { | |
| 1158 // There are two paths through which the server can request a certificate | |
| 1159 // from us. The first is during the initial handshake, the second is | |
| 1160 // during SSL renegotiation. | |
| 1161 // | |
| 1162 // In both cases, we want to close the connection before proceeding. | |
| 1163 // We do this for two reasons: | |
| 1164 // First, we don't want to keep the connection to the server hung for a | |
| 1165 // long time while the user selects a certificate. | |
| 1166 // Second, even if we did keep the connection open, NSS has a bug where | |
| 1167 // restarting the handshake for ClientAuth is currently broken. | |
| 1168 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); | |
| 1169 | |
| 1170 if (stream_.get()) { | |
| 1171 // Since we already have a stream, we're being called as part of SSL | |
| 1172 // renegotiation. | |
| 1173 DCHECK(!stream_request_.get()); | |
| 1174 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 1175 stream_->Close(true); | |
| 1176 stream_.reset(); | |
| 1177 } | |
| 1178 | |
| 1179 // The server is asking for a client certificate during the initial | |
| 1180 // handshake. | |
| 1181 stream_request_.reset(); | |
| 1182 | |
| 1183 // If the user selected one of the certificates in client_certs or declined | |
| 1184 // to provide one for this server before, use the past decision | |
| 1185 // automatically. | |
| 1186 scoped_refptr<X509Certificate> client_cert; | |
| 1187 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup( | |
| 1188 response_.cert_request_info->host_and_port, &client_cert); | |
| 1189 if (!found_cached_cert) | |
| 1190 return error; | |
| 1191 | |
| 1192 // Check that the certificate selected is still a certificate the server | |
| 1193 // is likely to accept, based on the criteria supplied in the | |
| 1194 // CertificateRequest message. | |
| 1195 if (client_cert.get()) { | |
| 1196 const std::vector<std::string>& cert_authorities = | |
| 1197 response_.cert_request_info->cert_authorities; | |
| 1198 | |
| 1199 bool cert_still_valid = cert_authorities.empty() || | |
| 1200 client_cert->IsIssuedByEncoded(cert_authorities); | |
| 1201 if (!cert_still_valid) | |
| 1202 return error; | |
| 1203 } | |
| 1204 | |
| 1205 // TODO(davidben): Add a unit test which covers this path; we need to be | |
| 1206 // able to send a legitimate certificate and also bypass/clear the | |
| 1207 // SSL session cache. | |
| 1208 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ? | |
| 1209 &proxy_ssl_config_ : &server_ssl_config_; | |
| 1210 ssl_config->send_client_cert = true; | |
| 1211 ssl_config->client_cert = client_cert; | |
| 1212 next_state_ = STATE_CREATE_STREAM; | |
| 1213 // Reset the other member variables. | |
| 1214 // Note: this is necessary only with SSL renegotiation. | |
| 1215 ResetStateForRestart(); | |
| 1216 return OK; | |
| 1217 } | |
| 1218 | |
| 1219 int HttpNetworkTransaction::HandleHttp11Required(int error) { | |
| 1220 DCHECK(error == ERR_HTTP_1_1_REQUIRED || | |
| 1221 error == ERR_PROXY_HTTP_1_1_REQUIRED); | |
| 1222 | |
| 1223 if (error == ERR_HTTP_1_1_REQUIRED) { | |
| 1224 HttpServerProperties::ForceHTTP11(&server_ssl_config_); | |
| 1225 } else { | |
| 1226 HttpServerProperties::ForceHTTP11(&proxy_ssl_config_); | |
| 1227 } | |
| 1228 ResetConnectionAndRequestForResend(); | |
| 1229 return OK; | |
| 1230 } | |
| 1231 | |
| 1232 void HttpNetworkTransaction::HandleClientAuthError(int error) { | |
| 1233 if (server_ssl_config_.send_client_cert && | |
| 1234 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) { | |
| 1235 session_->ssl_client_auth_cache()->Remove( | |
| 1236 HostPortPair::FromURL(request_->url)); | |
| 1237 } | |
| 1238 } | |
| 1239 | |
| 1240 // TODO(rch): This does not correctly handle errors when an SSL proxy is | |
| 1241 // being used, as all of the errors are handled as if they were generated | |
| 1242 // by the endpoint host, request_->url, rather than considering if they were | |
| 1243 // generated by the SSL proxy. http://crbug.com/69329 | |
| 1244 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { | |
| 1245 DCHECK(request_); | |
| 1246 HandleClientAuthError(error); | |
| 1247 | |
| 1248 bool should_fallback = false; | |
| 1249 uint16 version_max = server_ssl_config_.version_max; | |
| 1250 | |
| 1251 switch (error) { | |
| 1252 case ERR_CONNECTION_CLOSED: | |
| 1253 case ERR_SSL_PROTOCOL_ERROR: | |
| 1254 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH: | |
| 1255 if (version_max >= SSL_PROTOCOL_VERSION_TLS1 && | |
| 1256 version_max > server_ssl_config_.version_min) { | |
| 1257 // This could be a TLS-intolerant server or a server that chose a | |
| 1258 // cipher suite defined only for higher protocol versions (such as | |
| 1259 // an SSL 3.0 server that chose a TLS-only cipher suite). Fall | |
| 1260 // back to the next lower version and retry. | |
| 1261 // NOTE: if the SSLClientSocket class doesn't support TLS 1.1, | |
| 1262 // specifying TLS 1.1 in version_max will result in a TLS 1.0 | |
| 1263 // handshake, so falling back from TLS 1.1 to TLS 1.0 will simply | |
| 1264 // repeat the TLS 1.0 handshake. To avoid this problem, the default | |
| 1265 // version_max should match the maximum protocol version supported | |
| 1266 // by the SSLClientSocket class. | |
| 1267 version_max--; | |
| 1268 | |
| 1269 // Fallback to the lower SSL version. | |
| 1270 // While SSL 3.0 fallback should be eliminated because of security | |
| 1271 // reasons, there is a high risk of breaking the servers if this is | |
| 1272 // done in general. | |
| 1273 should_fallback = true; | |
| 1274 } | |
| 1275 break; | |
| 1276 case ERR_CONNECTION_RESET: | |
| 1277 if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 && | |
| 1278 version_max > server_ssl_config_.version_min) { | |
| 1279 // Some network devices that inspect application-layer packets seem to | |
| 1280 // inject TCP reset packets to break the connections when they see TLS | |
| 1281 // 1.1 in ClientHello or ServerHello. See http://crbug.com/130293. | |
| 1282 // | |
| 1283 // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or | |
| 1284 // 1.2. We don't lose much in this fallback because the explicit IV for | |
| 1285 // CBC mode in TLS 1.1 is approximated by record splitting in TLS | |
| 1286 // 1.0. The fallback will be more painful for TLS 1.2 when we have GCM | |
| 1287 // support. | |
| 1288 // | |
| 1289 // ERR_CONNECTION_RESET is a common network error, so we don't want it | |
| 1290 // to trigger a version fallback in general, especially the TLS 1.0 -> | |
| 1291 // SSL 3.0 fallback, which would drop TLS extensions. | |
| 1292 version_max--; | |
| 1293 should_fallback = true; | |
| 1294 } | |
| 1295 break; | |
| 1296 case ERR_SSL_BAD_RECORD_MAC_ALERT: | |
| 1297 if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 && | |
| 1298 version_max > server_ssl_config_.version_min) { | |
| 1299 // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or | |
| 1300 // 1.2 ClientHello, but then return a bad_record_mac alert. See | |
| 1301 // crbug.com/260358. In order to make the fallback as minimal as | |
| 1302 // possible, this fallback is only triggered for >= TLS 1.1. | |
| 1303 version_max--; | |
| 1304 should_fallback = true; | |
| 1305 } | |
| 1306 break; | |
| 1307 case ERR_SSL_INAPPROPRIATE_FALLBACK: | |
| 1308 // The server told us that we should not have fallen back. A buggy server | |
| 1309 // could trigger ERR_SSL_INAPPROPRIATE_FALLBACK with the initial | |
| 1310 // connection. |fallback_error_code_| is initialised to | |
| 1311 // ERR_SSL_INAPPROPRIATE_FALLBACK to catch this case. | |
| 1312 error = fallback_error_code_; | |
| 1313 break; | |
| 1314 } | |
| 1315 | |
| 1316 if (should_fallback) { | |
| 1317 net_log_.AddEvent( | |
| 1318 NetLog::TYPE_SSL_VERSION_FALLBACK, | |
| 1319 base::Bind(&NetLogSSLVersionFallbackCallback, | |
| 1320 &request_->url, error, server_ssl_config_.version_max, | |
| 1321 version_max)); | |
| 1322 fallback_error_code_ = error; | |
| 1323 server_ssl_config_.version_max = version_max; | |
| 1324 server_ssl_config_.version_fallback = true; | |
| 1325 ResetConnectionAndRequestForResend(); | |
| 1326 error = OK; | |
| 1327 } | |
| 1328 | |
| 1329 return error; | |
| 1330 } | |
| 1331 | |
| 1332 // This method determines whether it is safe to resend the request after an | |
| 1333 // IO error. It can only be called in response to request header or body | |
| 1334 // write errors or response header read errors. It should not be used in | |
| 1335 // other cases, such as a Connect error. | |
| 1336 int HttpNetworkTransaction::HandleIOError(int error) { | |
| 1337 // Because the peer may request renegotiation with client authentication at | |
| 1338 // any time, check and handle client authentication errors. | |
| 1339 HandleClientAuthError(error); | |
| 1340 | |
| 1341 switch (error) { | |
| 1342 // If we try to reuse a connection that the server is in the process of | |
| 1343 // closing, we may end up successfully writing out our request (or a | |
| 1344 // portion of our request) only to find a connection error when we try to | |
| 1345 // read from (or finish writing to) the socket. | |
| 1346 case ERR_CONNECTION_RESET: | |
| 1347 case ERR_CONNECTION_CLOSED: | |
| 1348 case ERR_CONNECTION_ABORTED: | |
| 1349 // There can be a race between the socket pool checking checking whether a | |
| 1350 // socket is still connected, receiving the FIN, and sending/reading data | |
| 1351 // on a reused socket. If we receive the FIN between the connectedness | |
| 1352 // check and writing/reading from the socket, we may first learn the socket | |
| 1353 // is disconnected when we get a ERR_SOCKET_NOT_CONNECTED. This will most | |
| 1354 // likely happen when trying to retrieve its IP address. | |
| 1355 // See http://crbug.com/105824 for more details. | |
| 1356 case ERR_SOCKET_NOT_CONNECTED: | |
| 1357 // If a socket is closed on its initial request, HttpStreamParser returns | |
| 1358 // ERR_EMPTY_RESPONSE. This may still be close/reuse race if the socket was | |
| 1359 // preconnected but failed to be used before the server timed it out. | |
| 1360 case ERR_EMPTY_RESPONSE: | |
| 1361 if (ShouldResendRequest()) { | |
| 1362 net_log_.AddEventWithNetErrorCode( | |
| 1363 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); | |
| 1364 ResetConnectionAndRequestForResend(); | |
| 1365 error = OK; | |
| 1366 } | |
| 1367 break; | |
| 1368 case ERR_SPDY_PING_FAILED: | |
| 1369 case ERR_SPDY_SERVER_REFUSED_STREAM: | |
| 1370 case ERR_QUIC_HANDSHAKE_FAILED: | |
| 1371 net_log_.AddEventWithNetErrorCode( | |
| 1372 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); | |
| 1373 ResetConnectionAndRequestForResend(); | |
| 1374 error = OK; | |
| 1375 break; | |
| 1376 } | |
| 1377 return error; | |
| 1378 } | |
| 1379 | |
| 1380 void HttpNetworkTransaction::ResetStateForRestart() { | |
| 1381 ResetStateForAuthRestart(); | |
| 1382 if (stream_) | |
| 1383 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 1384 stream_.reset(); | |
| 1385 } | |
| 1386 | |
| 1387 void HttpNetworkTransaction::ResetStateForAuthRestart() { | |
| 1388 send_start_time_ = base::TimeTicks(); | |
| 1389 send_end_time_ = base::TimeTicks(); | |
| 1390 | |
| 1391 pending_auth_target_ = HttpAuth::AUTH_NONE; | |
| 1392 read_buf_ = NULL; | |
| 1393 read_buf_len_ = 0; | |
| 1394 headers_valid_ = false; | |
| 1395 request_headers_.Clear(); | |
| 1396 response_ = HttpResponseInfo(); | |
| 1397 establishing_tunnel_ = false; | |
| 1398 } | |
| 1399 | |
| 1400 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const { | |
| 1401 return response_.headers.get(); | |
| 1402 } | |
| 1403 | |
| 1404 bool HttpNetworkTransaction::ShouldResendRequest() const { | |
| 1405 bool connection_is_proven = stream_->IsConnectionReused(); | |
| 1406 bool has_received_headers = GetResponseHeaders() != NULL; | |
| 1407 | |
| 1408 // NOTE: we resend a request only if we reused a keep-alive connection. | |
| 1409 // This automatically prevents an infinite resend loop because we'll run | |
| 1410 // out of the cached keep-alive connections eventually. | |
| 1411 if (connection_is_proven && !has_received_headers) | |
| 1412 return true; | |
| 1413 return false; | |
| 1414 } | |
| 1415 | |
| 1416 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() { | |
| 1417 if (stream_.get()) { | |
| 1418 stream_->Close(true); | |
| 1419 stream_.reset(); | |
| 1420 } | |
| 1421 | |
| 1422 // We need to clear request_headers_ because it contains the real request | |
| 1423 // headers, but we may need to resend the CONNECT request first to recreate | |
| 1424 // the SSL tunnel. | |
| 1425 request_headers_.Clear(); | |
| 1426 next_state_ = STATE_CREATE_STREAM; // Resend the request. | |
| 1427 } | |
| 1428 | |
| 1429 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { | |
| 1430 return UsingHttpProxyWithoutTunnel(); | |
| 1431 } | |
| 1432 | |
| 1433 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { | |
| 1434 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); | |
| 1435 } | |
| 1436 | |
| 1437 int HttpNetworkTransaction::HandleAuthChallenge() { | |
| 1438 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders()); | |
| 1439 DCHECK(headers.get()); | |
| 1440 | |
| 1441 int status = headers->response_code(); | |
| 1442 if (status != HTTP_UNAUTHORIZED && | |
| 1443 status != HTTP_PROXY_AUTHENTICATION_REQUIRED) | |
| 1444 return OK; | |
| 1445 HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ? | |
| 1446 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; | |
| 1447 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) | |
| 1448 return ERR_UNEXPECTED_PROXY_AUTH; | |
| 1449 | |
| 1450 // This case can trigger when an HTTPS server responds with a "Proxy | |
| 1451 // authentication required" status code through a non-authenticating | |
| 1452 // proxy. | |
| 1453 if (!auth_controllers_[target].get()) | |
| 1454 return ERR_UNEXPECTED_PROXY_AUTH; | |
| 1455 | |
| 1456 int rv = auth_controllers_[target]->HandleAuthChallenge( | |
| 1457 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false, | |
| 1458 net_log_); | |
| 1459 if (auth_controllers_[target]->HaveAuthHandler()) | |
| 1460 pending_auth_target_ = target; | |
| 1461 | |
| 1462 scoped_refptr<AuthChallengeInfo> auth_info = | |
| 1463 auth_controllers_[target]->auth_info(); | |
| 1464 if (auth_info.get()) | |
| 1465 response_.auth_challenge = auth_info; | |
| 1466 | |
| 1467 return rv; | |
| 1468 } | |
| 1469 | |
| 1470 bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const { | |
| 1471 return auth_controllers_[target].get() && | |
| 1472 auth_controllers_[target]->HaveAuth(); | |
| 1473 } | |
| 1474 | |
| 1475 GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const { | |
| 1476 switch (target) { | |
| 1477 case HttpAuth::AUTH_PROXY: { | |
| 1478 if (!proxy_info_.proxy_server().is_valid() || | |
| 1479 proxy_info_.proxy_server().is_direct()) { | |
| 1480 return GURL(); // There is no proxy server. | |
| 1481 } | |
| 1482 const char* scheme = proxy_info_.is_https() ? "https://" : "http://"; | |
| 1483 return GURL(scheme + | |
| 1484 proxy_info_.proxy_server().host_port_pair().ToString()); | |
| 1485 } | |
| 1486 case HttpAuth::AUTH_SERVER: | |
| 1487 if (ForWebSocketHandshake()) { | |
| 1488 const GURL& url = request_->url; | |
| 1489 url::Replacements<char> ws_to_http; | |
| 1490 if (url.SchemeIs("ws")) { | |
| 1491 ws_to_http.SetScheme("http", url::Component(0, 4)); | |
| 1492 } else { | |
| 1493 DCHECK(url.SchemeIs("wss")); | |
| 1494 ws_to_http.SetScheme("https", url::Component(0, 5)); | |
| 1495 } | |
| 1496 return url.ReplaceComponents(ws_to_http); | |
| 1497 } | |
| 1498 return request_->url; | |
| 1499 default: | |
| 1500 return GURL(); | |
| 1501 } | |
| 1502 } | |
| 1503 | |
| 1504 bool HttpNetworkTransaction::ForWebSocketHandshake() const { | |
| 1505 return websocket_handshake_stream_base_create_helper_ && | |
| 1506 request_->url.SchemeIsWSOrWSS(); | |
| 1507 } | |
| 1508 | |
| 1509 #define STATE_CASE(s) \ | |
| 1510 case s: \ | |
| 1511 description = base::StringPrintf("%s (0x%08X)", #s, s); \ | |
| 1512 break | |
| 1513 | |
| 1514 std::string HttpNetworkTransaction::DescribeState(State state) { | |
| 1515 std::string description; | |
| 1516 switch (state) { | |
| 1517 STATE_CASE(STATE_NOTIFY_BEFORE_CREATE_STREAM); | |
| 1518 STATE_CASE(STATE_CREATE_STREAM); | |
| 1519 STATE_CASE(STATE_CREATE_STREAM_COMPLETE); | |
| 1520 STATE_CASE(STATE_INIT_REQUEST_BODY); | |
| 1521 STATE_CASE(STATE_INIT_REQUEST_BODY_COMPLETE); | |
| 1522 STATE_CASE(STATE_BUILD_REQUEST); | |
| 1523 STATE_CASE(STATE_BUILD_REQUEST_COMPLETE); | |
| 1524 STATE_CASE(STATE_SEND_REQUEST); | |
| 1525 STATE_CASE(STATE_SEND_REQUEST_COMPLETE); | |
| 1526 STATE_CASE(STATE_READ_HEADERS); | |
| 1527 STATE_CASE(STATE_READ_HEADERS_COMPLETE); | |
| 1528 STATE_CASE(STATE_READ_BODY); | |
| 1529 STATE_CASE(STATE_READ_BODY_COMPLETE); | |
| 1530 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART); | |
| 1531 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE); | |
| 1532 STATE_CASE(STATE_NONE); | |
| 1533 default: | |
| 1534 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, | |
| 1535 state); | |
| 1536 break; | |
| 1537 } | |
| 1538 return description; | |
| 1539 } | |
| 1540 | |
| 1541 #undef STATE_CASE | |
| 1542 | |
| 1543 } // namespace net | |
| OLD | NEW |