| Index: net/http/http_network_transaction.cc | 
| =================================================================== | 
| --- net/http/http_network_transaction.cc	(revision 18321) | 
| +++ net/http/http_network_transaction.cc	(working copy) | 
| @@ -1,4 +1,4 @@ | 
| -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 
| +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 
| // Use of this source code is governed by a BSD-style license that can be | 
| // found in the LICENSE file. | 
|  | 
| @@ -17,6 +17,7 @@ | 
| #include "net/base/load_flags.h" | 
| #include "net/base/net_errors.h" | 
| #include "net/base/net_util.h" | 
| +#include "net/base/ssl_cert_request_info.h" | 
| #include "net/base/ssl_client_socket.h" | 
| #include "net/base/upload_data_stream.h" | 
| #include "net/http/http_auth.h" | 
| @@ -189,6 +190,21 @@ | 
| return rv; | 
| } | 
|  | 
| +int HttpNetworkTransaction::RestartWithCertificate( | 
| +    X509Certificate* client_cert, | 
| +    CompletionCallback* callback) { | 
| +  ssl_config_.client_cert = client_cert; | 
| +  ssl_config_.send_client_cert = true; | 
| +  next_state_ = STATE_INIT_CONNECTION; | 
| +  // Reset the other member variables. | 
| +  // Note: this is necessary only with SSL renegotiation. | 
| +  ResetStateForRestart(); | 
| +  int rv = DoLoop(OK); | 
| +  if (rv == ERR_IO_PENDING) | 
| +    user_callback_ = callback; | 
| +  return rv; | 
| +} | 
| + | 
| int HttpNetworkTransaction::RestartWithAuth( | 
| const std::wstring& username, | 
| const std::wstring& password, | 
| @@ -346,7 +362,8 @@ | 
| } | 
|  | 
| const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { | 
| -  return (response_.headers || response_.ssl_info.cert) ? &response_ : NULL; | 
| +  return (response_.headers || response_.ssl_info.cert || | 
| +          response_.cert_request_info) ? &response_ : NULL; | 
| } | 
|  | 
| LoadState HttpNetworkTransaction::GetLoadState() const { | 
| @@ -603,6 +620,8 @@ | 
|  | 
| if (result == OK) { | 
| next_state_ = STATE_WRITE_HEADERS; | 
| +  } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 
| +    HandleCertificateRequest(); | 
| } else { | 
| result = HandleSSLHandshakeError(result); | 
| } | 
| @@ -746,13 +765,19 @@ | 
| } | 
|  | 
| int HttpNetworkTransaction::DoReadHeadersComplete(int result) { | 
| -  if (using_ssl_ && IsCertificateError(result)) { | 
| -    // We don't handle a certificate error during SSL renegotiation, so we | 
| -    // have to return an error that's not in the certificate error range | 
| -    // (-2xx). | 
| -    LOG(ERROR) << "Got a server certificate with error " << result | 
| -               << " during SSL renegotiation"; | 
| -    result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; | 
| +  // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here | 
| +  // due to SSL renegotiation. | 
| +  if (using_ssl_) { | 
| +    if (IsCertificateError(result)) { | 
| +      // We don't handle a certificate error during SSL renegotiation, so we | 
| +      // have to return an error that's not in the certificate error range | 
| +      // (-2xx). | 
| +      LOG(ERROR) << "Got a server certificate with error " << result | 
| +                 << " during SSL renegotiation"; | 
| +      result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; | 
| +    } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 
| +      HandleCertificateRequest(); | 
| +    } | 
| } | 
|  | 
| if (result < 0) | 
| @@ -1217,6 +1242,18 @@ | 
| return error; | 
| } | 
|  | 
| +void HttpNetworkTransaction::HandleCertificateRequest() { | 
| +  response_.cert_request_info = new SSLCertRequestInfo; | 
| +  SSLClientSocket* ssl_socket = | 
| +      reinterpret_cast<SSLClientSocket*>(connection_.socket()); | 
| +  ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info); | 
| + | 
| +  // Close the connection while the user is selecting a certificate to send | 
| +  // to the server. | 
| +  connection_.socket()->Disconnect(); | 
| +  connection_.Reset(); | 
| +} | 
| + | 
| int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { | 
| switch (error) { | 
| case ERR_SSL_PROTOCOL_ERROR: | 
|  |